diff --git a/package-lock.json b/package-lock.json index 24ca249..31d5444 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "version": "1.7.1", "resolved": "https://registry.npmjs.org/@appium/logger/-/logger-1.7.1.tgz", "integrity": "sha512-9C2o9X/lBEDBUnKfAi3mRo9oG7Z03nmISLwsGkWxIWjMAvBdJD0RRSJMekWVKzfXN3byrI1WlCXTITzN4LAoLw==", + "license": "ISC", "dependencies": { "console-control-strings": "1.1.0", "lodash": "4.17.21", @@ -35,15 +36,11 @@ "npm": ">=8" } }, - "node_modules/@appium/logger/node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, "node_modules/@appium/schema": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@appium/schema/-/schema-0.8.1.tgz", "integrity": "sha512-3yzfQ/K7RMGnfYDgFG7JdCPsjjN3eS33n2SBeGJtd28mDtgO7EzcmtiUBQjbkxyu0Q7h8KOexiqndvgTCgHeGQ==", + "license": "Apache-2.0", "dependencies": { "json-schema": "0.4.0", "source-map-support": "0.5.21" @@ -57,6 +54,7 @@ "version": "6.1.1", "resolved": "https://registry.npmjs.org/@appium/support/-/support-6.1.1.tgz", "integrity": "sha512-kdv6zOCvVT93OeokEFqFN77yhgM8+u9qM7LMLooYd10/AOvI4jtrEy5B37FiaZYP3ONvvz8ohisU8/RA5FzDVQ==", + "license": "Apache-2.0", "dependencies": { "@appium/logger": "^1.7.1", "@appium/tsconfig": "^0.3.5", @@ -103,29 +101,11 @@ "sharp": "0.34.2" } }, - "node_modules/@appium/support/node_modules/form-data": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", - "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@appium/support/node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, "node_modules/@appium/support/node_modules/semver": { "version": "7.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -137,6 +117,7 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/teen_process/-/teen_process-2.3.2.tgz", "integrity": "sha512-eiYtJbYrMz5WbZL68u05qCgLMShPZhYKVewZFoyT6C2xvNdMfikCP7Nh0K3Phiy+H4bMZ8q5GtJROFcoYwQJmQ==", + "license": "Apache-2.0", "dependencies": { "bluebird": "^3.7.2", "lodash": "^4.17.21", @@ -152,6 +133,7 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/@appium/tsconfig/-/tsconfig-0.3.5.tgz", "integrity": "sha512-T8G5oe3is0Gn56PkeYjXracc0CS26L/obVuX7PHwEDcn1UKiJXFa2MYY73dRAWKJumAIIsJjssNUu6VttdWZWw==", + "license": "Apache-2.0", "dependencies": { "@tsconfig/node14": "14.1.3" }, @@ -164,6 +146,7 @@ "version": "0.26.0", "resolved": "https://registry.npmjs.org/@appium/types/-/types-0.26.0.tgz", "integrity": "sha512-EO7r3H9cd1WePt/Gtb+TKBeWulSKjtNHAxD0llqqQ5hFwfNHWcmdObHL/d8jkyG53E/f54VeBcjD+uCARRqDqw==", + "license": "Apache-2.0", "dependencies": { "@appium/logger": "^1.7.1", "@appium/schema": "^0.8.1", @@ -176,9 +159,10 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz", - "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", @@ -192,6 +176,7 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -200,10 +185,15 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "license": "MIT", "engines": { "node": ">=0.1.90" } }, + "node_modules/@device-stream/agent": { + "resolved": "packages/agent", + "link": true + }, "node_modules/@device-stream/android": { "resolved": "packages/android", "link": true @@ -225,9 +215,10 @@ "link": true }, "node_modules/@emnapi/runtime": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", - "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", + "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", + "license": "MIT", "optional": true, "dependencies": { "tslib": "^2.4.0" @@ -240,6 +231,7 @@ "cpu": [ "arm64" ], + "license": "Apache-2.0", "optional": true, "os": [ "darwin" @@ -261,6 +253,7 @@ "cpu": [ "x64" ], + "license": "Apache-2.0", "optional": true, "os": [ "darwin" @@ -282,6 +275,7 @@ "cpu": [ "arm64" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "darwin" @@ -297,6 +291,7 @@ "cpu": [ "x64" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "darwin" @@ -312,6 +307,10 @@ "cpu": [ "arm" ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -327,6 +326,10 @@ "cpu": [ "arm64" ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -342,6 +345,10 @@ "cpu": [ "ppc64" ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -357,6 +364,10 @@ "cpu": [ "s390x" ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -372,6 +383,10 @@ "cpu": [ "x64" ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -387,6 +402,10 @@ "cpu": [ "arm64" ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -402,6 +421,10 @@ "cpu": [ "x64" ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -417,6 +440,10 @@ "cpu": [ "arm" ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -438,6 +465,10 @@ "cpu": [ "arm64" ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -459,6 +490,10 @@ "cpu": [ "s390x" ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -480,6 +515,10 @@ "cpu": [ "x64" ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -501,6 +540,10 @@ "cpu": [ "arm64" ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -522,6 +565,10 @@ "cpu": [ "x64" ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -543,6 +590,7 @@ "cpu": [ "wasm32" ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, "dependencies": { "@emnapi/runtime": "^1.4.3" @@ -561,6 +609,7 @@ "cpu": [ "arm64" ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ "win32" @@ -579,6 +628,7 @@ "cpu": [ "ia32" ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ "win32" @@ -597,6 +647,7 @@ "cpu": [ "x64" ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ "win32" @@ -608,35 +659,11 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "optional": true, - "engines": { - "node": ">=14" - } - }, "node_modules/@sindresorhus/is": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", + "license": "MIT", "engines": { "node": ">=14.16" }, @@ -648,6 +675,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", + "license": "MIT", "dependencies": { "defer-to-connect": "^2.0.1" }, @@ -658,27 +686,32 @@ "node_modules/@tokenizer/token": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", + "license": "MIT" }, "node_modules/@tsconfig/node14": { "version": "14.1.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-14.1.3.tgz", - "integrity": "sha512-ZC9/Kq2c0+4l8sDx/z3YQyP7+OSMTQr/xxJaSFHLGhGL0t9bPjuX1Zwmg3C2VB5KWGgI8MXMRShXRJroy4utGA==" + "integrity": "sha512-ZC9/Kq2c0+4l8sDx/z3YQyP7+OSMTQr/xxJaSFHLGhGL0t9bPjuX1Zwmg3C2VB5KWGgI8MXMRShXRJroy4utGA==", + "license": "MIT" }, "node_modules/@types/http-cache-semantics": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==" + "integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==", + "license": "MIT" }, "node_modules/@types/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-RDvF6wTulMPjrNdCoYRC8gNR880JNGT8uB+REUpC2Ns4pRqQJhGz90wh7rgdXDPpCczF3VGktDuFGVnz8zP7HA==" + "version": "4.17.24", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.24.tgz", + "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==", + "license": "MIT" }, "node_modules/@types/node": { - "version": "20.19.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", - "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", + "version": "20.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.39.tgz", + "integrity": "sha512-orrrD74MBUyK8jOAD/r0+lfa1I2MO6I+vAkmAWzMYbCcgrN4lCrmK52gRFQq/JRxfYPfonkr4b0jcY7Olqdqbw==", + "license": "MIT", "dependencies": { "undici-types": "~6.21.0" } @@ -686,12 +719,14 @@ "node_modules/@types/normalize-package-data": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==" + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "license": "MIT" }, "node_modules/@types/teen_process": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/teen_process/-/teen_process-2.0.4.tgz", "integrity": "sha512-AJT0syZovEDa4j17szoRJX5BE2RxD3FVp6SownH43mF16TPnsV0zhtsvFGlgs5QkgsNpoooNnF+HjMow7Jd3jA==", + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -701,6 +736,7 @@ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -709,6 +745,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/@xhmikosr/archive-type/-/archive-type-6.0.1.tgz", "integrity": "sha512-PB3NeJL8xARZt52yDBupK0dNPn8uIVQDe15qNehUpoeeLWCZyAOam4vGXnoZGz2N9D1VXtjievJuCsXam2TmbQ==", + "license": "MIT", "dependencies": { "file-type": "^18.5.0" }, @@ -720,6 +757,7 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/@xhmikosr/decompress/-/decompress-9.0.1.tgz", "integrity": "sha512-9Lvlt6Qdpo9SaRQyRIXCo3lgU++eMZ68lzgjcTwtuKDrlwT635+5zsHZ1yrSx/Blc5IDuVLlPkBPj5CZkx+2+Q==", + "license": "MIT", "dependencies": { "@xhmikosr/decompress-tar": "^7.0.0", "@xhmikosr/decompress-tarbz2": "^7.0.0", @@ -737,6 +775,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/@xhmikosr/decompress-tar/-/decompress-tar-7.0.0.tgz", "integrity": "sha512-kyWf2hybtQVbWtB+FdRyOT+jyR5jxCNZPLqvQGB7djZj75lrpLUPEmRbyo86AtJ5OEtivpYaNWjCkqSJ8xtRWw==", + "license": "MIT", "dependencies": { "file-type": "^18.5.0", "is-stream": "^3.0.0", @@ -750,6 +789,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -761,6 +801,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/@xhmikosr/decompress-tarbz2/-/decompress-tarbz2-7.0.0.tgz", "integrity": "sha512-3QnjipYkRgh3Dee1MWDgKmANWxOQBVN4e1IwiGNe2fHYfMYTeSkVvWREt87UIoSucKUh3E95v8uGFttgTknZcA==", + "license": "MIT", "dependencies": { "@xhmikosr/decompress-tar": "^7.0.0", "file-type": "^18.5.0", @@ -776,6 +817,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -787,6 +829,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/@xhmikosr/decompress-targz/-/decompress-targz-7.0.0.tgz", "integrity": "sha512-7BNHJl92g9OLhw89zqcFS67V1LAtm4Ex02j6OiQzuE8P7Yy9lQcyBuEL3x6v436grLdL+BcFjgbmhWxnem4GHw==", + "license": "MIT", "dependencies": { "@xhmikosr/decompress-tar": "^7.0.0", "file-type": "^18.5.0", @@ -800,6 +843,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -811,6 +855,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/@xhmikosr/decompress-unzip/-/decompress-unzip-6.0.0.tgz", "integrity": "sha512-R1HAkjXLS7RAL74YFLxYY9zYflCcYGssld9KKFDu87PnJ4h4btdhzXfSC8J5i5A2njH3oYIoCzx03RIGTH07Sg==", + "license": "MIT", "dependencies": { "file-type": "^18.5.0", "get-stream": "^6.0.1", @@ -820,27 +865,11 @@ "node": "^14.14.0 || >=16.0.0" } }, - "node_modules/@xhmikosr/decompress-unzip/node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "engines": { - "node": "*" - } - }, - "node_modules/@xhmikosr/decompress-unzip/node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, "node_modules/@xhmikosr/downloader": { "version": "13.0.1", "resolved": "https://registry.npmjs.org/@xhmikosr/downloader/-/downloader-13.0.1.tgz", "integrity": "sha512-mBvWew1kZJHfNQVVfVllMjUDwCGN9apPa0t4/z1zaUJ9MzpXjRL3w8fsfJKB8gHN/h4rik9HneKfDbh2fErN+w==", + "license": "MIT", "dependencies": { "@xhmikosr/archive-type": "^6.0.1", "@xhmikosr/decompress": "^9.0.1", @@ -858,17 +887,19 @@ } }, "node_modules/@xmldom/xmldom": { - "version": "0.8.11", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz", - "integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==", + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.9.tgz", + "integrity": "sha512-qycIHAucxy/LXAYIjmLmtQ8q9GPnMbnjG1KXhWm9o5sCr6pOYDATkMPiTNa6/v8eELyqOQ2FsEqeoFYmgv/gJg==", + "license": "MIT", "engines": { - "node": ">=10.0.0" + "node": ">=14.6" } }, "node_modules/@yume-chan/adb": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@yume-chan/adb/-/adb-2.5.1.tgz", "integrity": "sha512-Nm9ZA0cOxfINE+BlZ7whgqjtoLpaZg1xcV8e0C7YbpG/KOHnQGseGTwbfqJFR6xdqbRvvrNL4jIGGpxvn31ykw==", + "license": "MIT", "dependencies": { "@yume-chan/async": "^4.1.3", "@yume-chan/event": "^2.0.0", @@ -881,6 +912,7 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/@yume-chan/adb-scrcpy/-/adb-scrcpy-2.3.2.tgz", "integrity": "sha512-wg45dep+dYy4MAVMtsooPAo/aXKiGbpGHzcQWoHnl4uE4YJKrZK0sK5L++rPNM0WbwlPdSpZ32jMJT+i0u1Mdw==", + "license": "MIT", "dependencies": { "@yume-chan/adb": "^2.3.1", "@yume-chan/async": "^4.1.3", @@ -894,6 +926,7 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/@yume-chan/adb-server-node-tcp/-/adb-server-node-tcp-2.5.2.tgz", "integrity": "sha512-ga9icFBRUk1n6lO+ymlj83qE+90kMLV8sQA3w9mZAisfdxxEEIq1cvXitFQJvDgL0NuFQruVI4JoZA/wrgpKOw==", + "license": "MIT", "dependencies": { "@yume-chan/adb": "^2.5.1", "@yume-chan/async": "^4.1.3", @@ -904,12 +937,14 @@ "node_modules/@yume-chan/async": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/@yume-chan/async/-/async-4.1.3.tgz", - "integrity": "sha512-0vzhNJMkWUPyjKzUK4rqHEeCU6YQtF78RsB1kFRB6Y2BLupmEQNxcSb0mjKabPL9jZpCCiLa5KL8oTOJClUVaw==" + "integrity": "sha512-0vzhNJMkWUPyjKzUK4rqHEeCU6YQtF78RsB1kFRB6Y2BLupmEQNxcSb0mjKabPL9jZpCCiLa5KL8oTOJClUVaw==", + "license": "MIT" }, "node_modules/@yume-chan/event": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@yume-chan/event/-/event-2.0.0.tgz", "integrity": "sha512-z56MDOcX1QlgLUCuA6th3r10negVb7A3gzY//TwSC9ZOvzuRlrAqXcxZf1T3hHfNMk/NFO9RIgQgegXYSfaqLw==", + "license": "MIT", "dependencies": { "@yume-chan/async": "^4.0.2" } @@ -918,6 +953,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/@yume-chan/fetch-scrcpy-server/-/fetch-scrcpy-server-1.0.0.tgz", "integrity": "sha512-k+Cc4eeiOw4AFhHpHgmTdEXTudqRLMangGioxNvX6lwd9yrvYh4jtulu3YCUu84MS0YDNuFneno/DrLj06pp1A==", + "license": "MIT", "dependencies": { "gh-release-fetch": "^4.0.3" }, @@ -928,12 +964,14 @@ "node_modules/@yume-chan/no-data-view": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@yume-chan/no-data-view/-/no-data-view-2.0.0.tgz", - "integrity": "sha512-0GRJrrt6wtZlbiE92jocHOnaAvjQ+Y7xwwhwOPqLkwf90Kj1JIHJ5Zh4wJVQSQIkzfRSOpM+jeEQdC2K15snlA==" + "integrity": "sha512-0GRJrrt6wtZlbiE92jocHOnaAvjQ+Y7xwwhwOPqLkwf90Kj1JIHJ5Zh4wJVQSQIkzfRSOpM+jeEQdC2K15snlA==", + "license": "MIT" }, "node_modules/@yume-chan/scrcpy": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@yume-chan/scrcpy/-/scrcpy-2.3.0.tgz", "integrity": "sha512-rpsNvy7H8mf6gVsWYRSkIXmk0wVsP3XOdw3kASokwZkSWtygB2Z1wjoPaEAvaayVCjsz+y/YfG35TOcykEihGw==", + "license": "MIT", "dependencies": { "@yume-chan/async": "^4.1.3", "@yume-chan/no-data-view": "^2.0.0", @@ -945,6 +983,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/@yume-chan/stream-extra/-/stream-extra-2.1.0.tgz", "integrity": "sha512-Sq1mDCLTIOu+TbI3VmFhcKL5hi+qZkDA3S+JezZb/AJm4ESC3hB7+LgQIQs3QEK/ZeRwMg37w4IOYHSh30R7BQ==", + "license": "MIT", "dependencies": { "@yume-chan/async": "^4.1.3", "@yume-chan/struct": "^2.0.1" @@ -954,6 +993,7 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/@yume-chan/struct/-/struct-2.3.2.tgz", "integrity": "sha512-afoCnSKV+5HRK7e4innVd9YTYDyNWdjA1CVQa1j8rWYnmr7HGZfdkHMQr+AESLk6GxWFMzOIPQIG6nYOTGMFIw==", + "license": "MIT", "dependencies": { "@yume-chan/async": "^4.1.3", "@yume-chan/no-data-view": "^2.0.0" @@ -963,6 +1003,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", "dependencies": { "event-target-shim": "^5.0.0" }, @@ -970,21 +1011,11 @@ "node": ">=6.5" } }, - "node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -999,6 +1030,7 @@ "version": "6.2.6", "resolved": "https://registry.npmjs.org/appium-ios-simulator/-/appium-ios-simulator-6.2.6.tgz", "integrity": "sha512-dUd2GzE8MsyK3ZB1CwSgaMhXZ/sw8d1bK5LrdLzP/AifSsxOLy/0vJBDshfxI6NRmJrtCLcRVVfXqSwNl7ArXQ==", + "license": "Apache-2.0", "dependencies": { "@appium/support": "^6.0.0", "@xmldom/xmldom": "^0.x", @@ -1021,6 +1053,7 @@ "version": "5.2.23", "resolved": "https://registry.npmjs.org/appium-xcode/-/appium-xcode-5.2.23.tgz", "integrity": "sha512-i0F6wii0CWWkj2+tpEx9WVPO5p8Pr+0hSIXGZN4ZXe+mq92GG6L7AGvnxyNe/pNjvsg+zw65rePsuT9afm+QaQ==", + "license": "Apache-2.0", "dependencies": { "@appium/support": "^6.0.0", "@types/lodash": "^4.14.192", @@ -1042,6 +1075,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", "integrity": "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==", + "license": "MIT", "dependencies": { "archiver-utils": "^5.0.2", "async": "^3.2.4", @@ -1059,6 +1093,7 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.2.tgz", "integrity": "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==", + "license": "MIT", "dependencies": { "glob": "^10.0.0", "graceful-fs": "^4.2.0", @@ -1075,17 +1110,20 @@ "node_modules/async": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==" + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" }, "node_modules/async-lock": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.4.1.tgz", - "integrity": "sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==" + "integrity": "sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==", + "license": "MIT" }, "node_modules/asyncbox": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/asyncbox/-/asyncbox-3.0.0.tgz", "integrity": "sha512-X7U0nedUMKV3nn9c4R0Zgvdvv6cw97tbDlHSZicq1snGPi/oX9DgGmFSURWtxDdnBWd3V0YviKhqAYAVvoWQ/A==", + "license": "Apache-2.0", "dependencies": { "bluebird": "^3.5.1", "lodash": "^4.17.4", @@ -1098,22 +1136,25 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" }, "node_modules/axios": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", - "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.14.0.tgz", + "integrity": "sha512-3Y8yrqLSwjuzpXuZ0oIYZ/XGgLwUIBU3uLvbcpb0pidD9ctpShJd43KSlEEkVQg6DS0G9NKyzOvBfUtDKEyHvQ==", + "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", + "proxy-from-env": "^2.1.0" } }, "node_modules/b4a": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.3.tgz", - "integrity": "sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.0.tgz", + "integrity": "sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg==", + "license": "Apache-2.0", "peerDependencies": { "react-native-b4a": "*" }, @@ -1124,14 +1165,19 @@ } }, "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==", + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } }, "node_modules/bare-events": { "version": "2.8.2", "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", + "license": "Apache-2.0", "peerDependencies": { "bare-abort-controller": "*" }, @@ -1141,6 +1187,83 @@ } } }, + "node_modules/bare-fs": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.6.0.tgz", + "integrity": "sha512-2YkS7NuiJceSEbyEOdSNLE9tsGd+f4+f7C+Nik/MCk27SYdwIMPT/yRKvg++FZhQXgk0KWJKJyXX9RhVV0RGqA==", + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.5.4", + "bare-path": "^3.0.0", + "bare-stream": "^2.6.4", + "bare-url": "^2.2.2", + "fast-fifo": "^1.3.2" + }, + "engines": { + "bare": ">=1.16.0" + }, + "peerDependencies": { + "bare-buffer": "*" + }, + "peerDependenciesMeta": { + "bare-buffer": { + "optional": true + } + } + }, + "node_modules/bare-os": { + "version": "3.8.7", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.8.7.tgz", + "integrity": "sha512-G4Gr1UsGeEy2qtDTZwL7JFLo2wapUarz7iTMcYcMFdS89AIQuBoyjgXZz0Utv7uHs3xA9LckhVbeBi8lEQrC+w==", + "license": "Apache-2.0", + "engines": { + "bare": ">=1.14.0" + } + }, + "node_modules/bare-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", + "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", + "license": "Apache-2.0", + "dependencies": { + "bare-os": "^3.0.1" + } + }, + "node_modules/bare-stream": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.12.0.tgz", + "integrity": "sha512-w28i8lkBgREV3rPXGbgK+BO66q+ZpKqRWrZLiCdmmUlLPrQ45CzkvRhN+7lnv00Gpi2zy5naRxnUFAxCECDm9g==", + "license": "Apache-2.0", + "dependencies": { + "streamx": "^2.25.0", + "teex": "^1.0.1" + }, + "peerDependencies": { + "bare-abort-controller": "*", + "bare-buffer": "*", + "bare-events": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + }, + "bare-buffer": { + "optional": true + }, + "bare-events": { + "optional": true + } + } + }, + "node_modules/bare-url": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.4.0.tgz", + "integrity": "sha512-NSTU5WN+fy/L0DDenfE8SXQna4voXuW0FHM7wH8i3/q9khUSchfPbPezO4zSFMnDGIf9YE+mt/RWhZgNRKRIXA==", + "license": "Apache-2.0", + "dependencies": { + "bare-path": "^3.0.0" + } + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -1158,17 +1281,20 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/base64-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/base64-stream/-/base64-stream-1.0.0.tgz", - "integrity": "sha512-BQQZftaO48FcE1Kof9CmXMFaAdqkcNorgc8CxesZv9nMbbTF1EFyQe89UOuh//QMmdtfUDXyO8rgUalemL5ODA==" + "integrity": "sha512-BQQZftaO48FcE1Kof9CmXMFaAdqkcNorgc8CxesZv9nMbbTF1EFyQe89UOuh//QMmdtfUDXyO8rgUalemL5ODA==", + "license": "MIT" }, "node_modules/big-integer": { "version": "1.6.52", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "license": "Unlicense", "engines": { "node": ">=0.6" } @@ -1176,12 +1302,14 @@ "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "license": "MIT" }, "node_modules/bplist-creator": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.1.1.tgz", "integrity": "sha512-Ese7052fdWrxp/vqSJkydgx/1MdBnNOCV2XVfbmdGWD2H6EYza+Q4pyYSuVSnCUD22hfI/BFI4jHaC3NLXLlJQ==", + "license": "MIT", "dependencies": { "stream-buffers": "2.2.x" } @@ -1190,6 +1318,7 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.2.tgz", "integrity": "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==", + "license": "MIT", "dependencies": { "big-integer": "1.6.x" }, @@ -1198,11 +1327,15 @@ } }, "node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" } }, "node_modules/buffer": { @@ -1223,6 +1356,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" @@ -1232,6 +1366,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", + "license": "MIT", "engines": { "node": ">=8.0.0" } @@ -1239,12 +1374,14 @@ "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" }, "node_modules/cacheable-lookup": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", + "license": "MIT", "engines": { "node": ">=14.16" } @@ -1253,6 +1390,7 @@ "version": "10.2.14", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", + "license": "MIT", "dependencies": { "@types/http-cache-semantics": "^4.0.2", "get-stream": "^6.0.1", @@ -1270,6 +1408,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" @@ -1282,6 +1421,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -1297,6 +1437,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -1308,6 +1449,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "license": "MIT", "optional": true, "dependencies": { "color-convert": "^2.0.1", @@ -1321,6 +1463,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -1331,12 +1474,14 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" }, "node_modules/color-string": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", "optional": true, "dependencies": { "color-name": "^1.0.0", @@ -1347,6 +1492,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, @@ -1357,12 +1503,14 @@ "node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" }, "node_modules/compress-commons": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", "integrity": "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==", + "license": "MIT", "dependencies": { "crc-32": "^1.2.0", "crc32-stream": "^6.0.0", @@ -1374,20 +1522,17 @@ "node": ">= 14" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "license": "ISC" }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" }, @@ -1398,12 +1543,14 @@ "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" }, "node_modules/crc-32": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "license": "Apache-2.0", "bin": { "crc32": "bin/crc32.njs" }, @@ -1415,6 +1562,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-6.0.0.tgz", "integrity": "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==", + "license": "MIT", "dependencies": { "crc-32": "^1.2.0", "readable-stream": "^4.0.0" @@ -1423,42 +1571,11 @@ "node": ">= 14" } }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cross-spawn/node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/data-uri-to-buffer": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", "engines": { "node": ">= 12" } @@ -1467,6 +1584,7 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "license": "MIT", "dependencies": { "ms": "^2.1.1" } @@ -1475,6 +1593,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", "dependencies": { "mimic-response": "^3.1.0" }, @@ -1489,6 +1608,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -1500,6 +1620,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "license": "MIT", "engines": { "node": ">=10" } @@ -1508,6 +1629,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", "engines": { "node": ">=0.4.0" } @@ -1516,6 +1638,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", "optional": true, "engines": { "node": ">=8" @@ -1525,6 +1648,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", @@ -1537,22 +1661,14 @@ "node_modules/duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "license": "MIT" }, "node_modules/error-ex": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" } @@ -1561,6 +1677,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -1569,6 +1686,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -1577,6 +1695,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", "dependencies": { "es-errors": "^1.3.0" }, @@ -1588,6 +1707,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", @@ -1602,6 +1722,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -1613,6 +1734,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", "engines": { "node": ">=6" } @@ -1621,6 +1743,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", "engines": { "node": ">=0.8.x" } @@ -1629,6 +1752,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "license": "Apache-2.0", "dependencies": { "bare-events": "^2.7.0" } @@ -1637,6 +1761,7 @@ "version": "2.2.2", "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", + "license": "MIT", "dependencies": { "mime-db": "^1.28.0" }, @@ -1648,6 +1773,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", + "license": "MIT", "dependencies": { "ext-list": "^2.0.0", "sort-keys-length": "^1.0.0" @@ -1659,15 +1785,8 @@ "node_modules/fast-fifo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", - "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dependencies": { - "pend": "~1.2.0" - } + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "license": "MIT" }, "node_modules/fetch-blob": { "version": "3.2.0", @@ -1683,6 +1802,7 @@ "url": "https://paypal.me/jimmywarting" } ], + "license": "MIT", "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" @@ -1695,6 +1815,7 @@ "version": "18.7.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.7.0.tgz", "integrity": "sha512-ihHtXRzXEziMrQ56VSgU7wkxh55iNchFkosu7Y9/S+tXHdKyrGjVK0ujbqNnsxzea+78MaLhN6PGmfYSAv1ACw==", + "license": "MIT", "dependencies": { "readable-web-to-node-stream": "^3.0.2", "strtok3": "^7.0.0", @@ -1711,6 +1832,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-3.0.0.tgz", "integrity": "sha512-hn4cQfU6GOT/7cFHXBqeBg2TbrMBgdD0kcjLhvSQYYwm3s4B6cjvBfb7nBALJLAXqmU5xajSa7X2NnUud/VCdw==", + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -1722,6 +1844,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-5.1.1.tgz", "integrity": "sha512-M45CbrJLGACfrPOkrTp3j2EcO9OBkKUYME0eiqOCa7i2poaklU0jhlIaMlr8ijLorT0uLAzrn3qXOp5684CkfA==", + "license": "MIT", "dependencies": { "filename-reserved-regex": "^3.0.0", "strip-outer": "^2.0.0", @@ -1738,6 +1861,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -1759,6 +1883,7 @@ "url": "https://github.com/sponsors/RubenVerborgh" } ], + "license": "MIT", "engines": { "node": ">=4.0" }, @@ -1768,25 +1893,11 @@ } } }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/form-data": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -1802,6 +1913,7 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", + "license": "MIT", "engines": { "node": ">= 14.17" } @@ -1810,6 +1922,7 @@ "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", "dependencies": { "fetch-blob": "^3.1.2" }, @@ -1832,6 +1945,7 @@ "version": "1.1.14", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", @@ -1842,12 +1956,14 @@ "node_modules/ftp-response-parser/node_modules/string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", + "license": "MIT" }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -1856,6 +1972,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", @@ -1879,6 +1996,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" @@ -1891,6 +2009,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -1902,6 +2021,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/gh-release-fetch/-/gh-release-fetch-4.0.3.tgz", "integrity": "sha512-TOiP1nwLsH5shG85Yt6v6Kjq5JU/44jXyEpbcfPgmj3C829yeXIlx9nAEwQRaxtRF3SJinn2lz7XUkfG9W/U4g==", + "license": "MIT", "dependencies": { "@xhmikosr/downloader": "^13.0.0", "node-fetch": "^3.3.1", @@ -1911,37 +2031,18 @@ "node": "^14.18.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/gh-release-fetch/node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "license": "BlueOak-1.0.0", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" }, - "bin": { - "glob": "dist/esm/bin.mjs" + "engines": { + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -1951,6 +2052,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -1962,6 +2064,7 @@ "version": "12.6.1", "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", + "license": "MIT", "dependencies": { "@sindresorhus/is": "^5.2.0", "@szmarczak/http-timer": "^5.0.1", @@ -1985,12 +2088,14 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", "engines": { "node": ">=8" } @@ -1999,6 +2104,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -2010,6 +2116,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" }, @@ -2024,6 +2131,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -2034,17 +2142,20 @@ "node_modules/hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "license": "ISC" }, "node_modules/http-cache-semantics": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==" + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause" }, "node_modules/http2-wrapper": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", + "license": "MIT", "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.2.0" @@ -2070,27 +2181,20 @@ "type": "consulting", "url": "https://feross.org/support" } - ] - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } + ], + "license": "BSD-3-Clause" }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" }, "node_modules/inspect-with-kind": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/inspect-with-kind/-/inspect-with-kind-1.0.5.tgz", "integrity": "sha512-MAQUJuIo7Xqk8EVNP+6d3CKq9c80hi4tjIbIAT6lmGW9W6WzlHiu9PS8uSuUYU+Do+j1baiFp3H25XEVxDIG2g==", + "license": "ISC", "dependencies": { "kind-of": "^6.0.2" } @@ -2098,12 +2202,14 @@ "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" }, "node_modules/is-core-module": { "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", "dependencies": { "hasown": "^2.0.2" }, @@ -2114,18 +2220,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, "node_modules/is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "license": "MIT", "engines": { "node": ">=8" } @@ -2134,6 +2233,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", "engines": { "node": ">=8" }, @@ -2145,6 +2245,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -2155,39 +2256,29 @@ "node_modules/isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "license": "MIT" }, "node_modules/isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.5.tgz", + "integrity": "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==", + "license": "BlueOak-1.0.0", "engines": { - "node": ">=16" - } - }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" + "node": ">=18" } }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" }, "node_modules/jsftp": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/jsftp/-/jsftp-2.1.3.tgz", "integrity": "sha512-r79EVB8jaNAZbq8hvanL8e8JGu2ZNr2bXdHC4ZdQhRImpSPpnWwm5DYVzQ5QxJmtGtKhNNuvqGgbNaFl604fEQ==", + "license": "MIT", "dependencies": { "debug": "^3.1.0", "ftp-response-parser": "^1.0.1", @@ -2203,22 +2294,26 @@ "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "license": "MIT" }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" }, "node_modules/json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "license": "(AFL-2.1 OR BSD-3-Clause)" }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } @@ -2227,6 +2322,7 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -2235,6 +2331,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/klaw/-/klaw-4.1.0.tgz", "integrity": "sha512-1zGZ9MF9H22UnkpVeuaGKOjfA2t6WrfdrJmGjy16ykcjnKQDmHVX+KI477rpbGevz/5FD4MC3xf1oxylBgcaQw==", + "license": "MIT", "engines": { "node": ">=14.14.0" } @@ -2243,6 +2340,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "license": "MIT", "dependencies": { "readable-stream": "^2.0.5" }, @@ -2253,12 +2351,14 @@ "node_modules/lazystream/node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" }, "node_modules/lazystream/node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -2272,12 +2372,14 @@ "node_modules/lazystream/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" }, "node_modules/lazystream/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" } @@ -2285,12 +2387,14 @@ "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -2305,24 +2409,22 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/lockfile/-/lockfile-1.0.4.tgz", "integrity": "sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==", + "license": "ISC", "dependencies": { "signal-exit": "^3.0.2" } }, - "node_modules/lockfile/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==" + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT" }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "license": "MIT", "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" @@ -2338,6 +2440,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -2348,12 +2451,14 @@ "node_modules/lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "license": "MIT", "dependencies": { "semver": "^7.5.3" }, @@ -2368,6 +2473,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -2376,6 +2482,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz", "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==", + "license": "MIT", "dependencies": { "is-plain-obj": "^2.1.0" }, @@ -2387,6 +2494,7 @@ "version": "1.54.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -2395,6 +2503,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -2406,6 +2515,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -2414,6 +2524,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -2422,14 +2533,15 @@ } }, "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^5.0.5" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -2439,14 +2551,16 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", "engines": { "node": ">=16 || 14 >=14.17" } @@ -2455,6 +2569,7 @@ "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", "dependencies": { "minimist": "^1.2.6" }, @@ -2466,6 +2581,7 @@ "version": "2.30.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "license": "MIT", "engines": { "node": "*" } @@ -2473,12 +2589,14 @@ "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/mv": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", "integrity": "sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg==", + "license": "MIT", "dependencies": { "mkdirp": "~0.5.1", "ncp": "~2.0.0", @@ -2492,6 +2610,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", "integrity": "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==", + "license": "MIT", "bin": { "ncp": "bin/ncp" } @@ -2511,14 +2630,34 @@ "url": "https://paypal.me/jimmywarting" } ], + "license": "MIT", "engines": { "node": ">=10.5.0" } }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "node_modules/node-simctl": { "version": "7.7.5", "resolved": "https://registry.npmjs.org/node-simctl/-/node-simctl-7.7.5.tgz", "integrity": "sha512-lWflzDW9xLuOOvR6mTJ9efbDtO/iSCH6rEGjxFxTV0vGgz5XjoZlW2BkNCCZib0B6Y23tCOiYhYJaMQYB8FKIQ==", + "license": "Apache-2.0", "dependencies": { "@appium/logger": "^1.3.0", "asyncbox": "^3.0.0", @@ -2540,6 +2679,7 @@ "version": "5.0.10", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "license": "ISC", "dependencies": { "glob": "^10.3.7" }, @@ -2554,6 +2694,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", + "license": "ISC", "dependencies": { "isexe": "^3.1.1" }, @@ -2568,6 +2709,7 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "license": "BSD-2-Clause", "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -2579,6 +2721,7 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", "bin": { "semver": "bin/semver" } @@ -2587,6 +2730,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -2595,6 +2739,7 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.1.1.tgz", "integrity": "sha512-JYc0DPlpGWB40kH5g07gGTrYuMqV653k3uBKY6uITPWds3M0ov3GaWGp9lbE3Bzngx8+XkfzgvASb9vk9JDFXQ==", + "license": "MIT", "engines": { "node": ">=14.16" }, @@ -2606,6 +2751,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", "dependencies": { "wrappy": "1" } @@ -2614,6 +2760,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", + "license": "MIT", "engines": { "node": ">=12.20" } @@ -2622,6 +2769,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/p-event/-/p-event-5.0.1.tgz", "integrity": "sha512-dd589iCQ7m1L0bmC5NLlVYfy3TbBEsMUfWx9PyAgPeIcFZ/E2yaTZ4Rz4MiBmmJShviiftHVXOqfnfzJ6kyMrQ==", + "license": "MIT", "dependencies": { "p-timeout": "^5.0.2" }, @@ -2636,6 +2784,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -2650,6 +2799,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -2664,6 +2814,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-5.1.0.tgz", "integrity": "sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -2671,15 +2822,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" - }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -2705,22 +2852,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", "engines": { "node": ">=8" } @@ -2728,27 +2860,39 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" }, "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "license": "BlueOak-1.0.0", "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" }, "engines": { - "node": ">=16 || 14 >=14.18" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.2.tgz", + "integrity": "sha512-wgWa6FWQ3QRRJbIjbsldRJZxdxYngT/dO0I5Ynmlnin8qy7tC6xYzbcJjtN4wHLXtkbVwHzk0C+OejVw1XM+DQ==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/peek-readable": { "version": "5.4.2", "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.4.2.tgz", "integrity": "sha512-peBp3qZyuS6cNIJ2akRNG1uo1WJ1d0wTxg/fxMdZ0BqCVhx242bSFHM9eNqflfJVS9SsgkzgT/1UgnsurBOTMg==", + "license": "MIT", "engines": { "node": ">=14.16" }, @@ -2760,17 +2904,20 @@ "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "license": "MIT" }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" }, "node_modules/pkg-dir": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "license": "MIT", "dependencies": { "find-up": "^5.0.0" }, @@ -2782,6 +2929,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", + "license": "MIT", "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", @@ -2795,6 +2943,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "license": "MIT", "engines": { "node": ">=4" } @@ -2803,6 +2952,7 @@ "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", "engines": { "node": ">= 0.6.0" } @@ -2810,17 +2960,23 @@ "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" }, "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } }, "node_modules/quick-lru": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -2832,6 +2988,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "license": "MIT", "dependencies": { "@types/normalize-package-data": "^2.4.0", "normalize-package-data": "^2.5.0", @@ -2846,6 +3003,7 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" } @@ -2854,6 +3012,7 @@ "version": "4.7.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "license": "MIT", "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", @@ -2869,6 +3028,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.4.tgz", "integrity": "sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw==", + "license": "MIT", "dependencies": { "readable-stream": "^4.7.0" }, @@ -2884,14 +3044,31 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", + "license": "Apache-2.0", "dependencies": { "minimatch": "^5.1.0" } }, + "node_modules/readdir-glob/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==", + "license": "MIT" + }, + "node_modules/readdir-glob/node_modules/brace-expansion": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/readdir-glob/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -2903,6 +3080,7 @@ "version": "1.22.11", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "license": "MIT", "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", @@ -2921,12 +3099,14 @@ "node_modules/resolve-alpn": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "license": "MIT" }, "node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "license": "MIT", "engines": { "node": ">=8" } @@ -2935,6 +3115,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", + "license": "MIT", "dependencies": { "lowercase-keys": "^3.0.0" }, @@ -2950,6 +3131,7 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", "integrity": "sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ==", "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", "dependencies": { "glob": "^6.0.1" }, @@ -2957,42 +3139,6 @@ "rimraf": "bin.js" } }, - "node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", - "integrity": "sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dependencies": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -3010,12 +3156,14 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/sanitize-filename": { "version": "1.6.3", "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", + "license": "WTFPL OR ISC", "dependencies": { "truncate-utf8-bytes": "^1.0.0" } @@ -3024,6 +3172,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==", + "license": "MIT", "dependencies": { "commander": "^2.8.1" }, @@ -3033,9 +3182,10 @@ } }, "node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -3046,13 +3196,15 @@ "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" }, "node_modules/sharp": { "version": "0.34.2", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.2.tgz", "integrity": "sha512-lszvBmB9QURERtyKT2bNmsgxXK0ShJrL/fvqlonCo7e6xBF8nT8xU6pW+PMIbLsz0RxQk3rgH9kd8UmvOzlMJg==", "hasInstallScript": true, + "license": "Apache-2.0", "optional": true, "dependencies": { "color": "^4.2.3", @@ -3089,29 +3241,11 @@ "@img/sharp-win32-x64": "0.34.2" } }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "engines": { - "node": ">=8" - } - }, "node_modules/shell-quote": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz", "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -3120,20 +3254,16 @@ } }, "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" }, "node_modules/simple-swizzle": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", + "license": "MIT", "optional": true, "dependencies": { "is-arrayish": "^0.3.1" @@ -3143,12 +3273,14 @@ "version": "0.3.4", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", + "license": "MIT", "optional": true }, "node_modules/sort-keys": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", "integrity": "sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==", + "license": "MIT", "dependencies": { "is-plain-obj": "^1.0.0" }, @@ -3160,6 +3292,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", "integrity": "sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==", + "license": "MIT", "dependencies": { "sort-keys": "^1.0.0" }, @@ -3171,6 +3304,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -3179,6 +3313,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -3187,6 +3322,7 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -3196,6 +3332,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "license": "Apache-2.0", "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -3204,26 +3341,30 @@ "node_modules/spdx-exceptions": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==" + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "license": "CC-BY-3.0" }, "node_modules/spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "license": "MIT", "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "node_modules/spdx-license-ids": { - "version": "3.0.22", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", - "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==" + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", + "license": "CC0-1.0" }, "node_modules/stream-buffers": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", "integrity": "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==", + "license": "Unlicense", "engines": { "node": ">= 0.10.0" } @@ -3232,15 +3373,17 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", "integrity": "sha512-6yHMqgLYDzQDcAkL+tjJDC5nSNuNIx0vZtRZeiPh7Saef7VHX9H5Ijn9l2VIol2zaNYlYEX6KyuT/237A58qEQ==", + "license": "MIT", "dependencies": { "duplexer": "~0.1.1", "through": "~2.3.4" } }, "node_modules/streamx": { - "version": "2.23.0", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", - "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", + "version": "2.25.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.25.0.tgz", + "integrity": "sha512-0nQuG6jf1w+wddNEEXCF4nTg3LtufWINB5eFEN+5TNZW7KWJp6x87+JFL43vaAUPyCfH1wID+mNVyW6OHtFamg==", + "license": "MIT", "dependencies": { "events-universal": "^1.0.0", "fast-fifo": "^1.3.2", @@ -3251,102 +3394,16 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" } }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/string-width-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, "node_modules/strip-dirs": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-3.0.0.tgz", "integrity": "sha512-I0sdgcFTfKQlUPZyAqPJmSG3HLO9rWDFnxonnIbskYNM3DwFOeTNB5KzVq3dA1GdRAc/25b5Y7UO2TQfKWw4aQ==", + "license": "ISC", "dependencies": { "inspect-with-kind": "^1.0.5", "is-plain-obj": "^1.1.0" @@ -3356,6 +3413,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -3364,6 +3422,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-2.0.0.tgz", "integrity": "sha512-A21Xsm1XzUkK0qK1ZrytDUvqsQWict2Cykhvi0fBQntGG5JSprESasEyV1EZ/4CiR5WB5KjzLTrP/bO37B0wPg==", + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -3375,6 +3434,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-7.1.1.tgz", "integrity": "sha512-mKX8HA/cdBqMKUr0MMZAFssCkIGoZeSCMXgnt79yKxNFguMLVFgRe6wB+fsL0NmoHDbeyZXczy7vEPSoo3rkzg==", + "license": "MIT", "dependencies": { "@tokenizer/token": "^0.3.0", "peek-readable": "^5.1.3" @@ -3391,6 +3451,7 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -3405,6 +3466,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -3413,11 +3475,13 @@ } }, "node_modules/tar-stream": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", - "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.8.tgz", + "integrity": "sha512-U6QpVRyCGHva435KoNWy9PRoi2IFYCgtEhq9nmrPPpbRacPs9IH4aJ3gbrFC8dPcXvdSZ4XXfXT5Fshbp2MtlQ==", + "license": "MIT", "dependencies": { "b4a": "^1.6.4", + "bare-fs": "^4.5.5", "fast-fifo": "^1.2.0", "streamx": "^2.15.0" } @@ -3426,6 +3490,7 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/teen_process/-/teen_process-2.3.3.tgz", "integrity": "sha512-NIdeetf/6gyEqLjnzvfgQe7PfipSceq2xDQM2Py2BkBnIIeWh3HRD3vNhulyO5WppfCv9z4mtsEHyq8kdiULTA==", + "license": "Apache-2.0", "dependencies": { "bluebird": "^3.7.2", "lodash": "^4.17.21", @@ -3437,10 +3502,20 @@ "npm": ">=8" } }, + "node_modules/teex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", + "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", + "license": "MIT", + "dependencies": { + "streamx": "^2.12.5" + } + }, "node_modules/text-decoder": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", - "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz", + "integrity": "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==", + "license": "Apache-2.0", "dependencies": { "b4a": "^1.6.4" } @@ -3448,12 +3523,14 @@ "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "license": "MIT" }, "node_modules/token-types": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/token-types/-/token-types-5.0.1.tgz", "integrity": "sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==", + "license": "MIT", "dependencies": { "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" @@ -3470,6 +3547,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-2.0.0.tgz", "integrity": "sha512-QUHBFTJGdOwmp0tbOG505xAgOp/YliZP/6UgafFXYZ26WT1bvQmSMJUvkeVSASuJJHbqsFbynTvkd5W8RBTipg==", + "license": "MIT", "dependencies": { "escape-string-regexp": "^5.0.0" }, @@ -3481,6 +3559,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", + "license": "WTFPL", "dependencies": { "utf8-byte-length": "^1.0.1" } @@ -3489,12 +3568,14 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", "optional": true }, "node_modules/type-fest": { "version": "4.41.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=16" }, @@ -3507,6 +3588,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3519,6 +3601,7 @@ "version": "1.4.3", "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "license": "MIT", "dependencies": { "buffer": "^5.2.1", "through": "^2.3.8" @@ -3542,6 +3625,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -3550,12 +3634,14 @@ "node_modules/undici-types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==" + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT" }, "node_modules/unorm": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz", "integrity": "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==", + "license": "MIT or GPL-2.0", "engines": { "node": ">= 0.4.0" } @@ -3563,12 +3649,14 @@ "node_modules/utf8-byte-length": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", - "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==" + "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", + "license": "(WTFPL OR MIT)" }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" }, "node_modules/uuid": { "version": "11.1.0", @@ -3578,6 +3666,7 @@ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], + "license": "MIT", "bin": { "uuid": "dist/esm/bin/uuid" } @@ -3586,6 +3675,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "license": "Apache-2.0", "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" @@ -3595,6 +3685,7 @@ "version": "3.3.3", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", "engines": { "node": ">= 8" } @@ -3603,6 +3694,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "license": "ISC", "dependencies": { "isexe": "^3.1.1" }, @@ -3613,96 +3705,17 @@ "node": "^16.13.0 || >=18.0.0" } }, - "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/wrap-ansi-cjs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" }, "node_modules/ws": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", - "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", + "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", + "license": "MIT", "engines": { "node": ">=10.0.0" }, @@ -3723,14 +3736,16 @@ "version": "15.1.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "license": "MIT", "engines": { "node": ">=8.0" } }, "node_modules/yauzl": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.2.0.tgz", - "integrity": "sha512-Ow9nuGZE+qp1u4JIPvg+uCiUr7xGQWdff7JQSk5VGYTAZMDe2q8lxJ10ygv10qmSj031Ty/6FNJpLO4o1Sgc+w==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.3.0.tgz", + "integrity": "sha512-PtGEvEP30p7sbIBJKUBjUnqgTVOyMURc4dLo9iNyAJnNIEz9pm88cCXF21w94Kg3k6RXkeZh5DHOGS0qEONvNQ==", + "license": "MIT", "dependencies": { "buffer-crc32": "~0.2.3", "pend": "~1.2.0" @@ -3743,6 +3758,7 @@ "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "license": "MIT", "engines": { "node": "*" } @@ -3751,6 +3767,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -3762,6 +3779,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz", "integrity": "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==", + "license": "MIT", "dependencies": { "archiver-utils": "^5.0.0", "compress-commons": "^6.0.2", @@ -3771,6 +3789,21 @@ "node": ">= 14" } }, + "packages/agent": { + "name": "@device-stream/agent", + "version": "1.1.0", + "license": "MIT", + "dependencies": { + "@device-stream/core": "^1.1.0" + }, + "devDependencies": { + "@types/node": "^20.10.0", + "typescript": "^5.3.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "packages/android": { "name": "@device-stream/android", "version": "1.1.0", diff --git a/package.json b/package.json index fbde509..4a5aa97 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "packages/*" ], "scripts": { - "build": "npm run build -w @device-stream/core && npm run build -w @device-stream/ios-simulator -w @device-stream/ios-device -w @device-stream/android", + "build": "npm run build -w @device-stream/core && npm run build -w @device-stream/ios-simulator -w @device-stream/ios-device -w @device-stream/android -w @device-stream/agent", + "build:agent": "npm run build -w @device-stream/agent", "build:core": "npm run build -w @device-stream/core", "build:ios-simulator": "npm run build -w @device-stream/ios-simulator", "build:ios-device": "npm run build -w @device-stream/ios-device", @@ -47,5 +48,13 @@ }, "volta": { "node": "22.22.1" + }, + "overrides": { + "axios": "^1.14.0", + "lodash": "4.18.1", + "form-data": "^4.0.4", + "glob": "^13.0.5", + "@xmldom/xmldom": ">=0.8.12", + "yauzl": ">=3.2.1" } } diff --git a/packages/agent/package.json b/packages/agent/package.json new file mode 100644 index 0000000..d3b0772 --- /dev/null +++ b/packages/agent/package.json @@ -0,0 +1,44 @@ +{ + "name": "@device-stream/agent", + "version": "1.1.0", + "description": "LLM agent intelligence layer — navigation graphs, skeleton fingerprinting, compact state for AI-driven device control", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "dist" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/HeiCg/device-stream.git", + "directory": "packages/agent" + }, + "publishConfig": { + "registry": "https://npm.pkg.github.com" + }, + "scripts": { + "build": "tsc", + "clean": "rm -rf dist", + "lint": "tsc --noEmit", + "prepublishOnly": "npm run build" + }, + "keywords": [ + "device-stream", + "agent", + "navigation-graph", + "accessibility", + "llm", + "ai-agent", + "mobile-automation" + ], + "license": "MIT", + "dependencies": { + "@device-stream/core": "^1.1.0" + }, + "devDependencies": { + "@types/node": "^20.10.0", + "typescript": "^5.3.0" + }, + "engines": { + "node": ">=18.0.0" + } +} diff --git a/packages/agent/src/agent-session.ts b/packages/agent/src/agent-session.ts new file mode 100644 index 0000000..37df3e1 --- /dev/null +++ b/packages/agent/src/agent-session.ts @@ -0,0 +1,305 @@ +/** + * AgentSession: main orchestrator wrapping DeviceService with navigation graph, + * skeleton fingerprinting, and LLM-optimized state capture. + * + * Every action automatically records state transitions into the graph, + * enabling deterministic replay of known paths. + */ + +import { DeviceService, DeviceStateSnapshot } from '@device-stream/core'; +import { + AgentSessionOptions, + CompactState, + ActionDescriptor, + ActionResult, + ScreenFingerprint, +} from './types'; +import { compressTree } from './tree-compressor'; +import { serializeToCompactText } from './compact-serializer'; +import { classifyZones, extractContext, computeFingerprint } from './skeleton-fingerprint'; +import { NavigationGraph } from './navigation-graph'; +import { findElement, computeCenter } from './element-actions'; + +const DEFAULT_STABILITY_DELAY_MS = 500; +const DEFAULT_MAX_ELEMENTS = 50; + +function delay(ms: number): Promise { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +export class AgentSession { + private deviceService: DeviceService; + private serial: string; + private graph: NavigationGraph; + private graphPath: string; + private maxElements: number; + private stabilityDelayMs: number; + private currentFingerprint: string | null = null; + + constructor(deviceService: DeviceService, options: AgentSessionOptions) { + this.deviceService = deviceService; + this.serial = options.serial; + this.graph = new NavigationGraph(); + this.graphPath = options.graphPath || `nav-graph-${options.serial}.json`; + this.maxElements = options.maxElements ?? DEFAULT_MAX_ELEMENTS; + this.stabilityDelayMs = options.stabilityDelayMs ?? DEFAULT_STABILITY_DELAY_MS; + } + + async initialize(): Promise { + this.graph = await NavigationGraph.load(this.graphPath); + } + + async getCompactState(): Promise { + if (!this.deviceService.getDeviceState) { + throw new Error('DeviceService does not support getDeviceState'); + } + + const snapshot = await this.deviceService.getDeviceState(this.serial); + return this.buildCompactState(snapshot); + } + + private buildCompactState(snapshot: DeviceStateSnapshot): CompactState { + const elements = compressTree(snapshot.tree, this.maxElements); + const compactTree = serializeToCompactText(elements); + const classified = classifyZones(elements, snapshot.tree); + const context = extractContext(snapshot.tree, snapshot.appInfo); + const fingerprint = computeFingerprint(classified, context); + + this.currentFingerprint = fingerprint.fingerprint; + + const knownScreen = !!this.graph.getNode(fingerprint.fingerprint); + const suggestedActions = knownScreen + ? this.graph.getAvailableActions(fingerprint.fingerprint) + : undefined; + + // Register node in graph + this.graph.getOrCreateNode( + fingerprint.fingerprint, + `${fingerprint.context.appPackage}:${fingerprint.context.toolbarTitle || 'unknown'}`, + fingerprint.context.appPackage, + fingerprint.anchorSummary, + suggestedActions || [], + ); + + return { + fingerprint, + compactTree, + elements, + appInfo: snapshot.appInfo, + deviceContext: snapshot.deviceContext, + knownScreen, + suggestedActions, + }; + } + + async performAction(action: ActionDescriptor): Promise { + const previousFingerprint = this.currentFingerprint || ''; + const startTime = Date.now(); + let success = true; + let error: string | undefined; + + try { + await this.executeAction(action); + } catch (e) { + success = false; + error = e instanceof Error ? e.message : String(e); + } + + await delay(this.stabilityDelayMs); + + const state = await this.getCompactState(); + const newFingerprint = state.fingerprint.fingerprint; + const latencyMs = Date.now() - startTime; + + if (previousFingerprint) { + this.graph.recordTransition( + previousFingerprint, + newFingerprint, + action, + latencyMs, + success, + ); + await this.graph.save(this.graphPath); + } + + return { + success, + previousFingerprint, + newFingerprint, + transitioned: previousFingerprint !== newFingerprint, + latencyMs, + error, + }; + } + + async navigateTo(targetFingerprint: string): Promise { + const results: ActionResult[] = []; + + if (!this.currentFingerprint) { + await this.getCompactState(); + } + + if (this.currentFingerprint === targetFingerprint) return results; + + const path = this.graph.findPath(this.currentFingerprint!, targetFingerprint); + if (!path) { + throw new Error( + `No known path from ${this.currentFingerprint} to ${targetFingerprint}`, + ); + } + + for (const action of path) { + const result = await this.performAction(action); + results.push(result); + + if (!result.success) break; + + // If we arrived early, stop + if (result.newFingerprint === targetFingerprint) break; + + // If we went off-track, try to re-plan + if (result.transitioned && result.newFingerprint !== targetFingerprint) { + const newPath = this.graph.findPath(result.newFingerprint, targetFingerprint); + if (!newPath) break; + // Continue with the new path in subsequent iterations + path.splice(0, path.length, ...newPath); + } + } + + return results; + } + + async tapElement( + selector: { index?: number; text?: string; resourceId?: string; contentDesc?: string; className?: string }, + ): Promise { + const state = await this.getCompactState(); + const element = findElement(state.elements, selector); + + if (!element) { + throw new Error(`Element not found: ${JSON.stringify(selector)}`); + } + + const center = computeCenter(element); + const action: ActionDescriptor = { + type: 'tap', + target: selector, + }; + + const previousFingerprint = this.currentFingerprint || ''; + const startTime = Date.now(); + let success = true; + let error: string | undefined; + + try { + await this.deviceService.tap(this.serial, center.x, center.y); + } catch (e) { + success = false; + error = e instanceof Error ? e.message : String(e); + } + + await delay(this.stabilityDelayMs); + + const newState = await this.getCompactState(); + const newFingerprint = newState.fingerprint.fingerprint; + const latencyMs = Date.now() - startTime; + + if (previousFingerprint) { + this.graph.recordTransition( + previousFingerprint, + newFingerprint, + action, + latencyMs, + success, + ); + await this.graph.save(this.graphPath); + } + + return { + success, + previousFingerprint, + newFingerprint, + transitioned: previousFingerprint !== newFingerprint, + latencyMs, + error, + }; + } + + getGraph(): NavigationGraph { + return this.graph; + } + + getCurrentFingerprint(): string | null { + return this.currentFingerprint; + } + + async close(): Promise { + await this.graph.save(this.graphPath); + } + + private async executeAction(action: ActionDescriptor): Promise { + const s = this.serial; + + switch (action.type) { + case 'tap': { + if (action.target) { + if (!this.deviceService.getDeviceState) { + throw new Error('DeviceService does not support getDeviceState'); + } + const snapshot = await this.deviceService.getDeviceState(s); + const elements = compressTree(snapshot.tree, this.maxElements); + const element = findElement(elements, action.target); + if (!element) { + throw new Error(`Element not found: ${JSON.stringify(action.target)}`); + } + const center = computeCenter(element); + await this.deviceService.tap(s, center.x, center.y); + } + break; + } + case 'back': { + if (!this.deviceService.back) { + throw new Error('DeviceService does not support back'); + } + await this.deviceService.back(s); + break; + } + case 'deeplink': { + if (!this.deviceService.openDeepLink) { + throw new Error('DeviceService does not support openDeepLink'); + } + await this.deviceService.openDeepLink(s, action.deepLink || ''); + break; + } + case 'type': { + await this.deviceService.typeText(s, action.text || ''); + break; + } + case 'scroll': { + if (!this.deviceService.scroll) { + throw new Error('DeviceService does not support scroll'); + } + await this.deviceService.scroll(s, action.direction || 'down'); + break; + } + case 'longPress': { + if (!this.deviceService.longPress) { + throw new Error('DeviceService does not support longPress'); + } + if (action.target) { + if (!this.deviceService.getDeviceState) { + throw new Error('DeviceService does not support getDeviceState'); + } + const snapshot = await this.deviceService.getDeviceState(s); + const elements = compressTree(snapshot.tree, this.maxElements); + const element = findElement(elements, action.target); + if (!element) { + throw new Error(`Element not found: ${JSON.stringify(action.target)}`); + } + const center = computeCenter(element); + await this.deviceService.longPress(s, center.x, center.y); + } + break; + } + } + } +} diff --git a/packages/agent/src/compact-serializer.ts b/packages/agent/src/compact-serializer.ts new file mode 100644 index 0000000..5d63e99 --- /dev/null +++ b/packages/agent/src/compact-serializer.ts @@ -0,0 +1,52 @@ +/** + * Serialize CompressedNode[] to a token-efficient text format for LLM consumption. + * + * Format: [index] ClassName "text" flags (x1,y1)-(x2,y2) + * Example: [1] Button "Login" clickable (100,400)-(300,460) + */ + +import { CompressedNode } from './types'; + +/** + * Convert compressed nodes to a compact text representation. + * Skips phantom nodes (no text, no contentDesc, no resourceId, not interactive). + */ +export function serializeToCompactText(nodes: CompressedNode[]): string { + const lines: string[] = []; + + for (const node of nodes) { + const hasLabel = node.text || node.contentDesc || node.resourceId; + const interactive = node.clickable || node.scrollable || node.focused || + node.checked === true || node.selected === true; + + // Skip phantom nodes that provide no value to the LLM + if (!hasLabel && !interactive) continue; + + const parts: string[] = [`[${node.index}]`, node.className]; + + // Label: prefer text, fall back to contentDesc, then resourceId + const label = node.text || node.contentDesc || node.resourceId; + if (label) { + parts.push(`"${label}"`); + } + + // Flags + const flags: string[] = []; + if (node.clickable) flags.push('clickable'); + if (node.scrollable) flags.push('scrollable'); + if (node.focused) flags.push('focused'); + if (node.checked) flags.push('checked'); + if (node.selected) flags.push('selected'); + if (!node.enabled) flags.push('disabled'); + if (flags.length > 0) { + parts.push(flags.join(' ')); + } + + // Bounds + parts.push(`(${node.bounds.x1},${node.bounds.y1})-(${node.bounds.x2},${node.bounds.y2})`); + + lines.push(parts.join(' ')); + } + + return lines.join('\n'); +} diff --git a/packages/agent/src/element-actions.ts b/packages/agent/src/element-actions.ts new file mode 100644 index 0000000..ae5dea9 --- /dev/null +++ b/packages/agent/src/element-actions.ts @@ -0,0 +1,34 @@ +/** + * Element-based actions: find elements by selector, compute tap coordinates. + */ + +import { CompressedNode, ElementSelector } from './types'; + +/** + * Find a compressed node matching the given selector. + * Priority: index → resourceId → text (substring) → contentDesc (substring) → className. + * Multiple criteria = AND logic. + */ +export function findElement( + elements: CompressedNode[], + selector: ElementSelector, +): CompressedNode | undefined { + return elements.find(el => { + if (selector.index !== undefined && el.index !== selector.index) return false; + if (selector.resourceId !== undefined && el.resourceId !== selector.resourceId) return false; + if (selector.text !== undefined && (!el.text || !el.text.includes(selector.text))) return false; + if (selector.contentDesc !== undefined && (!el.contentDesc || !el.contentDesc.includes(selector.contentDesc))) return false; + if (selector.className !== undefined && el.className !== selector.className) return false; + return true; + }); +} + +/** + * Compute the center point of a compressed node's bounds. + */ +export function computeCenter(node: CompressedNode): { x: number; y: number } { + return { + x: Math.round((node.bounds.x1 + node.bounds.x2) / 2), + y: Math.round((node.bounds.y1 + node.bounds.y2) / 2), + }; +} diff --git a/packages/agent/src/index.ts b/packages/agent/src/index.ts new file mode 100644 index 0000000..8db069a --- /dev/null +++ b/packages/agent/src/index.ts @@ -0,0 +1,40 @@ +/** + * @device-stream/agent + * + * Navigation graphs, skeleton fingerprinting, and LLM-optimized device control. + */ + +// Types +export { + CompressedNode, + ZoneType, + ClassifiedNode, + ScreenContext, + ScreenFingerprint, + ElementSelector, + ActionDescriptor, + ScreenNode, + GraphEdge, + NavigationGraphData, + AgentSessionOptions, + CompactState, + ActionResult, +} from './types'; + +// Tree compression +export { compressTree } from './tree-compressor'; + +// Compact serialization +export { serializeToCompactText } from './compact-serializer'; + +// Skeleton fingerprinting +export { classifyZones, extractContext, computeFingerprint } from './skeleton-fingerprint'; + +// Navigation graph +export { NavigationGraph } from './navigation-graph'; + +// Element actions +export { findElement, computeCenter } from './element-actions'; + +// Agent session +export { AgentSession } from './agent-session'; diff --git a/packages/agent/src/navigation-graph.ts b/packages/agent/src/navigation-graph.ts new file mode 100644 index 0000000..3804fbd --- /dev/null +++ b/packages/agent/src/navigation-graph.ts @@ -0,0 +1,286 @@ +/** + * Navigation graph: stores screen nodes and action edges. + * Enables deterministic replay of known paths between screens. + */ + +import { readFile, writeFile } from 'node:fs/promises'; +import { + ScreenNode, + GraphEdge, + NavigationGraphData, + ActionDescriptor, +} from './types'; + +const GRAPH_VERSION = 1; + +function actionKey(action: ActionDescriptor): string { + if (action.type === 'tap' && action.target) { + const t = action.target; + return `tap:${t.resourceId || t.text || t.contentDesc || t.index || 'none'}`; + } + if (action.type === 'deeplink') { + return `deeplink:${action.deepLink || 'none'}`; + } + if (action.type === 'type') { + return `type:${action.text || 'none'}`; + } + if (action.type === 'scroll') { + return `scroll:${action.direction || 'down'}`; + } + return action.type; +} + +function edgeId(from: string, to: string, action: ActionDescriptor): string { + return `${from}--${actionKey(action)}--${to}`; +} + +export class NavigationGraph { + private nodes: Map = new Map(); + private edges: Map = new Map(); + private adjacency: Map> = new Map(); + + constructor(data?: NavigationGraphData) { + if (data) { + for (const [fp, node] of Object.entries(data.nodes)) { + this.nodes.set(fp, node); + } + for (const edge of data.edges) { + this.edges.set(edge.id, edge); + if (!this.adjacency.has(edge.from)) { + this.adjacency.set(edge.from, new Set()); + } + this.adjacency.get(edge.from)!.add(edge.id); + } + } + } + + getOrCreateNode( + fingerprint: string, + screenType: string, + appPackage: string, + anchors: string[], + actions: ActionDescriptor[], + ): ScreenNode { + const existing = this.nodes.get(fingerprint); + if (existing) { + existing.visitCount++; + existing.lastVisitedAt = Date.now(); + // Merge new actions not already present + for (const action of actions) { + const key = actionKey(action); + if (!existing.availableActions.some(a => actionKey(a) === key)) { + existing.availableActions.push(action); + } + } + return existing; + } + + const node: ScreenNode = { + fingerprint, + screenType, + appPackage, + anchorElements: anchors, + availableActions: actions, + visitCount: 1, + lastVisitedAt: Date.now(), + }; + this.nodes.set(fingerprint, node); + return node; + } + + getNode(fingerprint: string): ScreenNode | undefined { + return this.nodes.get(fingerprint); + } + + recordTransition( + from: string, + to: string, + action: ActionDescriptor, + latencyMs: number, + success: boolean, + ): void { + const eid = edgeId(from, to, action); + const existing = this.edges.get(eid); + + if (existing) { + if (success) { + existing.successCount++; + // Running average of latency + const total = existing.avgLatencyMs * (existing.successCount - 1) + latencyMs; + existing.avgLatencyMs = Math.round(total / existing.successCount); + } else { + existing.failCount++; + } + existing.lastUsedAt = Date.now(); + } else { + const edge: GraphEdge = { + id: eid, + from, + to, + action, + successCount: success ? 1 : 0, + failCount: success ? 0 : 1, + avgLatencyMs: latencyMs, + lastUsedAt: Date.now(), + }; + this.edges.set(eid, edge); + if (!this.adjacency.has(from)) { + this.adjacency.set(from, new Set()); + } + this.adjacency.get(from)!.add(eid); + } + } + + getAvailableActions(fingerprint: string): ActionDescriptor[] { + const node = this.nodes.get(fingerprint); + const actions: ActionDescriptor[] = node ? [...node.availableActions] : []; + + // Add actions from known outgoing edges + const edgeIds = this.adjacency.get(fingerprint); + if (edgeIds) { + for (const eid of edgeIds) { + const edge = this.edges.get(eid)!; + const key = actionKey(edge.action); + if (!actions.some(a => actionKey(a) === key)) { + actions.push(edge.action); + } + } + } + + return actions; + } + + /** + * Find shortest path from source to target using Dijkstra. + * Edge weight = 1 / successRate (prefers reliable paths). + */ + findPath(from: string, to: string): ActionDescriptor[] | null { + if (from === to) return []; + if (!this.nodes.has(from) || !this.nodes.has(to)) return null; + + const dist = new Map(); + const prev = new Map(); + const visited = new Set(); + + dist.set(from, 0); + + while (true) { + // Find unvisited node with smallest distance + let current: string | null = null; + let minDist = Infinity; + for (const [fp, d] of dist) { + if (!visited.has(fp) && d < minDist) { + minDist = d; + current = fp; + } + } + + if (current === null) return null; // No path + if (current === to) break; // Found + + visited.add(current); + + const edgeIds = this.adjacency.get(current); + if (!edgeIds) continue; + + for (const eid of edgeIds) { + const edge = this.edges.get(eid)!; + if (visited.has(edge.to)) continue; + + const total = edge.successCount + edge.failCount; + const successRate = total > 0 ? edge.successCount / total : 0.5; + const weight = 1 / Math.max(successRate, 0.01); // Avoid division by zero + + const newDist = minDist + weight; + if (newDist < (dist.get(edge.to) ?? Infinity)) { + dist.set(edge.to, newDist); + prev.set(edge.to, { fingerprint: current, action: edge.action }); + } + } + } + + // Reconstruct path + const path: ActionDescriptor[] = []; + let cursor = to; + while (cursor !== from) { + const step = prev.get(cursor); + if (!step) return null; + path.unshift(step.action); + cursor = step.fingerprint; + } + + return path; + } + + /** + * Remove nodes not visited within maxAge milliseconds. + */ + prune(maxAge: number): number { + const cutoff = Date.now() - maxAge; + let removed = 0; + + for (const [fp, node] of this.nodes) { + if (node.lastVisitedAt < cutoff) { + this.nodes.delete(fp); + // Remove edges involving this node + const outgoing = this.adjacency.get(fp); + if (outgoing) { + for (const eid of outgoing) this.edges.delete(eid); + this.adjacency.delete(fp); + } + // Remove incoming edges + for (const [sourceFp, edgeIds] of this.adjacency) { + for (const eid of edgeIds) { + const edge = this.edges.get(eid); + if (edge && edge.to === fp) { + this.edges.delete(eid); + edgeIds.delete(eid); + } + } + } + removed++; + } + } + + return removed; + } + + get nodeCount(): number { + return this.nodes.size; + } + + get edgeCount(): number { + return this.edges.size; + } + + toJSON(): NavigationGraphData { + const nodes: Record = {}; + for (const [fp, node] of this.nodes) { + nodes[fp] = node; + } + return { + version: GRAPH_VERSION, + nodes, + edges: Array.from(this.edges.values()), + }; + } + + static fromJSON(data: NavigationGraphData): NavigationGraph { + return new NavigationGraph(data); + } + + async save(filePath: string): Promise { + const json = JSON.stringify(this.toJSON(), null, 2); + await writeFile(filePath, json, 'utf-8'); + } + + static async load(filePath: string): Promise { + try { + const json = await readFile(filePath, 'utf-8'); + const data = JSON.parse(json) as NavigationGraphData; + return new NavigationGraph(data); + } catch { + return new NavigationGraph(); + } + } +} diff --git a/packages/agent/src/skeleton-fingerprint.ts b/packages/agent/src/skeleton-fingerprint.ts new file mode 100644 index 0000000..961091f --- /dev/null +++ b/packages/agent/src/skeleton-fingerprint.ts @@ -0,0 +1,213 @@ +/** + * Skeleton fingerprinting: identify screen "type" by hashing structural anchors only. + * Ignores dynamic content inside scroll containers (feeds, lists, etc.). + * + * This allows agents to recognize "same screen, different content" — e.g., + * Instagram feed scrolled to different positions still fingerprints the same. + */ + +import { createHash } from 'node:crypto'; +import { AccessibilityNode, DeviceStateSnapshot } from '@device-stream/core'; +import { CompressedNode, ClassifiedNode, ZoneType, ScreenContext, ScreenFingerprint } from './types'; + +// Scroll container classNames whose descendants are CONTENT zone +const SCROLL_CONTAINERS = new Set([ + // Android + 'RecyclerView', 'ListView', 'ScrollView', 'ViewPager', 'ViewPager2', + 'NestedScrollView', 'HorizontalScrollView', + // iOS + 'UICollectionView', 'UITableView', 'UIScrollView', + // Short names (from compressTree) + 'XCUIElementTypeScrollView', 'XCUIElementTypeTable', 'XCUIElementTypeCollectionView', +]); + +// ResourceId patterns that indicate ANCHOR elements (even inside scroll containers) +const ANCHOR_RESOURCE_PATTERNS = [ + 'toolbar', 'action_bar', 'tab_', 'nav_', 'bottom_nav', 'bottom_bar', + 'floating_action', 'app_bar', 'top_bar', 'header', +]; + +// ClassNames that are always ANCHOR +const ANCHOR_CLASS_NAMES = new Set([ + 'TabLayout', 'TabBar', 'UISegmentedControl', 'Toolbar', 'ActionBar', + 'BottomNavigationView', 'NavigationBarView', 'UITabBar', 'UINavigationBar', +]); + +// ClassNames that indicate a text label (for context extraction) +const TEXT_CLASS_NAMES = new Set([ + 'TextView', 'XCUIElementTypeStaticText', 'StaticText', + 'UILabel', 'AppCompatTextView', 'MaterialTextView', +]); + +function shortClassName(fullName: string): string { + const lastDot = fullName.lastIndexOf('.'); + return lastDot >= 0 ? fullName.substring(lastDot + 1) : fullName; +} + +function sha256Hex(input: string, length: number): string { + return createHash('sha256').update(input).digest('hex').substring(0, length); +} + +function isScrollContainer(node: AccessibilityNode): boolean { + if (node.scrollable) return true; + const name = shortClassName(node.className); + return SCROLL_CONTAINERS.has(name); +} + +function isAnchorByResourceId(resourceId?: string): boolean { + if (!resourceId) return false; + const lower = resourceId.toLowerCase(); + return ANCHOR_RESOURCE_PATTERNS.some(p => lower.includes(p)); +} + +function isAnchorByClassName(className: string): boolean { + return ANCHOR_CLASS_NAMES.has(shortClassName(className)); +} + +/** + * Build a set of node indices that are inside scroll containers (CONTENT zone). + * Walks the original tree with children to find scroll boundaries. + */ +function findContentIndices( + nodes: AccessibilityNode[], + compressedNodes: CompressedNode[] +): Set { + const contentBounds: Array<{ x1: number; y1: number; x2: number; y2: number }> = []; + + // Find scroll container bounds in the original tree + function walkForScrollers(node: AccessibilityNode): void { + if (isScrollContainer(node)) { + contentBounds.push(node.bounds); + } + if (node.children) { + for (const child of node.children) { + walkForScrollers(child); + } + } + } + + for (const root of nodes) { + walkForScrollers(root); + } + + // A compressed node is CONTENT if its center is inside a scroll container's bounds + // AND it's not the scroll container itself + const contentIndices = new Set(); + for (const cn of compressedNodes) { + if (cn.scrollable) continue; // The container itself is ANCHOR + const cx = (cn.bounds.x1 + cn.bounds.x2) / 2; + const cy = (cn.bounds.y1 + cn.bounds.y2) / 2; + for (const sb of contentBounds) { + if (cx >= sb.x1 && cx <= sb.x2 && cy >= sb.y1 && cy <= sb.y2) { + contentIndices.add(cn.index); + break; + } + } + } + + return contentIndices; +} + +/** + * Classify compressed nodes into ANCHOR or CONTENT zones. + */ +export function classifyZones( + compressedNodes: CompressedNode[], + originalTree: AccessibilityNode[], +): ClassifiedNode[] { + const contentIndices = findContentIndices(originalTree, compressedNodes); + + return compressedNodes.map(node => { + let zone: ZoneType = contentIndices.has(node.index) ? 'CONTENT' : 'ANCHOR'; + + // Override: known anchor patterns are always ANCHOR + if (zone === 'CONTENT') { + if (isAnchorByResourceId(node.resourceId) || isAnchorByClassName(node.className)) { + zone = 'ANCHOR'; + } + } + + return { node, zone }; + }); +} + +/** + * Extract screen context from the original tree for the context hash. + */ +export function extractContext( + originalTree: AccessibilityNode[], + appInfo: DeviceStateSnapshot['appInfo'], +): ScreenContext { + let toolbarTitle: string | undefined; + let selectedTab: string | undefined; + + function walk(node: AccessibilityNode, insideToolbar: boolean): void { + const name = shortClassName(node.className); + + const isToolbar = isAnchorByClassName(node.className) || + isAnchorByResourceId(node.resourceId); + + // Look for toolbar title + if ((insideToolbar || isToolbar) && TEXT_CLASS_NAMES.has(name) && node.text && !toolbarTitle) { + toolbarTitle = node.text; + } + + // Look for selected tab + if (node.selected && (node.text || node.contentDesc) && !selectedTab) { + selectedTab = node.text || node.contentDesc; + } + + if (node.children) { + for (const child of node.children) { + walk(child, insideToolbar || isToolbar); + } + } + } + + for (const root of originalTree) { + walk(root, false); + } + + return { + toolbarTitle, + selectedTab, + appPackage: appInfo.packageName, + currentApp: appInfo.currentApp, + }; +} + +/** + * Compute the skeleton fingerprint from classified nodes and context. + */ +export function computeFingerprint( + classified: ClassifiedNode[], + context: ScreenContext, +): ScreenFingerprint { + // Skeleton hash: ANCHOR nodes only + const anchorStrings: string[] = []; + const anchorSummary: string[] = []; + + for (const { node, zone } of classified) { + if (zone !== 'ANCHOR') continue; + anchorStrings.push(`${node.className}|${node.resourceId || ''}`); + + const label = node.text || node.contentDesc || node.resourceId || node.className; + anchorSummary.push(label); + } + + // Sort for order-independence + anchorStrings.sort(); + const skeletonHash = sha256Hex(anchorStrings.join('\n'), 12); + + // Context hash + const contextString = `${context.appPackage}|${context.toolbarTitle || ''}|${context.selectedTab || ''}`; + const contextHash = sha256Hex(contextString, 8); + + return { + skeletonHash, + contextHash, + fingerprint: `${skeletonHash}:${contextHash}`, + context, + anchorSummary, + }; +} diff --git a/packages/agent/src/tree-compressor.ts b/packages/agent/src/tree-compressor.ts new file mode 100644 index 0000000..d464e4f --- /dev/null +++ b/packages/agent/src/tree-compressor.ts @@ -0,0 +1,119 @@ +/** + * TypeScript port of native TreeCompressor + NodeSerializer. + * Removes empty container nodes and flattens tree to numbered CompressedNode[]. + * + * Reference: native-servers/android-device-server/.../TreeCompressor.kt + * Reference: native-servers/android-device-server/.../NodeSerializer.kt + */ + +import { AccessibilityNode } from '@device-stream/core'; +import { CompressedNode } from './types'; + +// Containers that add no semantic value when empty +const CONTAINER_TYPES = new Set([ + // Android + 'FrameLayout', 'LinearLayout', 'RelativeLayout', 'ConstraintLayout', + 'ViewGroup', 'CoordinatorLayout', 'AppBarLayout', + 'CollapsingToolbarLayout', 'NestedScrollView', 'CardView', 'MaterialCardView', + // iOS + 'UIView', 'UIStackView', +]); + +// Pure layout containers whose empty subtrees can be skipped entirely +const SKIPPABLE_CONTAINERS = new Set([ + 'FrameLayout', 'LinearLayout', 'RelativeLayout', 'ConstraintLayout', + 'ViewGroup', 'UIView', 'UIStackView', +]); + +function shortClassName(fullName: string): string { + const lastDot = fullName.lastIndexOf('.'); + return lastDot >= 0 ? fullName.substring(lastDot + 1) : fullName; +} + +function stripResourceId(resourceId: string): string { + const slashIdx = resourceId.indexOf('/'); + return slashIdx >= 0 ? resourceId.substring(slashIdx + 1) : resourceId; +} + +function isInteractive(node: AccessibilityNode): boolean { + return node.clickable || node.scrollable || node.focused || + node.checked === true || node.selected === true; +} + +function hasContent(node: AccessibilityNode): boolean { + return !!(node.text || node.contentDesc || node.resourceId); +} + +function shouldKeep(node: AccessibilityNode): boolean { + if (isInteractive(node)) return true; + + const name = shortClassName(node.className); + if (CONTAINER_TYPES.has(name)) { + return hasContent(node); + } + + return true; +} + +function shouldSkipSubtree(node: AccessibilityNode): boolean { + const name = shortClassName(node.className); + if (!SKIPPABLE_CONTAINERS.has(name)) return false; + return !hasContent(node); +} + +function toCompressedNode(node: AccessibilityNode, index: number): CompressedNode { + return { + index, + className: shortClassName(node.className), + resourceId: node.resourceId ? stripResourceId(node.resourceId) : undefined, + text: node.text || undefined, + contentDesc: node.contentDesc || undefined, + bounds: { ...node.bounds }, + clickable: node.clickable, + scrollable: node.scrollable, + focused: node.focused, + enabled: node.enabled, + checked: node.checked, + selected: node.selected, + }; +} + +/** + * Compress an accessibility tree by removing empty containers, + * flatten to a 1-indexed CompressedNode array. + */ +export function compressTree( + nodes: AccessibilityNode[], + maxElements: number = 50 +): CompressedNode[] { + const result: CompressedNode[] = []; + let nextIndex = 1; + + function traverse(node: AccessibilityNode): void { + if (result.length >= maxElements) return; + + const keep = shouldKeep(node); + + if (keep) { + result.push(toCompressedNode(node, nextIndex++)); + } + + if (!keep && shouldSkipSubtree(node)) { + return; + } + + if (node.children) { + for (const child of node.children) { + if (result.length >= maxElements) break; + traverse(child); + } + } + } + + for (const root of nodes) { + if (result.length >= maxElements) break; + traverse(root); + } + + return result; +} diff --git a/packages/agent/src/types.ts b/packages/agent/src/types.ts new file mode 100644 index 0000000..c4861c5 --- /dev/null +++ b/packages/agent/src/types.ts @@ -0,0 +1,133 @@ +/** + * Type definitions for the @device-stream/agent package. + * Navigation graphs, skeleton fingerprinting, and LLM-optimized state. + */ + +import { AccessibilityNode, DeviceStateSnapshot } from '@device-stream/core'; + +// ─── Tree Compression ─── + +/** + * A compressed, flat UI element — stripped of noise, 1-indexed. + * Produced by tree compression (port of native TreeCompressor + NodeSerializer). + */ +export interface CompressedNode { + index: number; + className: string; + resourceId?: string; + text?: string; + contentDesc?: string; + bounds: { x1: number; y1: number; x2: number; y2: number }; + clickable: boolean; + scrollable: boolean; + focused: boolean; + enabled: boolean; + checked?: boolean; + selected?: boolean; +} + +// ─── Zone Classification ─── + +export type ZoneType = 'ANCHOR' | 'CONTENT'; + +export interface ClassifiedNode { + node: CompressedNode; + zone: ZoneType; +} + +// ─── Screen Context & Fingerprinting ─── + +export interface ScreenContext { + toolbarTitle?: string; + selectedTab?: string; + appPackage: string; + currentApp: string; +} + +export interface ScreenFingerprint { + skeletonHash: string; + contextHash: string; + fingerprint: string; + context: ScreenContext; + anchorSummary: string[]; +} + +// ─── Element Selector ─── + +export interface ElementSelector { + index?: number; + text?: string; + resourceId?: string; + contentDesc?: string; + className?: string; +} + +// ─── Actions ─── + +export interface ActionDescriptor { + type: 'tap' | 'back' | 'deeplink' | 'type' | 'scroll' | 'longPress'; + target?: ElementSelector; + deepLink?: string; + text?: string; + direction?: 'up' | 'down' | 'left' | 'right'; +} + +// ─── Navigation Graph ─── + +export interface ScreenNode { + fingerprint: string; + screenType: string; + appPackage: string; + anchorElements: string[]; + availableActions: ActionDescriptor[]; + visitCount: number; + lastVisitedAt: number; +} + +export interface GraphEdge { + id: string; + from: string; + to: string; + action: ActionDescriptor; + successCount: number; + failCount: number; + avgLatencyMs: number; + lastUsedAt: number; +} + +export interface NavigationGraphData { + version: number; + nodes: Record; + edges: GraphEdge[]; +} + +// ─── Agent Session ─── + +export interface AgentSessionOptions { + serial: string; + graphPath?: string; + maxElements?: number; + stabilityDelayMs?: number; +} + +export interface CompactState { + fingerprint: ScreenFingerprint; + compactTree: string; + elements: CompressedNode[]; + appInfo: DeviceStateSnapshot['appInfo']; + deviceContext: DeviceStateSnapshot['deviceContext']; + knownScreen: boolean; + suggestedActions?: ActionDescriptor[]; +} + +export interface ActionResult { + success: boolean; + previousFingerprint: string; + newFingerprint: string; + transitioned: boolean; + latencyMs: number; + error?: string; +} + +// Re-export core types used by consumers +export type { AccessibilityNode, DeviceStateSnapshot }; diff --git a/packages/agent/tsconfig.json b/packages/agent/tsconfig.json new file mode 100644 index 0000000..8d55dc9 --- /dev/null +++ b/packages/agent/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/android-server/package.json b/packages/android-server/package.json index 4ac264b..dd42be3 100644 --- a/packages/android-server/package.json +++ b/packages/android-server/package.json @@ -7,7 +7,9 @@ "build": "bash scripts/build.sh", "setup": "bash scripts/setup.sh", "start": "bash scripts/start.sh", - "clean": "cd ../../native-servers/android-device-server && ./gradlew clean" + "clean": "cd ../../native-servers/android-device-server && ./gradlew clean", + "lint": "echo 'No TypeScript sources to lint'", + "test": "echo 'No tests configured'" }, "keywords": [ "device-stream", diff --git a/packages/android/src/device-service.ts b/packages/android/src/device-service.ts index 6a7897b..cb049b6 100644 --- a/packages/android/src/device-service.ts +++ b/packages/android/src/device-service.ts @@ -3,7 +3,17 @@ * See: https://tangoadb.dev/ */ -import { Device, VideoStreamMetadata, BaseDeviceService } from '@device-stream/core'; +import { + Device, + VideoStreamMetadata, + BaseDeviceService, + AccessibilityNode, + DeviceStateSnapshot, + PlatformCapability, + AppInfo, + AppearanceMode, +} from '@device-stream/core'; +import { parseUiAutomatorXml } from './hierarchy-parser'; import { Adb, AdbServerClient } from '@yume-chan/adb'; import { AdbServerNodeTcpConnector } from '@yume-chan/adb-server-node-tcp'; @@ -357,44 +367,10 @@ export class AndroidDeviceService extends BaseDeviceService { } } - async launchApp(serial: string, packageId: string): Promise { - this.assertConnected(serial); - try { - const adb = await this.getAdbDevice(serial); - - await this.runShellCommand(adb, `monkey -p ${packageId} -c android.intent.category.LAUNCHER 1`); - - await new Promise(resolve => setTimeout(resolve, 1000)); - - console.log(`Launched app ${packageId} on Android device ${serial}`); - } catch (error) { - console.error(`Failed to launch app ${packageId} on ${serial}:`, error); - throw new Error(`Failed to launch app: ${error}`); - } - } - async forceStopApp(serial: string, packageId: string): Promise { this.assertConnected(serial); - try { - const adb = await this.getAdbDevice(serial); - await this.runShellCommand(adb, `am force-stop ${packageId}`); - console.log(`Force stopped app ${packageId} on Android device ${serial}`); - } catch (error) { - console.error(`Failed to force stop app ${packageId} on ${serial}:`, error); - throw new Error(`Failed to force stop app: ${error}`); - } - } - - async clearAppData(serial: string, packageId: string): Promise { - this.assertConnected(serial); - try { - const adb = await this.getAdbDevice(serial); - await this.runShellCommand(adb, `pm clear ${packageId}`); - console.log(`Cleared app data for ${packageId} on Android device ${serial}`); - } catch (error) { - console.error(`Failed to clear app data for ${packageId} on ${serial}:`, error); - throw new Error(`Failed to clear app data: ${error}`); - } + const adb = await this.getAdbDevice(serial); + await this.runShellCommand(adb, `am force-stop ${packageId}`); } async swipe( @@ -416,18 +392,174 @@ export class AndroidDeviceService extends BaseDeviceService { } } - async longPress(serial: string, x: number, y: number, duration: number = 1000): Promise { + // ─── Phase 2: Accessibility Tree + Device State ─── + + async getAccessibilityTree(serial: string, _maxElements?: number): Promise { + const xml = await this.captureUIHierarchy(serial); + return parseUiAutomatorXml(xml); + } + + async getDeviceState(serial: string): Promise { this.assertConnected(serial); - try { - const adb = await this.getAdbDevice(serial); - await this.runShellCommand(adb, `input swipe ${x} ${y} ${x} ${y} ${duration}`); - console.log(`Long pressed at (${x}, ${y}) on Android device ${serial}`); - } catch (error) { - console.error(`Failed to long press on Android device ${serial}:`, error); - throw new Error(`Failed to long press: ${error}`); + const start = Date.now(); + + const [xml, currentApp, screenshotBuf] = await Promise.all([ + this.captureUIHierarchy(serial), + this.getCurrentApp(serial), + this.screenshot(serial).catch(() => null), + ]); + + const tree = parseUiAutomatorXml(xml); + const device = this.deviceInfoCache.get(serial); + + return { + tree, + appInfo: { + currentApp, + packageName: currentApp, + keyboardVisible: false, + }, + deviceContext: { + screenWidth: device?.screenWidth ?? 1080, + screenHeight: device?.screenHeight ?? 1920, + }, + screenshot: screenshotBuf ? screenshotBuf.toString('base64') : undefined, + captureMs: Date.now() - start, + }; + } + + getCapabilities(): PlatformCapability[] { + return [ + 'accessibility', + 'appManagement', + 'deepLinks', + 'appearance', + 'permissions', + 'clipboard', + 'recording', + 'media', + 'logStream', + ]; + } + + // ─── Phase 3: App Management (wiring existing methods) ─── + + async launchApp(serial: string, appId: string): Promise { + this.assertConnected(serial); + const adb = await this.getAdbDevice(serial); + await this.runShellCommand(adb, `monkey -p ${appId} -c android.intent.category.LAUNCHER 1`); + await new Promise(resolve => setTimeout(resolve, 1000)); + } + + async terminateApp(serial: string, appId: string): Promise { + await this.forceStopApp(serial, appId); + } + + async installApp(serial: string, path: string): Promise { + this.assertConnected(serial); + const adb = await this.getAdbDevice(serial); + const result = await this.runShellCommand(adb, `pm install -r "${path}"`); + if (result.includes('Failure')) { + throw new Error(`Failed to install app: ${result.trim()}`); } } + async uninstallApp(serial: string, appId: string): Promise { + this.assertConnected(serial); + const adb = await this.getAdbDevice(serial); + await this.runShellCommand(adb, `pm uninstall ${appId}`); + } + + async listInstalledApps(serial: string): Promise { + this.assertConnected(serial); + const adb = await this.getAdbDevice(serial); + const output = await this.runShellCommand(adb, 'pm list packages -3'); + const packages = output + .split('\n') + .filter((line: string) => line.startsWith('package:')) + .map((line: string) => line.replace('package:', '').trim()) + .filter(Boolean); + + return packages.map((pkg: string) => ({ + bundleId: pkg, + name: pkg, + type: 'user' as const, + })); + } + + async clearAppData(serial: string, appId: string): Promise { + this.assertConnected(serial); + const adb = await this.getAdbDevice(serial); + await this.runShellCommand(adb, `pm clear ${appId}`); + } + + // ─── Phase 4: Device Control ─── + + async openDeepLink(serial: string, url: string): Promise { + this.assertConnected(serial); + const adb = await this.getAdbDevice(serial); + await this.runShellCommand(adb, `am start -a android.intent.action.VIEW -d '${url}'`); + } + + async back(serial: string): Promise { + this.assertConnected(serial); + const adb = await this.getAdbDevice(serial); + await this.runShellCommand(adb, 'input keyevent KEYCODE_BACK'); + } + + async longPress(serial: string, x: number, y: number, duration: number = 1000): Promise { + this.assertConnected(serial); + const adb = await this.getAdbDevice(serial); + await this.runShellCommand(adb, `input swipe ${x} ${y} ${x} ${y} ${duration}`); + } + + async setAppearance(serial: string, mode: AppearanceMode): Promise { + this.assertConnected(serial); + const adb = await this.getAdbDevice(serial); + await this.runShellCommand(adb, `cmd uimode night ${mode === 'dark' ? 'yes' : 'no'}`); + } + + async getAppearance(serial: string): Promise { + this.assertConnected(serial); + const adb = await this.getAdbDevice(serial); + const output = await this.runShellCommand(adb, 'cmd uimode night'); + return output.includes('yes') ? 'dark' : 'light'; + } + + async grantPermission(serial: string, appId: string, permission: string): Promise { + this.assertConnected(serial); + const adb = await this.getAdbDevice(serial); + await this.runShellCommand(adb, `pm grant ${appId} ${permission}`); + } + + async revokePermission(serial: string, appId: string, permission: string): Promise { + this.assertConnected(serial); + const adb = await this.getAdbDevice(serial); + await this.runShellCommand(adb, `pm revoke ${appId} ${permission}`); + } + + // ─── Phase 5: I/O ─── + + async getClipboard(serial: string): Promise { + this.assertConnected(serial); + const adb = await this.getAdbDevice(serial); + const output = await this.runShellCommand(adb, 'cmd clipboard get-text'); + return output.trim(); + } + + async setClipboard(serial: string, text: string): Promise { + this.assertConnected(serial); + const adb = await this.getAdbDevice(serial); + const escaped = text.replace(/'/g, "'\\''"); + await this.runShellCommand(adb, `cmd clipboard set-text '${escaped}'`); + } + + async addMedia(serial: string, path: string): Promise { + this.assertConnected(serial); + const adb = await this.getAdbDevice(serial); + await this.runShellCommand(adb, `am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d file://${path}`); + } + async listPackages(serial: string): Promise { this.assertConnected(serial); try { diff --git a/packages/android/src/hierarchy-parser.ts b/packages/android/src/hierarchy-parser.ts new file mode 100644 index 0000000..c2598da --- /dev/null +++ b/packages/android/src/hierarchy-parser.ts @@ -0,0 +1,172 @@ +/** + * Parser for Android uiautomator dump XML → AccessibilityNode[] + * + * uiautomator dump produces XML like: + * + * + * ... + * + * + */ + +import { AccessibilityNode } from '@device-stream/core'; + +/** + * Parse a bounds string like "[0,0][1080,1920]" into {x1,y1,x2,y2} + */ +function parseBounds(bounds: string): { x1: number; y1: number; x2: number; y2: number } { + const match = bounds.match(/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/); + if (!match) { + return { x1: 0, y1: 0, x2: 0, y2: 0 }; + } + return { + x1: parseInt(match[1], 10), + y1: parseInt(match[2], 10), + x2: parseInt(match[3], 10), + y2: parseInt(match[4], 10), + }; +} + +/** + * Extract an attribute value from an XML node string. + * Uses string search to avoid dynamic RegExp construction. + */ +function attr(nodeStr: string, name: string): string { + const needle = `${name}="`; + const start = nodeStr.indexOf(needle); + if (start === -1) return ''; + const valueStart = start + needle.length; + const valueEnd = nodeStr.indexOf('"', valueStart); + if (valueEnd === -1) return ''; + return nodeStr.substring(valueStart, valueEnd); +} + +function attrBool(nodeStr: string, name: string): boolean { + return attr(nodeStr, name) === 'true'; +} + +/** + * Parse uiautomator dump XML into a flat AccessibilityNode array. + * Preserves hierarchy via the children field. + */ +export function parseUiAutomatorXml(xml: string): AccessibilityNode[] { + const nodes: AccessibilityNode[] = []; + let globalIndex = 0; + + function parseNode(xmlFragment: string): AccessibilityNode | null { + // Match the opening tag with attributes + const openMatch = xmlFragment.match(/^]*)>/s); + if (!openMatch) return null; + + const attrs = openMatch[1]; + const bounds = parseBounds(attr(attrs, 'bounds')); + + const node: AccessibilityNode = { + index: globalIndex++, + className: attr(attrs, 'class'), + resourceId: attr(attrs, 'resource-id') || undefined, + text: attr(attrs, 'text') || undefined, + contentDesc: attr(attrs, 'content-desc') || undefined, + bounds, + clickable: attrBool(attrs, 'clickable'), + scrollable: attrBool(attrs, 'scrollable'), + focused: attrBool(attrs, 'focused'), + enabled: attrBool(attrs, 'enabled'), + checked: attrBool(attrs, 'checkable') ? attrBool(attrs, 'checked') : undefined, + selected: attrBool(attrs, 'selected') || undefined, + }; + + // Find children by extracting inner content between opening and closing tags + const children = extractChildNodes(xmlFragment); + if (children.length > 0) { + node.children = []; + for (const childXml of children) { + const childNode = parseNode(childXml); + if (childNode) { + node.children.push(childNode); + } + } + if (node.children.length === 0) { + delete node.children; + } + } + + return node; + } + + /** + * Extract direct child ... elements from an XML fragment. + * Handles nested nodes by tracking depth. + */ + function extractChildNodes(xml: string): string[] { + const children: string[] = []; + // Skip past the opening tag of the parent + const firstClose = xml.indexOf('>'); + if (firstClose === -1) return children; + + const inner = xml.substring(firstClose + 1); + let depth = 0; + let start = -1; + + // Scan for or /> patterns + let i = 0; + while (i < inner.length) { + if (inner.startsWith('', i)) { + if (depth === 0) { + start = i; + } + depth++; + i += 5; + } else if (inner.startsWith('', i)) { + depth--; + if (depth === 0 && start !== -1) { + children.push(inner.substring(start, i + 7)); + start = -1; + } + i += 7; + } else if (inner.startsWith('/>', i) && depth > 0) { + // Self-closing node + // Check if we're inside a node tag + const before = inner.substring(start !== -1 ? start : 0, i); + const lastOpen = before.lastIndexOf(' element and extract its child nodes + const hierarchyMatch = xml.match(/]*>([\s\S]*)<\/hierarchy>/); + if (!hierarchyMatch) { + // Try to find individual elements at the top + const topNodes = extractChildNodes(`${xml}`); + for (const nodeXml of topNodes) { + const node = parseNode(nodeXml); + if (node) nodes.push(node); + } + return nodes; + } + + const hierarchyContent = `${hierarchyMatch[1]}`; + const topNodes = extractChildNodes(hierarchyContent); + for (const nodeXml of topNodes) { + const node = parseNode(nodeXml); + if (node) nodes.push(node); + } + + return nodes; +} diff --git a/packages/android/src/scrcpy-service.ts b/packages/android/src/scrcpy-service.ts index e681a88..4fe066d 100644 --- a/packages/android/src/scrcpy-service.ts +++ b/packages/android/src/scrcpy-service.ts @@ -104,7 +104,7 @@ export class ScrcpyService { const { videoStream, ws, serial } = session; try { - const reader = videoStream.getReader(); + const reader = videoStream.getReader() as unknown as ReadableStreamDefaultReader; session.reader = reader; while (true) { diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 92f1079..2c16946 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -22,6 +22,13 @@ export { DeviceFarmStats, QueuedTask, DeviceFarmEvent, + PlatformCapability, + AccessibilityNode, + DeviceStateSnapshot, + AppInfo, + LogLevel, + LogEntry, + AppearanceMode, } from './types'; // Interfaces diff --git a/packages/core/src/interfaces.ts b/packages/core/src/interfaces.ts index 1e08e98..630274a 100644 --- a/packages/core/src/interfaces.ts +++ b/packages/core/src/interfaces.ts @@ -8,6 +8,12 @@ import { DeviceConnection, VideoStreamMetadata, ScrollDirection, + AccessibilityNode, + DeviceStateSnapshot, + AppInfo, + LogEntry, + PlatformCapability, + AppearanceMode, } from './types'; /** @@ -89,6 +95,150 @@ export interface DeviceService { * Stop screen mirroring stream */ stopMirroring(serial: string): Promise; + + // ─── State ─── + + /** + * Get the accessibility tree (UI hierarchy) for AI agent automation + */ + getAccessibilityTree?(serial: string, maxElements?: number): Promise; + + /** + * Get combined device state (a11y tree + app info + device context) + */ + getDeviceState?(serial: string): Promise; + + /** + * Get the list of capabilities this platform supports + */ + getCapabilities?(): PlatformCapability[]; + + // ─── App Management ─── + + /** + * Launch an app by bundle/package ID + */ + launchApp?(serial: string, appId: string): Promise; + + /** + * Terminate a running app + */ + terminateApp?(serial: string, appId: string): Promise; + + /** + * Install an app from a local file path + */ + installApp?(serial: string, path: string): Promise; + + /** + * Uninstall an app by bundle/package ID + */ + uninstallApp?(serial: string, appId: string): Promise; + + /** + * List installed applications + */ + listInstalledApps?(serial: string): Promise; + + /** + * Clear app data/cache + */ + clearAppData?(serial: string, appId: string): Promise; + + // ─── Navigation ─── + + /** + * Open a deep link / URL on the device + */ + openDeepLink?(serial: string, url: string): Promise; + + /** + * Press the back button / navigate back + */ + back?(serial: string): Promise; + + /** + * Perform a long press at coordinates + */ + longPress?(serial: string, x: number, y: number, duration?: number): Promise; + + // ─── Settings ─── + + /** + * Set simulated GPS location + */ + setLocation?(serial: string, lat: number, lng: number): Promise; + + /** + * Clear simulated GPS location + */ + clearLocation?(serial: string): Promise; + + /** + * Set appearance mode (light/dark) + */ + setAppearance?(serial: string, mode: AppearanceMode): Promise; + + /** + * Get current appearance mode + */ + getAppearance?(serial: string): Promise; + + /** + * Set device locale + */ + setLocale?(serial: string, locale: string): Promise; + + // ─── Permissions ─── + + /** + * Grant a permission to an app + */ + grantPermission?(serial: string, appId: string, permission: string): Promise; + + /** + * Revoke a permission from an app + */ + revokePermission?(serial: string, appId: string, permission: string): Promise; + + // ─── I/O ─── + + /** + * Get device clipboard text + */ + getClipboard?(serial: string): Promise; + + /** + * Set device clipboard text + */ + setClipboard?(serial: string, text: string): Promise; + + /** + * Add media (photo/video) to the device gallery + */ + addMedia?(serial: string, path: string): Promise; + + // ─── Streaming ─── + + /** + * Start streaming device logs + */ + startLogStream?(serial: string, filter?: string): Promise; + + /** + * Stop streaming device logs + */ + stopLogStream?(serial: string): Promise; + + /** + * Start screen recording + */ + startRecording?(serial: string): Promise; + + /** + * Stop screen recording and return the video buffer + */ + stopRecording?(serial: string): Promise; } /** @@ -157,6 +307,110 @@ export abstract class BaseDeviceService implements DeviceService { throw new Error(`scroll is not supported on platform: ${this.platform}`); } + async getAccessibilityTree(_serial: string, _maxElements?: number): Promise { + throw new Error(`getAccessibilityTree is not supported on platform: ${this.platform}`); + } + + async getDeviceState(_serial: string): Promise { + throw new Error(`getDeviceState is not supported on platform: ${this.platform}`); + } + + getCapabilities(): PlatformCapability[] { + return []; + } + + async launchApp(_serial: string, _appId: string): Promise { + throw new Error(`launchApp is not supported on platform: ${this.platform}`); + } + + async terminateApp(_serial: string, _appId: string): Promise { + throw new Error(`terminateApp is not supported on platform: ${this.platform}`); + } + + async installApp(_serial: string, _path: string): Promise { + throw new Error(`installApp is not supported on platform: ${this.platform}`); + } + + async uninstallApp(_serial: string, _appId: string): Promise { + throw new Error(`uninstallApp is not supported on platform: ${this.platform}`); + } + + async listInstalledApps(_serial: string): Promise { + throw new Error(`listInstalledApps is not supported on platform: ${this.platform}`); + } + + async clearAppData(_serial: string, _appId: string): Promise { + throw new Error(`clearAppData is not supported on platform: ${this.platform}`); + } + + async openDeepLink(_serial: string, _url: string): Promise { + throw new Error(`openDeepLink is not supported on platform: ${this.platform}`); + } + + async back(_serial: string): Promise { + throw new Error(`back is not supported on platform: ${this.platform}`); + } + + async longPress(_serial: string, _x: number, _y: number, _duration?: number): Promise { + throw new Error(`longPress is not supported on platform: ${this.platform}`); + } + + async setLocation(_serial: string, _lat: number, _lng: number): Promise { + throw new Error(`setLocation is not supported on platform: ${this.platform}`); + } + + async clearLocation(_serial: string): Promise { + throw new Error(`clearLocation is not supported on platform: ${this.platform}`); + } + + async setAppearance(_serial: string, _mode: AppearanceMode): Promise { + throw new Error(`setAppearance is not supported on platform: ${this.platform}`); + } + + async getAppearance(_serial: string): Promise { + throw new Error(`getAppearance is not supported on platform: ${this.platform}`); + } + + async setLocale(_serial: string, _locale: string): Promise { + throw new Error(`setLocale is not supported on platform: ${this.platform}`); + } + + async grantPermission(_serial: string, _appId: string, _permission: string): Promise { + throw new Error(`grantPermission is not supported on platform: ${this.platform}`); + } + + async revokePermission(_serial: string, _appId: string, _permission: string): Promise { + throw new Error(`revokePermission is not supported on platform: ${this.platform}`); + } + + async getClipboard(_serial: string): Promise { + throw new Error(`getClipboard is not supported on platform: ${this.platform}`); + } + + async setClipboard(_serial: string, _text: string): Promise { + throw new Error(`setClipboard is not supported on platform: ${this.platform}`); + } + + async addMedia(_serial: string, _path: string): Promise { + throw new Error(`addMedia is not supported on platform: ${this.platform}`); + } + + async startLogStream(_serial: string, _filter?: string): Promise { + throw new Error(`startLogStream is not supported on platform: ${this.platform}`); + } + + async stopLogStream(_serial: string): Promise { + throw new Error(`stopLogStream is not supported on platform: ${this.platform}`); + } + + async startRecording(_serial: string): Promise { + throw new Error(`startRecording is not supported on platform: ${this.platform}`); + } + + async stopRecording(_serial: string): Promise { + throw new Error(`stopRecording is not supported on platform: ${this.platform}`); + } + // Abstract methods to be implemented by platform-specific services abstract listDevices(): Promise; abstract connect(serial: string): Promise; diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index b4e66f8..b2fe86a 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -194,3 +194,95 @@ export type DeviceFarmEvent = | { type: 'device:error'; device: FarmDevice; error: string } | { type: 'queue:added'; taskId: string; platform: DevicePlatform } | { type: 'queue:fulfilled'; taskId: string; deviceId: string }; + +// ─── New types for competitive feature parity ─── + +/** + * Platform capability identifiers. + * Each platform adapter declares which capabilities it supports. + */ +export type PlatformCapability = + | 'accessibility' + | 'appManagement' + | 'deepLinks' + | 'location' + | 'appearance' + | 'locale' + | 'permissions' + | 'clipboard' + | 'recording' + | 'media' + | 'logStream' + | 'biometrics' + | 'pushNotification'; + +/** + * A node in the UI accessibility tree. + * Matches the format produced by both Android uiautomator and iOS WDA. + */ +export interface AccessibilityNode { + index: number; + className: string; + resourceId?: string; + text?: string; + contentDesc?: string; + bounds: { x1: number; y1: number; x2: number; y2: number }; + clickable: boolean; + scrollable: boolean; + focused: boolean; + enabled: boolean; + checked?: boolean; + selected?: boolean; + children?: AccessibilityNode[]; +} + +/** + * Combined device state snapshot — a11y tree + app info + device context. + * Inspired by droidrun-portal's `/state_full` and ios-portal's `/state` endpoints. + */ +export interface DeviceStateSnapshot { + tree: AccessibilityNode[]; + appInfo: { + currentApp: string; + packageName: string; + keyboardVisible: boolean; + }; + deviceContext: { + screenWidth: number; + screenHeight: number; + displayRotation?: number; + }; + screenshot?: string; + captureMs?: number; +} + +/** + * Information about an installed application + */ +export interface AppInfo { + bundleId: string; + name: string; + version?: string; + type: 'user' | 'system'; +} + +/** + * Log level for device log entries + */ +export type LogLevel = 'verbose' | 'debug' | 'info' | 'warn' | 'error' | 'fatal'; + +/** + * A single log entry from a device log stream + */ +export interface LogEntry { + timestamp: number; + level: LogLevel; + tag: string; + message: string; + pid?: number; +} + +/** + * Appearance mode for device UI + */ +export type AppearanceMode = 'light' | 'dark'; diff --git a/packages/ios-device/src/device-service.ts b/packages/ios-device/src/device-service.ts index 39c055c..2a003e5 100644 --- a/packages/ios-device/src/device-service.ts +++ b/packages/ios-device/src/device-service.ts @@ -8,7 +8,11 @@ import { VideoStreamMetadata, BaseDeviceService, DeviceMutexManager, + AccessibilityNode, + DeviceStateSnapshot, + PlatformCapability, } from '@device-stream/core'; +import { parseWdaSourceXml } from './wda-hierarchy-parser'; import { goIOSClient } from './go-ios-client'; import { webDriverAgentClient } from './wda-client'; import { mjpegStreamClient } from './mjpeg-client'; @@ -386,6 +390,57 @@ export class IOSDeviceService extends BaseDeviceService { } } + async activateApp(serial: string, bundleId: string): Promise { + this.assertConnected(serial); + await webDriverAgentClient.activateApp(serial, bundleId); + } + + // ─── Phase 2: Accessibility Tree + Device State ─── + + async getAccessibilityTree(serial: string, _maxElements?: number): Promise { + const xml = await this.captureUIHierarchy(serial); + return parseWdaSourceXml(xml); + } + + async getDeviceState(serial: string): Promise { + this.assertConnected(serial); + const start = Date.now(); + + const [xml, appInfo, screenshotBuf] = await Promise.all([ + this.captureUIHierarchy(serial), + webDriverAgentClient.getActiveAppInfo(serial).catch(() => ({ bundleId: 'unknown', name: 'unknown', pid: 0 })), + this.screenshot(serial).catch(() => null), + ]); + + const tree = parseWdaSourceXml(xml); + const dims = this.screenDimensionsCache.get(serial); + + return { + tree, + appInfo: { + currentApp: appInfo.name, + packageName: appInfo.bundleId, + keyboardVisible: false, + }, + deviceContext: { + screenWidth: dims?.width ?? 1170, + screenHeight: dims?.height ?? 2532, + }, + screenshot: screenshotBuf ? screenshotBuf.toString('base64') : undefined, + captureMs: Date.now() - start, + }; + } + + getCapabilities(): PlatformCapability[] { + return [ + 'accessibility', + 'appManagement', + 'deepLinks', + ]; + } + + // ─── Phase 3: App Management (wiring existing methods) ─── + async launchApp(serial: string, bundleId: string): Promise { this.assertConnected(serial); await webDriverAgentClient.launchApp(serial, bundleId); @@ -397,14 +452,15 @@ export class IOSDeviceService extends BaseDeviceService { await webDriverAgentClient.terminateApp(serial, bundleId); } - async activateApp(serial: string, bundleId: string): Promise { - this.assertConnected(serial); - await webDriverAgentClient.activateApp(serial, bundleId); - } + // ─── Phase 4: Navigation ─── - async longPress(serial: string, x: number, y: number, duration: number = 1000): Promise { + async back(serial: string): Promise { this.assertConnected(serial); - await webDriverAgentClient.longPress(serial, x, y, duration); + const dims = this.screenDimensionsCache.get(serial); + const width = dims?.width ?? 1170; + const height = dims?.height ?? 2532; + // iOS back: swipe from left edge to 40% width + await webDriverAgentClient.swipe(serial, 5, Math.floor(height / 2), Math.floor(width * 0.4), Math.floor(height / 2), 300); } /** diff --git a/packages/ios-device/src/wda-hierarchy-parser.ts b/packages/ios-device/src/wda-hierarchy-parser.ts new file mode 100644 index 0000000..aa513fe --- /dev/null +++ b/packages/ios-device/src/wda-hierarchy-parser.ts @@ -0,0 +1,183 @@ +/** + * Parser for WDA /source XML → AccessibilityNode[] + * + * WDA returns XML with XCUIElementType* tag names: + * + * + * + * + * + * + * + * + * + */ + +import { AccessibilityNode } from '@device-stream/core'; + +function attr(nodeStr: string, name: string): string { + const needle = `${name}="`; + const start = nodeStr.indexOf(needle); + if (start === -1) return ''; + const valueStart = start + needle.length; + const valueEnd = nodeStr.indexOf('"', valueStart); + if (valueEnd === -1) return ''; + return nodeStr.substring(valueStart, valueEnd); +} + +function attrBool(nodeStr: string, name: string): boolean { + return attr(nodeStr, name) === 'true'; +} + +function attrInt(nodeStr: string, name: string, fallback: number = 0): number { + const val = attr(nodeStr, name); + const n = parseInt(val, 10); + return isNaN(n) ? fallback : n; +} + +/** + * Parse WDA /source XML into AccessibilityNode[]. + */ +export function parseWdaSourceXml(xml: string): AccessibilityNode[] { + const nodes: AccessibilityNode[] = []; + let globalIndex = 0; + + function parseNode(xmlFragment: string): AccessibilityNode | null { + // Match opening tag (XCUIElementType* or other) + const openMatch = xmlFragment.match(/^<(\w+)\s([^>]*?)(\/)?>|^<(\w+)\s([^>]*)>/s); + if (!openMatch) return null; + + const tagName = openMatch[1] || openMatch[4] || ''; + const attrs = openMatch[2] || openMatch[5] || ''; + const isSelfClosing = openMatch[3] === '/'; + + const x = attrInt(attrs, 'x'); + const y = attrInt(attrs, 'y'); + const w = attrInt(attrs, 'width'); + const h = attrInt(attrs, 'height'); + + // Use the type attribute if present, otherwise use the tag name + const className = attr(attrs, 'type') || tagName; + + const node: AccessibilityNode = { + index: globalIndex++, + className, + resourceId: attr(attrs, 'name') || undefined, + text: attr(attrs, 'value') || attr(attrs, 'label') || undefined, + contentDesc: attr(attrs, 'label') || undefined, + bounds: { x1: x, y1: y, x2: x + w, y2: y + h }, + clickable: attrBool(attrs, 'accessible'), + scrollable: className.includes('ScrollView'), + focused: attrBool(attrs, 'focused'), + enabled: attrBool(attrs, 'enabled'), + selected: attrBool(attrs, 'selected') || undefined, + }; + + if (!isSelfClosing) { + const children = extractChildNodes(xmlFragment, tagName); + if (children.length > 0) { + node.children = []; + for (const childXml of children) { + const childNode = parseNode(childXml); + if (childNode) { + node.children.push(childNode); + } + } + if (node.children.length === 0) { + delete node.children; + } + } + } + + return node; + } + + function extractChildNodes(xml: string, parentTag: string): string[] { + const children: string[] = []; + const firstClose = xml.indexOf('>'); + if (firstClose === -1) return children; + + const inner = xml.substring(firstClose + 1); + let depth = 0; + let start = -1; + let i = 0; + + while (i < inner.length) { + if (inner[i] === '<' && inner[i + 1] !== '/') { + // Opening tag + const tagEnd = inner.indexOf('>', i); + if (tagEnd === -1) break; + + const tagContent = inner.substring(i, tagEnd + 1); + const isSelf = tagContent.endsWith('/>'); + + if (depth === 0) { + start = i; + } + + if (isSelf) { + if (depth === 0) { + children.push(tagContent); + start = -1; + } + } else { + depth++; + } + + i = tagEnd + 1; + } else if (inner.startsWith('', i); + if (closeEnd === -1) break; + + depth--; + if (depth === 0 && start !== -1) { + children.push(inner.substring(start, closeEnd + 1)); + start = -1; + } + + // Break if we hit the parent closing tag + const closingTag = inner.substring(i + 2, closeEnd); + if (depth < 0 || closingTag === parentTag) break; + + i = closeEnd + 1; + } else { + i++; + } + } + + return children; + } + + // Strip outer wrapper tags (AppiumAUT, etc.) + // Find the first XCUIElementType* tag + const xcuiMatch = xml.match(/<(XCUIElementType\w+)\s/); + if (xcuiMatch) { + const startIdx = xml.indexOf(xcuiMatch[0]); + const tag = xcuiMatch[1]; + const endTag = ``; + const endIdx = xml.lastIndexOf(endTag); + if (endIdx !== -1) { + const fragment = xml.substring(startIdx, endIdx + endTag.length); + const node = parseNode(fragment); + if (node) { + // Return the app node's children as the tree, or wrap if no children + if (node.children && node.children.length > 0) { + return node.children; + } + return [node]; + } + } + } + + // Fallback: try to parse the whole thing + const wrapped = `${xml}`; + const topChildren = extractChildNodes(wrapped, 'root'); + for (const childXml of topChildren) { + const node = parseNode(childXml); + if (node) nodes.push(node); + } + + return nodes; +}