This is an automated email from the ASF dual-hosted git repository.

gkoszyk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iggy.git


The following commit(s) were added to refs/heads/master by this push:
     new 886e11027 feat(js): add getClusterMetadata command (#2187)
886e11027 is described below

commit 886e1102732890f924b5b9acc91d959cc60f30c1
Author: T1B0 <[email protected]>
AuthorDate: Thu Oct 30 13:02:05 2025 +0100

    feat(js): add getClusterMetadata command (#2187)
    
    Co-authored-by: Piotr Gankiewicz <[email protected]>
    Co-authored-by: Grzegorz Koszyk 
<[email protected]>
---
 .github/actions/node-npm/pre-merge/action.yml      |   2 +
 foreign/node/package-lock.json                     | 614 +++++++++++----------
 foreign/node/src/client/client.socket.ts           |   2 +-
 foreign/node/src/e2e/tcp.cluster.e2e.ts            |  64 +++
 foreign/node/src/wire/cluster/cluster.type.ts      |  91 +++
 foreign/node/src/wire/cluster/cluster.utils.ts     | 151 +++++
 .../get-cluster-metadata.command.ts}               |  22 +-
 .../src/wire/{error.utils.ts => cluster/index.ts}  |  10 +-
 foreign/node/src/wire/command-set.ts               |  10 +
 foreign/node/src/wire/command.code.ts              |   1 +
 foreign/node/src/wire/command.utils.ts             |   7 -
 foreign/node/src/wire/error.utils.ts               |  21 +
 foreign/node/src/wire/system/get-stats.command.ts  |   2 +-
 13 files changed, 695 insertions(+), 302 deletions(-)

diff --git a/.github/actions/node-npm/pre-merge/action.yml 
b/.github/actions/node-npm/pre-merge/action.yml
index edbd847e1..07adb0723 100644
--- a/.github/actions/node-npm/pre-merge/action.yml
+++ b/.github/actions/node-npm/pre-merge/action.yml
@@ -84,6 +84,8 @@ runs:
       id: iggy
       if: inputs.task == 'e2e'
       uses: ./.github/actions/utils/server-start
+      env:
+        IGGY_CLUSTER_ENABLED: true
       continue-on-error: true
 
     - name: E2E tests
diff --git a/foreign/node/package-lock.json b/foreign/node/package-lock.json
index d4fc7b511..c5075d742 100644
--- a/foreign/node/package-lock.json
+++ b/foreign/node/package-lock.json
@@ -643,9 +643,9 @@
       }
     },
     "node_modules/@cucumber/query": {
-      "version": "13.5.0",
-      "resolved": 
"https://registry.npmjs.org/@cucumber/query/-/query-13.5.0.tgz";,
-      "integrity": 
"sha512-8L/7qMRixZZJl0S+ao4sq7IobLD1gAdr2H0KDVg81r4M063ZeWDNBSXAr2BXSAYL5I7cpNxpfbfU2VgXPaqapA==",
+      "version": "13.6.0",
+      "resolved": 
"https://registry.npmjs.org/@cucumber/query/-/query-13.6.0.tgz";,
+      "integrity": 
"sha512-tiDneuD5MoWsJ9VKPBmQok31mSX9Ybl+U4wqDoXeZgsXHDURqzM3rnpWVV3bC34y9W6vuFxrlwF/m7HdOxwqRw==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -664,21 +664,21 @@
       "license": "MIT"
     },
     "node_modules/@emnapi/core": {
-      "version": "1.4.5",
-      "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.5.tgz";,
-      "integrity": 
"sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==",
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.5.0.tgz";,
+      "integrity": 
"sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg==",
       "dev": true,
       "license": "MIT",
       "optional": true,
       "dependencies": {
-        "@emnapi/wasi-threads": "1.0.4",
+        "@emnapi/wasi-threads": "1.1.0",
         "tslib": "^2.4.0"
       }
     },
     "node_modules/@emnapi/runtime": {
-      "version": "1.4.5",
-      "resolved": 
"https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.5.tgz";,
-      "integrity": 
"sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==",
+      "version": "1.5.0",
+      "resolved": 
"https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz";,
+      "integrity": 
"sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==",
       "dev": true,
       "license": "MIT",
       "optional": true,
@@ -687,9 +687,9 @@
       }
     },
     "node_modules/@emnapi/wasi-threads": {
-      "version": "1.0.4",
-      "resolved": 
"https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.4.tgz";,
-      "integrity": 
"sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==",
+      "version": "1.1.0",
+      "resolved": 
"https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz";,
+      "integrity": 
"sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==",
       "dev": true,
       "license": "MIT",
       "optional": true,
@@ -698,9 +698,9 @@
       }
     },
     "node_modules/@eslint-community/eslint-utils": {
-      "version": "4.7.0",
-      "resolved": 
"https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz";,
-      "integrity": 
"sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==",
+      "version": "4.9.0",
+      "resolved": 
"https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz";,
+      "integrity": 
"sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -756,9 +756,9 @@
       }
     },
     "node_modules/@eslint/config-helpers": {
-      "version": "0.3.0",
-      "resolved": 
"https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz";,
-      "integrity": 
"sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==",
+      "version": "0.3.1",
+      "resolved": 
"https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz";,
+      "integrity": 
"sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==",
       "dev": true,
       "license": "Apache-2.0",
       "peer": true,
@@ -767,9 +767,9 @@
       }
     },
     "node_modules/@eslint/core": {
-      "version": "0.15.1",
-      "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz";,
-      "integrity": 
"sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==",
+      "version": "0.15.2",
+      "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz";,
+      "integrity": 
"sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==",
       "dev": true,
       "license": "Apache-2.0",
       "peer": true,
@@ -832,9 +832,9 @@
       "peer": true
     },
     "node_modules/@eslint/js": {
-      "version": "9.32.0",
-      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.32.0.tgz";,
-      "integrity": 
"sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg==",
+      "version": "9.36.0",
+      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.36.0.tgz";,
+      "integrity": 
"sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==",
       "dev": true,
       "license": "MIT",
       "peer": true,
@@ -857,14 +857,14 @@
       }
     },
     "node_modules/@eslint/plugin-kit": {
-      "version": "0.3.4",
-      "resolved": 
"https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.4.tgz";,
-      "integrity": 
"sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==",
+      "version": "0.3.5",
+      "resolved": 
"https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz";,
+      "integrity": 
"sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==",
       "dev": true,
       "license": "Apache-2.0",
       "peer": true,
       "dependencies": {
-        "@eslint/core": "^0.15.1",
+        "@eslint/core": "^0.15.2",
         "levn": "^0.4.1"
       },
       "engines": {
@@ -883,35 +883,20 @@
       }
     },
     "node_modules/@humanfs/node": {
-      "version": "0.16.6",
-      "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz";,
-      "integrity": 
"sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==",
+      "version": "0.16.7",
+      "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz";,
+      "integrity": 
"sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==",
       "dev": true,
       "license": "Apache-2.0",
       "peer": true,
       "dependencies": {
         "@humanfs/core": "^0.19.1",
-        "@humanwhocodes/retry": "^0.3.0"
+        "@humanwhocodes/retry": "^0.4.0"
       },
       "engines": {
         "node": ">=18.18.0"
       }
     },
-    "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": {
-      "version": "0.3.1",
-      "resolved": 
"https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz";,
-      "integrity": 
"sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==",
-      "dev": true,
-      "license": "Apache-2.0",
-      "peer": true,
-      "engines": {
-        "node": ">=18.18"
-      },
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/nzakas";
-      }
-    },
     "node_modules/@humanwhocodes/module-importer": {
       "version": "1.0.1",
       "resolved": 
"https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz";,
@@ -1047,9 +1032,9 @@
       }
     },
     "node_modules/@octokit/core": {
-      "version": "7.0.3",
-      "resolved": "https://registry.npmjs.org/@octokit/core/-/core-7.0.3.tgz";,
-      "integrity": 
"sha512-oNXsh2ywth5aowwIa7RKtawnkdH6LgU1ztfP9AIUCQCvzysB+WeU8o2kyyosDPwBZutPpjZDKPQGIzzrfTWweQ==",
+      "version": "7.0.4",
+      "resolved": "https://registry.npmjs.org/@octokit/core/-/core-7.0.4.tgz";,
+      "integrity": 
"sha512-jOT8V1Ba5BdC79sKrRWDdMT5l1R+XNHTPR6CPWzUP2EcfAcvIHZWF0eAbmRcpOOP5gVIwnqNg0C4nvh6Abc3OA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -1057,7 +1042,7 @@
         "@octokit/graphql": "^9.0.1",
         "@octokit/request": "^10.0.2",
         "@octokit/request-error": "^7.0.0",
-        "@octokit/types": "^14.0.0",
+        "@octokit/types": "^15.0.0",
         "before-after-hook": "^4.0.0",
         "universal-user-agent": "^7.0.0"
       },
@@ -1079,6 +1064,23 @@
         "node": ">= 20"
       }
     },
+    "node_modules/@octokit/endpoint/node_modules/@octokit/openapi-types": {
+      "version": "25.1.0",
+      "resolved": 
"https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz";,
+      "integrity": 
"sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@octokit/endpoint/node_modules/@octokit/types": {
+      "version": "14.1.0",
+      "resolved": 
"https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz";,
+      "integrity": 
"sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@octokit/openapi-types": "^25.1.0"
+      }
+    },
     "node_modules/@octokit/graphql": {
       "version": "9.0.1",
       "resolved": 
"https://registry.npmjs.org/@octokit/graphql/-/graphql-9.0.1.tgz";,
@@ -1094,13 +1096,30 @@
         "node": ">= 20"
       }
     },
-    "node_modules/@octokit/openapi-types": {
+    "node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": {
       "version": "25.1.0",
       "resolved": 
"https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz";,
       "integrity": 
"sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==",
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/@octokit/graphql/node_modules/@octokit/types": {
+      "version": "14.1.0",
+      "resolved": 
"https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz";,
+      "integrity": 
"sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@octokit/openapi-types": "^25.1.0"
+      }
+    },
+    "node_modules/@octokit/openapi-types": {
+      "version": "26.0.0",
+      "resolved": 
"https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-26.0.0.tgz";,
+      "integrity": 
"sha512-7AtcfKtpo77j7Ts73b4OWhOZHTKo/gGY8bB3bNBQz4H+GRSWqx2yvj8TXRsbdTE0eRmYmXOEY66jM7mJ7LzfsA==",
+      "dev": true,
+      "license": "MIT"
+    },
     "node_modules/@octokit/plugin-paginate-rest": {
       "version": "13.1.1",
       "resolved": 
"https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-13.1.1.tgz";,
@@ -1117,6 +1136,23 @@
         "@octokit/core": ">=6"
       }
     },
+    
"node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types":
 {
+      "version": "25.1.0",
+      "resolved": 
"https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz";,
+      "integrity": 
"sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": {
+      "version": "14.1.0",
+      "resolved": 
"https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz";,
+      "integrity": 
"sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@octokit/openapi-types": "^25.1.0"
+      }
+    },
     "node_modules/@octokit/plugin-retry": {
       "version": "8.0.1",
       "resolved": 
"https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-8.0.1.tgz";,
@@ -1135,6 +1171,23 @@
         "@octokit/core": ">=7"
       }
     },
+    "node_modules/@octokit/plugin-retry/node_modules/@octokit/openapi-types": {
+      "version": "25.1.0",
+      "resolved": 
"https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz";,
+      "integrity": 
"sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@octokit/plugin-retry/node_modules/@octokit/types": {
+      "version": "14.1.0",
+      "resolved": 
"https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz";,
+      "integrity": 
"sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@octokit/openapi-types": "^25.1.0"
+      }
+    },
     "node_modules/@octokit/plugin-throttling": {
       "version": "11.0.1",
       "resolved": 
"https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-11.0.1.tgz";,
@@ -1152,6 +1205,23 @@
         "@octokit/core": "^7.0.0"
       }
     },
+    
"node_modules/@octokit/plugin-throttling/node_modules/@octokit/openapi-types": {
+      "version": "25.1.0",
+      "resolved": 
"https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz";,
+      "integrity": 
"sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@octokit/plugin-throttling/node_modules/@octokit/types": {
+      "version": "14.1.0",
+      "resolved": 
"https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz";,
+      "integrity": 
"sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@octokit/openapi-types": "^25.1.0"
+      }
+    },
     "node_modules/@octokit/request": {
       "version": "10.0.3",
       "resolved": 
"https://registry.npmjs.org/@octokit/request/-/request-10.0.3.tgz";,
@@ -1182,7 +1252,14 @@
         "node": ">= 20"
       }
     },
-    "node_modules/@octokit/types": {
+    "node_modules/@octokit/request-error/node_modules/@octokit/openapi-types": 
{
+      "version": "25.1.0",
+      "resolved": 
"https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz";,
+      "integrity": 
"sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@octokit/request-error/node_modules/@octokit/types": {
       "version": "14.1.0",
       "resolved": 
"https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz";,
       "integrity": 
"sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==",
@@ -1192,6 +1269,33 @@
         "@octokit/openapi-types": "^25.1.0"
       }
     },
+    "node_modules/@octokit/request/node_modules/@octokit/openapi-types": {
+      "version": "25.1.0",
+      "resolved": 
"https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz";,
+      "integrity": 
"sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@octokit/request/node_modules/@octokit/types": {
+      "version": "14.1.0",
+      "resolved": 
"https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz";,
+      "integrity": 
"sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@octokit/openapi-types": "^25.1.0"
+      }
+    },
+    "node_modules/@octokit/types": {
+      "version": "15.0.0",
+      "resolved": 
"https://registry.npmjs.org/@octokit/types/-/types-15.0.0.tgz";,
+      "integrity": 
"sha512-8o6yDfmoGJUIeR9OfYU0/TUJTnMPG2r68+1yEdUeG2Fdqpj8Qetg0ziKIgcBm0RW/j29H41WP37CYCEhp6GoHQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@octokit/openapi-types": "^26.0.0"
+      }
+    },
     "node_modules/@oxc-resolver/binding-darwin-arm64": {
       "version": "1.12.0",
       "resolved": 
"https://registry.npmjs.org/@oxc-resolver/binding-darwin-arm64/-/binding-darwin-arm64-1.12.0.tgz";,
@@ -1552,9 +1656,9 @@
       }
     },
     "node_modules/@semantic-release/github": {
-      "version": "11.0.3",
-      "resolved": 
"https://registry.npmjs.org/@semantic-release/github/-/github-11.0.3.tgz";,
-      "integrity": 
"sha512-T2fKUyFkHHkUNa5XNmcsEcDPuG23hwBKptfUVcFXDVG2cSjXXZYDOfVYwfouqbWo/8UefotLaoGfQeK+k3ep6A==",
+      "version": "11.0.6",
+      "resolved": 
"https://registry.npmjs.org/@semantic-release/github/-/github-11.0.6.tgz";,
+      "integrity": 
"sha512-ctDzdSMrT3H+pwKBPdyCPty6Y47X8dSrjd3aPZ5KKIKKWTwZBE9De8GtsH3TyAlw3Uyo2stegMx6rJMXKpJwJA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -1566,13 +1670,13 @@
         "aggregate-error": "^5.0.0",
         "debug": "^4.3.4",
         "dir-glob": "^3.0.1",
-        "globby": "^14.0.0",
         "http-proxy-agent": "^7.0.0",
         "https-proxy-agent": "^7.0.0",
         "issue-parser": "^7.0.0",
         "lodash-es": "^4.17.21",
         "mime": "^4.0.0",
         "p-filter": "^4.0.0",
+        "tinyglobby": "^0.2.14",
         "url-join": "^5.0.0"
       },
       "engines": {
@@ -1610,9 +1714,9 @@
       }
     },
     "node_modules/@semantic-release/github/node_modules/clean-stack": {
-      "version": "5.2.0",
-      "resolved": 
"https://registry.npmjs.org/clean-stack/-/clean-stack-5.2.0.tgz";,
-      "integrity": 
"sha512-TyUIUJgdFnCISzG5zu3291TAsE77ddchd0bepon1VVQrKLGKFED4iXFEDQ24mIPdPBbyE16PK3F8MYE1CmcBEQ==",
+      "version": "5.3.0",
+      "resolved": 
"https://registry.npmjs.org/clean-stack/-/clean-stack-5.3.0.tgz";,
+      "integrity": 
"sha512-9ngPTOhYGQqNVSfeJkYXHmF7AGWp4/nN5D/QqNQs3Dvxd1Kk/WpjHfNujKHYUQ/5CoGyOyFNoWSPk5afzP0QVg==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -1652,9 +1756,9 @@
       }
     },
     "node_modules/@semantic-release/github/node_modules/mime": {
-      "version": "4.0.7",
-      "resolved": "https://registry.npmjs.org/mime/-/mime-4.0.7.tgz";,
-      "integrity": 
"sha512-2OfDPL+e03E0LrXaGYOtTFIYhiuzep94NSsuhrNULq+stylcJedcHdzHtz0atMUuGwJfFYs0YL5xeC/Ca2x0eQ==",
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/mime/-/mime-4.1.0.tgz";,
+      "integrity": 
"sha512-X5ju04+cAzsojXKes0B/S4tcYtFAJ6tTMuSPBEn9CPGlrWr8Fiw7qYeLT0XyH80HSoAoqWCaz+MWKh22P7G1cw==",
       "dev": true,
       "funding": [
         "https://github.com/sponsors/broofa";
@@ -1705,19 +1809,6 @@
         "node": ">=18"
       }
     },
-    
"node_modules/@semantic-release/npm/node_modules/@sindresorhus/merge-streams": {
-      "version": "4.0.0",
-      "resolved": 
"https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz";,
-      "integrity": 
"sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=18"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus";
-      }
-    },
     "node_modules/@semantic-release/npm/node_modules/aggregate-error": {
       "version": "5.0.0",
       "resolved": 
"https://registry.npmjs.org/aggregate-error/-/aggregate-error-5.0.0.tgz";,
@@ -1736,9 +1827,9 @@
       }
     },
     "node_modules/@semantic-release/npm/node_modules/clean-stack": {
-      "version": "5.2.0",
-      "resolved": 
"https://registry.npmjs.org/clean-stack/-/clean-stack-5.2.0.tgz";,
-      "integrity": 
"sha512-TyUIUJgdFnCISzG5zu3291TAsE77ddchd0bepon1VVQrKLGKFED4iXFEDQ24mIPdPBbyE16PK3F8MYE1CmcBEQ==",
+      "version": "5.3.0",
+      "resolved": 
"https://registry.npmjs.org/clean-stack/-/clean-stack-5.3.0.tgz";,
+      "integrity": 
"sha512-9ngPTOhYGQqNVSfeJkYXHmF7AGWp4/nN5D/QqNQs3Dvxd1Kk/WpjHfNujKHYUQ/5CoGyOyFNoWSPk5afzP0QVg==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -1997,9 +2088,9 @@
       }
     },
     "node_modules/@sindresorhus/merge-streams": {
-      "version": "2.3.0",
-      "resolved": 
"https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz";,
-      "integrity": 
"sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==",
+      "version": "4.0.0",
+      "resolved": 
"https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz";,
+      "integrity": 
"sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -2010,9 +2101,9 @@
       }
     },
     "node_modules/@swc-node/core": {
-      "version": "1.13.3",
-      "resolved": 
"https://registry.npmjs.org/@swc-node/core/-/core-1.13.3.tgz";,
-      "integrity": 
"sha512-OGsvXIid2Go21kiNqeTIn79jcaX4l0G93X2rAnas4LFoDyA9wAwVK7xZdm+QsKoMn5Mus2yFLCc4OtX2dD/PWA==",
+      "version": "1.14.1",
+      "resolved": 
"https://registry.npmjs.org/@swc-node/core/-/core-1.14.1.tgz";,
+      "integrity": 
"sha512-jrt5GUaZUU6cmMS+WTJEvGvaB6j1YNKPHPzC2PUi2BjaFbtxURHj6641Az6xN7b665hNniAIdvjxWcRml5yCnw==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -2023,7 +2114,7 @@
         "url": "https://github.com/sponsors/Brooooooklyn";
       },
       "peerDependencies": {
-        "@swc/core": ">= 1.4.13",
+        "@swc/core": ">= 1.13.3",
         "@swc/types": ">= 0.1"
       }
     },
@@ -2063,16 +2154,16 @@
       }
     },
     "node_modules/@swc/core": {
-      "version": "1.13.3",
-      "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.13.3.tgz";,
-      "integrity": 
"sha512-ZaDETVWnm6FE0fc+c2UE8MHYVS3Fe91o5vkmGfgwGXFbxYvAjKSqxM/j4cRc9T7VZNSJjriXq58XkfCp3Y6f+w==",
+      "version": "1.13.5",
+      "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.13.5.tgz";,
+      "integrity": 
"sha512-WezcBo8a0Dg2rnR82zhwoR6aRNxeTGfK5QCD6TQ+kg3xx/zNT02s/0o+81h/3zhvFSB24NtqEr8FTw88O5W/JQ==",
       "dev": true,
       "hasInstallScript": true,
       "license": "Apache-2.0",
       "peer": true,
       "dependencies": {
         "@swc/counter": "^0.1.3",
-        "@swc/types": "^0.1.23"
+        "@swc/types": "^0.1.24"
       },
       "engines": {
         "node": ">=10"
@@ -2082,16 +2173,16 @@
         "url": "https://opencollective.com/swc";
       },
       "optionalDependencies": {
-        "@swc/core-darwin-arm64": "1.13.3",
-        "@swc/core-darwin-x64": "1.13.3",
-        "@swc/core-linux-arm-gnueabihf": "1.13.3",
-        "@swc/core-linux-arm64-gnu": "1.13.3",
-        "@swc/core-linux-arm64-musl": "1.13.3",
-        "@swc/core-linux-x64-gnu": "1.13.3",
-        "@swc/core-linux-x64-musl": "1.13.3",
-        "@swc/core-win32-arm64-msvc": "1.13.3",
-        "@swc/core-win32-ia32-msvc": "1.13.3",
-        "@swc/core-win32-x64-msvc": "1.13.3"
+        "@swc/core-darwin-arm64": "1.13.5",
+        "@swc/core-darwin-x64": "1.13.5",
+        "@swc/core-linux-arm-gnueabihf": "1.13.5",
+        "@swc/core-linux-arm64-gnu": "1.13.5",
+        "@swc/core-linux-arm64-musl": "1.13.5",
+        "@swc/core-linux-x64-gnu": "1.13.5",
+        "@swc/core-linux-x64-musl": "1.13.5",
+        "@swc/core-win32-arm64-msvc": "1.13.5",
+        "@swc/core-win32-ia32-msvc": "1.13.5",
+        "@swc/core-win32-x64-msvc": "1.13.5"
       },
       "peerDependencies": {
         "@swc/helpers": ">=0.5.17"
@@ -2103,9 +2194,9 @@
       }
     },
     "node_modules/@swc/core-darwin-arm64": {
-      "version": "1.13.3",
-      "resolved": 
"https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.13.3.tgz";,
-      "integrity": 
"sha512-ux0Ws4pSpBTqbDS9GlVP354MekB1DwYlbxXU3VhnDr4GBcCOimpocx62x7cFJkSpEBF8bmX8+/TTCGKh4PbyXw==",
+      "version": "1.13.5",
+      "resolved": 
"https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.13.5.tgz";,
+      "integrity": 
"sha512-lKNv7SujeXvKn16gvQqUQI5DdyY8v7xcoO3k06/FJbHJS90zEwZdQiMNRiqpYw/orU543tPaWgz7cIYWhbopiQ==",
       "cpu": [
         "arm64"
       ],
@@ -2121,9 +2212,9 @@
       }
     },
     "node_modules/@swc/core-darwin-x64": {
-      "version": "1.13.3",
-      "resolved": 
"https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.13.3.tgz";,
-      "integrity": 
"sha512-p0X6yhxmNUOMZrbeZ3ZNsPige8lSlSe1llllXvpCLkKKxN/k5vZt1sULoq6Nj4eQ7KeHQVm81/+AwKZyf/e0TA==",
+      "version": "1.13.5",
+      "resolved": 
"https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.13.5.tgz";,
+      "integrity": 
"sha512-ILd38Fg/w23vHb0yVjlWvQBoE37ZJTdlLHa8LRCFDdX4WKfnVBiblsCU9ar4QTMNdeTBEX9iUF4IrbNWhaF1Ng==",
       "cpu": [
         "x64"
       ],
@@ -2139,9 +2230,9 @@
       }
     },
     "node_modules/@swc/core-linux-arm-gnueabihf": {
-      "version": "1.13.3",
-      "resolved": 
"https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.13.3.tgz";,
-      "integrity": 
"sha512-OmDoiexL2fVWvQTCtoh0xHMyEkZweQAlh4dRyvl8ugqIPEVARSYtaj55TBMUJIP44mSUOJ5tytjzhn2KFxFcBA==",
+      "version": "1.13.5",
+      "resolved": 
"https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.13.5.tgz";,
+      "integrity": 
"sha512-Q6eS3Pt8GLkXxqz9TAw+AUk9HpVJt8Uzm54MvPsqp2yuGmY0/sNaPPNVqctCX9fu/Nu8eaWUen0si6iEiCsazQ==",
       "cpu": [
         "arm"
       ],
@@ -2157,9 +2248,9 @@
       }
     },
     "node_modules/@swc/core-linux-arm64-gnu": {
-      "version": "1.13.3",
-      "resolved": 
"https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.13.3.tgz";,
-      "integrity": 
"sha512-STfKku3QfnuUj6k3g9ld4vwhtgCGYIFQmsGPPgT9MK/dI3Lwnpe5Gs5t1inoUIoGNP8sIOLlBB4HV4MmBjQuhw==",
+      "version": "1.13.5",
+      "resolved": 
"https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.13.5.tgz";,
+      "integrity": 
"sha512-aNDfeN+9af+y+M2MYfxCzCy/VDq7Z5YIbMqRI739o8Ganz6ST+27kjQFd8Y/57JN/hcnUEa9xqdS3XY7WaVtSw==",
       "cpu": [
         "arm64"
       ],
@@ -2175,9 +2266,9 @@
       }
     },
     "node_modules/@swc/core-linux-arm64-musl": {
-      "version": "1.13.3",
-      "resolved": 
"https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.13.3.tgz";,
-      "integrity": 
"sha512-bc+CXYlFc1t8pv9yZJGus372ldzOVscBl7encUBlU1m/Sig0+NDJLz6cXXRcFyl6ABNOApWeR4Yl7iUWx6C8og==",
+      "version": "1.13.5",
+      "resolved": 
"https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.13.5.tgz";,
+      "integrity": 
"sha512-9+ZxFN5GJag4CnYnq6apKTnnezpfJhCumyz0504/JbHLo+Ue+ZtJnf3RhyA9W9TINtLE0bC4hKpWi8ZKoETyOQ==",
       "cpu": [
         "arm64"
       ],
@@ -2193,9 +2284,9 @@
       }
     },
     "node_modules/@swc/core-linux-x64-gnu": {
-      "version": "1.13.3",
-      "resolved": 
"https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.13.3.tgz";,
-      "integrity": 
"sha512-dFXoa0TEhohrKcxn/54YKs1iwNeW6tUkHJgXW33H381SvjKFUV53WR231jh1sWVJETjA3vsAwxKwR23s7UCmUA==",
+      "version": "1.13.5",
+      "resolved": 
"https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.13.5.tgz";,
+      "integrity": 
"sha512-WD530qvHrki8Ywt/PloKUjaRKgstQqNGvmZl54g06kA+hqtSE2FTG9gngXr3UJxYu/cNAjJYiBifm7+w4nbHbA==",
       "cpu": [
         "x64"
       ],
@@ -2211,9 +2302,9 @@
       }
     },
     "node_modules/@swc/core-linux-x64-musl": {
-      "version": "1.13.3",
-      "resolved": 
"https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.13.3.tgz";,
-      "integrity": 
"sha512-ieyjisLB+ldexiE/yD8uomaZuZIbTc8tjquYln9Quh5ykOBY7LpJJYBWvWtm1g3pHv6AXlBI8Jay7Fffb6aLfA==",
+      "version": "1.13.5",
+      "resolved": 
"https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.13.5.tgz";,
+      "integrity": 
"sha512-Luj8y4OFYx4DHNQTWjdIuKTq2f5k6uSXICqx+FSabnXptaOBAbJHNbHT/06JZh6NRUouaf0mYXN0mcsqvkhd7Q==",
       "cpu": [
         "x64"
       ],
@@ -2229,9 +2320,9 @@
       }
     },
     "node_modules/@swc/core-win32-arm64-msvc": {
-      "version": "1.13.3",
-      "resolved": 
"https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.13.3.tgz";,
-      "integrity": 
"sha512-elTQpnaX5vESSbhCEgcwXjpMsnUbqqHfEpB7ewpkAsLzKEXZaK67ihSRYAuAx6ewRQTo7DS5iTT6X5aQD3MzMw==",
+      "version": "1.13.5",
+      "resolved": 
"https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.13.5.tgz";,
+      "integrity": 
"sha512-cZ6UpumhF9SDJvv4DA2fo9WIzlNFuKSkZpZmPG1c+4PFSEMy5DFOjBSllCvnqihCabzXzpn6ykCwBmHpy31vQw==",
       "cpu": [
         "arm64"
       ],
@@ -2247,9 +2338,9 @@
       }
     },
     "node_modules/@swc/core-win32-ia32-msvc": {
-      "version": "1.13.3",
-      "resolved": 
"https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.13.3.tgz";,
-      "integrity": 
"sha512-nvehQVEOdI1BleJpuUgPLrclJ0TzbEMc+MarXDmmiRFwEUGqj+pnfkTSb7RZyS1puU74IXdK/YhTirHurtbI9w==",
+      "version": "1.13.5",
+      "resolved": 
"https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.13.5.tgz";,
+      "integrity": 
"sha512-C5Yi/xIikrFUzZcyGj9L3RpKljFvKiDMtyDzPKzlsDrKIw2EYY+bF88gB6oGY5RGmv4DAX8dbnpRAqgFD0FMEw==",
       "cpu": [
         "ia32"
       ],
@@ -2265,9 +2356,9 @@
       }
     },
     "node_modules/@swc/core-win32-x64-msvc": {
-      "version": "1.13.3",
-      "resolved": 
"https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.13.3.tgz";,
-      "integrity": 
"sha512-A+JSKGkRbPLVV2Kwx8TaDAV0yXIXm/gc8m98hSkVDGlPBBmydgzNdWy3X7HTUBM7IDk7YlWE7w2+RUGjdgpTmg==",
+      "version": "1.13.5",
+      "resolved": 
"https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.13.5.tgz";,
+      "integrity": 
"sha512-YrKdMVxbYmlfybCSbRtrilc6UA8GF5aPmGKBdPvjrarvsmf4i7ZHGCEnLtfOMd3Lwbs2WUZq3WdMbozYeLU93Q==",
       "cpu": [
         "x64"
       ],
@@ -2291,9 +2382,9 @@
       "peer": true
     },
     "node_modules/@swc/types": {
-      "version": "0.1.23",
-      "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.23.tgz";,
-      "integrity": 
"sha512-u1iIVZV9Q0jxY+yM2vw/hZGDNudsN85bBpTqzAQ9rzkxW9D+e3aEM4Han+ow518gSewkXgjmEK0BD79ZcNVgPw==",
+      "version": "0.1.25",
+      "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.25.tgz";,
+      "integrity": 
"sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==",
       "dev": true,
       "license": "Apache-2.0",
       "peer": true,
@@ -2312,9 +2403,9 @@
       }
     },
     "node_modules/@tybys/wasm-util": {
-      "version": "0.10.0",
-      "resolved": 
"https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.0.tgz";,
-      "integrity": 
"sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==",
+      "version": "0.10.1",
+      "resolved": 
"https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz";,
+      "integrity": 
"sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==",
       "dev": true,
       "license": "MIT",
       "optional": true,
@@ -2680,9 +2771,9 @@
       }
     },
     "node_modules/ansi-escapes": {
-      "version": "7.0.0",
-      "resolved": 
"https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz";,
-      "integrity": 
"sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==",
+      "version": "7.1.0",
+      "resolved": 
"https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.1.0.tgz";,
+      "integrity": 
"sha512-YdhtCd19sKRKfAAUsrcC1wzm4JuzJoiX4pOJqIoW2qmKj5WzG/dL8uUJ0361zaXtHqK7gEhOwtAtz7t3Yq3X5g==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -2706,9 +2797,9 @@
       }
     },
     "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==",
+      "version": "6.2.3",
+      "resolved": 
"https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz";,
+      "integrity": 
"sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -2833,9 +2924,9 @@
       }
     },
     "node_modules/chalk": {
-      "version": "5.5.0",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.5.0.tgz";,
-      "integrity": 
"sha512-1tm8DTaJhPBG3bIkVeZt1iZM9GfSX2lzOeDVZH9R9ffRHpmHvxZ/QhgQH/aDTkswQVt+YHdXAdS/In/30OjCbg==",
+      "version": "5.6.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz";,
+      "integrity": 
"sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -3495,9 +3586,9 @@
       "license": "MIT"
     },
     "node_modules/env-ci": {
-      "version": "11.1.1",
-      "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-11.1.1.tgz";,
-      "integrity": 
"sha512-mT3ks8F0kwpo7SYNds6nWj0PaRh+qJxIeBVBXAKTN9hphAzZv7s0QAZQbqnB1fAv/r4pJUGE15BV9UrS31FP2w==",
+      "version": "11.2.0",
+      "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-11.2.0.tgz";,
+      "integrity": 
"sha512-D5kWfzkmaOQDioPmiviWAVtKmpPT4/iJmMVQxWxMPJTFyTkdc5JQUfc5iXEeWxcOdsYTKSAiA/Age4NUOqKsRA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -3676,9 +3767,9 @@
       }
     },
     "node_modules/error-ex": {
-      "version": "1.3.2",
-      "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz";,
-      "integrity": 
"sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+      "version": "1.3.4",
+      "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz";,
+      "integrity": 
"sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -3720,21 +3811,21 @@
       }
     },
     "node_modules/eslint": {
-      "version": "9.32.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.32.0.tgz";,
-      "integrity": 
"sha512-LSehfdpgMeWcTZkWZVIJl+tkZ2nuSkyyB9C27MZqFWXuph7DvaowgcTvKqxvpLW1JZIk8PN7hFY3Rj9LQ7m7lg==",
+      "version": "9.36.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.36.0.tgz";,
+      "integrity": 
"sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==",
       "dev": true,
       "license": "MIT",
       "peer": true,
       "dependencies": {
-        "@eslint-community/eslint-utils": "^4.2.0",
+        "@eslint-community/eslint-utils": "^4.8.0",
         "@eslint-community/regexpp": "^4.12.1",
         "@eslint/config-array": "^0.21.0",
-        "@eslint/config-helpers": "^0.3.0",
-        "@eslint/core": "^0.15.0",
+        "@eslint/config-helpers": "^0.3.1",
+        "@eslint/core": "^0.15.2",
         "@eslint/eslintrc": "^3.3.1",
-        "@eslint/js": "9.32.0",
-        "@eslint/plugin-kit": "^0.3.4",
+        "@eslint/js": "9.36.0",
+        "@eslint/plugin-kit": "^0.3.5",
         "@humanfs/node": "^0.16.6",
         "@humanwhocodes/module-importer": "^1.0.1",
         "@humanwhocodes/retry": "^0.4.2",
@@ -4158,9 +4249,9 @@
       "peer": true
     },
     "node_modules/fast-uri": {
-      "version": "3.0.6",
-      "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz";,
-      "integrity": 
"sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==",
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz";,
+      "integrity": 
"sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==",
       "dev": true,
       "funding": [
         {
@@ -4350,9 +4441,9 @@
       }
     },
     "node_modules/fs-extra": {
-      "version": "11.3.0",
-      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz";,
-      "integrity": 
"sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==",
+      "version": "11.3.2",
+      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.2.tgz";,
+      "integrity": 
"sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -4582,63 +4673,6 @@
         "url": "https://github.com/sponsors/sindresorhus";
       }
     },
-    "node_modules/globby": {
-      "version": "14.1.0",
-      "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz";,
-      "integrity": 
"sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "@sindresorhus/merge-streams": "^2.1.0",
-        "fast-glob": "^3.3.3",
-        "ignore": "^7.0.3",
-        "path-type": "^6.0.0",
-        "slash": "^5.1.0",
-        "unicorn-magic": "^0.3.0"
-      },
-      "engines": {
-        "node": ">=18"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus";
-      }
-    },
-    "node_modules/globby/node_modules/ignore": {
-      "version": "7.0.5",
-      "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz";,
-      "integrity": 
"sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">= 4"
-      }
-    },
-    "node_modules/globby/node_modules/path-type": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz";,
-      "integrity": 
"sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=18"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus";
-      }
-    },
-    "node_modules/globby/node_modules/unicorn-magic": {
-      "version": "0.3.0",
-      "resolved": 
"https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz";,
-      "integrity": 
"sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=18"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus";
-      }
-    },
     "node_modules/graceful-fs": {
       "version": "4.2.11",
       "resolved": 
"https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz";,
@@ -4840,9 +4874,9 @@
       }
     },
     "node_modules/import-meta-resolve": {
-      "version": "4.1.0",
-      "resolved": 
"https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz";,
-      "integrity": 
"sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==",
+      "version": "4.2.0",
+      "resolved": 
"https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz";,
+      "integrity": 
"sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==",
       "dev": true,
       "license": "MIT",
       "funding": {
@@ -5182,9 +5216,9 @@
       "peer": true
     },
     "node_modules/jsonfile": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz";,
-      "integrity": 
"sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+      "version": "6.2.0",
+      "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz";,
+      "integrity": 
"sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -5485,9 +5519,9 @@
       }
     },
     "node_modules/marked-terminal/node_modules/ansi-regex": {
-      "version": "6.1.0",
-      "resolved": 
"https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz";,
-      "integrity": 
"sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+      "version": "6.2.2",
+      "resolved": 
"https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz";,
+      "integrity": 
"sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -5695,9 +5729,9 @@
       }
     },
     "node_modules/normalize-url": {
-      "version": "8.0.2",
-      "resolved": 
"https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.2.tgz";,
-      "integrity": 
"sha512-Ee/R3SyN4BuynXcnTaekmaVdbDAEiNrHqjQIA37mHU8G9pf7aaAD4ZX3XjBLo6rsdcxA/gtkcNYZLt30ACgynw==",
+      "version": "8.1.0",
+      "resolved": 
"https://registry.npmjs.org/normalize-url/-/normalize-url-8.1.0.tgz";,
+      "integrity": 
"sha512-X06Mfd/5aKsRHc0O0J5CUedwnPmnDtLF2+nq+KN9KSDlJHkPuh0JUviWjEWMe0SW/9TDdSLVPuk7L5gGTIA1/w==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -8840,9 +8874,9 @@
       }
     },
     "node_modules/pretty-ms": {
-      "version": "9.2.0",
-      "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.2.0.tgz";,
-      "integrity": 
"sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==",
+      "version": "9.3.0",
+      "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz";,
+      "integrity": 
"sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -9206,19 +9240,6 @@
         "node": ">=18"
       }
     },
-    "node_modules/semantic-release/node_modules/@sindresorhus/merge-streams": {
-      "version": "4.0.0",
-      "resolved": 
"https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz";,
-      "integrity": 
"sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=18"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus";
-      }
-    },
     "node_modules/semantic-release/node_modules/aggregate-error": {
       "version": "5.0.0",
       "resolved": 
"https://registry.npmjs.org/aggregate-error/-/aggregate-error-5.0.0.tgz";,
@@ -9237,9 +9258,9 @@
       }
     },
     "node_modules/semantic-release/node_modules/clean-stack": {
-      "version": "5.2.0",
-      "resolved": 
"https://registry.npmjs.org/clean-stack/-/clean-stack-5.2.0.tgz";,
-      "integrity": 
"sha512-TyUIUJgdFnCISzG5zu3291TAsE77ddchd0bepon1VVQrKLGKFED4iXFEDQ24mIPdPBbyE16PK3F8MYE1CmcBEQ==",
+      "version": "5.3.0",
+      "resolved": 
"https://registry.npmjs.org/clean-stack/-/clean-stack-5.3.0.tgz";,
+      "integrity": 
"sha512-9ngPTOhYGQqNVSfeJkYXHmF7AGWp4/nN5D/QqNQs3Dvxd1Kk/WpjHfNujKHYUQ/5CoGyOyFNoWSPk5afzP0QVg==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -9660,19 +9681,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/slash": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz";,
-      "integrity": 
"sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=14.16"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus";
-      }
-    },
     "node_modules/source-map": {
       "version": "0.6.1",
       "resolved": 
"https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz";,
@@ -9731,9 +9739,9 @@
       }
     },
     "node_modules/spdx-license-ids": {
-      "version": "3.0.21",
-      "resolved": 
"https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz";,
-      "integrity": 
"sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==",
+      "version": "3.0.22",
+      "resolved": 
"https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz";,
+      "integrity": 
"sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==",
       "dev": true,
       "license": "CC0-1.0"
     },
@@ -9863,9 +9871,9 @@
       }
     },
     "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==",
+      "version": "7.1.2",
+      "resolved": 
"https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz";,
+      "integrity": 
"sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -9903,9 +9911,9 @@
       }
     },
     "node_modules/strip-ansi/node_modules/ansi-regex": {
-      "version": "6.1.0",
-      "resolved": 
"https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz";,
-      "integrity": 
"sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+      "version": "6.2.2",
+      "resolved": 
"https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz";,
+      "integrity": 
"sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -10151,6 +10159,54 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/tinyglobby": {
+      "version": "0.2.15",
+      "resolved": 
"https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz";,
+      "integrity": 
"sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "fdir": "^6.5.0",
+        "picomatch": "^4.0.3"
+      },
+      "engines": {
+        "node": ">=12.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/SuperchupuDev";
+      }
+    },
+    "node_modules/tinyglobby/node_modules/fdir": {
+      "version": "6.5.0",
+      "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz";,
+      "integrity": 
"sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=12.0.0"
+      },
+      "peerDependencies": {
+        "picomatch": "^3 || ^4"
+      },
+      "peerDependenciesMeta": {
+        "picomatch": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/tinyglobby/node_modules/picomatch": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz";,
+      "integrity": 
"sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert";
+      }
+    },
     "node_modules/to-regex-range": {
       "version": "5.0.1",
       "resolved": 
"https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz";,
@@ -10649,9 +10705,9 @@
       }
     },
     "node_modules/yoctocolors": {
-      "version": "2.1.1",
-      "resolved": 
"https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.1.tgz";,
-      "integrity": 
"sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==",
+      "version": "2.1.2",
+      "resolved": 
"https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz";,
+      "integrity": 
"sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==",
       "dev": true,
       "license": "MIT",
       "engines": {
diff --git a/foreign/node/src/client/client.socket.ts 
b/foreign/node/src/client/client.socket.ts
index 08be5ce56..92df8b91b 100644
--- a/foreign/node/src/client/client.socket.ts
+++ b/foreign/node/src/client/client.socket.ts
@@ -84,7 +84,7 @@ export class CommandResponseStream extends EventEmitter {
     if (!this.isAuthenticated && !UNLOGGED_COMMAND_CODE.includes(command))
       await this.authenticate(this.options.credentials);
 
-    return new Promise(async (resolve, reject) => {
+    return new Promise((resolve, reject) => {
       if (last)
         this._execQueue.push({ command, payload, resolve, reject });
       else
diff --git a/foreign/node/src/e2e/tcp.cluster.e2e.ts 
b/foreign/node/src/e2e/tcp.cluster.e2e.ts
new file mode 100644
index 000000000..3a08ef222
--- /dev/null
+++ b/foreign/node/src/e2e/tcp.cluster.e2e.ts
@@ -0,0 +1,64 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+import { after, describe, it } from 'node:test';
+import assert from 'node:assert/strict';
+import { getTestClient } from './test-client.utils.js';
+
+// cluster mode still in dev atm
+// response is mocked from /core/configs/server.toml
+const expectedMeta = {
+  "name": "iggy-cluster",
+  "id": 1,
+  "transport": "TCP",
+  "nodes": [
+    {
+      "id": 1,
+      "name": "iggy-node-1",
+      "address": "127.0.0.1:8090",
+      "role": "Leader",
+      "status": "Healthy"
+    },
+    {
+      "id": 2,
+      "name": "iggy-node-2",
+      "address": "127.0.0.1:8091",
+      "role": "Follower",
+      "status": "Healthy"
+    }
+  ]
+};
+
+describe('e2e -> system', async () => {
+
+  const c = getTestClient();
+
+  it('e2e -> cluster::getClusterMetadata', async () => {
+    const meta = await c.cluster.getClusterMetadata();
+    assert.deepEqual(
+      meta,
+      expectedMeta
+    );
+  });
+
+  after(() => {
+    c.destroy();
+  });
+});
diff --git a/foreign/node/src/wire/cluster/cluster.type.ts 
b/foreign/node/src/wire/cluster/cluster.type.ts
new file mode 100644
index 000000000..e0cbe6af0
--- /dev/null
+++ b/foreign/node/src/wire/cluster/cluster.type.ts
@@ -0,0 +1,91 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { type ValueOf, reverseRecord } from "../../type.utils.js";
+
+export const ClusterNodeRole = {
+  Leader: 0,
+  Follower: 1
+} as const;
+
+export type ClusterNodeRole = typeof ClusterNodeRole;
+export type ClusterNodeRoleKey = keyof ClusterNodeRole;
+export type ClusterNodeRoleValue = ValueOf<ClusterNodeRole>;
+export const ReverseClusterNodeRole = reverseRecord(ClusterNodeRole);
+
+export const ClusterNodeStatus = {
+  // Node is healthy and responsive
+  Healthy: 0,
+  // Node is starting up
+  Starting: 1,
+  // Node is shutting down
+  Stopping: 2,
+  // Node is unreachable
+  Unreachable: 3,
+  // Node is in maintenance mode
+  Maintenance: 4,
+} as const;
+
+export type ClusterNodeStatus = typeof ClusterNodeStatus;
+export type ClusterNodeStatusKey = keyof ClusterNodeStatus;
+export type ClusterNodeStatusValue = ValueOf<ClusterNodeStatus>;
+export const ReverseClusterNodeStatus = reverseRecord(ClusterNodeStatus);
+
+
+export const TransportProtocol = {
+  TCP: 1,
+  QUIC: 2,
+  HTTP: 3
+} as const;
+
+export type TransportProtocol = typeof TransportProtocol;
+export type TransportProtocolKey = keyof TransportProtocol;
+export type TransportProtocolValue = ValueOf<TransportProtocol>;
+export const ReverseTransportProtocol = reverseRecord(TransportProtocol);
+
+
+export const isClusterNodeRole = (n: number): n is ClusterNodeRoleValue =>
+  n in ReverseClusterNodeRole;
+
+export const isClusterNodeStatus = (n: number): n is ClusterNodeStatusValue =>
+  n in ReverseClusterNodeStatus;
+
+export const isTransportProtocol = (n: number): n is TransportProtocolValue =>
+  n in ReverseTransportProtocol;
+
+
+export const mapClusterNodeRole = (n: number): ClusterNodeRoleKey => {
+  if(!isClusterNodeRole(n))
+    throw new Error('Invalid ClusterNodeRole', { cause: { role: n, 
ClusterNodeRole }});
+  return ReverseClusterNodeRole[n];
+}
+
+export const mapClusterNodeStatus = (n: number): ClusterNodeStatusKey => {
+  if(!isClusterNodeStatus(n))
+    throw new Error('Invalid ClusterNodeStatus', { cause: { status: n, 
ClusterNodeStatus }});
+  return ReverseClusterNodeStatus[n];
+}
+
+export const mapTransportProtocol = (n: number): TransportProtocolKey => {
+  if(!isTransportProtocol(n))
+    throw new Error(
+      'Invalid TransportProtocol', { cause: { transport: n, TransportProtocol 
} }
+    );
+  return ReverseTransportProtocol[n];
+}
diff --git a/foreign/node/src/wire/cluster/cluster.utils.ts 
b/foreign/node/src/wire/cluster/cluster.utils.ts
new file mode 100644
index 000000000..2913389f5
--- /dev/null
+++ b/foreign/node/src/wire/cluster/cluster.utils.ts
@@ -0,0 +1,151 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { deserializeError } from '../error.utils.js';
+
+import {
+  type ClusterNodeRoleKey,
+  type ClusterNodeStatusKey,
+  type TransportProtocolKey,
+  mapClusterNodeRole,
+  mapClusterNodeStatus,
+  mapTransportProtocol,
+} from './cluster.type.js';
+
+
+export type ClusterNode = {
+  id: number
+  name: string
+  address: string
+  role: ClusterNodeRoleKey
+  status: ClusterNodeStatusKey
+}
+
+type DeserializedClusterNode = { length: number, data: ClusterNode }
+
+const CLUSTER_NODE_MIN_BUFFER_SIZE = 16; // 4 + 1 + 4 + 1 + 4 + 1 + 1;
+
+export const deserializeNode = (b: Buffer, pos = 0): DeserializedClusterNode 
=> {
+  if (b.length - pos < CLUSTER_NODE_MIN_BUFFER_SIZE)
+    deserializeError(
+      'cluster node', pos, b.length, CLUSTER_NODE_MIN_BUFFER_SIZE
+    );
+
+  const id = b.readUInt32LE(pos);
+  pos += 4;
+
+  const nameLen = b.readUInt32LE(pos);
+  if (b.length - pos < 4 + nameLen)
+    deserializeError(
+      'cluster node', pos, b.length, 4 + nameLen, { id, nameLen }
+    );
+
+  const name = b.subarray(pos + 4, pos + 4 + nameLen).toString();
+  pos += nameLen + 4;
+
+  const addrLen = b.readUInt32LE(pos);
+  if (b.length - pos < 4 + addrLen)
+    deserializeError(
+      'cluster node', pos, b.length, 4 + addrLen, { id, nameLen, name, addrLen 
}
+    );
+
+  const address = b.subarray(pos + 4, pos + 4 + addrLen).toString();
+  pos += addrLen + 4;
+
+  if (b.length - pos < 2)
+    deserializeError(
+      'cluster node', pos, b.length, 2, { id, nameLen, name, addrLen, address }
+    );
+
+  const role = mapClusterNodeRole(b.readUInt8(pos));
+  pos += 1;
+
+  const status = mapClusterNodeStatus(b.readUInt8(pos));
+  pos += 1;
+
+  return {
+    length: 4 + nameLen + 4 + addrLen + 4 + 1 + 1,
+    data: {
+      id,
+      name,
+      address,
+      role,
+      status
+    }
+  }
+};
+
+export type ClusterMetadata = {
+  // Name of the cluster.
+  name: string,
+  // Unique identifier of the cluster.
+  id: number,
+  // Transport used for cluster communication
+  // (for binary protocol it's u8, 1=TCP, 2=QUIC, 3=HTTP).
+  transport: TransportProtocolKey,
+  // List of all nodes in the cluster.
+  nodes: ClusterNode[],
+};
+
+// min = 4 + 1 + 4 + 1 + 1 + 4 + CLUSTER_NODE_MIN_BUFFER_SIZE;
+const CLUSTER_METADATA_MIN_SIZE = 15 + CLUSTER_NODE_MIN_BUFFER_SIZE;
+
+export const deserializeMetadata = (b: Buffer, pos = 0): ClusterMetadata => {
+  if (b.length - pos < CLUSTER_METADATA_MIN_SIZE)
+    deserializeError(
+      'cluster metadata', pos, b.length, CLUSTER_METADATA_MIN_SIZE
+    );
+
+  const nameLen = b.readUInt32LE(pos);
+  if (b.length - pos < 4 + nameLen)
+    deserializeError(
+      'cluster metadata', pos, b.length, 4 + nameLen, { nameLen }
+    );
+
+  const name = b.subarray(pos + 4, pos + 4 + nameLen).toString();
+  pos += nameLen + 4;
+
+  if (b.length - pos < 4 + 1 + 4)
+    deserializeError(
+      'cluster metadata', pos, b.length, 4 + 1 + 4, { nameLen, name }
+    );
+
+  const id = b.readUInt32LE(pos);
+  pos += 4;
+
+  const transport = mapTransportProtocol(b.readUInt8(pos));
+  pos += 1;
+
+  const nodeCount = b.readUInt32LE(pos);
+  pos += 4;
+
+  const nodes: ClusterNode[] = [];
+  for (let i = 0; i < nodeCount; i++) {
+    const { length, data } = deserializeNode(b, pos);
+    nodes.push(data);
+    pos += length;
+  }
+
+  return {
+    name,
+    id,
+    transport,
+    nodes
+  }
+};
diff --git a/foreign/node/src/wire/error.utils.ts 
b/foreign/node/src/wire/cluster/get-cluster-metadata.command.ts
similarity index 59%
copy from foreign/node/src/wire/error.utils.ts
copy to foreign/node/src/wire/cluster/get-cluster-metadata.command.ts
index 9a97ddfb8..5aec29820 100644
--- a/foreign/node/src/wire/error.utils.ts
+++ b/foreign/node/src/wire/cluster/get-cluster-metadata.command.ts
@@ -17,11 +17,21 @@
  * under the License.
  */
 
+import type { CommandResponse } from '../../client/index.js';
+import { wrapCommand } from '../command.utils.js';
+import { COMMAND_CODE } from '../command.code.js';
+import { deserializeMetadata, type ClusterMetadata } from './cluster.utils.js';
 
-import { translateCommandCode } from './command.code.js';
-import { translateErrorCode } from './error.code.js';
 
-export const responseError = (cmdCode: number, errCode: number) => new Error(
-  `command: { code: ${cmdCode}, name: ${translateCommandCode(cmdCode)} } ` +
-  `error: {code: ${errCode}, message: ${translateErrorCode(errCode)} }`
-);
+export const GET_CLUSTER_METADATA = {
+  code: COMMAND_CODE.GetClusterMetadata,
+  
+  serialize: () => {
+    return Buffer.alloc(0);
+  },
+
+  deserialize: (r: CommandResponse): ClusterMetadata => 
deserializeMetadata(r.data)
+};
+
+
+export const getClusterMetadata = wrapCommand<void, 
ClusterMetadata>(GET_CLUSTER_METADATA);
diff --git a/foreign/node/src/wire/error.utils.ts 
b/foreign/node/src/wire/cluster/index.ts
similarity index 70%
copy from foreign/node/src/wire/error.utils.ts
copy to foreign/node/src/wire/cluster/index.ts
index 9a97ddfb8..f5927ee73 100644
--- a/foreign/node/src/wire/error.utils.ts
+++ b/foreign/node/src/wire/cluster/index.ts
@@ -17,11 +17,5 @@
  * under the License.
  */
 
-
-import { translateCommandCode } from './command.code.js';
-import { translateErrorCode } from './error.code.js';
-
-export const responseError = (cmdCode: number, errCode: number) => new Error(
-  `command: { code: ${cmdCode}, name: ${translateCommandCode(cmdCode)} } ` +
-  `error: {code: ${errCode}, message: ${translateErrorCode(errCode)} }`
-);
+export * from './get-cluster-metadata.command.js';
+export * from './cluster.type.js';
diff --git a/foreign/node/src/wire/command-set.ts 
b/foreign/node/src/wire/command-set.ts
index 941f3429e..4b4f8339c 100644
--- a/foreign/node/src/wire/command-set.ts
+++ b/foreign/node/src/wire/command-set.ts
@@ -70,6 +70,8 @@ import { deleteSegments } from 
'./segment/delete-segments.command.js';
 import { getStats } from './system/get-stats.command.js';
 import { ping } from './system/ping.command.js';
 
+import { getClusterMetadata } from './cluster/get-cluster-metadata.command.js';
+
 import { getTokens } from './token/get-tokens.command.js';
 import { createToken } from './token/create-token.command.js';
 import { deleteToken } from './token/delete-token.command.js';
@@ -192,6 +194,13 @@ const systemAPI = (c: ClientProvider) => ({
 
 type SystemAPI = ReturnType<typeof systemAPI>;
 
+const clusterAPI = (c: ClientProvider) => ({
+  getClusterMetadata: getClusterMetadata(c)
+});
+
+type ClusterAPI = ReturnType<typeof clusterAPI>;
+
+
 export abstract class AbstractAPI {
   clientProvider: ClientProvider;
 
@@ -213,6 +222,7 @@ export abstract class CommandAPI extends AbstractAPI {
   offset: OffsetAPI = offsetAPI(this.clientProvider);
   message: MessageAPI = messageAPI(this.clientProvider);
   system: SystemAPI = systemAPI(this.clientProvider);
+  cluster: ClusterAPI = clusterAPI(this.clientProvider);
 
   constructor(c: ClientProvider) {
     super(c);
diff --git a/foreign/node/src/wire/command.code.ts 
b/foreign/node/src/wire/command.code.ts
index 1b0199c04..3f4c8130c 100644
--- a/foreign/node/src/wire/command.code.ts
+++ b/foreign/node/src/wire/command.code.ts
@@ -24,6 +24,7 @@ export const COMMAND_CODE = {
   Ping: 1,
   GetStats: 10,
   GetSnapshot: 11,                    // @TODO GET_SNAPSHOT_FILE_CODE: u32 = 11
+  GetClusterMetadata: 12,             // GET_CLUSTER_METADATA_CODE: u32 = 12
   GetMe: 20,
   GetClient: 21,
   GetClients: 22,
diff --git a/foreign/node/src/wire/command.utils.ts 
b/foreign/node/src/wire/command.utils.ts
index 703f4dc75..5e5ff9196 100644
--- a/foreign/node/src/wire/command.utils.ts
+++ b/foreign/node/src/wire/command.utils.ts
@@ -28,13 +28,6 @@ export type Command<I, O> = {
   deserialize: (r: CommandResponse) => O
 }
 
-// export function wrapCommand<I, O>(cmd: Command<I, O>) {
-//   return (client: RawClient) =>
-//     async (arg: I) => cmd.deserialize(
-//       await client.sendCommand(cmd.code, cmd.serialize(arg))
-//     );
-// };
-
 
 export function wrapCommand<I, O>(cmd: Command<I, O>) {
   return (getClient: ClientProvider) =>
diff --git a/foreign/node/src/wire/error.utils.ts 
b/foreign/node/src/wire/error.utils.ts
index 9a97ddfb8..d05a04590 100644
--- a/foreign/node/src/wire/error.utils.ts
+++ b/foreign/node/src/wire/error.utils.ts
@@ -25,3 +25,24 @@ export const responseError = (cmdCode: number, errCode: 
number) => new Error(
   `command: { code: ${cmdCode}, name: ${translateCommandCode(cmdCode)} } ` +
   `error: {code: ${errCode}, message: ${translateErrorCode(errCode)} }`
 );
+
+export class DeserializeError extends Error {
+  constructor(message: string, cause?: Record<string , unknown>) {
+    super(message, cause);
+    this.name = "DeserializeError";
+    Object.setPrototypeOf(this, DeserializeError.prototype);
+  }
+}
+
+export const deserializeError = (
+  name: string,
+  position: number,
+  buffer_size: number,
+  lookup?: number,
+  read?: Record<string, unknown>
+) => {
+  throw new DeserializeError(
+    `cannot deserialize ${name}: buffer too small`,
+    { cause: { position, buffer_size, lookup, read } }
+  );
+}
diff --git a/foreign/node/src/wire/system/get-stats.command.ts 
b/foreign/node/src/wire/system/get-stats.command.ts
index e9d4e5de5..0d3c6ad99 100644
--- a/foreign/node/src/wire/system/get-stats.command.ts
+++ b/foreign/node/src/wire/system/get-stats.command.ts
@@ -18,7 +18,7 @@
  */
 
 
-import type { CommandResponse } from '../../client/client.type.js';
+import type { CommandResponse } from '../../client/index.js';
 import { COMMAND_CODE } from '../command.code.js';
 import { wrapCommand } from '../command.utils.js';
 

Reply via email to