diff --git a/package-lock.json b/package-lock.json index 69e24ee..e1ec05c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,7 +28,7 @@ "prettier": "3.3.3", "react": "^18.3.1", "react-dom": "^18.3.1", - "semantic-release": "^23.1.1", + "semantic-release": "^24.0.0", "ts-jest": "^29.2.3", "ts-node": "^10.9.2", "typescript": "^5.5.4", @@ -635,70 +635,6 @@ "rxjs": "^7.8.1" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@esbuild/darwin-arm64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", @@ -715,294 +651,6 @@ "node": ">=12" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -2254,6 +1902,7 @@ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -2267,6 +1916,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -2293,6 +1943,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -2306,6 +1957,7 @@ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -2319,6 +1971,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -2332,6 +1985,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -2345,6 +1999,7 @@ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -2371,6 +2026,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -2384,6 +2040,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -2397,6 +2054,7 @@ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -2410,6 +2068,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -2594,15 +2253,16 @@ } }, "node_modules/@semantic-release/commit-analyzer": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@semantic-release/commit-analyzer/-/commit-analyzer-12.0.0.tgz", - "integrity": "sha512-qG+md5gdes+xa8zP7lIo1fWE17zRdO8yMCaxh9lyL65TQleoSv8WHHOqRURfghTytUh+NpkSyBprQ5hrkxOKVQ==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/commit-analyzer/-/commit-analyzer-13.0.0.tgz", + "integrity": "sha512-KtXWczvTAB1ZFZ6B4O+w8HkfYm/OgQb1dUGNFZtDgQ0csggrmkq8sTxhd+lwGF8kMb59/RnG9o4Tn7M/I8dQ9Q==", "dev": true, "license": "MIT", "dependencies": { - "conventional-changelog-angular": "^7.0.0", - "conventional-commits-filter": "^4.0.0", - "conventional-commits-parser": "^5.0.0", + "conventional-changelog-angular": "^8.0.0", + "conventional-changelog-writer": "^8.0.0", + "conventional-commits-filter": "^5.0.0", + "conventional-commits-parser": "^6.0.0", "debug": "^4.0.0", "import-from-esm": "^1.0.3", "lodash-es": "^4.17.21", @@ -3034,22 +2694,22 @@ "dev": true }, "node_modules/@semantic-release/release-notes-generator": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@semantic-release/release-notes-generator/-/release-notes-generator-13.0.0.tgz", - "integrity": "sha512-LEeZWb340keMYuREMyxrODPXJJ0JOL8D/mCl74B4LdzbxhtXV2LrPN2QBEcGJrlQhoqLO0RhxQb6masHytKw+A==", + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/@semantic-release/release-notes-generator/-/release-notes-generator-14.0.1.tgz", + "integrity": "sha512-K0w+5220TM4HZTthE5dDpIuFrnkN1NfTGPidJFm04ULT1DEZ9WG89VNXN7F0c+6nMEpWgqmPvb7vY7JkB2jyyA==", "dev": true, "license": "MIT", "dependencies": { - "conventional-changelog-angular": "^7.0.0", - "conventional-changelog-writer": "^7.0.0", - "conventional-commits-filter": "^4.0.0", - "conventional-commits-parser": "^5.0.0", + "conventional-changelog-angular": "^8.0.0", + "conventional-changelog-writer": "^8.0.0", + "conventional-commits-filter": "^5.0.0", + "conventional-commits-parser": "^6.0.0", "debug": "^4.0.0", "get-stream": "^7.0.0", "import-from-esm": "^1.0.3", "into-stream": "^7.0.0", "lodash-es": "^4.17.21", - "read-pkg-up": "^11.0.0" + "read-package-up": "^11.0.0" }, "engines": { "node": ">=20.8.1" @@ -3597,6 +3257,13 @@ "@types/react": "*" } }, + "node_modules/@types/semver": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -4610,37 +4277,36 @@ } }, "node_modules/conventional-changelog-angular": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", - "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-8.0.0.tgz", + "integrity": "sha512-CLf+zr6St0wIxos4bmaKHRXWAcsCXrJU6F4VdNDrGRK3B8LDLKoX3zuMV5GhtbGkVR/LohZ6MT6im43vZLSjmA==", "dev": true, "license": "ISC", "dependencies": { "compare-func": "^2.0.0" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/conventional-changelog-writer": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-7.0.1.tgz", - "integrity": "sha512-Uo+R9neH3r/foIvQ0MKcsXkX642hdm9odUp7TqgFS7BsalTcjzRlIfWZrZR1gbxOozKucaKt5KAbjW8J8xRSmA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-8.0.0.tgz", + "integrity": "sha512-TQcoYGRatlAnT2qEWDON/XSfnVG38JzA7E0wcGScu7RElQBkg9WWgZd1peCWFcWDh1xfb2CfsrcvOn1bbSzztA==", "dev": true, "license": "MIT", "dependencies": { - "conventional-commits-filter": "^4.0.0", + "@types/semver": "^7.5.5", + "conventional-commits-filter": "^5.0.0", "handlebars": "^4.7.7", - "json-stringify-safe": "^5.0.1", - "meow": "^12.0.1", - "semver": "^7.5.2", - "split2": "^4.0.0" + "meow": "^13.0.0", + "semver": "^7.5.2" }, "bin": { - "conventional-changelog-writer": "cli.mjs" + "conventional-changelog-writer": "dist/cli/index.js" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/conventional-changelog-writer/node_modules/semver": { @@ -4657,32 +4323,29 @@ } }, "node_modules/conventional-commits-filter": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-4.0.0.tgz", - "integrity": "sha512-rnpnibcSOdFcdclpFwWa+pPlZJhXE7l+XK04zxhbWrhgpR96h33QLz8hITTXbcYICxVr3HZFtbtUAQ+4LdBo9A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-5.0.0.tgz", + "integrity": "sha512-tQMagCOC59EVgNZcC5zl7XqO30Wki9i9J3acbUvkaosCT6JX3EeFwJD7Qqp4MCikRnzS18WXV3BLIQ66ytu6+Q==", "dev": true, "license": "MIT", "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/conventional-commits-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", - "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-6.0.0.tgz", + "integrity": "sha512-TbsINLp48XeMXR8EvGjTnKGsZqBemisPoyWESlpRyR8lif0lcwzqz+NMtYSj1ooF/WYjSuu7wX0CtdeeMEQAmA==", "dev": true, "license": "MIT", "dependencies": { - "is-text-path": "^2.0.0", - "JSONStream": "^1.3.5", - "meow": "^12.0.1", - "split2": "^4.0.0" + "meow": "^13.0.0" }, "bin": { - "conventional-commits-parser": "cli.mjs" + "conventional-commits-parser": "dist/cli/index.js" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/convert-hrtime": { @@ -9325,13 +8988,13 @@ } }, "node_modules/meow": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", - "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", + "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", "dev": true, "license": "MIT", "engines": { - "node": ">=16.10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -13342,6 +13005,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -13447,17 +13111,17 @@ } }, "node_modules/semantic-release": { - "version": "23.1.1", - "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-23.1.1.tgz", - "integrity": "sha512-qqJDBhbtHsjUEMsojWKGuL5lQFCJuPtiXKEIlFKyTzDDGTAE/oyvznaP8GeOr5PvcqBJ6LQz4JCENWPLeehSpA==", + "version": "24.0.0", + "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-24.0.0.tgz", + "integrity": "sha512-v46CRPw+9eI3ZuYGF2oAjqPqsfbnfFTwLBgQsv/lch4goD09ytwOTESMN4QIrx/wPLxUGey60/NMx+ANQtWRsA==", "dev": true, "license": "MIT", "dependencies": { - "@semantic-release/commit-analyzer": "^12.0.0", + "@semantic-release/commit-analyzer": "^13.0.0-beta.1", "@semantic-release/error": "^4.0.0", "@semantic-release/github": "^10.0.0", "@semantic-release/npm": "^12.0.0", - "@semantic-release/release-notes-generator": "^13.0.0", + "@semantic-release/release-notes-generator": "^14.0.0-beta.1", "aggregate-error": "^5.0.0", "cosmiconfig": "^9.0.0", "debug": "^4.0.0", diff --git a/package.json b/package.json index 38526fd..677ce90 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "prettier": "3.3.3", "react": "^18.3.1", "react-dom": "^18.3.1", - "semantic-release": "^23.1.1", + "semantic-release": "^24.0.0", "ts-jest": "^29.2.3", "ts-node": "^10.9.2", "typescript": "^5.5.4", diff --git a/sandbox/sandbox-page.tsx b/sandbox/sandbox-page.tsx index 8c4275c..e34a437 100644 --- a/sandbox/sandbox-page.tsx +++ b/sandbox/sandbox-page.tsx @@ -1,9 +1,10 @@ import React, { useEffect } from 'react'; import { useAccountList } from '../src/api/authorize'; import { URLUtils } from '@deriv-com/utils'; -import { useSubscribe } from '../src/base'; +import { useAPI, useSubscribe } from '../src/base'; export const SandboxPage = () => { + const { derivAPIClient } = useAPI(); const { data } = useAccountList(); const { data: exchangeRateData, subscribe: subscribeExchangeRates } = useSubscribe('exchange_rates'); const { @@ -14,6 +15,10 @@ export const SandboxPage = () => { error: ticksError, } = useSubscribe('ticks'); + const handleSwitchFrench = async () => { + await derivAPIClient.switchConnection('wss://blue.derivws.com/websockets/v3?app_id=36300&l=FR&brand=deriv'); + }; + useEffect(() => { const handleSubscribe = async () => { await subscribeExchangeRates({ base_currency: 'USD', target_currency: 'AED' }); @@ -37,6 +42,7 @@ export const SandboxPage = () => { Subscribe to Different Ticks + ); }; diff --git a/src/base/index.ts b/src/base/index.ts index 591b673..972a867 100644 --- a/src/base/index.ts +++ b/src/base/index.ts @@ -1,4 +1,4 @@ -import { useAppData, useAuthData } from './use-context-hooks'; +import { useAppData, useAuthData, useAPI } from './use-context-hooks'; import { useAuthorizeQuery } from './use-authorize-query'; import { useQuery } from './use-query'; import { useMutation } from './use-mutation'; @@ -6,4 +6,14 @@ import { useSubscribe } from './use-subscribe'; import { useAuthorizedSubscription } from './use-authorized-subscription'; import { useInfiniteQuery } from './use-infinite-query'; -export { useAppData, useAuthData, useAuthorizeQuery, useQuery, useMutation, useSubscribe, useAuthorizedSubscription, useInfiniteQuery }; +export { + useAppData, + useAuthData, + useAPI, + useAuthorizeQuery, + useQuery, + useMutation, + useSubscribe, + useAuthorizedSubscription, + useInfiniteQuery, +}; diff --git a/src/client-library/deriv-api-client.ts b/src/client-library/deriv-api-client.ts index 98bc9c8..58bc6c7 100644 --- a/src/client-library/deriv-api-client.ts +++ b/src/client-library/deriv-api-client.ts @@ -8,7 +8,7 @@ import { TSocketSubscribeResponseData, } from '../types/api.types'; -type DerivAPIClientOptions = { +export type DerivAPIClientOptions = { onOpen?: (e: Event) => void; onClose?: (e: CloseEvent) => void; }; @@ -26,6 +26,7 @@ type SubscriptionHandler = { name: T; status: 'active' | 'idle' | 'error'; data?: TSocketSubscribeResponseData; + payload: TSocketRequestPayload; counter: number; subscriptions: Map) => void>; onError?: (error: TSocketError['error']) => void; @@ -38,19 +39,19 @@ type SubscriptionMap >; -type SendFunctionArgs = { +export type SendFunctionArgs = { name: T; payload?: TSocketRequestPayload; }; -type SubscribeFunctionArgs = { +export type SubscribeFunctionArgs = { name: T; payload?: TSocketRequestPayload; onData: (data: TSocketSubscribeResponseData) => void; onError?: (error: TSocketError['error']) => void; }; -type UnsubscribeHandlerArgs = { +export type UnsubscribeHandlerArgs = { id: number; hash: string; }; @@ -61,6 +62,11 @@ export class DerivAPIClient { subscribeHandler: SubscriptionMap; req_id: number; waitForWebSocketOpen: ReturnType; + waitForWebSocketCall?: ReturnType & { + name: TSocketEndpointNames; + type: 'all' | 'subscribe' | 'request'; + }; + authorizePayload: TSocketRequestPayload<'authorize'> | null = null; keepAliveIntervalId: NodeJS.Timeout | null = null; constructor(endpoint: string, options?: DerivAPIClientOptions) { @@ -83,6 +89,12 @@ export class DerivAPIClient { this.websocket.addEventListener('message', async response => { const parsedData = JSON.parse(response.data); + // If name matches for the calls you asynchronously wait, resolve + if (this.waitForWebSocketCall && parsedData.msg_type === this.waitForWebSocketCall?.name) { + const { resolve } = this.waitForWebSocketCall; + resolve({}); + } + if (parsedData.subscription || parsedData.echo_req?.subscribe) { const { req_id, ...payload } = parsedData.echo_req; const subscribeHash = await ObjectUtils.hashObject({ ...payload }); @@ -133,8 +145,18 @@ export class DerivAPIClient { this.requestHandler.set(this.req_id.toString(), newRequestHandler as RequestHandler); await this.waitForWebSocketOpen?.promise; + if (this.waitForWebSocketCall?.type === 'request' || this.waitForWebSocketCall?.type === 'all') { + await this.waitForWebSocketCall.promise; + } this.websocket.send(JSON.stringify(requestPayload)); + if (name === 'authorize') { + const { req_id, ...cleanedPayload } = requestPayload as TSocketRequestPayload<'authorize'> & { + req_id: number; + }; + this.authorizePayload = cleanedPayload; + } + return promise; } @@ -148,12 +170,14 @@ export class DerivAPIClient { const subscriptionHash = await ObjectUtils.hashObject(subscriptionPayload); const matchingSubscription = this.subscribeHandler.get(subscriptionHash); + // If no existing subscription, create a new handler and send the subscribe payload if (!matchingSubscription) { this.req_id = this.req_id + 1; const newSubscriptionHandler: SubscriptionHandler = { name, status: 'idle', + payload: subscriptionPayload as unknown as TSocketRequestPayload, onError: onError, subscriptions: new Map(), subscription_id: '', @@ -167,10 +191,14 @@ export class DerivAPIClient { ); await this.waitForWebSocketOpen?.promise; + if (this.waitForWebSocketCall?.type === 'subscribe' || this.waitForWebSocketCall?.type === 'all') { + await this.waitForWebSocketCall.promise; + } this.websocket.send(JSON.stringify({ ...subscriptionPayload, req_id: this.req_id })); return { id: newSubscriptionHandler.counter, hash: subscriptionHash }; } else { + // If there is already a subscription, simply append the onData callback directly to the subscription list const currentCounter = matchingSubscription.counter + 1; matchingSubscription.subscriptions.set( currentCounter, @@ -202,7 +230,23 @@ export class DerivAPIClient { } } - switchConnection() {} + async waitFor(name: TSocketEndpointNames, type: 'all' | 'subscribe' | 'request') { + this.waitForWebSocketCall = { ...PromiseUtils.createPromise(), name, type }; + } + + async reinitializeSubscriptions( + subscribeHandler: SubscriptionMap, + authorizeData?: TSocketRequestPayload<'authorize'> | null + ) { + if (authorizeData) { + this.authorizePayload = authorizeData; + await this.send({ name: 'authorize', payload: { ...authorizeData } }); + } + this.subscribeHandler = subscribeHandler; + for (const subs of subscribeHandler.values()) { + await this.send({ name: subs.name, payload: subs.payload }); + } + } isSocketClosingOrClosed() { return ![2, 3].includes(this.websocket.readyState); diff --git a/src/client-library/deriv-api-manager.ts b/src/client-library/deriv-api-manager.ts new file mode 100644 index 0000000..2b614d5 --- /dev/null +++ b/src/client-library/deriv-api-manager.ts @@ -0,0 +1,46 @@ +import { TSocketEndpointNames, TSocketSubscribableEndpointNames } from '../types/api.types'; +import { + DerivAPIClient, + DerivAPIClientOptions, + SendFunctionArgs, + SubscribeFunctionArgs, + UnsubscribeHandlerArgs, +} from './deriv-api-client'; + +export class DerivAPIManager { + options?: DerivAPIClientOptions; + activeClient: DerivAPIClient; + clientList: Map = new Map(); + + constructor(endpoint: string, options?: DerivAPIClientOptions) { + const client = new DerivAPIClient(endpoint, options); + this.clientList.set(endpoint, client); + this.activeClient = client; + this.options = options; + } + + async send(args: SendFunctionArgs) { + return this.activeClient.send(args); + } + + async subscribe(args: SubscribeFunctionArgs) { + return this.activeClient.subscribe(args); + } + + async unsubscribe(args: UnsubscribeHandlerArgs) { + return this.activeClient.unsubscribe(args); + } + + async switchConnection(endpoint: string) { + const matchingInstance = this.clientList.get(endpoint); + if (matchingInstance) { + this.activeClient = matchingInstance; + return; + } + const subscribeHandlers = this.activeClient.subscribeHandler; + const newInstance = new DerivAPIClient(endpoint, this.options); + await newInstance.reinitializeSubscriptions(subscribeHandlers, this.activeClient.authorizePayload); + this.clientList.set(endpoint, newInstance); + this.activeClient = newInstance; + } +} diff --git a/src/context/api-context.tsx b/src/context/api-context.tsx index 7455d9e..648a925 100644 --- a/src/context/api-context.tsx +++ b/src/context/api-context.tsx @@ -1,22 +1,11 @@ import { createContext, PropsWithChildren } from 'react'; import { URLUtils } from '@deriv-com/utils'; -import { DerivAPIClient } from '../client-library/deriv-api-client'; +import { DerivAPIManager } from '../client-library/deriv-api-manager'; -export const derivAPIClient = new DerivAPIClient(URLUtils.getWebsocketURL(), { - onOpen: () => { - localStorage.setItem('api.connecting', 'false'); - }, - onClose: () => { - const isConnecting = localStorage.getItem('api.connecting') ?? 'false'; - if (isConnecting === 'false') { - localStorage.setItem('api.connecting', 'true'); - window.location.reload(); - } - }, -}); +export const derivAPIClient = new DerivAPIManager(URLUtils.getWebsocketURL()); type APIData = { - derivAPIClient: DerivAPIClient; + derivAPIClient: DerivAPIManager; }; export const APIDataContext = createContext(null);