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);