diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index abf9756c6f..140d0911d3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node: ['23', '22', '20', '18'] + node: ['24', '23', '22', '20', '18'] name: Node ${{ matrix.node }} validation steps: - uses: actions/checkout@v4.2.2 diff --git a/README.md b/README.md index c8bab32e0c..1baec2c3a3 100644 --- a/README.md +++ b/README.md @@ -114,14 +114,15 @@ We switched from `request` to `fetch` as the HTTP(S) backend for the `1.0.0` rel Generally speaking newer clients will work with older Kubernetes, but compatability isn't 100% guaranteed. -| client version | older versions | 1.28 | 1.29 | 1.30 | 1.31 | 1.32 | -| -------------- | -------------- | ---- | ---- | ---- | ---- | ---- | -| 0.19.x | - | ✓ | x | x | x | x | -| 0.20.x | - | + | ✓ | x | x | x | -| 0.21.x | - | + | + | ✓ | x | x | -| 0.22.x | - | + | + | + | ✓ | x | -| 1.0.x | - | + | + | + | + | ✓ | -| 1.1.x | - | + | + | + | + | ✓ | +| client version | older versions | 1.28 | 1.29 | 1.30 | 1.31 | 1.32 | 1.33| +| -------------- | -------------- | ---- | ---- | ---- | ---- | ---- |----| +| 0.19.x | - | ✓ | x | x | x | x | x | +| 0.20.x | - | + | ✓ | x | x | x | x | +| 0.21.x | - | + | + | ✓ | x | x | x | +| 0.22.x | - | + | + | + | ✓ | x | x | +| 1.0.x | - | + | + | + | + | ✓ | x | +| 1.1.x | - | + | + | + | + | ✓ | x | +| 1.2.x | - | + | + | + | + | + | ✓ | Key: diff --git a/package-lock.json b/package-lock.json index 9dcae7a648..2668113ed2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@kubernetes/client-node", - "version": "1.2.0", + "version": "1.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@kubernetes/client-node", - "version": "1.2.0", + "version": "1.3.0", "license": "Apache-2.0", "dependencies": { "@types/js-yaml": "^4.0.1", @@ -23,7 +23,8 @@ "rfc4648": "^1.3.0", "socks-proxy-agent": "^8.0.4", "stream-buffers": "^3.0.2", - "tar-fs": "^3.0.8" + "tar-fs": "^3.0.8", + "ws": "^8.18.2" }, "devDependencies": { "@eslint/js": "^9.18.0", @@ -570,9 +571,9 @@ } }, "node_modules/@eslint/core": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", - "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz", + "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -631,13 +632,16 @@ } }, "node_modules/@eslint/js": { - "version": "9.26.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.26.0.tgz", - "integrity": "sha512-I9XlJawFdSMvWjDt6wksMCrgns5ggLNfFwFvnShsleWruvXM514Qxk8V246efTw+eo9JABvVz+u3q2RiAowKxQ==", + "version": "9.27.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.27.0.tgz", + "integrity": "sha512-G5JD9Tu5HJEu4z2Uo4aHY2sLV64B7CDMXxFzqzjl3NKd6RVzSXNoE80jk7Y0lJkTTkjiIhBAqmlYwjuBY3tvpA==", "dev": true, "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" } }, "node_modules/@eslint/object-schema": { @@ -651,13 +655,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz", - "integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz", + "integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.13.0", + "@eslint/core": "^0.14.0", "levn": "^0.4.1" }, "engines": { @@ -824,28 +828,6 @@ "jsep": "^0.4.0||^1.0.0" } }, - "node_modules/@modelcontextprotocol/sdk": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.11.0.tgz", - "integrity": "sha512-k/1pb70eD638anoi0e8wUGAlbMJXyvdV4p62Ko+EZ7eBe1xMx8Uhak1R5DgfoofsK5IBBnRwsYGTaLZl+6/+RQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "content-type": "^1.0.5", - "cors": "^2.8.5", - "cross-spawn": "^7.0.3", - "eventsource": "^3.0.2", - "express": "^5.0.1", - "express-rate-limit": "^7.5.0", - "pkce-challenge": "^5.0.0", - "raw-body": "^3.0.0", - "zod": "^3.23.8", - "zod-to-json-schema": "^3.24.1" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -992,9 +974,9 @@ } }, "node_modules/@types/node": { - "version": "22.15.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.11.tgz", - "integrity": "sha512-rlyK0vuU7VLEYQfXuC7QTFxDvkb6tKhDI7wR4r6ZzM0k8BJd44W0jxo6xmUjqSs4AlYmiYfLJU2f0pAG/FtCRw==", + "version": "22.15.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.23.tgz", + "integrity": "sha512-7Ec1zaFPF4RJ0eXu1YT/xgiebqwqoJz8rYPDi/O2BcZ++Wpt0Kq9cl0eg6NN6bYbPnR67ZLo7St5Q3UK0SnARw==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -1027,19 +1009,19 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.0.tgz", - "integrity": "sha512-/jU9ettcntkBFmWUzzGgsClEi2ZFiikMX5eEQsmxIAWMOn4H3D4rvHssstmAHGVvrYnaMqdWWWg0b5M6IN/MTQ==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.33.0.tgz", + "integrity": "sha512-CACyQuqSHt7ma3Ns601xykeBK/rDeZa3w6IS6UtMQbixO5DWy+8TilKkviGDH6jtWCo8FGRKEK5cLLkPvEammQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.32.0", - "@typescript-eslint/type-utils": "8.32.0", - "@typescript-eslint/utils": "8.32.0", - "@typescript-eslint/visitor-keys": "8.32.0", + "@typescript-eslint/scope-manager": "8.33.0", + "@typescript-eslint/type-utils": "8.33.0", + "@typescript-eslint/utils": "8.33.0", + "@typescript-eslint/visitor-keys": "8.33.0", "graphemer": "^1.4.0", - "ignore": "^5.3.1", + "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, @@ -1051,22 +1033,32 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "@typescript-eslint/parser": "^8.33.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.4.tgz", + "integrity": "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/@typescript-eslint/parser": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.32.0.tgz", - "integrity": "sha512-B2MdzyWxCE2+SqiZHAjPphft+/2x2FlO9YBx7eKE1BCb+rqBlQdhtAEhzIEdozHd55DXPmxBdpMygFJjfjjA9A==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.33.0.tgz", + "integrity": "sha512-JaehZvf6m0yqYp34+RVnihBAChkqeH+tqqhS0GuX1qgPpwLvmTPheKEs6OeCK6hVJgXZHJ2vbjnC9j119auStQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.32.0", - "@typescript-eslint/types": "8.32.0", - "@typescript-eslint/typescript-estree": "8.32.0", - "@typescript-eslint/visitor-keys": "8.32.0", + "@typescript-eslint/scope-manager": "8.33.0", + "@typescript-eslint/types": "8.33.0", + "@typescript-eslint/typescript-estree": "8.33.0", + "@typescript-eslint/visitor-keys": "8.33.0", "debug": "^4.3.4" }, "engines": { @@ -1081,33 +1073,69 @@ "typescript": ">=4.8.4 <5.9.0" } }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.33.0.tgz", + "integrity": "sha512-d1hz0u9l6N+u/gcrk6s6gYdl7/+pp8yHheRTqP6X5hVDKALEaTn8WfGiit7G511yueBEL3OpOEpD+3/MBdoN+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.33.0", + "@typescript-eslint/types": "^8.33.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.0.tgz", - "integrity": "sha512-jc/4IxGNedXkmG4mx4nJTILb6TMjL66D41vyeaPWvDUmeYQzF3lKtN15WsAeTr65ce4mPxwopPSo1yUUAWw0hQ==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.33.0.tgz", + "integrity": "sha512-LMi/oqrzpqxyO72ltP+dBSP6V0xiUb4saY7WLtxSfiNEBI8m321LLVFU9/QDJxjDQG9/tjSqKz/E3380TEqSTw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.32.0", - "@typescript-eslint/visitor-keys": "8.32.0" + "@typescript-eslint/types": "8.33.0", + "@typescript-eslint/visitor-keys": "8.33.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.33.0.tgz", + "integrity": "sha512-sTkETlbqhEoiFmGr1gsdq5HyVbSOF0145SYDJ/EQmXHtKViCaGvnyLqWFFHtEXoS0J1yU8Wyou2UGmgW88fEug==", + "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.32.0.tgz", - "integrity": "sha512-t2vouuYQKEKSLtJaa5bB4jHeha2HJczQ6E5IXPDPgIty9EqcJxpr1QHQ86YyIPwDwxvUmLfP2YADQ5ZY4qddZg==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.33.0.tgz", + "integrity": "sha512-lScnHNCBqL1QayuSrWeqAL5GmqNdVUQAAMTaCwdYEdWfIrSrOGzyLGRCHXcCixa5NK6i5l0AfSO2oBSjCjf4XQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.32.0", - "@typescript-eslint/utils": "8.32.0", + "@typescript-eslint/typescript-estree": "8.33.0", + "@typescript-eslint/utils": "8.33.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -1124,9 +1152,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.0.tgz", - "integrity": "sha512-O5Id6tGadAZEMThM6L9HmVf5hQUXNSxLVKeGJYWNhhVseps/0LddMkp7//VDkzwJ69lPL0UmZdcZwggj9akJaA==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.33.0.tgz", + "integrity": "sha512-DKuXOKpM5IDT1FA2g9x9x1Ug81YuKrzf4mYX8FAVSNu5Wo/LELHWQyM1pQaDkI42bX15PWl0vNPt1uGiIFUOpg==", "dev": true, "license": "MIT", "engines": { @@ -1138,14 +1166,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.0.tgz", - "integrity": "sha512-pU9VD7anSCOIoBFnhTGfOzlVFQIA1XXiQpH/CezqOBaDppRwTglJzCC6fUQGpfwey4T183NKhF1/mfatYmjRqQ==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.33.0.tgz", + "integrity": "sha512-vegY4FQoB6jL97Tu/lWRsAiUUp8qJTqzAmENH2k59SJhw0Th1oszb9Idq/FyyONLuNqT1OADJPXfyUNOR8SzAQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.32.0", - "@typescript-eslint/visitor-keys": "8.32.0", + "@typescript-eslint/project-service": "8.33.0", + "@typescript-eslint/tsconfig-utils": "8.33.0", + "@typescript-eslint/types": "8.33.0", + "@typescript-eslint/visitor-keys": "8.33.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1165,16 +1195,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.0.tgz", - "integrity": "sha512-8S9hXau6nQ/sYVtC3D6ISIDoJzS1NsCK+gluVhLN2YkBPX+/1wkwyUiDKnxRh15579WoOIyVWnoyIf3yGI9REw==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.33.0.tgz", + "integrity": "sha512-lPFuQaLA9aSNa7D5u2EpRiqdAUhzShwGg/nhpBlc4GR6kcTABttCuyjFs8BcEZ8VWrjCBof/bePhP3Q3fS+Yrw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.32.0", - "@typescript-eslint/types": "8.32.0", - "@typescript-eslint/typescript-estree": "8.32.0" + "@typescript-eslint/scope-manager": "8.33.0", + "@typescript-eslint/types": "8.33.0", + "@typescript-eslint/typescript-estree": "8.33.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1189,13 +1219,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.0.tgz", - "integrity": "sha512-1rYQTCLFFzOI5Nl0c8LUpJT8HxpwVRn9E4CkMsYfuN6ctmQqExjSTzzSk0Tz2apmXy7WU6/6fyaZVVA/thPN+w==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.33.0.tgz", + "integrity": "sha512-7RW7CMYoskiz5OOGAWjJFxgb7c5UNjTG292gYhWeOAcFmYCtVCSqjqSBj5zMhxbXo2JOW95YYrUWJfU0zrpaGQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.32.0", + "@typescript-eslint/types": "8.33.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -1206,43 +1236,6 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/accepts/node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/accepts/node_modules/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/acorn": { "version": "8.14.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", @@ -1418,27 +1411,6 @@ } } }, - "node_modules/body-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", - "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "bytes": "^3.1.2", - "content-type": "^1.0.5", - "debug": "^4.4.0", - "http-errors": "^2.0.0", - "iconv-lite": "^0.6.3", - "on-finished": "^2.4.1", - "qs": "^6.14.0", - "raw-body": "^3.0.0", - "type-is": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -1462,16 +1434,6 @@ "node": ">=8" } }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/c8": { "version": "10.1.3", "resolved": "https://registry.npmjs.org/c8/-/c8-10.1.3.tgz", @@ -1529,23 +1491,6 @@ "node": ">= 0.4" } }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1690,29 +1635,6 @@ "dev": true, "license": "MIT" }, - "node_modules/content-disposition": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", - "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -1720,40 +1642,6 @@ "dev": true, "license": "MIT" }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.6.0" - } - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -1802,16 +1690,6 @@ "node": ">=0.4.0" } }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -1833,13 +1711,6 @@ "dev": true, "license": "MIT" }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true, - "license": "MIT" - }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -1847,16 +1718,6 @@ "dev": true, "license": "MIT" }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -1975,13 +1836,6 @@ "node": ">=6" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true, - "license": "MIT" - }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -1996,9 +1850,9 @@ } }, "node_modules/eslint": { - "version": "9.26.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.26.0.tgz", - "integrity": "sha512-Hx0MOjPh6uK9oq9nVsATZKE/Wlbai7KFjfCuw9UHaguDW3x+HF0O5nIi3ud39TWgrTjTO5nHxmL3R1eANinWHQ==", + "version": "9.27.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.27.0.tgz", + "integrity": "sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q==", "dev": true, "license": "MIT", "dependencies": { @@ -2006,14 +1860,13 @@ "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.20.0", "@eslint/config-helpers": "^0.2.1", - "@eslint/core": "^0.13.0", + "@eslint/core": "^0.14.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.26.0", - "@eslint/plugin-kit": "^0.2.8", + "@eslint/js": "9.27.0", + "@eslint/plugin-kit": "^0.3.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", - "@modelcontextprotocol/sdk": "^1.8.0", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -2037,8 +1890,7 @@ "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "zod": "^3.24.2" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" @@ -2195,121 +2047,6 @@ "node": ">=0.10.0" } }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventsource": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.6.tgz", - "integrity": "sha512-l19WpE2m9hSuyP06+FbuUUf1G+R0SFLrtQfbRb9PRr+oimOfxQhgGCbVaXg5IvZyyTThJsxh6L/srkMiCeBPDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eventsource-parser": "^3.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/eventsource-parser": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.1.tgz", - "integrity": "sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/express": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", - "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "accepts": "^2.0.0", - "body-parser": "^2.2.0", - "content-disposition": "^1.0.0", - "content-type": "^1.0.5", - "cookie": "^0.7.1", - "cookie-signature": "^1.2.1", - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "finalhandler": "^2.1.0", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "merge-descriptors": "^2.0.0", - "mime-types": "^3.0.0", - "on-finished": "^2.4.1", - "once": "^1.4.0", - "parseurl": "^1.3.3", - "proxy-addr": "^2.0.7", - "qs": "^6.14.0", - "range-parser": "^1.2.1", - "router": "^2.2.0", - "send": "^1.1.0", - "serve-static": "^2.2.0", - "statuses": "^2.0.1", - "type-is": "^2.0.1", - "vary": "^1.1.2" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/express-rate-limit": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.0.tgz", - "integrity": "sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://github.com/sponsors/express-rate-limit" - }, - "peerDependencies": { - "express": "^4.11 || 5 || ^5.0.0-beta.1" - } - }, - "node_modules/express/node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express/node_modules/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2403,24 +2140,6 @@ "node": ">=8" } }, - "node_modules/finalhandler": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", - "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "on-finished": "^2.4.1", - "parseurl": "^1.3.3", - "statuses": "^2.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -2491,26 +2210,6 @@ "node": ">= 6" } }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -2736,23 +2435,6 @@ "dev": true, "license": "MIT" }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/husky": { "version": "9.1.7", "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", @@ -2769,19 +2451,6 @@ "url": "https://github.com/sponsors/typicode" } }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -2819,13 +2488,6 @@ "node": ">=0.8.19" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, "node_modules/ip-address": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", @@ -2839,16 +2501,6 @@ "node": ">= 12" } }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2892,13 +2544,6 @@ "node": ">=0.12.0" } }, - "node_modules/is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", - "dev": true, - "license": "MIT" - }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -3180,29 +2825,6 @@ "dev": true, "license": "MIT" }, - "node_modules/media-typer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/merge-descriptors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -3297,16 +2919,6 @@ "dev": true, "license": "MIT" }, - "node_modules/negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/nock": { "version": "13.5.6", "resolved": "https://registry.npmjs.org/nock/-/nock-13.5.6.tgz", @@ -3343,50 +2955,14 @@ } }, "node_modules/oauth4webapi": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.4.1.tgz", - "integrity": "sha512-sPv0Phrf0HjFNRr23b1yC7Q9VAeri3fdrx4sr4KKN6PmLLY/zJD3B4UHLs/p7oYlFBbxJVl/VI6bSvjmKBoexg==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.5.1.tgz", + "integrity": "sha512-txg/jZQwcbaF7PMJgY7aoxc9QuCxHVFMiEkDIJ60DwDz3PbtXPQnrzo+3X4IRYGChIwWLabRBRpf1k9hO9+xrQ==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/panva" } }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3397,13 +2973,13 @@ } }, "node_modules/openid-client": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-6.4.2.tgz", - "integrity": "sha512-4zBRTsKNRTyKxV5cFzl+LtamsYx/FsWhejjax+qgMkFNGtLj1gMtng2iSoJqqWUT0FHU3IUhO53aeBePg7Sp/g==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-6.5.0.tgz", + "integrity": "sha512-fAfYaTnOYE2kQCqEJGX9KDObW2aw7IQy4jWpU/+3D3WoCFLbix5Hg6qIPQ6Js9r7f8jDUmsnnguRNCSw4wU/IQ==", "license": "MIT", "dependencies": { "jose": "^6.0.10", - "oauth4webapi": "^3.4.1" + "oauth4webapi": "^3.5.1" }, "funding": { "url": "https://github.com/sponsors/panva" @@ -3479,16 +3055,6 @@ "node": ">=6" } }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -3536,16 +3102,6 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/path-to-regexp": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", - "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - } - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -3566,16 +3122,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pkce-challenge": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", - "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16.20.0" - } - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -3660,20 +3206,6 @@ "node": ">= 8" } }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/pump": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", @@ -3704,22 +3236,6 @@ "node": ">=6" } }, - "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -3741,32 +3257,6 @@ ], "license": "MIT" }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", - "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.6.3", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -3814,23 +3304,6 @@ "integrity": "sha512-rRg/6Lb+IGfJqO05HZkN50UtY7K/JhxJag1kP23+zyMfrvoB0B7RWv06MbOzoc79RgCdNTiUaNsTT1AJZ7Z+cg==", "license": "MIT" }, - "node_modules/router": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", - "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "depd": "^2.0.0", - "is-promise": "^4.0.0", - "parseurl": "^1.3.3", - "path-to-regexp": "^8.0.0" - }, - "engines": { - "node": ">= 18" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -3855,34 +3328,6 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "license": "MIT" - }, "node_modules/semver": { "version": "7.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", @@ -3896,75 +3341,6 @@ "node": ">=10" } }, - "node_modules/send": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", - "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.5", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "mime-types": "^3.0.1", - "ms": "^2.1.3", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "statuses": "^2.0.1" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/send/node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/send/node_modules/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-static": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", - "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "parseurl": "^1.3.3", - "send": "^1.2.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true, - "license": "ISC" - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -3988,82 +3364,6 @@ "node": ">=8" } }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -4121,16 +3421,6 @@ "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", "license": "BSD-3-Clause" }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/stream-buffers": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-3.0.3.tgz", @@ -4284,9 +3574,9 @@ } }, "node_modules/tar-fs": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.8.tgz", - "integrity": "sha512-ZoROL70jptorGAlgAYiLoBLItEKw/fUxg9BSYK/dF/GAGYFJOJJJMvjPAKDJraCXFwadD456FCuvLWgfhMsPwg==", + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.9.tgz", + "integrity": "sha512-XF4w9Xp+ZQgifKakjZYmFdkLoSWd34VGKcsTCwlNWM7QG3ZbaxnTsaBwnjFZqHRf/rROxaR8rXnbtwdvaDI+lA==", "license": "MIT", "dependencies": { "pump": "^3.0.0", @@ -4352,16 +3642,6 @@ "node": ">=8.0" } }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -4431,48 +3711,10 @@ "node": ">= 0.8.0" } }, - "node_modules/type-is": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", - "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", - "dev": true, - "license": "MIT", - "dependencies": { - "content-type": "^1.0.5", - "media-typer": "^1.1.0", - "mime-types": "^3.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/type-is/node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/type-is/node_modules/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/typedoc": { - "version": "0.28.4", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.28.4.tgz", - "integrity": "sha512-xKvKpIywE1rnqqLgjkoq0F3wOqYaKO9nV6YkkSat6IxOWacUCc/7Es0hR3OPmkIqkPoEn7U3x+sYdG72rstZQA==", + "version": "0.28.5", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.28.5.tgz", + "integrity": "sha512-5PzUddaA9FbaarUzIsEc4wNXCiO4Ot3bJNeMF2qKpYlTmM9TTaSHQ7162w756ERCkXER/+o2purRG6YOAv6EMA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -4508,15 +3750,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.32.0.tgz", - "integrity": "sha512-UMq2kxdXCzinFFPsXc9o2ozIpYCCOiEC46MG3yEh5Vipq6BO27otTtEBZA1fQ66DulEUgE97ucQ/3YY66CPg0A==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.33.0.tgz", + "integrity": "sha512-5YmNhF24ylCsvdNW2oJwMzTbaeO4bg90KeGtMjUw0AGtHksgEPLRTUil+coHwCfiu4QjVJFnjp94DmU6zV7DhQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.32.0", - "@typescript-eslint/parser": "8.32.0", - "@typescript-eslint/utils": "8.32.0" + "@typescript-eslint/eslint-plugin": "8.33.0", + "@typescript-eslint/parser": "8.33.0", + "@typescript-eslint/utils": "8.33.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4543,16 +3785,6 @@ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "license": "MIT" }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -4578,16 +3810,6 @@ "node": ">=10.12.0" } }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -4732,11 +3954,10 @@ "license": "ISC" }, "node_modules/ws": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", + "version": "8.18.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz", + "integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=10.0.0" }, @@ -4862,26 +4083,6 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } - }, - "node_modules/zod": { - "version": "3.24.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.4.tgz", - "integrity": "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-to-json-schema": { - "version": "3.24.5", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz", - "integrity": "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==", - "dev": true, - "license": "ISC", - "peerDependencies": { - "zod": "^3.24.1" - } } } } diff --git a/package.json b/package.json index 4d3feb52aa..36e5747468 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kubernetes/client-node", - "version": "1.2.0", + "version": "1.3.0", "description": "NodeJS client for kubernetes", "type": "module", "repository": { @@ -69,7 +69,8 @@ "rfc4648": "^1.3.0", "socks-proxy-agent": "^8.0.4", "stream-buffers": "^3.0.2", - "tar-fs": "^3.0.8" + "tar-fs": "^3.0.8", + "ws": "^8.18.2" }, "devDependencies": { "@eslint/js": "^9.18.0", diff --git a/src/azure_auth.ts b/src/azure_auth.ts index 1b69048ddd..2db7c6601e 100644 --- a/src/azure_auth.ts +++ b/src/azure_auth.ts @@ -29,7 +29,7 @@ export class AzureAuth implements Authenticator { public async applyAuthentication(user: User, opts: https.RequestOptions): Promise { const token = this.getToken(user); if (token) { - opts.headers!.Authorization = `Bearer ${token}`; + opts.headers!['Authorization'] = `Bearer ${token}`; } } diff --git a/src/cache.ts b/src/cache.ts index af5e5bc852..be9bf6688f 100644 --- a/src/cache.ts +++ b/src/cache.ts @@ -34,6 +34,7 @@ export class ListWatch implements ObjectCache, In private readonly watch: Watch; private readonly listFn: ListPromise; private readonly labelSelector?: string; + private readonly fieldSelector?: string; public constructor( path: string, @@ -41,11 +42,13 @@ export class ListWatch implements ObjectCache, In listFn: ListPromise, autoStart: boolean = true, labelSelector?: string, + fieldSelector?: string, ) { this.path = path; this.watch = watch; this.listFn = listFn; this.labelSelector = labelSelector; + this.fieldSelector = fieldSelector; this.callbackCache[ADD] = []; this.callbackCache[UPDATE] = []; @@ -140,7 +143,10 @@ export class ListWatch implements ObjectCache, In private async doneHandler(err: any): Promise { this._stop(); - if (err && err.statusCode === 410) { + if ( + err && + ((err as { statusCode?: number }).statusCode === 410 || (err as { code?: number }).code === 410) + ) { this.resourceVersion = ''; } else if (err) { this.callbackCache[ERROR].forEach((elt: ErrorCallback) => elt(err)); @@ -162,17 +168,21 @@ export class ListWatch implements ObjectCache, In } this.objects = deleteItems(this.objects, list.items, this.callbackCache[DELETE].slice()); this.addOrUpdateItems(list.items); - this.resourceVersion = list.metadata!.resourceVersion || ''; + this.resourceVersion = list.metadata ? list.metadata!.resourceVersion || '' : ''; } const queryParams = { resourceVersion: this.resourceVersion, } as { resourceVersion: string | undefined; labelSelector: string | undefined; + fieldSelector: string | undefined; }; if (this.labelSelector !== undefined) { queryParams.labelSelector = ObjectSerializer.serialize(this.labelSelector, 'string'); } + if (this.fieldSelector !== undefined) { + queryParams.fieldSelector = ObjectSerializer.serialize(this.fieldSelector, 'string'); + } this.request = await this.watch.watch( this.path, queryParams, @@ -182,6 +192,9 @@ export class ListWatch implements ObjectCache, In } private addOrUpdateItems(items: T[]): void { + if (items === undefined || items === null) { + return; + } items.forEach((obj: T) => { addOrUpdateObject( this.objects, @@ -192,13 +205,18 @@ export class ListWatch implements ObjectCache, In }); } - private watchHandler(phase: string, obj: T, watchObj?: any): void { + private async watchHandler( + phase: string, + obj: T, + watchObj?: { type: string; object: KubernetesObject }, + ): Promise { switch (phase) { case 'ERROR': if ((obj as { code?: number }).code === 410) { this.resourceVersion = ''; } - break; + // We don't restart here, because it should be handled by the watch exiting if necessary + return; case 'ADDED': case 'MODIFIED': addOrUpdateObject( @@ -215,15 +233,16 @@ export class ListWatch implements ObjectCache, In // nothing to do, here for documentation, mostly. break; } - if (watchObj && watchObj.metadata) { - this.resourceVersion = watchObj.metadata.resourceVersion; - } + this.resourceVersion = obj.metadata ? obj.metadata!.resourceVersion || '' : ''; } } // exported for testing export function cacheMapFromList(newObjects: T[]): CacheMap { const objects: CacheMap = new Map(); + if (newObjects === undefined || newObjects === null) { + return objects; + } // build up the new list for (const obj of newObjects) { let namespaceObjects = objects.get(obj.metadata!.namespace || ''); diff --git a/src/cache_test.ts b/src/cache_test.ts index 315a4f55c5..9746425149 100644 --- a/src/cache_test.ts +++ b/src/cache_test.ts @@ -235,6 +235,7 @@ describe('ListWatchCache', () => { watchHandler('ADDED', { metadata: { name: 'name3', + resourceVersion: 'blah', } as V1ObjectMeta, } as V1Namespace); @@ -245,40 +246,28 @@ describe('ListWatchCache', () => { } as V1ObjectMeta, } as V1Namespace); - watchHandler( - 'DELETED', - { - metadata: { - name: 'name2', - resourceVersion: 'blah', - } as V1ObjectMeta, - } as V1Namespace, - { - metadata: { - resourceVersion: '54321', - }, - }, - ); + watchHandler('DELETED', { + metadata: { + name: 'name2', + resourceVersion: '54321', + } as V1ObjectMeta, + } as V1Namespace); const [addResult, updateResult, deleteResult] = await Promise.all([ addPromise, updatePromise, deletePromise, ]); - deepStrictEqual(addResult.metadata, { name: 'name3' }); + deepStrictEqual(addResult.metadata, { name: 'name3', resourceVersion: 'blah' }); deepStrictEqual(updateResult.metadata, { name: 'name3', resourceVersion: 'baz' }); - deepStrictEqual(deleteResult.metadata, { name: 'name2', resourceVersion: 'blah' }); + deepStrictEqual(deleteResult.metadata, { name: 'name2', resourceVersion: '54321' }); strictEqual(informer.latestResourceVersion(), '54321'); - watchHandler( - 'BOOKMARK', - {}, - { - metadata: { - resourceVersion: '5454', - }, + watchHandler('BOOKMARK', { + metadata: { + resourceVersion: '5454', }, - ); + }); strictEqual(informer.latestResourceVersion(), '5454'); }); @@ -1205,9 +1194,10 @@ describe('ListWatchCache', () => { { metadata: { name: 'name3', + resourceVersion: '23456', } as V1ObjectMeta, } as V1Namespace, - { metadata: { resourceVersion: '23456' } }, + { type: 'ADDED', metadata: { resourceVersion: '23456' } }, ); await informer.stop(); @@ -1259,9 +1249,87 @@ describe('ListWatchCache', () => { { metadata: { name: 'name3', + resourceVersion: '23456', } as V1ObjectMeta, } as V1Namespace, - { metadata: { resourceVersion: '23456' } }, + { type: 'ADDED', metadata: { resourceVersion: '23456' } }, + ); + + await informer.stop(); + + let errorEmitted = false; + informer.on('error', () => (errorEmitted = true)); + + promise = new Promise((resolve) => { + mock.when( + fakeWatch.watch(mock.anything(), mock.anything(), mock.anything(), mock.anything()), + ).thenCall(() => { + resolve({}); + }); + }); + + informer.start(); + await promise; + + const [, , , doneHandler] = mock.capture(fakeWatch.watch).last(); + + const object = { + kind: 'Status', + apiVersion: 'v1', + metadata: {}, + status: 'Failure', + message: 'too old resource version: 12345 (1234)', + reason: 'Expired', + code: 410, + }; + await watchHandler('ERROR', object, { type: 'ERROR', object }); + await doneHandler(null); + + mock.verify( + fakeWatch.watch(mock.anything(), mock.anything(), mock.anything(), mock.anything()), + ).thrice(); + strictEqual(errorEmitted, false); + strictEqual(listCalls, 2); + }); + + it('should list if the watch errors from the last version', async () => { + const fakeWatch = mock.mock(Watch); + + let listCalls = 0; + const listFn: ListPromise = function (): Promise { + return new Promise((resolve, reject) => { + listCalls++; + resolve({ + metadata: { + resourceVersion: '12345', + } as V1ListMeta, + items: [], + } as V1NamespaceList); + }); + }; + let promise = new Promise((resolve) => { + mock.when( + fakeWatch.watch(mock.anything(), mock.anything(), mock.anything(), mock.anything()), + ).thenCall(() => { + resolve({}); + }); + }); + + const informer = new ListWatch('/some/path', mock.instance(fakeWatch), listFn, false); + + informer.start(); + await promise; + + const [, , watchHandler] = mock.capture(fakeWatch.watch).last(); + watchHandler( + 'ADDED', + { + metadata: { + name: 'name3', + resourceVersion: '23456', + } as V1ObjectMeta, + } as V1Namespace, + { type: 'ADDED', metadata: { resourceVersion: '23456' } }, ); await informer.stop(); @@ -1335,6 +1403,8 @@ describe('ListWatchCache', () => { ); await informer.stop(); + strictEqual(listCalls, 1); + listCalls = 0; let errorEmitted = false; informer.on('error', () => (errorEmitted = true)); diff --git a/src/config_test.ts b/src/config_test.ts index c2544a82e8..ea8e4e2dc1 100644 --- a/src/config_test.ts +++ b/src/config_test.ts @@ -962,7 +962,7 @@ describe('KubeConfig', () => { const opts = {} as RequestOptions; await config.applyToHTTPSOptions(opts); - strictEqual(opts.headers!.Authorization, `Bearer ${token}`); + strictEqual(opts.headers!['Authorization'], `Bearer ${token}`); }); it('should populate from auth provider', async () => { const config = new KubeConfig(); @@ -982,11 +982,11 @@ describe('KubeConfig', () => { const opts = {} as RequestOptions; await config.applyToHTTPSOptions(opts); - strictEqual(opts.headers!.Authorization, `Bearer ${token}`); + strictEqual(opts.headers!['Authorization'], `Bearer ${token}`); opts.headers = {}; opts.headers.Host = 'foo.com'; await config.applyToHTTPSOptions(opts); - strictEqual(opts.headers.Authorization, `Bearer ${token}`); + strictEqual(opts.headers!['Authorization'], `Bearer ${token}`); }); it('should populate from auth provider without expirty', async () => { @@ -1006,7 +1006,7 @@ describe('KubeConfig', () => { const opts = {} as RequestOptions; await config.applyToHTTPSOptions(opts); - strictEqual(opts.headers!.Authorization, `Bearer ${token}`); + strictEqual(opts.headers!['Authorization'], `Bearer ${token}`); }); it('should populate rejectUnauthorized=false when skipTLSVerify is set', async () => { @@ -1115,7 +1115,7 @@ describe('KubeConfig', () => { ); const opts = {} as RequestOptions; await config.applyToHTTPSOptions(opts); - strictEqual(opts.headers!.Authorization, `Bearer ${token}`); + strictEqual(opts.headers!['Authorization'], `Bearer ${token}`); }); it('should exec with expired token', async () => { @@ -1143,7 +1143,7 @@ describe('KubeConfig', () => { ); const opts = {} as RequestOptions; await config.applyToHTTPSOptions(opts); - strictEqual(opts.headers!.Authorization, `Bearer ${token}`); + strictEqual(opts.headers!['Authorization'], `Bearer ${token}`); }); it('should exec without access-token', async () => { @@ -1170,7 +1170,7 @@ describe('KubeConfig', () => { ); const opts = {} as RequestOptions; await config.applyToHTTPSOptions(opts); - strictEqual(opts.headers!.Authorization, `Bearer ${token}`); + strictEqual(opts.headers!['Authorization'], `Bearer ${token}`); }); it('should exec without access-token', async () => { // TODO: fix this test for Windows @@ -1196,7 +1196,7 @@ describe('KubeConfig', () => { ); const opts = {} as RequestOptions; await config.applyToHTTPSOptions(opts); - strictEqual(opts.headers!.Authorization, `Bearer ${token}`); + strictEqual(opts.headers!['Authorization'], `Bearer ${token}`); }); it('should exec succesfully with spaces in cmd', async () => { // TODO: fix this test for Windows @@ -1222,7 +1222,7 @@ describe('KubeConfig', () => { ); const opts = {} as RequestOptions; await config.applyToHTTPSOptions(opts); - strictEqual(opts.headers!.Authorization, `Bearer ${token}`); + strictEqual(opts.headers!['Authorization'], `Bearer ${token}`); }); it('should exec with exec auth and env vars', async () => { // TODO: fix this test for Windows @@ -1255,7 +1255,7 @@ describe('KubeConfig', () => { // TODO: inject the exec command here and validate env vars? const opts = {} as RequestOptions; await config.applyToHTTPSOptions(opts); - strictEqual(opts.headers!.Authorization, `Bearer ${token}`); + strictEqual(opts.headers!['Authorization'], `Bearer ${token}`); }); it('should exec with exec auth', async () => { // TODO: fix this test for Windows @@ -1288,7 +1288,7 @@ describe('KubeConfig', () => { // TODO: inject the exec command here? const opts = {} as RequestOptions; await config.applyToHTTPSOptions(opts); - strictEqual(opts.headers!.Authorization, `Bearer ${token}`); + strictEqual(opts.headers!['Authorization'], `Bearer ${token}`); }); it('should exec with exec auth (other location)', async () => { // TODO: fix this test for Windows @@ -1316,7 +1316,7 @@ describe('KubeConfig', () => { // TODO: inject the exec command here? const opts = {} as RequestOptions; await config.applyToHTTPSOptions(opts); - strictEqual(opts.headers!.Authorization, `Bearer ${token}`); + strictEqual(opts.headers!['Authorization'], `Bearer ${token}`); }); it('should cache exec with name', async () => { // TODO: fix this test for Windows @@ -1776,7 +1776,7 @@ describe('KubeConfig', () => { // Simulate token retrieval const token = 'test-token'; opts.headers = opts.headers || {}; - opts.headers.Authorization = `Bearer ${token}`; + opts.headers['Authorization'] = `Bearer ${token}`; } else { throw new Error('No custom configuration found'); } @@ -1802,7 +1802,7 @@ describe('KubeConfig', () => { const opts: RequestOptions = {}; await kc.applyToHTTPSOptions(opts); - strictEqual(opts.headers!.Authorization, 'Bearer test-token'); + strictEqual(opts.headers!['Authorization'], 'Bearer test-token'); }); }); diff --git a/src/exec_auth.ts b/src/exec_auth.ts index 3ac70dfa4e..fbd97a26f8 100644 --- a/src/exec_auth.ts +++ b/src/exec_auth.ts @@ -56,7 +56,7 @@ export class ExecAuth implements Authenticator { if (!opts.headers) { opts.headers = {} as OutgoingHttpHeaders; } - opts.headers!.Authorization = `Bearer ${token}`; + opts.headers!['Authorization'] = `Bearer ${token}`; } } diff --git a/src/exec_auth_test.ts b/src/exec_auth_test.ts index 9be3e262d5..e323b5880e 100644 --- a/src/exec_auth_test.ts +++ b/src/exec_auth_test.ts @@ -486,7 +486,7 @@ describe('ExecAuth', () => { }, opts, ); - strictEqual(opts.headers?.Authorization, 'Bearer foo'); + strictEqual(opts.headers!['Authorization'], 'Bearer foo'); }); it('should handle null credentials correctly', async () => { const auth = new ExecAuth(); diff --git a/src/file_auth.ts b/src/file_auth.ts index b8b7644636..d6d4f56c9b 100644 --- a/src/file_auth.ts +++ b/src/file_auth.ts @@ -20,7 +20,7 @@ export class FileAuth implements Authenticator { this.refreshToken(user.authProvider.config.tokenFile); } if (this.token) { - opts.headers!.Authorization = `Bearer ${this.token}`; + opts.headers!['Authorization'] = `Bearer ${this.token}`; } } diff --git a/src/gcp_auth.ts b/src/gcp_auth.ts index 0f3d680e08..1bf1089618 100644 --- a/src/gcp_auth.ts +++ b/src/gcp_auth.ts @@ -28,7 +28,7 @@ export class GoogleCloudPlatformAuth implements Authenticator { public async applyAuthentication(user: User, opts: https.RequestOptions): Promise { const token = this.getToken(user); if (token) { - opts.headers!.Authorization = `Bearer ${token}`; + opts.headers!['Authorization'] = `Bearer ${token}`; } } diff --git a/src/index.ts b/src/index.ts index 10fb300ede..fb6b1bba01 100644 --- a/src/index.ts +++ b/src/index.ts @@ -19,5 +19,5 @@ export * from './middleware.js'; export * from './patch.js'; export { type ConfigOptions, type User, type Cluster, type Context } from './config_types.js'; -// Export FetchError so that instanceof checks in user code will definitely use the same instance -export { FetchError } from 'node-fetch'; +// Export AbortError and FetchError so that instanceof checks in user code will definitely use the same instances +export { AbortError, FetchError } from 'node-fetch'; diff --git a/src/oidc_auth.ts b/src/oidc_auth.ts index af5e0c1311..f8c1536ac9 100644 --- a/src/oidc_auth.ts +++ b/src/oidc_auth.ts @@ -85,7 +85,7 @@ export class OpenIDConnectAuth implements Authenticator { ): Promise { const token = await this.getToken(user, overrideClient); if (token) { - opts.headers!.Authorization = `Bearer ${token}`; + opts.headers!['Authorization'] = `Bearer ${token}`; } } diff --git a/src/serializer.ts b/src/serializer.ts index 29c3fc144e..919a5df082 100644 --- a/src/serializer.ts +++ b/src/serializer.ts @@ -1,5 +1,13 @@ import { ObjectSerializer as InternalSerializer, V1ObjectMeta } from './gen/models/ObjectSerializer.js'; +type KubernetesObjectHeader = { + apiVersion: string; + kind: string; +}; + +const isKubernetesObject = (data: unknown): data is KubernetesObjectHeader => + !!data && typeof data === 'object' && 'apiVersion' in data && 'kind' in data; + type AttributeType = { name: string; baseName: string; @@ -38,30 +46,38 @@ class KubernetesObject { format: '', }, ]; -} - -const isKubernetesObject = (data: unknown): boolean => - !!data && typeof data === 'object' && 'apiVersion' in data && 'kind' in data; -/** - * Wraps the ObjectSerializer to support custom resources and generic Kubernetes objects. - */ -export class ObjectSerializer extends InternalSerializer { - public static serialize(data: any, type: string, format: string = ''): any { - const obj = InternalSerializer.serialize(data, type, format); - if (obj !== data) { - return obj; + public serialize(): any { + const instance: Record = {}; + for (const attributeType of KubernetesObject.attributeTypeMap) { + const value = this[attributeType.baseName]; + if (value !== undefined) { + instance[attributeType.name] = InternalSerializer.serialize( + this[attributeType.baseName], + attributeType.type, + attributeType.format, + ); + } + } + // add all unknown properties as is. + for (const [key, value] of Object.entries(this)) { + if (KubernetesObject.attributeTypeMap.find((t) => t.name === key)) { + continue; + } + instance[key] = value; } + return instance; + } + public static fromUnknown(data: unknown): KubernetesObject { if (!isKubernetesObject(data)) { - return obj; + throw new Error(`Unable to deseriliaze non-Kubernetes object ${data}.`); } - - const instance: Record = {}; + const instance = new KubernetesObject(); for (const attributeType of KubernetesObject.attributeTypeMap) { const value = data[attributeType.baseName]; if (value !== undefined) { - instance[attributeType.name] = InternalSerializer.serialize( + instance[attributeType.name] = InternalSerializer.deserialize( data[attributeType.baseName], attributeType.type, attributeType.format, @@ -77,11 +93,102 @@ export class ObjectSerializer extends InternalSerializer { } return instance; } +} - public static deserialize(data: any, type: string, format: string = ''): any { - const obj = InternalSerializer.deserialize(data, type, format); +export interface Serializer { + serialize(data: any, type: string, format?: string): any; + deserialize(data: any, type: string, format?): any; +} + +export type GroupVersionKind = { + group: string; + version: string; + kind: string; +}; + +type ModelRegistry = { + [gv: string]: { + [kind: string]: Serializer; + }; +}; + +const gvString = ({ group, version }: GroupVersionKind): string => [group, version].join('/'); + +const gvkFromObject = (obj: KubernetesObjectHeader): GroupVersionKind => { + const [g, v] = obj.apiVersion.split('/'); + return { + kind: obj.kind, + group: v ? g : '', + version: v ? v : g, + }; +}; + +/** + * Default serializer that uses the KubernetesObject to serialize and deserialize + * any object using only the minimum required attributes. + */ +export const defaultSerializer: Serializer = { + serialize: (data: any, type: string, format?: string): any => { + if (data instanceof KubernetesObject) { + return data.serialize(); + } + return KubernetesObject.fromUnknown(data).serialize(); + }, + deserialize: (data: any, type: string, format?): any => { + return KubernetesObject.fromUnknown(data); + }, +}; + +/** + * Wraps the ObjectSerializer to support custom resources and generic Kubernetes objects. + * + * CustomResources that are unknown to the ObjectSerializer can be registered + * by using ObjectSerializer.registerModel(). + */ +export class ObjectSerializer extends InternalSerializer { + private static modelRegistry: ModelRegistry = {}; + + /** + * Adds a dedicated seriliazer for a Kubernetes resource. + * Every resource is uniquly identified using its group, version and kind. + * @param gvk + * @param serializer + */ + public static registerModel(gvk: GroupVersionKind, serializer: Serializer) { + const gv = gvString(gvk); + const kinds = (this.modelRegistry[gv] ??= {}); + if (kinds[gvk.kind]) { + throw new Error(`Kind ${gvk.kind} of ${gv} is already defined`); + } + kinds[gvk.kind] = serializer; + } + + /** + * Removes all registered models from the registry. + */ + public static clearModelRegistry(): void { + this.modelRegistry = {}; + } + + private static getSerializerForObject(obj: unknown): undefined | Serializer { + if (!isKubernetesObject(obj)) { + return undefined; + } + const gvk = gvkFromObject(obj); + return ObjectSerializer.modelRegistry[gvString(gvk)]?.[gvk.kind]; + } + + public static serialize(data: any, type: string, format: string = ''): any { + const serializer = ObjectSerializer.getSerializerForObject(data); + if (serializer) { + return serializer.serialize(data, type, format); + } + if (data instanceof KubernetesObject) { + return data.serialize(); + } + + const obj = InternalSerializer.serialize(data, type, format); if (obj !== data) { - // the serializer knows the type and already deserialized it. return obj; } @@ -89,11 +196,11 @@ export class ObjectSerializer extends InternalSerializer { return obj; } - const instance = new KubernetesObject(); + const instance: Record = {}; for (const attributeType of KubernetesObject.attributeTypeMap) { const value = data[attributeType.baseName]; if (value !== undefined) { - instance[attributeType.name] = InternalSerializer.deserialize( + instance[attributeType.name] = InternalSerializer.serialize( data[attributeType.baseName], attributeType.type, attributeType.format, @@ -109,4 +216,22 @@ export class ObjectSerializer extends InternalSerializer { } return instance; } + + public static deserialize(data: any, type: string, format: string = ''): any { + const serializer = ObjectSerializer.getSerializerForObject(data); + if (serializer) { + return serializer.deserialize(data, type, format); + } + const obj = InternalSerializer.deserialize(data, type, format); + if (obj !== data) { + // the serializer knows the type and already deserialized it. + return obj; + } + + if (!isKubernetesObject(data)) { + return obj; + } + + return KubernetesObject.fromUnknown(data); + } } diff --git a/src/serializer_test.ts b/src/serializer_test.ts index 9ed7d5be97..a0976d0293 100644 --- a/src/serializer_test.ts +++ b/src/serializer_test.ts @@ -1,8 +1,31 @@ -import { describe, it } from 'node:test'; +import { afterEach, beforeEach, describe, it } from 'node:test'; import { deepEqual, deepStrictEqual } from 'node:assert'; -import { ObjectSerializer } from './serializer.js'; +import { defaultSerializer, ObjectSerializer } from './serializer.js'; describe('ObjectSerializer', () => { + beforeEach(() => { + ObjectSerializer.registerModel( + { + group: 'my-group.io', + version: 'v1', + kind: 'V1MyCustomResource', + }, + defaultSerializer, + ); + ObjectSerializer.registerModel( + { + group: 'my-group.io', + version: 'v1', + kind: 'Deployment', + }, + defaultSerializer, + ); + }); + + afterEach(() => { + ObjectSerializer.clearModelRegistry(); + }); + describe('serialize', () => { it('should serialize a known object', () => { const s = { @@ -47,6 +70,98 @@ describe('ObjectSerializer', () => { }); }); + [ + { + name: 'should serialize a registered custom object', + input: { + type: 'V1MyCustomResource', + obj: { + apiVersion: 'my-group.io/v1', + kind: 'MyCustomResource', + metadata: { + name: 'k8s-js-client-test', + namespace: 'default', + creationTimestamp: new Date('2022-01-01T00:00:00.000Z'), + }, + data: { + key: 'value', + }, + }, + }, + expected: { + apiVersion: 'my-group.io/v1', + kind: 'MyCustomResource', + metadata: { + name: 'k8s-js-client-test', + namespace: 'default', + creationTimestamp: '2022-01-01T00:00:00.000Z', + uid: undefined, + annotations: undefined, + labels: undefined, + finalizers: undefined, + generateName: undefined, + selfLink: undefined, + resourceVersion: undefined, + generation: undefined, + ownerReferences: undefined, + deletionTimestamp: undefined, + deletionGracePeriodSeconds: undefined, + managedFields: undefined, + }, + data: { + key: 'value', + }, + }, + }, + { + name: 'should serialize a registered custom object with a duplicated core resource kind', + input: { + type: 'V1Deployment', + obj: { + apiVersion: 'my-group.io/v1', + kind: 'Deployment', + metadata: { + name: 'k8s-js-client-test', + namespace: 'default', + creationTimestamp: new Date('2022-01-01T00:00:00.000Z'), + }, + data: { + key: 'value', + }, + }, + }, + expected: { + apiVersion: 'my-group.io/v1', + kind: 'Deployment', + metadata: { + name: 'k8s-js-client-test', + namespace: 'default', + creationTimestamp: '2022-01-01T00:00:00.000Z', + uid: undefined, + annotations: undefined, + labels: undefined, + finalizers: undefined, + generateName: undefined, + selfLink: undefined, + resourceVersion: undefined, + generation: undefined, + ownerReferences: undefined, + deletionTimestamp: undefined, + deletionGracePeriodSeconds: undefined, + managedFields: undefined, + }, + data: { + key: 'value', + }, + }, + }, + ].forEach(({ name, input, expected }) => { + it(name, () => { + const res = ObjectSerializer.serialize(input.obj, input.type); + deepStrictEqual(res, expected); + }); + }); + it('should serialize a unknown kubernetes object', () => { const s = { apiVersion: 'v1alpha1', @@ -160,5 +275,73 @@ describe('ObjectSerializer', () => { const res = ObjectSerializer.serialize(s, 'unknown'); deepStrictEqual(res, s); }); + + [ + { + name: 'should deserialize a registered custom object', + input: { + type: 'V1MyCustomResource', + obj: { + apiVersion: 'my-group.io/v1', + kind: 'MyCustomResource', + metadata: { + name: 'k8s-js-client-test', + namespace: 'default', + creationTimestamp: '2022-01-01T00:00:00.000Z', + }, + data: { + key: 'value', + }, + }, + }, + expected: { + apiVersion: 'my-group.io/v1', + kind: 'MyCustomResource', + metadata: { + name: 'k8s-js-client-test', + namespace: 'default', + creationTimestamp: new Date('2022-01-01T00:00:00.000Z'), + }, + data: { + key: 'value', + }, + }, + }, + { + name: 'should deserialize a registered custom object with a duplicated core resource kind', + input: { + type: 'V1Deployment', + obj: { + apiVersion: 'my-group.io/v1', + kind: 'Deployment', + metadata: { + name: 'k8s-js-client-test', + namespace: 'default', + creationTimestamp: '2022-01-01T00:00:00.000Z', + }, + data: { + key: 'value', + }, + }, + }, + expected: { + apiVersion: 'my-group.io/v1', + kind: 'Deployment', + metadata: { + name: 'k8s-js-client-test', + namespace: 'default', + creationTimestamp: new Date('2022-01-01T00:00:00.000Z'), + }, + data: { + key: 'value', + }, + }, + }, + ].forEach(({ name, input, expected }) => { + it(name, () => { + const res = ObjectSerializer.deserialize(input.obj, input.type); + deepEqual(res, expected); + }); + }); }); });