diff --git a/package-lock.json b/package-lock.json index f066e74b..7c4cdaa2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14424,6 +14424,8 @@ }, "node_modules/npm/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==", "dev": true, "inBundle": true, "license": "ISC", @@ -14453,6 +14455,8 @@ }, "node_modules/npm/node_modules/@isaacs/cliui/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==", "dev": true, "inBundle": true, "license": "MIT" @@ -14476,6 +14480,8 @@ }, "node_modules/npm/node_modules/@isaacs/cliui/node_modules/strip-ansi": { "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "inBundle": true, "license": "MIT", @@ -14491,12 +14497,16 @@ }, "node_modules/npm/node_modules/@isaacs/string-locale-compare": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz", + "integrity": "sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/@npmcli/agent": { "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.2.2.tgz", + "integrity": "sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og==", "dev": true, "inBundle": true, "license": "ISC", @@ -14513,6 +14523,8 @@ }, "node_modules/npm/node_modules/@npmcli/arborist": { "version": "7.5.4", + "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-7.5.4.tgz", + "integrity": "sha512-nWtIc6QwwoUORCRNzKx4ypHqCk3drI+5aeYdMTQQiRCcn4lOOgfQh7WyZobGYTxXPSq1VwV53lkpN/BRlRk08g==", "dev": true, "inBundle": true, "license": "ISC", @@ -14562,6 +14574,8 @@ }, "node_modules/npm/node_modules/@npmcli/config": { "version": "8.3.4", + "resolved": "https://registry.npmjs.org/@npmcli/config/-/config-8.3.4.tgz", + "integrity": "sha512-01rtHedemDNhUXdicU7s+QYz/3JyV5Naj84cvdXGH4mgCdL+agmSYaLF4LUG4vMCLzhBO8YtS0gPpH1FGvbgAw==", "dev": true, "inBundle": true, "license": "ISC", @@ -14581,6 +14595,8 @@ }, "node_modules/npm/node_modules/@npmcli/fs": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz", + "integrity": "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==", "dev": true, "inBundle": true, "license": "ISC", @@ -14593,6 +14609,8 @@ }, "node_modules/npm/node_modules/@npmcli/git": { "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-5.0.8.tgz", + "integrity": "sha512-liASfw5cqhjNW9UFd+ruwwdEf/lbOAQjLL2XY2dFW/bkJheXDYZgOyul/4gVvEV4BWkTXjYGmDqMw9uegdbJNQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -14613,6 +14631,8 @@ }, "node_modules/npm/node_modules/@npmcli/installed-package-contents": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.1.0.tgz", + "integrity": "sha512-c8UuGLeZpm69BryRykLuKRyKFZYJsZSCT4aVY5ds4omyZqJ172ApzgfKJ5eV/r3HgLdUYgFVe54KSFVjKoe27w==", "dev": true, "inBundle": true, "license": "ISC", @@ -14629,6 +14649,8 @@ }, "node_modules/npm/node_modules/@npmcli/map-workspaces": { "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-3.0.6.tgz", + "integrity": "sha512-tkYs0OYnzQm6iIRdfy+LcLBjcKuQCeE5YLb8KnrIlutJfheNaPvPpgoFEyEFgbjzl5PLZ3IA/BWAwRU0eHuQDA==", "dev": true, "inBundle": true, "license": "ISC", @@ -14644,6 +14666,8 @@ }, "node_modules/npm/node_modules/@npmcli/metavuln-calculator": { "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/metavuln-calculator/-/metavuln-calculator-7.1.1.tgz", + "integrity": "sha512-Nkxf96V0lAx3HCpVda7Vw4P23RILgdi/5K1fmj2tZkWIYLpXAN8k2UVVOsW16TsS5F8Ws2I7Cm+PU1/rsVF47g==", "dev": true, "inBundle": true, "license": "ISC", @@ -14660,6 +14684,8 @@ }, "node_modules/npm/node_modules/@npmcli/name-from-folder": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-2.0.0.tgz", + "integrity": "sha512-pwK+BfEBZJbKdNYpHHRTNBwBoqrN/iIMO0AiGvYsp3Hoaq0WbgGSWQR6SCldZovoDpY3yje5lkFUe6gsDgJ2vg==", "dev": true, "inBundle": true, "license": "ISC", @@ -14669,6 +14695,8 @@ }, "node_modules/npm/node_modules/@npmcli/node-gyp": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", + "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==", "dev": true, "inBundle": true, "license": "ISC", @@ -14678,6 +14706,8 @@ }, "node_modules/npm/node_modules/@npmcli/package-json": { "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-5.2.0.tgz", + "integrity": "sha512-qe/kiqqkW0AGtvBjL8TJKZk/eBBSpnJkUWvHdQ9jM2lKHXRYYJuyNpJPlJw3c8QjC2ow6NZYiLExhUaeJelbxQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -14696,6 +14726,8 @@ }, "node_modules/npm/node_modules/@npmcli/promise-spawn": { "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-7.0.2.tgz", + "integrity": "sha512-xhfYPXoV5Dy4UkY0D+v2KkwvnDfiA/8Mt3sWCGI/hM03NsYIH8ZaG6QzS9x7pje5vHZBZJ2v6VRFVTWACnqcmQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -14708,6 +14740,8 @@ }, "node_modules/npm/node_modules/@npmcli/query": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/query/-/query-3.1.0.tgz", + "integrity": "sha512-C/iR0tk7KSKGldibYIB9x8GtO/0Bd0I2mhOaDb8ucQL/bQVTmGoeREaFj64Z5+iCBRf3dQfed0CjJL7I8iTkiQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -14720,6 +14754,8 @@ }, "node_modules/npm/node_modules/@npmcli/redact": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/redact/-/redact-2.0.1.tgz", + "integrity": "sha512-YgsR5jCQZhVmTJvjduTOIHph0L73pK8xwMVaDY0PatySqVM9AZj93jpoXYSJqfHFxFkN9dmqTw6OiqExsS3LPw==", "dev": true, "inBundle": true, "license": "ISC", @@ -14729,6 +14765,8 @@ }, "node_modules/npm/node_modules/@npmcli/run-script": { "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-8.1.0.tgz", + "integrity": "sha512-y7efHHwghQfk28G2z3tlZ67pLG0XdfYbcVG26r7YIXALRsrVQcTq4/tdenSmdOrEsNahIYA/eh8aEVROWGFUDg==", "dev": true, "inBundle": true, "license": "ISC", @@ -14746,6 +14784,8 @@ }, "node_modules/npm/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==", "dev": true, "inBundle": true, "license": "MIT", @@ -14756,6 +14796,8 @@ }, "node_modules/npm/node_modules/@sigstore/bundle": { "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-2.3.2.tgz", + "integrity": "sha512-wueKWDk70QixNLB363yHc2D2ItTgYiMTdPwK8D9dKQMR3ZQ0c35IxP5xnwQ8cNLoCgCRcHf14kE+CLIvNX1zmA==", "dev": true, "inBundle": true, "license": "Apache-2.0", @@ -14768,6 +14810,8 @@ }, "node_modules/npm/node_modules/@sigstore/core": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-1.1.0.tgz", + "integrity": "sha512-JzBqdVIyqm2FRQCulY6nbQzMpJJpSiJ8XXWMhtOX9eKgaXXpfNOF53lzQEjIydlStnd/eFtuC1dW4VYdD93oRg==", "dev": true, "inBundle": true, "license": "Apache-2.0", @@ -14777,6 +14821,8 @@ }, "node_modules/npm/node_modules/@sigstore/protobuf-specs": { "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.3.2.tgz", + "integrity": "sha512-c6B0ehIWxMI8wiS/bj6rHMPqeFvngFV7cDU/MY+B16P9Z3Mp9k8L93eYZ7BYzSickzuqAQqAq0V956b3Ju6mLw==", "dev": true, "inBundle": true, "license": "Apache-2.0", @@ -14786,6 +14832,8 @@ }, "node_modules/npm/node_modules/@sigstore/sign": { "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-2.3.2.tgz", + "integrity": "sha512-5Vz5dPVuunIIvC5vBb0APwo7qKA4G9yM48kPWJT+OEERs40md5GoUR1yedwpekWZ4m0Hhw44m6zU+ObsON+iDA==", "dev": true, "inBundle": true, "license": "Apache-2.0", @@ -14803,6 +14851,8 @@ }, "node_modules/npm/node_modules/@sigstore/tuf": { "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-2.3.4.tgz", + "integrity": "sha512-44vtsveTPUpqhm9NCrbU8CWLe3Vck2HO1PNLw7RIajbB7xhtn5RBPm1VNSCMwqGYHhDsBJG8gDF0q4lgydsJvw==", "dev": true, "inBundle": true, "license": "Apache-2.0", @@ -14816,6 +14866,8 @@ }, "node_modules/npm/node_modules/@sigstore/verify": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-1.2.1.tgz", + "integrity": "sha512-8iKx79/F73DKbGfRf7+t4dqrc0bRr0thdPrxAtCKWRm/F0tG71i6O1rvlnScncJLLBZHn3h8M3c1BSUAb9yu8g==", "dev": true, "inBundle": true, "license": "Apache-2.0", @@ -14830,6 +14882,8 @@ }, "node_modules/npm/node_modules/@tufjs/canonical-json": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz", + "integrity": "sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==", "dev": true, "inBundle": true, "license": "MIT", @@ -14839,6 +14893,8 @@ }, "node_modules/npm/node_modules/@tufjs/models": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-2.0.1.tgz", + "integrity": "sha512-92F7/SFyufn4DXsha9+QfKnN03JGqtMFMXgSHbZOo8JG59WkTni7UzAouNQDf7AuP9OAMxVOPQcqG3sB7w+kkg==", "dev": true, "inBundle": true, "license": "MIT", @@ -14852,6 +14908,8 @@ }, "node_modules/npm/node_modules/abbrev": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -14861,6 +14919,8 @@ }, "node_modules/npm/node_modules/agent-base": { "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "dev": true, "inBundle": true, "license": "MIT", @@ -14873,6 +14933,8 @@ }, "node_modules/npm/node_modules/aggregate-error": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, "inBundle": true, "license": "MIT", @@ -14886,6 +14948,8 @@ }, "node_modules/npm/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==", "dev": true, "inBundle": true, "license": "MIT", @@ -14895,6 +14959,8 @@ }, "node_modules/npm/node_modules/ansi-styles": { "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, "inBundle": true, "license": "MIT", @@ -14907,24 +14973,32 @@ }, "node_modules/npm/node_modules/aproba": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/archy": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/balanced-match": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/bin-links": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/bin-links/-/bin-links-4.0.4.tgz", + "integrity": "sha512-cMtq4W5ZsEwcutJrVId+a/tjt8GSbS+h0oNkdl6+6rBuEv8Ot33Bevj5KPm40t309zuhVic8NjpuL42QCiJWWA==", "dev": true, "inBundle": true, "license": "ISC", @@ -14940,6 +15014,8 @@ }, "node_modules/npm/node_modules/binary-extensions": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, "inBundle": true, "license": "MIT", @@ -14952,6 +15028,8 @@ }, "node_modules/npm/node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "inBundle": true, "license": "MIT", @@ -14961,6 +15039,8 @@ }, "node_modules/npm/node_modules/cacache": { "version": "18.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.4.tgz", + "integrity": "sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -14984,6 +15064,8 @@ }, "node_modules/npm/node_modules/chalk": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, "inBundle": true, "license": "MIT", @@ -14996,6 +15078,8 @@ }, "node_modules/npm/node_modules/chownr": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -15005,6 +15089,8 @@ }, "node_modules/npm/node_modules/ci-info": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz", + "integrity": "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==", "dev": true, "funding": [ { @@ -15020,6 +15106,8 @@ }, "node_modules/npm/node_modules/cidr-regex": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/cidr-regex/-/cidr-regex-4.1.1.tgz", + "integrity": "sha512-ekKcVp+iRB9zlKFXyx7io7nINgb0oRjgRdXNEodp1OuxRui8FXr/CA40Tz1voWUp9DPPrMyQKy01vJhDo4N1lw==", "dev": true, "inBundle": true, "license": "BSD-2-Clause", @@ -15032,6 +15120,8 @@ }, "node_modules/npm/node_modules/clean-stack": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true, "inBundle": true, "license": "MIT", @@ -15041,6 +15131,8 @@ }, "node_modules/npm/node_modules/cli-columns": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-columns/-/cli-columns-4.0.0.tgz", + "integrity": "sha512-XW2Vg+w+L9on9wtwKpyzluIPCWXjaBahI7mTcYjx+BVIYD9c3yqcv/yKC7CmdCZat4rq2yiE1UMSJC5ivKfMtQ==", "dev": true, "inBundle": true, "license": "MIT", @@ -15054,6 +15146,8 @@ }, "node_modules/npm/node_modules/cmd-shim": { "version": "6.0.3", + "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-6.0.3.tgz", + "integrity": "sha512-FMabTRlc5t5zjdenF6mS0MBeFZm0XqHqeOkcskKFb/LYCcRQ5fVgLOHVc4Lq9CqABd9zhjwPjMBCJvMCziSVtA==", "dev": true, "inBundle": true, "license": "ISC", @@ -15063,6 +15157,8 @@ }, "node_modules/npm/node_modules/color-convert": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "inBundle": true, "license": "MIT", @@ -15075,18 +15171,24 @@ }, "node_modules/npm/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==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/common-ancestor-path": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz", + "integrity": "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/cross-spawn": { "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "inBundle": true, "license": "MIT", @@ -15116,6 +15218,8 @@ }, "node_modules/npm/node_modules/cssesc": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, "inBundle": true, "license": "MIT", @@ -15151,6 +15255,8 @@ }, "node_modules/npm/node_modules/diff": { "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "dev": true, "inBundle": true, "license": "BSD-3-Clause", @@ -15160,18 +15266,24 @@ }, "node_modules/npm/node_modules/eastasianwidth": { "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/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==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/encoding": { "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", "dev": true, "inBundle": true, "license": "MIT", @@ -15182,6 +15294,8 @@ }, "node_modules/npm/node_modules/env-paths": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "dev": true, "inBundle": true, "license": "MIT", @@ -15191,18 +15305,24 @@ }, "node_modules/npm/node_modules/err-code": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/exponential-backoff": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", "dev": true, "inBundle": true, "license": "Apache-2.0" }, "node_modules/npm/node_modules/fastest-levenshtein": { "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "dev": true, "inBundle": true, "license": "MIT", @@ -15212,6 +15332,8 @@ }, "node_modules/npm/node_modules/foreground-child": { "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", "dev": true, "inBundle": true, "license": "ISC", @@ -15228,6 +15350,8 @@ }, "node_modules/npm/node_modules/fs-minipass": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", "dev": true, "inBundle": true, "license": "ISC", @@ -15240,6 +15364,8 @@ }, "node_modules/npm/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==", "dev": true, "inBundle": true, "license": "ISC", @@ -15260,12 +15386,16 @@ }, "node_modules/npm/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==", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/hosted-git-info": { "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", "dev": true, "inBundle": true, "license": "ISC", @@ -15278,12 +15408,16 @@ }, "node_modules/npm/node_modules/http-cache-semantics": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", "dev": true, "inBundle": true, "license": "BSD-2-Clause" }, "node_modules/npm/node_modules/http-proxy-agent": { "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dev": true, "inBundle": true, "license": "MIT", @@ -15297,6 +15431,8 @@ }, "node_modules/npm/node_modules/https-proxy-agent": { "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "dev": true, "inBundle": true, "license": "MIT", @@ -15310,6 +15446,8 @@ }, "node_modules/npm/node_modules/iconv-lite": { "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "inBundle": true, "license": "MIT", @@ -15323,6 +15461,8 @@ }, "node_modules/npm/node_modules/ignore-walk": { "version": "6.0.5", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.5.tgz", + "integrity": "sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==", "dev": true, "inBundle": true, "license": "ISC", @@ -15335,6 +15475,8 @@ }, "node_modules/npm/node_modules/imurmurhash": { "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "inBundle": true, "license": "MIT", @@ -15344,6 +15486,8 @@ }, "node_modules/npm/node_modules/indent-string": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, "inBundle": true, "license": "MIT", @@ -15353,6 +15497,8 @@ }, "node_modules/npm/node_modules/ini": { "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", + "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==", "dev": true, "inBundle": true, "license": "ISC", @@ -15362,6 +15508,8 @@ }, "node_modules/npm/node_modules/init-package-json": { "version": "6.0.3", + "resolved": "https://registry.npmjs.org/init-package-json/-/init-package-json-6.0.3.tgz", + "integrity": "sha512-Zfeb5ol+H+eqJWHTaGca9BovufyGeIfr4zaaBorPmJBMrJ+KBnN+kQx2ZtXdsotUTgldHmHQV44xvUWOUA7E2w==", "dev": true, "inBundle": true, "license": "ISC", @@ -15380,6 +15528,8 @@ }, "node_modules/npm/node_modules/ip-address": { "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", "dev": true, "inBundle": true, "license": "MIT", @@ -15393,6 +15543,8 @@ }, "node_modules/npm/node_modules/ip-regex": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-5.0.0.tgz", + "integrity": "sha512-fOCG6lhoKKakwv+C6KdsOnGvgXnmgfmp0myi3bcNwj3qfwPAxRKWEuFhvEFF7ceYIz6+1jRZ+yguLFAmUNPEfw==", "dev": true, "inBundle": true, "license": "MIT", @@ -15405,6 +15557,8 @@ }, "node_modules/npm/node_modules/is-cidr": { "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-cidr/-/is-cidr-5.1.0.tgz", + "integrity": "sha512-OkVS+Ht2ssF27d48gZdB+ho1yND1VbkJRKKS6Pc1/Cw7uqkd9IOJg8/bTwBDQL6tfBhSdguPRnlGiE8pU/X5NQ==", "dev": true, "inBundle": true, "license": "BSD-2-Clause", @@ -15417,6 +15571,8 @@ }, "node_modules/npm/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==", "dev": true, "inBundle": true, "license": "MIT", @@ -15426,18 +15582,24 @@ }, "node_modules/npm/node_modules/is-lambda": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/isexe": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/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==", "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", @@ -15453,12 +15615,16 @@ }, "node_modules/npm/node_modules/jsbn": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/json-parse-even-better-errors": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", + "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", "dev": true, "inBundle": true, "license": "MIT", @@ -15468,6 +15634,8 @@ }, "node_modules/npm/node_modules/json-stringify-nice": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz", + "integrity": "sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw==", "dev": true, "inBundle": true, "license": "ISC", @@ -15477,6 +15645,8 @@ }, "node_modules/npm/node_modules/jsonparse": { "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", "dev": true, "engines": [ "node >= 0.2.0" @@ -15486,18 +15656,24 @@ }, "node_modules/npm/node_modules/just-diff": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/just-diff/-/just-diff-6.0.2.tgz", + "integrity": "sha512-S59eriX5u3/QhMNq3v/gm8Kd0w8OS6Tz2FS1NG4blv+z0MuQcBRJyFWjdovM0Rad4/P4aUPFtnkNjMjyMlMSYA==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/just-diff-apply": { "version": "5.5.0", + "resolved": "https://registry.npmjs.org/just-diff-apply/-/just-diff-apply-5.5.0.tgz", + "integrity": "sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/libnpmaccess": { "version": "8.0.6", + "resolved": "https://registry.npmjs.org/libnpmaccess/-/libnpmaccess-8.0.6.tgz", + "integrity": "sha512-uM8DHDEfYG6G5gVivVl+yQd4pH3uRclHC59lzIbSvy7b5FEwR+mU49Zq1jEyRtRFv7+M99mUW9S0wL/4laT4lw==", "dev": true, "inBundle": true, "license": "ISC", @@ -15511,6 +15687,8 @@ }, "node_modules/npm/node_modules/libnpmdiff": { "version": "6.1.4", + "resolved": "https://registry.npmjs.org/libnpmdiff/-/libnpmdiff-6.1.4.tgz", + "integrity": "sha512-KCNoCY8kjQ16/EE4VoW7AYqecsb9frNIh/cPwWQSk1s2grzZMQH+Scp7Yo7Fk6SWTkyVDLZEYfUT/vKONYrfmg==", "dev": true, "inBundle": true, "license": "ISC", @@ -15530,6 +15708,8 @@ }, "node_modules/npm/node_modules/libnpmexec": { "version": "8.1.4", + "resolved": "https://registry.npmjs.org/libnpmexec/-/libnpmexec-8.1.4.tgz", + "integrity": "sha512-/5mQ8d7PJT3Ok1iTfXVZaev4mppno9IbimHv7x1g8ZLIQtRE0SWrdFN7SB43vzxexdw0bJ3LKu2OsY6L3h60Kg==", "dev": true, "inBundle": true, "license": "ISC", @@ -15551,6 +15731,8 @@ }, "node_modules/npm/node_modules/libnpmfund": { "version": "5.0.12", + "resolved": "https://registry.npmjs.org/libnpmfund/-/libnpmfund-5.0.12.tgz", + "integrity": "sha512-lox1UHcv8/r/TE+T9B+aOylU3c13tK2IuwwUwUm+YMw+C/iq14dqskHqhGPTqa75ZJbiVOW7PMWO92Wn5HG49Q==", "dev": true, "inBundle": true, "license": "ISC", @@ -15563,6 +15745,8 @@ }, "node_modules/npm/node_modules/libnpmhook": { "version": "10.0.5", + "resolved": "https://registry.npmjs.org/libnpmhook/-/libnpmhook-10.0.5.tgz", + "integrity": "sha512-XulT+N/s3o9oFlIq6pGRv3OG2qR1NVRbVQOKLchycDwyf16RZA3oXbeEgs2H3oE7hRZPUMBZqsalQXMMPal3cQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -15576,6 +15760,8 @@ }, "node_modules/npm/node_modules/libnpmorg": { "version": "6.0.6", + "resolved": "https://registry.npmjs.org/libnpmorg/-/libnpmorg-6.0.6.tgz", + "integrity": "sha512-4MVxsAS4H2z7su/sU0GsrirfBm4ssfqPRSDvoZ8qmRw58kEWJ0qE0cQ2VilRlFgCWKzKPhfoPeyNPyxBTnOusA==", "dev": true, "inBundle": true, "license": "ISC", @@ -15589,6 +15775,8 @@ }, "node_modules/npm/node_modules/libnpmpack": { "version": "7.0.4", + "resolved": "https://registry.npmjs.org/libnpmpack/-/libnpmpack-7.0.4.tgz", + "integrity": "sha512-oKZA0afbueiC88lskXzAEr3DCN9BTMbUySjUce6qhBV9CjYF2R/x347KhgHu75+p9W2Rd57ZvKz81c5a2+9h6Q==", "dev": true, "inBundle": true, "license": "ISC", @@ -15604,6 +15792,8 @@ }, "node_modules/npm/node_modules/libnpmpublish": { "version": "9.0.9", + "resolved": "https://registry.npmjs.org/libnpmpublish/-/libnpmpublish-9.0.9.tgz", + "integrity": "sha512-26zzwoBNAvX9AWOPiqqF6FG4HrSCPsHFkQm7nT+xU1ggAujL/eae81RnCv4CJ2In9q9fh10B88sYSzKCUh/Ghg==", "dev": true, "inBundle": true, "license": "ISC", @@ -15623,6 +15813,8 @@ }, "node_modules/npm/node_modules/libnpmsearch": { "version": "7.0.6", + "resolved": "https://registry.npmjs.org/libnpmsearch/-/libnpmsearch-7.0.6.tgz", + "integrity": "sha512-PmiER4bgiIqN9OjBtgPn2/PxwU+OdJWtLBFM+vewOrn4VmaNAHSUKDt/wxOOkZSDLyMICVUBp61Ji1+XxhSrKw==", "dev": true, "inBundle": true, "license": "ISC", @@ -15635,6 +15827,8 @@ }, "node_modules/npm/node_modules/libnpmteam": { "version": "6.0.5", + "resolved": "https://registry.npmjs.org/libnpmteam/-/libnpmteam-6.0.5.tgz", + "integrity": "sha512-iJW4Cq42GMqMwZEV+Mx8ZLj0Np5kGXQ9P/BAekHjIpYC1v3/vJqbmfJkzkwFvGxEhUotmx+xpLChZCDJ7c3rxA==", "dev": true, "inBundle": true, "license": "ISC", @@ -15648,6 +15842,8 @@ }, "node_modules/npm/node_modules/libnpmversion": { "version": "6.0.3", + "resolved": "https://registry.npmjs.org/libnpmversion/-/libnpmversion-6.0.3.tgz", + "integrity": "sha512-Kjk1anQ9sPn7E/qF1jXumItvr2OA1914tYWkSTXH9G2rYoY+Ol1+KNrWfGeje2aBvFfKlt4VeKdCfM3yxMXNBw==", "dev": true, "inBundle": true, "license": "ISC", @@ -15664,12 +15860,16 @@ }, "node_modules/npm/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==", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/make-fetch-happen": { "version": "13.0.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.1.tgz", + "integrity": "sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==", "dev": true, "inBundle": true, "license": "ISC", @@ -15693,6 +15893,8 @@ }, "node_modules/npm/node_modules/minimatch": { "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "inBundle": true, "license": "ISC", @@ -15708,6 +15910,8 @@ }, "node_modules/npm/node_modules/minipass": { "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, "inBundle": true, "license": "ISC", @@ -15717,6 +15921,8 @@ }, "node_modules/npm/node_modules/minipass-collect": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", + "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", "dev": true, "inBundle": true, "license": "ISC", @@ -15729,6 +15935,8 @@ }, "node_modules/npm/node_modules/minipass-fetch": { "version": "3.0.5", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.5.tgz", + "integrity": "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==", "dev": true, "inBundle": true, "license": "MIT", @@ -15746,6 +15954,8 @@ }, "node_modules/npm/node_modules/minipass-flush": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", "dev": true, "inBundle": true, "license": "ISC", @@ -15770,6 +15980,8 @@ }, "node_modules/npm/node_modules/minipass-pipeline": { "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", "dev": true, "inBundle": true, "license": "ISC", @@ -15794,6 +16006,8 @@ }, "node_modules/npm/node_modules/minipass-sized": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", "dev": true, "inBundle": true, "license": "ISC", @@ -15818,6 +16032,8 @@ }, "node_modules/npm/node_modules/minizlib": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "dev": true, "inBundle": true, "license": "MIT", @@ -15843,6 +16059,8 @@ }, "node_modules/npm/node_modules/mkdirp": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, "inBundle": true, "license": "MIT", @@ -15855,12 +16073,16 @@ }, "node_modules/npm/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==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/mute-stream": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", "dev": true, "inBundle": true, "license": "ISC", @@ -15870,6 +16092,8 @@ }, "node_modules/npm/node_modules/negotiator": { "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true, "inBundle": true, "license": "MIT", @@ -15879,6 +16103,8 @@ }, "node_modules/npm/node_modules/node-gyp": { "version": "10.2.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.2.0.tgz", + "integrity": "sha512-sp3FonBAaFe4aYTcFdZUn2NYkbP7xroPGYvQmP4Nl5PxamznItBnNCgjrVTKrEfQynInMsJvZrdmqUnysCJ8rw==", "dev": true, "inBundle": true, "license": "MIT", @@ -15903,6 +16129,8 @@ }, "node_modules/npm/node_modules/nopt": { "version": "7.2.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", + "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", "dev": true, "inBundle": true, "license": "ISC", @@ -15918,6 +16146,8 @@ }, "node_modules/npm/node_modules/normalize-package-data": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", + "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", "dev": true, "inBundle": true, "license": "BSD-2-Clause", @@ -15932,6 +16162,8 @@ }, "node_modules/npm/node_modules/npm-audit-report": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/npm-audit-report/-/npm-audit-report-5.0.0.tgz", + "integrity": "sha512-EkXrzat7zERmUhHaoren1YhTxFwsOu5jypE84k6632SXTHcQE1z8V51GC6GVZt8LxkC+tbBcKMUBZAgk8SUSbw==", "dev": true, "inBundle": true, "license": "ISC", @@ -15941,6 +16173,8 @@ }, "node_modules/npm/node_modules/npm-bundled": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.1.tgz", + "integrity": "sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -15953,6 +16187,8 @@ }, "node_modules/npm/node_modules/npm-install-checks": { "version": "6.3.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.3.0.tgz", + "integrity": "sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==", "dev": true, "inBundle": true, "license": "BSD-2-Clause", @@ -15965,6 +16201,8 @@ }, "node_modules/npm/node_modules/npm-normalize-package-bin": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", + "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -15974,6 +16212,8 @@ }, "node_modules/npm/node_modules/npm-package-arg": { "version": "11.0.3", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.3.tgz", + "integrity": "sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw==", "dev": true, "inBundle": true, "license": "ISC", @@ -15989,6 +16229,8 @@ }, "node_modules/npm/node_modules/npm-packlist": { "version": "8.0.2", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-8.0.2.tgz", + "integrity": "sha512-shYrPFIS/JLP4oQmAwDyk5HcyysKW8/JLTEA32S0Z5TzvpaeeX2yMFfoK1fjEBnCBvVyIB/Jj/GBFdm0wsgzbA==", "dev": true, "inBundle": true, "license": "ISC", @@ -16001,6 +16243,8 @@ }, "node_modules/npm/node_modules/npm-pick-manifest": { "version": "9.1.0", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-9.1.0.tgz", + "integrity": "sha512-nkc+3pIIhqHVQr085X9d2JzPzLyjzQS96zbruppqC9aZRm/x8xx6xhI98gHtsfELP2bE+loHq8ZaHFHhe+NauA==", "dev": true, "inBundle": true, "license": "ISC", @@ -16016,6 +16260,8 @@ }, "node_modules/npm/node_modules/npm-profile": { "version": "10.0.0", + "resolved": "https://registry.npmjs.org/npm-profile/-/npm-profile-10.0.0.tgz", + "integrity": "sha512-DXnge3nHYnEnPxmVd/kPmgcXKXwVUqFihGnU+EJUiu5mIOs3awq6zEm0rRp3kSQNhFsoqdLu8L1TIfRyeBOCog==", "dev": true, "inBundle": true, "license": "ISC", @@ -16029,6 +16275,8 @@ }, "node_modules/npm/node_modules/npm-registry-fetch": { "version": "17.1.0", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-17.1.0.tgz", + "integrity": "sha512-5+bKQRH0J1xG1uZ1zMNvxW0VEyoNWgJpY9UDuluPFLKDfJ9u2JmmjmTJV1srBGQOROfdBMiVvnH2Zvpbm+xkVA==", "dev": true, "inBundle": true, "license": "ISC", @@ -16048,6 +16296,8 @@ }, "node_modules/npm/node_modules/npm-user-validate": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/npm-user-validate/-/npm-user-validate-2.0.1.tgz", + "integrity": "sha512-d17PKaF2h8LSGFl5j4b1gHOJt1fgH7YUcCm1kNSJvaLWWKXlBsuUvx0bBEkr0qhsVA9XP5LtRZ83hdlhm2QkgA==", "dev": true, "inBundle": true, "license": "BSD-2-Clause", @@ -16057,6 +16307,8 @@ }, "node_modules/npm/node_modules/p-map": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "dev": true, "inBundle": true, "license": "MIT", @@ -16072,12 +16324,16 @@ }, "node_modules/npm/node_modules/package-json-from-dist": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", "dev": true, "inBundle": true, "license": "BlueOak-1.0.0" }, "node_modules/npm/node_modules/pacote": { "version": "18.0.6", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-18.0.6.tgz", + "integrity": "sha512-+eK3G27SMwsB8kLIuj4h1FUhHtwiEUo21Tw8wNjmvdlpOEr613edv+8FUsTj/4F/VN5ywGE19X18N7CC2EJk6A==", "dev": true, "inBundle": true, "license": "ISC", @@ -16109,6 +16365,8 @@ }, "node_modules/npm/node_modules/parse-conflict-json": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/parse-conflict-json/-/parse-conflict-json-3.0.1.tgz", + "integrity": "sha512-01TvEktc68vwbJOtWZluyWeVGWjP+bZwXtPDMQVbBKzbJ/vZBif0L69KH1+cHv1SZ6e0FKLvjyHe8mqsIqYOmw==", "dev": true, "inBundle": true, "license": "ISC", @@ -16123,6 +16381,8 @@ }, "node_modules/npm/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==", "dev": true, "inBundle": true, "license": "MIT", @@ -16132,6 +16392,8 @@ }, "node_modules/npm/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==", "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", @@ -16148,6 +16410,8 @@ }, "node_modules/npm/node_modules/postcss-selector-parser": { "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", "dev": true, "inBundle": true, "license": "MIT", @@ -16161,6 +16425,8 @@ }, "node_modules/npm/node_modules/proc-log": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", + "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", "dev": true, "inBundle": true, "license": "ISC", @@ -16170,6 +16436,8 @@ }, "node_modules/npm/node_modules/proggy": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/proggy/-/proggy-2.0.0.tgz", + "integrity": "sha512-69agxLtnI8xBs9gUGqEnK26UfiexpHy+KUpBQWabiytQjnn5wFY8rklAi7GRfABIuPNnQ/ik48+LGLkYYJcy4A==", "dev": true, "inBundle": true, "license": "ISC", @@ -16179,6 +16447,8 @@ }, "node_modules/npm/node_modules/promise-all-reject-late": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz", + "integrity": "sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==", "dev": true, "inBundle": true, "license": "ISC", @@ -16197,12 +16467,16 @@ }, "node_modules/npm/node_modules/promise-inflight": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/promise-retry": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", "dev": true, "inBundle": true, "license": "MIT", @@ -16216,6 +16490,8 @@ }, "node_modules/npm/node_modules/promzard": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/promzard/-/promzard-1.0.2.tgz", + "integrity": "sha512-2FPputGL+mP3jJ3UZg/Dl9YOkovB7DX0oOr+ck5QbZ5MtORtds8k/BZdn+02peDLI8/YWbmzx34k5fA+fHvCVQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -16228,6 +16504,8 @@ }, "node_modules/npm/node_modules/qrcode-terminal": { "version": "0.12.0", + "resolved": "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz", + "integrity": "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ==", "dev": true, "inBundle": true, "bin": { @@ -16236,6 +16514,8 @@ }, "node_modules/npm/node_modules/read": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/read/-/read-3.0.1.tgz", + "integrity": "sha512-SLBrDU/Srs/9EoWhU5GdbAoxG1GzpQHo/6qiGItaoLJ1thmYpcNIM1qISEUvyHBzfGlWIyd6p2DNi1oV1VmAuw==", "dev": true, "inBundle": true, "license": "ISC", @@ -16248,6 +16528,8 @@ }, "node_modules/npm/node_modules/read-cmd-shim": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-4.0.0.tgz", + "integrity": "sha512-yILWifhaSEEytfXI76kB9xEEiG1AiozaCJZ83A87ytjRiN+jVibXjedjCRNjoZviinhG+4UkalO3mWTd8u5O0Q==", "dev": true, "inBundle": true, "license": "ISC", @@ -16257,6 +16539,8 @@ }, "node_modules/npm/node_modules/read-package-json-fast": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", + "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", "dev": true, "inBundle": true, "license": "ISC", @@ -16270,6 +16554,8 @@ }, "node_modules/npm/node_modules/retry": { "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", "dev": true, "inBundle": true, "license": "MIT", @@ -16279,6 +16565,8 @@ }, "node_modules/npm/node_modules/safer-buffer": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "inBundle": true, "license": "MIT", @@ -16286,6 +16574,8 @@ }, "node_modules/npm/node_modules/semver": { "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, "inBundle": true, "license": "ISC", @@ -16298,6 +16588,8 @@ }, "node_modules/npm/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==", "dev": true, "inBundle": true, "license": "MIT", @@ -16310,6 +16602,8 @@ }, "node_modules/npm/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==", "dev": true, "inBundle": true, "license": "MIT", @@ -16319,6 +16613,8 @@ }, "node_modules/npm/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==", "dev": true, "inBundle": true, "license": "ISC", @@ -16331,6 +16627,8 @@ }, "node_modules/npm/node_modules/sigstore": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-2.3.1.tgz", + "integrity": "sha512-8G+/XDU8wNsJOQS5ysDVO0Etg9/2uA5gR9l4ZwijjlwxBcrU6RPfwi2+jJmbP+Ap1Hlp/nVAaEO4Fj22/SL2gQ==", "dev": true, "inBundle": true, "license": "Apache-2.0", @@ -16348,6 +16646,8 @@ }, "node_modules/npm/node_modules/smart-buffer": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "dev": true, "inBundle": true, "license": "MIT", @@ -16358,6 +16658,8 @@ }, "node_modules/npm/node_modules/socks": { "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", "dev": true, "inBundle": true, "license": "MIT", @@ -16372,6 +16674,8 @@ }, "node_modules/npm/node_modules/socks-proxy-agent": { "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", "dev": true, "inBundle": true, "license": "MIT", @@ -16386,6 +16690,8 @@ }, "node_modules/npm/node_modules/spdx-correct": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, "inBundle": true, "license": "Apache-2.0", @@ -16406,12 +16712,16 @@ }, "node_modules/npm/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==", "dev": true, "inBundle": true, "license": "CC-BY-3.0" }, "node_modules/npm/node_modules/spdx-expression-parse": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", + "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", "dev": true, "inBundle": true, "license": "MIT", @@ -16428,12 +16738,16 @@ }, "node_modules/npm/node_modules/sprintf-js": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", "dev": true, "inBundle": true, "license": "BSD-3-Clause" }, "node_modules/npm/node_modules/ssri": { "version": "10.0.6", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", + "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -16446,6 +16760,8 @@ }, "node_modules/npm/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==", "dev": true, "inBundle": true, "license": "MIT", @@ -16461,6 +16777,8 @@ "node_modules/npm/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==", "dev": true, "inBundle": true, "license": "MIT", @@ -16475,6 +16793,8 @@ }, "node_modules/npm/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==", "dev": true, "inBundle": true, "license": "MIT", @@ -16488,6 +16808,8 @@ "node_modules/npm/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==", "dev": true, "inBundle": true, "license": "MIT", @@ -16500,6 +16822,8 @@ }, "node_modules/npm/node_modules/supports-color": { "version": "9.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", + "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", "dev": true, "inBundle": true, "license": "MIT", @@ -16512,6 +16836,8 @@ }, "node_modules/npm/node_modules/tar": { "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "dev": true, "inBundle": true, "license": "ISC", @@ -16562,18 +16888,24 @@ }, "node_modules/npm/node_modules/text-table": { "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/tiny-relative-date": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tiny-relative-date/-/tiny-relative-date-1.3.0.tgz", + "integrity": "sha512-MOQHpzllWxDCHHaDno30hhLfbouoYlOI8YlMNtvKe1zXbjEVhbcEovQxvZrPvtiYW630GQDoMMarCnjfyfHA+A==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/treeverse": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/treeverse/-/treeverse-3.0.0.tgz", + "integrity": "sha512-gcANaAnd2QDZFmHFEOF4k7uc1J/6a6z3DJMd/QwEyxLoKGiptJRwid582r7QIsFlFMIZ3SnxfS52S4hm2DHkuQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -16583,6 +16915,8 @@ }, "node_modules/npm/node_modules/tuf-js": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-2.2.1.tgz", + "integrity": "sha512-GwIJau9XaA8nLVbUXsN3IlFi7WmQ48gBUrl3FTkkL/XLu/POhBzfmX9hd33FNMX1qAsfl6ozO1iMmW9NC8YniA==", "dev": true, "inBundle": true, "license": "MIT", @@ -16597,6 +16931,8 @@ }, "node_modules/npm/node_modules/unique-filename": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", + "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", "dev": true, "inBundle": true, "license": "ISC", @@ -16609,6 +16945,8 @@ }, "node_modules/npm/node_modules/unique-slug": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", + "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -16621,12 +16959,16 @@ }, "node_modules/npm/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==", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/validate-npm-package-license": { "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==", "dev": true, "inBundle": true, "license": "Apache-2.0", @@ -16647,6 +16989,8 @@ }, "node_modules/npm/node_modules/validate-npm-package-name": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", + "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -16656,12 +17000,16 @@ }, "node_modules/npm/node_modules/walk-up-path": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-3.0.1.tgz", + "integrity": "sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/npm/node_modules/which": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", "dev": true, "inBundle": true, "license": "ISC", @@ -16686,6 +17034,8 @@ }, "node_modules/npm/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==", "dev": true, "inBundle": true, "license": "MIT", @@ -16704,6 +17054,8 @@ "node_modules/npm/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==", "dev": true, "inBundle": true, "license": "MIT", @@ -16748,6 +17100,8 @@ }, "node_modules/npm/node_modules/wrap-ansi/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==", "dev": true, "inBundle": true, "license": "MIT" @@ -16771,6 +17125,8 @@ }, "node_modules/npm/node_modules/wrap-ansi/node_modules/strip-ansi": { "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "inBundle": true, "license": "MIT", @@ -16786,6 +17142,8 @@ }, "node_modules/npm/node_modules/write-file-atomic": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", "dev": true, "inBundle": true, "license": "ISC", @@ -16799,6 +17157,8 @@ }, "node_modules/npm/node_modules/yallist": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true, "inBundle": true, "license": "ISC" diff --git a/src/constants.ts b/src/constants.ts index cff4a16c..f8f6bac5 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -18,6 +18,13 @@ export const GossipsubIDv10 = '/meshsub/1.0.0' */ export const GossipsubIDv11 = '/meshsub/1.1.0' +/** + * The protocol ID for version 1.2.0 of the Gossipsub protocol + * See the spec for details about how v1.2.0 compares to v1.1.0: + * https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.2.md + */ +export const GossipsubIDv12 = '/meshsub/1.2.0' + // Overlay parameters /** @@ -249,3 +256,6 @@ export const DEFAULT_METRIC_MESH_MESSAGE_DELIVERIES_WINDOWS = 1000 /** Wait for 1 more heartbeats before clearing a backoff */ export const BACKOFF_SLACK = 1 + +export const GossipsubIdontwantMinDataSize = 512 +export const GossipsubIdontwantMaxMessages = 512 diff --git a/src/index.ts b/src/index.ts index 6c27ed11..d9b0445b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -88,7 +88,7 @@ type ReceivedMessageResult = | ({ code: MessageStatus.invalid, msgIdStr?: MsgIdStr } & RejectReasonObj) | { code: MessageStatus.valid, messageId: MessageId, msg: Message } -export const multicodec: string = constants.GossipsubIDv11 +export const multicodec: string = constants.GossipsubIDv12 export interface GossipsubOpts extends GossipsubOptsSpec, PubSubInit { /** if dial should fallback to floodsub */ @@ -211,6 +211,20 @@ export interface GossipsubOpts extends GossipsubOptsSpec, PubSubInit { * It should be a number between 0 and 1, with a reasonable default of 0.25 */ gossipFactor: number + + /** + * The minimum message size in bytes to be considered for sending IDONTWANT messages + * + * @default 512 + */ + idontwantMinDataSize?: number + + /** + * The maximum number of IDONTWANT messages per heartbeat per peer + * + * @default 512 + */ + idontwantMaxMessages?: number } export interface GossipsubMessage { @@ -274,7 +288,7 @@ export class GossipSub extends TypedEventEmitter implements Pub * The signature policy to follow by default */ public readonly globalSignaturePolicy: typeof StrictSign | typeof StrictNoSign - public multicodecs: string[] = [constants.GossipsubIDv11, constants.GossipsubIDv10] + public multicodecs: string[] = [constants.GossipsubIDv12, constants.GossipsubIDv11, constants.GossipsubIDv10] private publishConfig: PublishConfig | undefined @@ -409,11 +423,24 @@ export class GossipSub extends TypedEventEmitter implements Pub */ readonly gossipTracer: IWantTracer + /** + * Tracks IDONTWANT messages received by peers in the current heartbeat + */ + private readonly idontwantCounts = new Map() + + /** + * Tracks IDONTWANT messages received by peers and the heartbeat they were received in + * + * idontwants are stored for `mcacheLength` heartbeats before being pruned, + * so this map is bounded by peerCount * idontwantMaxMessages * mcacheLength + */ + private readonly idontwants = new Map>() + private readonly components: GossipSubComponents private directPeerInitial: ReturnType | null = null - public static multicodec: string = constants.GossipsubIDv11 + public static multicodec: string = constants.GossipsubIDv12 // Options readonly opts: Required @@ -462,6 +489,8 @@ export class GossipSub extends TypedEventEmitter implements Pub opportunisticGraftTicks: constants.GossipsubOpportunisticGraftTicks, directConnectTicks: constants.GossipsubDirectConnectTicks, gossipFactor: constants.GossipsubGossipFactor, + idontwantMinDataSize: constants.GossipsubIdontwantMinDataSize, + idontwantMaxMessages: constants.GossipsubIdontwantMaxMessages, ...options, scoreParams: createPeerScoreParams(options.scoreParams), scoreThresholds: createPeerScoreThresholds(options.scoreThresholds) @@ -750,6 +779,8 @@ export class GossipSub extends TypedEventEmitter implements Pub this.seenCache.clear() if (this.fastMsgIdCache != null) this.fastMsgIdCache.clear() if (this.directPeerInitial != null) clearTimeout(this.directPeerInitial) + this.idontwantCounts.clear() + this.idontwants.clear() this.log('stopped') } @@ -956,6 +987,9 @@ export class GossipSub extends TypedEventEmitter implements Pub this.control.delete(id) // Remove from backoff mapping this.outbound.delete(id) + // Remove from idontwant tracking + this.idontwantCounts.delete(id) + this.idontwants.delete(id) // Remove from peer scoring this.score.removePeer(id) @@ -1019,6 +1053,10 @@ export class GossipSub extends TypedEventEmitter implements Pub prune: this.decodeRpcLimits.maxControlMessages, prune$: { peers: this.decodeRpcLimits.maxPeerInfos + }, + idontwant: this.decodeRpcLimits.maxControlMessages, + idontwant$: { + messageIDs: this.decodeRpcLimits.maxIdontwantMessageIDs } } } @@ -1310,6 +1348,11 @@ export class GossipSub extends TypedEventEmitter implements Pub this.seenCache.put(msgIdStr) } + // possibly send IDONTWANTs to mesh peers + if ((rpcMsg.data?.length ?? 0) >= this.opts.idontwantMinDataSize) { + this.sendIDontWants(msgId, rpcMsg.topic, propagationSource.toString()) + } + // (Optional) Provide custom validation here with dynamic validators per topic // NOTE: This custom topicValidator() must resolve fast (< 100ms) to allow scores // to not penalize peers for long validation times. @@ -1359,10 +1402,11 @@ export class GossipSub extends TypedEventEmitter implements Pub return } - const iwant = (controlMsg.ihave != null) ? this.handleIHave(id, controlMsg.ihave) : [] - const ihave = (controlMsg.iwant != null) ? this.handleIWant(id, controlMsg.iwant) : [] - const prune = (controlMsg.graft != null) ? await this.handleGraft(id, controlMsg.graft) : [] - ;(controlMsg.prune != null) && (await this.handlePrune(id, controlMsg.prune)) + const iwant = (controlMsg.ihave?.length > 0) ? this.handleIHave(id, controlMsg.ihave) : [] + const ihave = (controlMsg.iwant?.length > 0) ? this.handleIWant(id, controlMsg.iwant) : [] + const prune = (controlMsg.graft?.length > 0) ? await this.handleGraft(id, controlMsg.graft) : [] + ;(controlMsg.prune?.length > 0) && (await this.handlePrune(id, controlMsg.prune)) + ;(controlMsg.idontwant?.length > 0) && this.handleIdontwant(id, controlMsg.idontwant) if ((iwant.length === 0) && (ihave.length === 0) && (prune.length === 0)) { return @@ -1691,6 +1735,39 @@ export class GossipSub extends TypedEventEmitter implements Pub } } + private handleIdontwant (id: PeerIdStr, idontwant: RPC.ControlIDontWant[]): void { + let idontwantCount = this.idontwantCounts.get(id) ?? 0 + // return early if we have already received too many IDONTWANT messages from the peer + if (idontwantCount >= this.opts.idontwantMaxMessages) { + return + } + const startIdontwantCount = idontwantCount + + let idontwants = this.idontwants.get(id) + if (idontwants == null) { + idontwants = new Map() + this.idontwants.set(id, idontwants) + } + let idonthave = 0 + // eslint-disable-next-line no-labels + out: for (const { messageIDs } of idontwant) { + for (const msgId of messageIDs) { + if (idontwantCount >= this.opts.idontwantMaxMessages) { + // eslint-disable-next-line no-labels + break out + } + idontwantCount++ + + const msgIdStr = this.msgIdToStrFn(msgId) + idontwants.set(msgIdStr, this.heartbeatTicks) + if (!this.mcache.msgs.has(msgIdStr)) idonthave++ + } + } + this.idontwantCounts.set(id, idontwantCount) + const total = idontwantCount - startIdontwantCount + this.metrics?.onIdontwantRcv(total, idonthave) + } + /** * Add standard backoff log for a peer in a topic */ @@ -2353,6 +2430,27 @@ export class GossipSub extends TypedEventEmitter implements Pub this.sendRpc(id, out) } + private sendIDontWants (msgId: Uint8Array, topic: string, source: PeerIdStr): void { + const ids = this.mesh.get(topic) + if (ids == null) { + return + } + + // don't send IDONTWANT to: + // - the source + // - peers that don't support v1.2 + const tosend = new Set(ids) + tosend.delete(source) + for (const id of tosend) { + if (this.streamsOutbound.get(id)?.protocol !== constants.GossipsubIDv12) { + tosend.delete(id) + } + } + + const idontwantRpc = createGossipRpc([], { idontwant: [{ messageIDs: [msgId] }] }) + this.sendRpcInBatch(tosend, idontwantRpc) + } + /** * Send an rpc object to a peer */ @@ -2701,6 +2799,18 @@ export class GossipSub extends TypedEventEmitter implements Pub // apply IWANT request penalties this.applyIwantPenalties() + // clean up IDONTWANT counters + this.idontwantCounts.clear() + + // clean up old tracked IDONTWANTs + for (const idontwants of this.idontwants.values()) { + for (const [msgId, heartbeatTick] of idontwants) { + if (this.heartbeatTicks - heartbeatTick >= this.opts.mcacheLength) { + idontwants.delete(msgId) + } + } + } + // ensure direct peers are connected if (this.heartbeatTicks % this.opts.directConnectTicks === 0) { // we only do this every few ticks to allow pending connections to complete and account for restarts/downtime @@ -3069,6 +3179,12 @@ export class GossipSub extends TypedEventEmitter implements Pub } metrics.cacheSize.set({ cache: 'backoff' }, backoffSize) + let idontwantsCount = 0 + for (const idontwant of this.idontwants.values()) { + idontwantsCount += idontwant.size + } + metrics.cacheSize.set({ cache: 'idontwants' }, idontwantsCount) + // Peer counts for (const [topicStr, peers] of this.topics) { diff --git a/src/message/decodeRpc.ts b/src/message/decodeRpc.ts index dc9579c6..7b9ecd99 100644 --- a/src/message/decodeRpc.ts +++ b/src/message/decodeRpc.ts @@ -3,6 +3,7 @@ export interface DecodeRPCLimits { maxMessages: number maxIhaveMessageIDs: number maxIwantMessageIDs: number + maxIdontwantMessageIDs: number maxControlMessages: number maxPeerInfos: number } @@ -12,6 +13,7 @@ export const defaultDecodeRpcLimits: DecodeRPCLimits = { maxMessages: Infinity, maxIhaveMessageIDs: Infinity, maxIwantMessageIDs: Infinity, + maxIdontwantMessageIDs: Infinity, maxControlMessages: Infinity, maxPeerInfos: Infinity } diff --git a/src/message/rpc.proto b/src/message/rpc.proto index daefc676..efe8fafe 100644 --- a/src/message/rpc.proto +++ b/src/message/rpc.proto @@ -24,6 +24,7 @@ message RPC { repeated ControlIWant iwant = 2; repeated ControlGraft graft = 3; repeated ControlPrune prune = 4; + repeated ControlIDontWant idontwant = 5; } message ControlIHave { @@ -49,4 +50,9 @@ message RPC { optional bytes peerID = 1; optional bytes signedPeerRecord = 2; } + + message ControlIDontWant { + repeated bytes messageIDs = 1; + } + } \ No newline at end of file diff --git a/src/message/rpc.ts b/src/message/rpc.ts index 32990a74..660bbbd8 100644 --- a/src/message/rpc.ts +++ b/src/message/rpc.ts @@ -197,6 +197,7 @@ export namespace RPC { iwant: RPC.ControlIWant[] graft: RPC.ControlGraft[] prune: RPC.ControlPrune[] + idontwant: RPC.ControlIDontWant[] } export namespace ControlMessage { @@ -237,6 +238,13 @@ export namespace RPC { } } + if (obj.idontwant != null) { + for (const value of obj.idontwant) { + w.uint32(42) + RPC.ControlIDontWant.codec().encode(value, w) + } + } + if (opts.lengthDelimited !== false) { w.ldelim() } @@ -245,7 +253,8 @@ export namespace RPC { ihave: [], iwant: [], graft: [], - prune: [] + prune: [], + idontwant: [] } const end = length == null ? reader.len : reader.pos + length @@ -294,6 +303,16 @@ export namespace RPC { })) break } + case 5: { + if (opts.limits?.idontwant != null && obj.idontwant.length === opts.limits.idontwant) { + throw new MaxLengthError('Decode error - map field "idontwant" had too many elements') + } + + obj.idontwant.push(RPC.ControlIDontWant.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.idontwant$ + })) + break + } default: { reader.skipType(tag & 7) break @@ -673,6 +692,72 @@ export namespace RPC { } } + export interface ControlIDontWant { + messageIDs: Uint8Array[] + } + + export namespace ControlIDontWant { + let _codec: Codec + + export const codec = (): Codec => { + if (_codec == null) { + _codec = message((obj, w, opts = {}) => { + if (opts.lengthDelimited !== false) { + w.fork() + } + + if (obj.messageIDs != null) { + for (const value of obj.messageIDs) { + w.uint32(10) + w.bytes(value) + } + } + + if (opts.lengthDelimited !== false) { + w.ldelim() + } + }, (reader, length, opts = {}) => { + const obj: any = { + messageIDs: [] + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + if (opts.limits?.messageIDs != null && obj.messageIDs.length === opts.limits.messageIDs) { + throw new MaxLengthError('Decode error - map field "messageIDs" had too many elements') + } + + obj.messageIDs.push(reader.bytes()) + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + + return obj + }) + } + + return _codec + } + + export const encode = (obj: Partial): Uint8Array => { + return encodeMessage(obj, ControlIDontWant.codec()) + } + + export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): ControlIDontWant => { + return decodeMessage(buf, ControlIDontWant.codec(), opts) + } + } + let _codec: Codec export const codec = (): Codec => { diff --git a/src/metrics.ts b/src/metrics.ts index d098f03a..afba2e7b 100644 --- a/src/metrics.ts +++ b/src/metrics.ts @@ -259,7 +259,7 @@ export function getMetrics ( /* General Metrics */ /** - * Gossipsub supports floodsub, gossipsub v1.0 and gossipsub v1.1. Peers are classified based + * Gossipsub supports floodsub, gossipsub v1.0, v1.1, and v1.2. Peers are classified based * on which protocol they support. This metric keeps track of the number of peers that are * connected of each type. */ peersPerProtocol: register.gauge<{ protocol: string }>({ @@ -361,6 +361,7 @@ export function getMetrics ( rpcSentIWant: register.gauge({ name: 'gossipsub_rpc_sent_iwant_total', help: 'RPC sent' }), rpcSentGraft: register.gauge({ name: 'gossipsub_rpc_sent_graft_total', help: 'RPC sent' }), rpcSentPrune: register.gauge({ name: 'gossipsub_rpc_sent_prune_total', help: 'RPC sent' }), + rpcSentIDontWant: register.gauge({ name: 'gossipsub_rpc_sent_idontwant_total', help: 'RPC sent' }), // publish message. Track peers sent to and bytes /** Total count of msg published by topic */ @@ -592,6 +593,16 @@ export function getMetrics ( name: 'gossipsub_iwant_rcv_dont_have_msgids_total', help: 'Total requested messageIDs that we do not have' }), + /** Total received IDONTWANT messages */ + idontwantRcvMsgids: register.gauge({ + name: 'gossipsub_idontwant_rcv_msgids_total', + help: 'Total received IDONTWANT messages' + }), + /** Total received IDONTWANT messageIDs that we don't have */ + idontwantRcvDonthaveMsgids: register.gauge({ + name: 'gossipsub_idontwant_rcv_dont_have_msgids_total', + help: 'Total received IDONTWANT messageIDs that we do not have in mcache' + }), iwantPromiseStarted: register.gauge({ name: 'gossipsub_iwant_promise_sent_total', help: 'Total count of started IWANT promises' @@ -808,6 +819,11 @@ export function getMetrics ( this.iwantRcvDonthaveMsgids.inc(iwantDonthave) }, + onIdontwantRcv (idontwant: number, idontwantDonthave: number): void { + this.idontwantRcvMsgids.inc(idontwant) + this.idontwantRcvDonthaveMsgids.inc(idontwantDonthave) + }, + onForwardMsg (topicStr: TopicStr, tosendCount: number): void { const topic = this.toTopic(topicStr) this.msgForwardCount.inc({ topic }, 1) @@ -917,11 +933,13 @@ export function getMetrics ( const iwant = rpc.control.iwant?.length ?? 0 const graft = rpc.control.graft?.length ?? 0 const prune = rpc.control.prune?.length ?? 0 + const idontwant = rpc.control.idontwant?.length ?? 0 if (ihave > 0) this.rpcSentIHave.inc(ihave) if (iwant > 0) this.rpcSentIWant.inc(iwant) if (graft > 0) this.rpcSentGraft.inc(graft) if (prune > 0) this.rpcSentPrune.inc(prune) - if (ihave > 0 || iwant > 0 || graft > 0 || prune > 0) this.rpcSentControl.inc(1) + if (idontwant > 0) this.rpcSentIDontWant.inc(idontwant) + if (ihave > 0 || iwant > 0 || graft > 0 || prune > 0 || idontwant > 0) this.rpcSentControl.inc(1) } }, diff --git a/src/utils/create-gossip-rpc.ts b/src/utils/create-gossip-rpc.ts index 9ba7891e..efd59fcb 100644 --- a/src/utils/create-gossip-rpc.ts +++ b/src/utils/create-gossip-rpc.ts @@ -12,7 +12,8 @@ export function createGossipRpc (messages: RPC.Message[] = [], control?: Partial graft: control.graft ?? [], prune: control.prune ?? [], ihave: control.ihave ?? [], - iwant: control.iwant ?? [] + iwant: control.iwant ?? [], + idontwant: control.idontwant ?? [] } : undefined } @@ -24,7 +25,8 @@ export function ensureControl (rpc: RPC): Required { graft: [], prune: [], ihave: [], - iwant: [] + iwant: [], + idontwant: [] } } diff --git a/test/e2e/go-gossipsub.spec.ts b/test/e2e/go-gossipsub.spec.ts index ebb81e87..190b6c4c 100644 --- a/test/e2e/go-gossipsub.spec.ts +++ b/test/e2e/go-gossipsub.spec.ts @@ -1201,7 +1201,8 @@ describe('go-libp2p-pubsub gossipsub tests', function () { graft: [toGraft(topic1), toGraft(topic2), toGraft(topic3)], prune: [toPrune(topic1), toPrune(topic2), toPrune(topic3)], ihave: [], - iwant: [] + iwant: [], + idontwant: [] }) const expectedRpc: RPC = { @@ -1211,7 +1212,8 @@ describe('go-libp2p-pubsub gossipsub tests', function () { graft: [toGraft(topic1)], prune: [toPrune(topic2), toPrune(topic3)], ihave: [], - iwant: [] + iwant: [], + idontwant: [] } } diff --git a/test/gossip.spec.ts b/test/gossip.spec.ts index ffe195ad..e656f4d1 100644 --- a/test/gossip.spec.ts +++ b/test/gossip.spec.ts @@ -7,6 +7,7 @@ import { expect } from 'aegir/chai' import { pEvent } from 'p-event' import sinon, { type SinonStubbedInstance } from 'sinon' import { stubInterface } from 'sinon-ts' +import { concat } from 'uint8arrays' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import { GossipsubDhi } from '../src/constants.js' import { GossipSub } from '../src/index.js' @@ -28,7 +29,8 @@ describe('gossip', () => { IPColocationFactorThreshold: GossipsubDhi + 3 }, maxInboundDataLength: 4000000, - allowPublishToZeroTopicPeers: false + allowPublishToZeroTopicPeers: false, + idontwantMaxMessages: 10 } }) }) @@ -84,6 +86,112 @@ describe('gossip', () => { nodeASpy.pushGossip.restore() }) + it('should send idontwant to peers in topic', async function () { + // This test checks that idontwants and idontwantsCounts are correctly incrmemented + // - idontwantCounts should track the number of idontwant messages received from a peer for a single heartbeat + // - it should increment on receive of idontwant msgs (up to limit) + // - it should be emptied after heartbeat + // - idontwants should track the idontwant messages received from a peer along with the heartbeatId when received + // - it should increment on receive of idontwant msgs (up to limit) + // - it should be emptied after mcacheLength heartbeats + this.timeout(10e4) + const nodeA = nodes[0] + const otherNodes = nodes.slice(1) + const topic = 'Z' + const idontwantMaxMessages = nodeA.pubsub.opts.idontwantMaxMessages + const idontwantMinDataSize = nodeA.pubsub.opts.idontwantMinDataSize + + const subscriptionPromises = nodes.map(async (n) => pEvent(n.pubsub, 'subscription-change')) + // add subscriptions to each node + nodes.forEach((n) => { n.pubsub.subscribe(topic) }) + + // every node connected to every other + await connectAllPubSubNodes(nodes) + + // wait for subscriptions to be transmitted + await Promise.all(subscriptionPromises) + + // await mesh rebalancing + await Promise.all(nodes.map(async (n) => pEvent(n.pubsub, 'gossipsub:heartbeat'))) + + // publish a bunch of messages, enough to fill up our idontwant caches + for (let i = 0; i < idontwantMaxMessages * 2; i++) { + const msg = concat([ + uint8ArrayFromString(i.toString()), + new Uint8Array(idontwantMinDataSize) + ]) + await nodeA.pubsub.publish(topic, msg) + } + // track the heartbeat when each node received the last message + // eslint-disable-next-line @typescript-eslint/dot-notation + const ticks = otherNodes.map((n) => n.pubsub['heartbeatTicks']) + + // there's no event currently implemented to await, so just wait a bit - flaky :( + // TODO figure out something more robust + await new Promise((resolve) => setTimeout(resolve, 200)) + + // other nodes should have received idontwant messages + // check that idontwants <= GossipsubIdontwantMaxMessages + for (let i = 0; i < otherNodes.length; i++) { + const node = otherNodes[i] + // eslint-disable-next-line @typescript-eslint/dot-notation + const currentTick = node.pubsub['heartbeatTicks'] + + // eslint-disable-next-line @typescript-eslint/dot-notation + const idontwantCounts = node.pubsub['idontwantCounts'] + let minCount = Infinity + let maxCount = 0 + for (const count of idontwantCounts.values()) { + minCount = Math.min(minCount, count) + maxCount = Math.max(maxCount, count) + } + // expect(minCount).to.be.greaterThan(0) + expect(maxCount).to.be.lessThanOrEqual(idontwantMaxMessages) + + // eslint-disable-next-line @typescript-eslint/dot-notation + const idontwants = node.pubsub['idontwants'] + let minIdontwants = Infinity + let maxIdontwants = 0 + for (const idontwant of idontwants.values()) { + minIdontwants = Math.min(minIdontwants, idontwant.size) + maxIdontwants = Math.max(maxIdontwants, idontwant.size) + } + // expect(minIdontwants).to.be.greaterThan(0) + expect(maxIdontwants).to.be.lessThanOrEqual(idontwantMaxMessages) + + // sanity check that the idontwantCount matches idontwants.size + // only the case if there hasn't been a heartbeat + if (currentTick === ticks[i]) { + expect(minCount).to.be.equal(minIdontwants) + expect(maxCount).to.be.equal(maxIdontwants) + } + } + + await Promise.all(otherNodes.map(async (n) => pEvent(n.pubsub, 'gossipsub:heartbeat'))) + + // after a heartbeat + // idontwants are still tracked + // but idontwantCounts have been cleared + for (const node of nodes) { + // eslint-disable-next-line @typescript-eslint/dot-notation + const idontwantCounts = node.pubsub['idontwantCounts'] + for (const count of idontwantCounts.values()) { + expect(count).to.be.equal(0) + } + + // eslint-disable-next-line @typescript-eslint/dot-notation + const idontwants = node.pubsub['idontwants'] + let minIdontwants = Infinity + let maxIdontwants = 0 + for (const idontwant of idontwants.values()) { + minIdontwants = Math.min(minIdontwants, idontwant.size) + maxIdontwants = Math.max(maxIdontwants, idontwant.size) + } + // expect(minIdontwants).to.be.greaterThan(0) + expect(maxIdontwants).to.be.lessThanOrEqual(idontwantMaxMessages) + } + }) + it('Should allow publishing to zero peers if flag is passed', async function () { this.timeout(10e4) const nodeA = nodes[0] @@ -245,7 +353,7 @@ describe('gossip', () => { // set spy. NOTE: Forcing private property to be public const nodeASpy = sinon.spy(nodeA.pubsub, 'piggybackControl') // manually add control message to be sent to peerB - const graft = { ihave: [], iwant: [], graft: [{ topicID: topic }], prune: [] } + const graft = { ihave: [], iwant: [], graft: [{ topicID: topic }], prune: [], idontwant: [] } ;(nodeA.pubsub).control.set(peerB, graft) ;(nodeA.pubsub).gossip.set(peerB, [])