diff --git a/RELEASE_GUIDE.md b/RELEASE_GUIDE.md
index 8821fedc38..d46911b0ce 100644
--- a/RELEASE_GUIDE.md
+++ b/RELEASE_GUIDE.md
@@ -15,6 +15,8 @@ All releases will be made by creating a PR which bumps the version field in the
1. If you are making a patch release (or a prerelease for one) make sure you are on the `release/v.` branch.
1. Run `npm run create-release-pr`.
1. Pick the PRs that you want to include in this release using the keys listed.
+ - If you are making a patch release this might include fixing up some cherry-picking of commits. These actions should be done in a separate terminal.
+ - If a package version is having a major version bump then `npm` will complain about `peerDependency` conflicts. These will have to be fixed up separately.
1. Once the PR is created, approved, and then merged the `Release Open Lens` workflow will create a tag and release for you.
1. If you are making a major or minor release, create a `release/v.` branch and push it to `origin` so that future patch releases can be made from it.
1. If you released a major or minor version, create a new patch milestone and move all bug issues to that milestone and all enhancement issues to the next minor milestone.
diff --git a/package-lock.json b/package-lock.json
index 2b313d03d2..946b5f8168 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -73,20 +73,20 @@
}
},
"node_modules/@babel/core": {
- "version": "7.21.3",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.3.tgz",
- "integrity": "sha512-qIJONzoa/qiHghnm0l1n4i/6IIziDpzqc36FBs4pzMhDUraHqponwJLiAKm1hGLP3OSB/TVNz6rMwVGpwxxySw==",
+ "version": "7.21.0",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.0.tgz",
+ "integrity": "sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA==",
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.18.6",
- "@babel/generator": "^7.21.3",
+ "@babel/generator": "^7.21.0",
"@babel/helper-compilation-targets": "^7.20.7",
- "@babel/helper-module-transforms": "^7.21.2",
+ "@babel/helper-module-transforms": "^7.21.0",
"@babel/helpers": "^7.21.0",
- "@babel/parser": "^7.21.3",
+ "@babel/parser": "^7.21.0",
"@babel/template": "^7.20.7",
- "@babel/traverse": "^7.21.3",
- "@babel/types": "^7.21.3",
+ "@babel/traverse": "^7.21.0",
+ "@babel/types": "^7.21.0",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
@@ -115,9 +115,9 @@
}
},
"node_modules/@babel/eslint-parser": {
- "version": "7.21.3",
- "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.21.3.tgz",
- "integrity": "sha512-kfhmPimwo6k4P8zxNs8+T7yR44q1LdpsZdE1NkCsVlfiuTPRfnGgjaF8Qgug9q9Pou17u6wneYF0lDCZJATMFg==",
+ "version": "7.19.1",
+ "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.19.1.tgz",
+ "integrity": "sha512-AqNf2QWt1rtu2/1rLswy6CDP7H9Oh3mMhk177Y67Rg8d7RD9WfOLLv8CGn6tisFvS2htm86yIe1yLF6I1UDaGQ==",
"peer": true,
"dependencies": {
"@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1",
@@ -151,11 +151,11 @@
}
},
"node_modules/@babel/generator": {
- "version": "7.21.3",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz",
- "integrity": "sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==",
+ "version": "7.21.1",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.1.tgz",
+ "integrity": "sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA==",
"dependencies": {
- "@babel/types": "^7.21.3",
+ "@babel/types": "^7.21.0",
"@jridgewell/gen-mapping": "^0.3.2",
"@jridgewell/trace-mapping": "^0.3.17",
"jsesc": "^2.5.1"
@@ -595,9 +595,9 @@
}
},
"node_modules/@babel/parser": {
- "version": "7.21.3",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz",
- "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==",
+ "version": "7.21.2",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.2.tgz",
+ "integrity": "sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==",
"bin": {
"parser": "bin/babel-parser.js"
},
@@ -1269,9 +1269,9 @@
}
},
"node_modules/@babel/plugin-transform-destructuring": {
- "version": "7.21.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.21.3.tgz",
- "integrity": "sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA==",
+ "version": "7.20.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.20.7.tgz",
+ "integrity": "sha512-Xwg403sRrZb81IVB79ZPqNQME23yhugYVqgTxAhT99h485F4f+GMELFhhOsscDUB7HCswepKeCKLn/GZvUKoBA==",
"peer": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.20.2"
@@ -1523,9 +1523,9 @@
}
},
"node_modules/@babel/plugin-transform-parameters": {
- "version": "7.21.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.21.3.tgz",
- "integrity": "sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ==",
+ "version": "7.20.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.7.tgz",
+ "integrity": "sha512-WiWBIkeHKVOSYPO0pWkxGPfKeWrCJyD3NJ53+Lrp/QMSZbsVPovrVl2aWZ19D/LTVnaDv5Ap7GJ/B2CTOZdrfA==",
"peer": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.20.2"
@@ -1754,12 +1754,11 @@
}
},
"node_modules/@babel/plugin-transform-typescript": {
- "version": "7.21.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.21.3.tgz",
- "integrity": "sha512-RQxPz6Iqt8T0uw/WsJNReuBpWpBqs/n7mNo18sKLoTbMp+UrEekhH+pKSVC7gWz+DNjo9gryfV8YzCiT45RgMw==",
+ "version": "7.21.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.21.0.tgz",
+ "integrity": "sha512-xo///XTPp3mDzTtrqXoBlK9eiAYW3wv9JXglcn/u1bi60RW11dEUxIgA8cbnDhutS1zacjMRmAwxE0gMklLnZg==",
"peer": true,
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.18.6",
"@babel/helper-create-class-features-plugin": "^7.21.0",
"@babel/helper-plugin-utils": "^7.20.2",
"@babel/plugin-syntax-typescript": "^7.20.0"
@@ -1997,18 +1996,18 @@
}
},
"node_modules/@babel/traverse": {
- "version": "7.21.3",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz",
- "integrity": "sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==",
+ "version": "7.21.2",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.2.tgz",
+ "integrity": "sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw==",
"dependencies": {
"@babel/code-frame": "^7.18.6",
- "@babel/generator": "^7.21.3",
+ "@babel/generator": "^7.21.1",
"@babel/helper-environment-visitor": "^7.18.9",
"@babel/helper-function-name": "^7.21.0",
"@babel/helper-hoist-variables": "^7.18.6",
"@babel/helper-split-export-declaration": "^7.18.6",
- "@babel/parser": "^7.21.3",
- "@babel/types": "^7.21.3",
+ "@babel/parser": "^7.21.2",
+ "@babel/types": "^7.21.2",
"debug": "^4.1.0",
"globals": "^11.1.0"
},
@@ -2017,9 +2016,9 @@
}
},
"node_modules/@babel/types": {
- "version": "7.21.3",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz",
- "integrity": "sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==",
+ "version": "7.21.2",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.2.tgz",
+ "integrity": "sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw==",
"dependencies": {
"@babel/helper-string-parser": "^7.19.4",
"@babel/helper-validator-identifier": "^7.19.1",
@@ -2100,92 +2099,25 @@
}
},
"node_modules/@electron/get": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.14.1.tgz",
- "integrity": "sha512-BrZYyL/6m0ZXz/lDxy/nlVhQz+WF+iPS6qXolEU8atw7h6v1aYkjwJZ63m+bJMBTxDE66X+r2tPS4a/8C82sZw==",
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.2.tgz",
+ "integrity": "sha512-eFZVFoRXb3GFGd7Ak7W4+6jBl9wBtiZ4AaYOse97ej6mKj5tkyO0dUnUChs1IhJZtx1BENo4/p4WUTXpi6vT+g==",
"dependencies": {
"debug": "^4.1.1",
"env-paths": "^2.2.0",
"fs-extra": "^8.1.0",
- "got": "^9.6.0",
+ "got": "^11.8.5",
"progress": "^2.0.3",
"semver": "^6.2.0",
"sumchecker": "^3.0.1"
},
"engines": {
- "node": ">=8.6"
+ "node": ">=12"
},
"optionalDependencies": {
- "global-agent": "^3.0.0",
- "global-tunnel-ng": "^2.7.1"
+ "global-agent": "^3.0.0"
}
},
- "node_modules/@electron/get/node_modules/@sindresorhus/is": {
- "version": "0.14.0",
- "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
- "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/@electron/get/node_modules/@szmarczak/http-timer": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz",
- "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==",
- "dependencies": {
- "defer-to-connect": "^1.0.1"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/@electron/get/node_modules/cacheable-request": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz",
- "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==",
- "dependencies": {
- "clone-response": "^1.0.2",
- "get-stream": "^5.1.0",
- "http-cache-semantics": "^4.0.0",
- "keyv": "^3.0.0",
- "lowercase-keys": "^2.0.0",
- "normalize-url": "^4.1.0",
- "responselike": "^1.0.2"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@electron/get/node_modules/cacheable-request/node_modules/get-stream": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
- "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
- "dependencies": {
- "pump": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/@electron/get/node_modules/decompress-response": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
- "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==",
- "dependencies": {
- "mimic-response": "^1.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/@electron/get/node_modules/defer-to-connect": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz",
- "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ=="
- },
"node_modules/@electron/get/node_modules/fs-extra": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
@@ -2199,51 +2131,6 @@
"node": ">=6 <7 || >=8"
}
},
- "node_modules/@electron/get/node_modules/get-stream": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
- "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
- "dependencies": {
- "pump": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/@electron/get/node_modules/got": {
- "version": "9.6.0",
- "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz",
- "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==",
- "dependencies": {
- "@sindresorhus/is": "^0.14.0",
- "@szmarczak/http-timer": "^1.1.2",
- "cacheable-request": "^6.0.0",
- "decompress-response": "^3.3.0",
- "duplexer3": "^0.1.4",
- "get-stream": "^4.1.0",
- "lowercase-keys": "^1.0.1",
- "mimic-response": "^1.0.1",
- "p-cancelable": "^1.0.0",
- "to-readable-stream": "^1.0.0",
- "url-parse-lax": "^3.0.0"
- },
- "engines": {
- "node": ">=8.6"
- }
- },
- "node_modules/@electron/get/node_modules/got/node_modules/lowercase-keys": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
- "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/@electron/get/node_modules/json-buffer": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz",
- "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ=="
- },
"node_modules/@electron/get/node_modules/jsonfile": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
@@ -2252,55 +2139,6 @@
"graceful-fs": "^4.1.6"
}
},
- "node_modules/@electron/get/node_modules/keyv": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz",
- "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==",
- "dependencies": {
- "json-buffer": "3.0.0"
- }
- },
- "node_modules/@electron/get/node_modules/normalize-url": {
- "version": "4.5.1",
- "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz",
- "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@electron/get/node_modules/p-cancelable": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz",
- "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/@electron/get/node_modules/pump": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
- "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
- "dependencies": {
- "end-of-stream": "^1.1.0",
- "once": "^1.3.1"
- }
- },
- "node_modules/@electron/get/node_modules/responselike": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
- "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==",
- "dependencies": {
- "lowercase-keys": "^1.0.0"
- }
- },
- "node_modules/@electron/get/node_modules/responselike/node_modules/lowercase-keys": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
- "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/@electron/get/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@@ -3114,9 +2952,9 @@
}
},
"node_modules/@floating-ui/core": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.2.4.tgz",
- "integrity": "sha512-SQOeVbMwb1di+mVWWJLpsUTToKfqVNioXys011beCAhyOIFtS+GQoW4EQSneuxzmQKddExDwQ+X0hLl4lJJaSQ==",
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.2.3.tgz",
+ "integrity": "sha512-upVRtrNZuYNsw+EoxkiBFRPROnU8UTy/u/dZ9U0W14BlemPYODwhhxYXSR2Y9xOnvr1XtptJRWx7gL8Te1qaog==",
"dev": true
},
"node_modules/@floating-ui/dom": {
@@ -4686,6 +4524,14 @@
"resolved": "packages/bump-version-for-cron",
"link": true
},
+ "node_modules/@k8slens/cluster-settings": {
+ "resolved": "packages/cluster-settings",
+ "link": true
+ },
+ "node_modules/@k8slens/computed-channel": {
+ "resolved": "packages/technical-features/messaging/computed-channel",
+ "link": true
+ },
"node_modules/@k8slens/core": {
"resolved": "packages/core",
"link": true
@@ -4722,6 +4568,22 @@
"resolved": "packages/technical-features/application/legacy-extensions",
"link": true
},
+ "node_modules/@k8slens/messaging": {
+ "resolved": "packages/technical-features/messaging/agnostic",
+ "link": true
+ },
+ "node_modules/@k8slens/messaging-fake-bridge": {
+ "resolved": "packages/technical-features/messaging/message-bridge-fake",
+ "link": true
+ },
+ "node_modules/@k8slens/messaging-for-main": {
+ "resolved": "packages/technical-features/messaging/electron/main",
+ "link": true
+ },
+ "node_modules/@k8slens/messaging-for-renderer": {
+ "resolved": "packages/technical-features/messaging/electron/renderer",
+ "link": true
+ },
"node_modules/@k8slens/node-fetch": {
"resolved": "packages/node-fetch",
"link": true
@@ -4738,6 +4600,10 @@
"resolved": "packages/semver",
"link": true
},
+ "node_modules/@k8slens/startable-stoppable": {
+ "resolved": "packages/utility-features/startable-stoppable",
+ "link": true
+ },
"node_modules/@k8slens/test-utils": {
"resolved": "packages/utility-features/test-utils",
"link": true
@@ -6882,7 +6748,6 @@
"version": "12.1.5",
"resolved": "https://registry.npmjs.org/@testing-library/react/-/react-12.1.5.tgz",
"integrity": "sha512-OfTXCJUFgjd/digLUuPxa0+/3ZxsQmE7ub9kcbW/wi96Bh3o/p5vrETcBGfP17NWPGqeYYl5LTRpwyGoMC4ysg==",
- "dev": true,
"dependencies": {
"@babel/runtime": "^7.12.5",
"@testing-library/dom": "^8.0.0",
@@ -6900,7 +6765,6 @@
"version": "8.20.0",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.0.tgz",
"integrity": "sha512-d9ULIT+a4EXLX3UU8FBjauG9NnsZHkHztXoIcTsOKoOw030fyjheN9svkTULjJxtYag9DZz5Jz5qkWZDPxTFwA==",
- "dev": true,
"dependencies": {
"@babel/code-frame": "^7.10.4",
"@babel/runtime": "^7.12.5",
@@ -6918,14 +6782,12 @@
"node_modules/@testing-library/react/node_modules/@types/aria-query": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.1.tgz",
- "integrity": "sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==",
- "dev": true
+ "integrity": "sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q=="
},
"node_modules/@testing-library/react/node_modules/ansi-styles": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
- "dev": true,
"engines": {
"node": ">=10"
},
@@ -6937,7 +6799,6 @@
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz",
"integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==",
- "dev": true,
"dependencies": {
"deep-equal": "^2.0.5"
}
@@ -6946,7 +6807,6 @@
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
"integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
- "dev": true,
"dependencies": {
"ansi-regex": "^5.0.1",
"ansi-styles": "^5.0.0",
@@ -7506,16 +7366,6 @@
"integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==",
"dev": true
},
- "node_modules/@types/mini-css-extract-plugin": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/@types/mini-css-extract-plugin/-/mini-css-extract-plugin-2.5.1.tgz",
- "integrity": "sha512-evjjtJttaUexgg3au9ZJFy76tV9mySwX3a4Jl82BuormBYluWLRt0xk2urWrhOdPgDWzulRFyotwYOJTmkSgKw==",
- "deprecated": "This is a stub types definition. mini-css-extract-plugin provides its own type definitions, so you do not need this installed.",
- "dev": true,
- "dependencies": {
- "mini-css-extract-plugin": "*"
- }
- },
"node_modules/@types/minimatch": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz",
@@ -7663,7 +7513,6 @@
"version": "17.0.19",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.19.tgz",
"integrity": "sha512-PiYG40pnQRdPHnlf7tZnp0aQ6q9tspYr72vD61saO6zFCybLfMqwUCN0va1/P+86DXn18ZWeW30Bk7xlC5eEAQ==",
- "dev": true,
"dependencies": {
"@types/react": "^17"
}
@@ -7862,16 +7711,6 @@
"integrity": "sha512-6pwWTx8oUtWvsiZUCrhrK/53MzKVLnuNSSaZILPy3uMes9QnTrLMar9BDlJArbMOjDcjb3QXFk6Rz8qmmuySZw==",
"dev": true
},
- "node_modules/@types/tempy": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/@types/tempy/-/tempy-0.3.0.tgz",
- "integrity": "sha512-graSgBSy4TEsenfAasXh28mxfdrLkgrFlXU8QFShFVNHEGHCg5IfO5LBlZjq2SAUnCm/VdxvuQKlp2buPR/YwA==",
- "deprecated": "This is a stub types definition. tempy provides its own type definitions, so you do not need this installed.",
- "dev": true,
- "dependencies": {
- "tempy": "*"
- }
- },
"node_modules/@types/testing-library__jest-dom": {
"version": "5.14.5",
"resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.5.tgz",
@@ -7981,6 +7820,16 @@
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz",
"integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA=="
},
+ "node_modules/@types/yauzl": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz",
+ "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==",
+ "optional": true,
+ "peer": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "5.55.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.55.0.tgz",
@@ -11058,6 +10907,7 @@
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
"integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+ "dev": true,
"engines": [
"node >= 0.8"
],
@@ -11071,12 +10921,14 @@
"node_modules/concat-stream/node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+ "dev": true
},
"node_modules/concat-stream/node_modules/readable-stream": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "dev": true,
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
@@ -11091,6 +10943,7 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
"dependencies": {
"safe-buffer": "~5.1.0"
}
@@ -11182,7 +11035,7 @@
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz",
"integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==",
- "devOptional": true,
+ "dev": true,
"dependencies": {
"ini": "^1.3.4",
"proto-list": "~1.2.1"
@@ -12661,11 +12514,6 @@
"integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==",
"dev": true
},
- "node_modules/duplexer3": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz",
- "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA=="
- },
"node_modules/duplexify": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
@@ -12740,20 +12588,20 @@
}
},
"node_modules/electron": {
- "version": "19.1.9",
- "resolved": "https://registry.npmjs.org/electron/-/electron-19.1.9.tgz",
- "integrity": "sha512-XT5LkTzIHB+ZtD3dTmNnKjVBWrDWReCKt9G1uAFLz6uJMEVcIUiYO+fph5pLXETiBw/QZBx8egduMEfIccLx+g==",
+ "version": "22.3.3",
+ "resolved": "https://registry.npmjs.org/electron/-/electron-22.3.3.tgz",
+ "integrity": "sha512-+ZJDVfyhw7J2A46/kGKscktIhzOisTeJKrUBJLXa7PTB+U+cwyoxCBIaIOnDsdicBCX4nAc1mo6YMQjQQdAmgw==",
"hasInstallScript": true,
"dependencies": {
- "@electron/get": "^1.14.1",
+ "@electron/get": "^2.0.0",
"@types/node": "^16.11.26",
- "extract-zip": "^1.0.3"
+ "extract-zip": "^2.0.1"
},
"bin": {
"electron": "cli.js"
},
"engines": {
- "node": ">= 8.6"
+ "node": ">= 12.20.55"
}
},
"node_modules/electron-builder": {
@@ -12944,9 +12792,9 @@
}
},
"node_modules/electron-to-chromium": {
- "version": "1.4.329",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.329.tgz",
- "integrity": "sha512-dcwPzNUG4+reo5z+wHnrl2eZMu4kz+nLQEeepxLEDTLDC7Mi7AVTM4NXWct1TZyu3G4oQgygaAfbByaBtPqw2Q=="
+ "version": "1.4.328",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.328.tgz",
+ "integrity": "sha512-DE9tTy2PNmy1v55AZAO542ui+MLC2cvINMK4P2LXGsJdput/ThVG9t+QGecPuAZZSgC8XoI+Jh9M1OG9IoNSCw=="
},
"node_modules/electron-updater": {
"version": "4.6.5",
@@ -13058,7 +12906,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
- "devOptional": true,
+ "dev": true,
"engines": {
"node": ">= 0.8"
}
@@ -15017,42 +14865,46 @@
}
},
"node_modules/extract-zip": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz",
- "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
+ "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
"dependencies": {
- "concat-stream": "^1.6.2",
- "debug": "^2.6.9",
- "mkdirp": "^0.5.4",
+ "debug": "^4.1.1",
+ "get-stream": "^5.1.0",
"yauzl": "^2.10.0"
},
"bin": {
"extract-zip": "cli.js"
- }
- },
- "node_modules/extract-zip/node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/extract-zip/node_modules/mkdirp": {
- "version": "0.5.6",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
- "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
- "dependencies": {
- "minimist": "^1.2.6"
},
- "bin": {
- "mkdirp": "bin/cmd.js"
+ "engines": {
+ "node": ">= 10.17.0"
+ },
+ "optionalDependencies": {
+ "@types/yauzl": "^2.9.1"
}
},
- "node_modules/extract-zip/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+ "node_modules/extract-zip/node_modules/get-stream": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
+ "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
+ "dependencies": {
+ "pump": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/extract-zip/node_modules/pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
},
"node_modules/extsprintf": {
"version": "1.3.0",
@@ -16110,22 +15962,6 @@
"node": ">=10.0"
}
},
- "node_modules/global-tunnel-ng": {
- "version": "2.7.1",
- "resolved": "https://registry.npmjs.org/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz",
- "integrity": "sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==",
- "optional": true,
- "peer": true,
- "dependencies": {
- "encodeurl": "^1.0.2",
- "lodash": "^4.17.10",
- "npm-conf": "^1.1.3",
- "tunnel": "^0.0.6"
- },
- "engines": {
- "node": ">=0.10"
- }
- },
"node_modules/globals": {
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
@@ -21295,16 +21131,6 @@
"language-subtag-registry": "~0.3.2"
}
},
- "node_modules/launch-editor": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz",
- "integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==",
- "dev": true,
- "dependencies": {
- "picocolors": "^1.0.0",
- "shell-quote": "^1.7.3"
- }
- },
"node_modules/lazy-cache": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz",
@@ -24098,30 +23924,6 @@
"npm-normalize-package-bin": "^1.0.1"
}
},
- "node_modules/npm-conf": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz",
- "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==",
- "optional": true,
- "peer": true,
- "dependencies": {
- "config-chain": "^1.1.11",
- "pify": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/npm-conf/node_modules/pify": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
- "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
- "optional": true,
- "peer": true,
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/npm-install-checks": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-5.0.0.tgz",
@@ -28539,14 +28341,6 @@
"node": ">= 0.8.0"
}
},
- "node_modules/prepend-http": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
- "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==",
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/prettier": {
"version": "2.8.4",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.4.tgz",
@@ -28741,7 +28535,7 @@
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
"integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==",
- "devOptional": true
+ "dev": true
},
"node_modules/protocols": {
"version": "2.0.1",
@@ -32445,14 +32239,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/to-readable-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz",
- "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -32765,16 +32551,6 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
- "node_modules/tunnel": {
- "version": "0.0.6",
- "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
- "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
- "optional": true,
- "peer": true,
- "engines": {
- "node": ">=0.6.11 <=0.7.0 || >=0.7.3"
- }
- },
"node_modules/tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
@@ -32850,8 +32626,7 @@
"node_modules/typed-emitter": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-1.4.0.tgz",
- "integrity": "sha512-weBmoo3HhpKGgLBOYwe8EB31CzDFuaK7CCL+axXhUYhn4jo6DSkHnbefboCF5i4DQ2aMFe0C/FdTWcPdObgHyg==",
- "dev": true
+ "integrity": "sha512-weBmoo3HhpKGgLBOYwe8EB31CzDFuaK7CCL+axXhUYhn4jo6DSkHnbefboCF5i4DQ2aMFe0C/FdTWcPdObgHyg=="
},
"node_modules/typed-regex": {
"version": "0.0.8",
@@ -32861,7 +32636,8 @@
"node_modules/typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
- "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
+ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
+ "dev": true
},
"node_modules/typedoc": {
"version": "0.23.25",
@@ -33185,17 +32961,6 @@
"requires-port": "^1.0.0"
}
},
- "node_modules/url-parse-lax": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz",
- "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==",
- "dependencies": {
- "prepend-http": "^2.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/use-isomorphic-layout-effect": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz",
@@ -33633,9 +33398,9 @@
}
},
"node_modules/webpack-dev-server": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.12.0.tgz",
- "integrity": "sha512-XRN9YRnvOj3TQQ5w/0pR1y1xDcVnbWtNkTri46kuEbaWUPTHsWUvOyAAI7PZHLY+hsFki2kRltJjKMw7e+IiqA==",
+ "version": "4.11.1",
+ "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.11.1.tgz",
+ "integrity": "sha512-lILVz9tAUy1zGFwieuaQtYiadImb5M3d+H+L1zDYalYoDl0cksAB1UNyuE5MMWJrG6zR1tXkCP2fitl7yoUJiw==",
"dev": true,
"dependencies": {
"@types/bonjour": "^3.5.9",
@@ -33657,7 +33422,6 @@
"html-entities": "^2.3.2",
"http-proxy-middleware": "^2.0.3",
"ipaddr.js": "^2.0.1",
- "launch-editor": "^2.6.0",
"open": "^8.0.9",
"p-retry": "^4.5.0",
"rimraf": "^3.0.2",
@@ -33667,7 +33431,7 @@
"sockjs": "^0.3.24",
"spdy": "^4.0.2",
"webpack-dev-middleware": "^5.3.1",
- "ws": "^8.13.0"
+ "ws": "^8.4.2"
},
"bin": {
"webpack-dev-server": "bin/webpack-dev-server.js"
@@ -34382,6 +34146,25 @@
"integrity": "sha512-ZOzvDRWp8dCVBmgnkIqYCArgdFOO9YzocZp8Ra25N/RStKiWvMOXHMz+GjSeVNe5TstaTmTWPucGJkDw0XXJWA==",
"dev": true
},
+ "packages/cluster-settings": {
+ "name": "@k8slens/cluster-settings",
+ "version": "6.5.0-alpha.1",
+ "license": "MIT",
+ "devDependencies": {
+ "@ogre-tools/injectable": "^15.1.2",
+ "@swc/cli": "^0.1.61",
+ "@swc/core": "^1.3.37",
+ "@types/node": "^16.18.11",
+ "@types/semver": "^7.3.13",
+ "rimraf": "^4.1.2"
+ }
+ },
+ "packages/cluster-settings/node_modules/@types/node": {
+ "version": "16.18.18",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.18.tgz",
+ "integrity": "sha512-fwGw1uvQAzabxL1pyoknPlJIF2t7+K90uTqynleKRx24n3lYcxWa3+KByLhgkF8GEAK2c7hC8Ki0RkNM5H15jQ==",
+ "dev": true
+ },
"packages/core": {
"name": "@k8slens/core",
"version": "6.5.0-alpha.3",
@@ -34390,6 +34173,7 @@
"@astronautlabs/jsonpath": "^1.1.0",
"@hapi/call": "^9.0.1",
"@hapi/subtext": "^7.1.0",
+ "@k8slens/cluster-settings": "^6.5.0-alpha.1",
"@k8slens/node-fetch": "^6.5.0-alpha.1",
"@kubernetes/client-node": "^0.18.1",
"@material-ui/styles": "^4.11.5",
@@ -34401,7 +34185,6 @@
"@sentry/electron": "^3.0.8",
"@sentry/integrations": "^6.19.3",
"@side/jest-runtime": "^1.1.0",
- "abort-controller": "^3.0.0",
"auto-bind": "^4.0.0",
"await-lock": "^2.2.2",
"byline": "^5.0.0",
@@ -34460,6 +34243,7 @@
},
"devDependencies": {
"@async-fn/jest": "1.6.4",
+ "@k8slens/messaging-fake-bridge": "^1.0.0-alpha.1",
"@material-ui/core": "^4.12.3",
"@material-ui/icons": "^4.11.2",
"@material-ui/lab": "^4.0.0-alpha.60",
@@ -34490,7 +34274,6 @@
"@types/marked": "^4.0.8",
"@types/md5-file": "^4.0.2",
"@types/memorystream": "^0.3.0",
- "@types/mini-css-extract-plugin": "^2.4.0",
"@types/mock-fs": "^4.13.1",
"@types/node": "^16.18.11",
"@types/proper-lockfile": "^4.1.2",
@@ -34507,7 +34290,6 @@
"@types/semver": "^7.3.13",
"@types/tar": "^6.1.4",
"@types/tcp-port-used": "^1.0.1",
- "@types/tempy": "^0.3.0",
"@types/triple-beam": "^1.3.2",
"@types/url-parse": "^1.4.8",
"@types/uuid": "^8.3.4",
@@ -34529,7 +34311,7 @@
"css-loader": "^6.7.3",
"deepdash": "^5.3.9",
"dompurify": "^2.4.4",
- "electron": "^19.1.9",
+ "electron": "^22.3.3",
"electron-builder": "^23.6.0",
"esbuild": "^0.17.8",
"esbuild-loader": "^2.21.0",
@@ -34598,7 +34380,11 @@
"@k8slens/application": "^6.5.0-alpha.0",
"@k8slens/application-for-electron-main": "^6.5.0-alpha.0",
"@k8slens/legacy-extensions": "^1.0.0-alpha.0",
+ "@k8slens/messaging": "^1.0.0-alpha.1",
+ "@k8slens/messaging-for-main": "^1.0.0-alpha.1",
+ "@k8slens/messaging-for-renderer": "^1.0.0-alpha.1",
"@k8slens/run-many": "^1.0.0-alpha.1",
+ "@k8slens/startable-stoppable": "^1.0.0-alpha.1",
"@k8slens/test-utils": "^1.0.0-alpha.1",
"@k8slens/utilities": "^1.0.0-alpha.1",
"@types/byline": "^4.2.33",
@@ -36664,7 +36450,11 @@
"@k8slens/generate-tray-icons": "^6.5.0-alpha.1",
"@k8slens/legacy-extension-example": "^1.0.0-alpha.1",
"@k8slens/legacy-extensions": "^1.0.0-alpha.1",
+ "@k8slens/messaging": "^1.0.0-alpha.1",
+ "@k8slens/messaging-for-main": "^1.0.0-alpha.1",
+ "@k8slens/messaging-for-renderer": "^1.0.0-alpha.1",
"@k8slens/run-many": "^1.0.0-alpha.1",
+ "@k8slens/startable-stoppable": "^1.0.0-alpha.1",
"@k8slens/test-utils": "^1.0.0-alpha.1",
"@k8slens/utilities": "^1.0.0-alpha.1",
"@ogre-tools/fp": "^15.1.2",
@@ -36702,14 +36492,13 @@
"@types/webpack-dev-server": "^4.7.2",
"@types/webpack-env": "^1.18.0",
"@types/webpack-node-externals": "2.5.3",
- "abort-controller": "^3.0.0",
"autoprefixer": "^10.4.13",
"circular-dependency-plugin": "^5.2.2",
"concurrently": "^7.6.0",
"copy-webpack-plugin": "^11.0.0",
"cross-env": "^7.0.3",
"css-loader": "^6.7.2",
- "electron": "^19.1.9",
+ "electron": "^22.3.3",
"electron-builder": "^23.6.0",
"electron-notarize": "^0.3.0",
"esbuild-loader": "^2.20.0",
@@ -37203,7 +36992,7 @@
"@k8slens/feature-core": "^6.5.0-alpha.0",
"@ogre-tools/injectable": "^15.1.2",
"@ogre-tools/injectable-extension-for-auto-registration": "^15.1.2",
- "electron": "^19.1.9"
+ "electron": "^22.3.3"
}
},
"packages/technical-features/application/legacy-extensions": {
@@ -37228,30 +37017,180 @@
"@ogre-tools/injectable": "^15.1.2"
}
},
+ "packages/technical-features/messaging/agnostic": {
+ "name": "@k8slens/messaging",
+ "version": "1.0.0-alpha.1",
+ "license": "MIT",
+ "devDependencies": {
+ "@k8slens/eslint-config": "^6.5.0-alpha.1"
+ },
+ "peerDependencies": {
+ "@k8slens/application": "^6.5.0-alpha.0",
+ "@k8slens/feature-core": "^6.5.0-alpha.0",
+ "@k8slens/startable-stoppable": "^1.0.0-alpha.1",
+ "@ogre-tools/injectable": "^15.1.2",
+ "@ogre-tools/injectable-extension-for-auto-registration": "^15.1.2",
+ "@ogre-tools/injectable-extension-for-mobx": "^15.1.2",
+ "lodash": "^4.17.21",
+ "mobx": "^6.7.0"
+ }
+ },
+ "packages/technical-features/messaging/computed-channel": {
+ "name": "@k8slens/computed-channel",
+ "version": "1.0.0-alpha.1",
+ "license": "MIT",
+ "devDependencies": {
+ "@k8slens/eslint-config": "^6.5.0-alpha.1",
+ "@k8slens/messaging-fake-bridge": "^1.0.0-alpha.1",
+ "type-fest": "^2.14.0"
+ },
+ "peerDependencies": {
+ "@k8slens/application": "^6.5.0-alpha.0",
+ "@k8slens/feature-core": "^6.5.0-alpha.0",
+ "@k8slens/messaging": "^1.0.0-alpha.1",
+ "@ogre-tools/fp": "^15.1.2",
+ "@ogre-tools/injectable": "^15.1.2",
+ "@ogre-tools/injectable-extension-for-auto-registration": "^15.1.2",
+ "@ogre-tools/injectable-extension-for-mobx": "^15.1.2",
+ "lodash": "^4.17.21",
+ "mobx": "^6.8.0"
+ }
+ },
+ "packages/technical-features/messaging/electron/main": {
+ "name": "@k8slens/messaging-for-main",
+ "version": "1.0.0-alpha.1",
+ "license": "MIT",
+ "devDependencies": {
+ "@k8slens/eslint-config": "^6.5.0-alpha.1"
+ },
+ "peerDependencies": {
+ "@k8slens/application": "^6.5.0-alpha.0",
+ "@k8slens/feature-core": "^6.5.0-alpha.0",
+ "@k8slens/messaging": "^1.0.0-alpha.1",
+ "@ogre-tools/injectable": "^15.1.2",
+ "@ogre-tools/injectable-extension-for-auto-registration": "^15.1.2",
+ "electron": "^22.3.3",
+ "lodash": "^4.17.21"
+ }
+ },
+ "packages/technical-features/messaging/electron/renderer": {
+ "name": "@k8slens/messaging-for-renderer",
+ "version": "1.0.0-alpha.1",
+ "license": "MIT",
+ "devDependencies": {
+ "@k8slens/eslint-config": "^6.5.0-alpha.1"
+ },
+ "peerDependencies": {
+ "@k8slens/application": "^6.5.0-alpha.0",
+ "@k8slens/messaging": "^1.0.0-alpha.1",
+ "@k8slens/run-many": "^1.0.0-alpha.1",
+ "@k8slens/startable-stoppable": "^1.0.0-alpha.1",
+ "@ogre-tools/injectable": "^15.1.2",
+ "@ogre-tools/injectable-extension-for-auto-registration": "^15.1.2",
+ "electron": "^22.3.3",
+ "lodash": "^4.17.21"
+ }
+ },
+ "packages/technical-features/messaging/message-bridge-fake": {
+ "name": "@k8slens/messaging-fake-bridge",
+ "version": "1.0.0-alpha.1",
+ "license": "MIT",
+ "devDependencies": {
+ "@async-fn/jest": "^1.6.4",
+ "@k8slens/eslint-config": "^6.5.0-alpha.1",
+ "@k8slens/feature-core": "6.5.0-alpha.1",
+ "@ogre-tools/injectable-extension-for-mobx": "^15.1.2",
+ "mobx": "^6.7.0"
+ },
+ "peerDependencies": {
+ "@k8slens/messaging": "^1.0.0-alpha.1",
+ "@ogre-tools/fp": "^15.1.2",
+ "@ogre-tools/injectable": "^15.1.2",
+ "lodash": "^4.17.21"
+ }
+ },
"packages/utility-features/run-many": {
"name": "@k8slens/run-many",
"version": "1.0.0-alpha.1",
"license": "MIT",
+ "devDependencies": {
+ "@types/uuid": "^9.0.1"
+ },
"peerDependencies": {
"@k8slens/test-utils": "^1.0.0-alpha.1",
"@k8slens/utilities": "^1.0.0-alpha.1",
- "@ogre-tools/fp": "^15.1.1",
- "@ogre-tools/injectable": "^15.1.1"
+ "@ogre-tools/fp": "^15.1.2",
+ "@ogre-tools/injectable": "^15.1.2",
+ "type-fest": "^2.19.0",
+ "typed-emitter": "^1.4.0",
+ "uuid": "^8.3.2"
+ }
+ },
+ "packages/utility-features/run-many/node_modules/@types/uuid": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.1.tgz",
+ "integrity": "sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==",
+ "dev": true
+ },
+ "packages/utility-features/startable-stoppable": {
+ "name": "@k8slens/startable-stoppable",
+ "version": "1.0.0-alpha.1",
+ "license": "MIT",
+ "devDependencies": {
+ "@k8slens/eslint-config": "^6.5.0-alpha.1"
}
},
"packages/utility-features/test-utils": {
"name": "@k8slens/test-utils",
"version": "1.0.0-alpha.1",
- "license": "MIT"
+ "license": "MIT",
+ "devDependencies": {
+ "@types/lodash": "^4.14.191"
+ },
+ "peerDependencies": {
+ "@ogre-tools/injectable": "^15.1.2",
+ "@ogre-tools/injectable-react": "^15.1.2",
+ "@testing-library/react": "^12.1.5",
+ "lodash": "^4.17.21",
+ "react": "^17.0.2"
+ }
},
"packages/utility-features/utilities": {
"name": "@k8slens/utilities",
"version": "1.0.0-alpha.1",
"license": "MIT",
+ "devDependencies": {
+ "@types/crypto-js": "^4.1.1",
+ "@types/lodash": "^4.14.191",
+ "@types/react": "^17.0.2",
+ "@types/react-router": "^5.1.20",
+ "@types/readable-stream": "^2.3.15",
+ "@types/semver": "^7.3.13",
+ "@types/tar": "^6.1.4",
+ "type-fest": "^2.14.0"
+ },
"peerDependencies": {
+ "@astronautlabs/jsonpath": "^1.1.0",
+ "crypto-js": "^4.1.1",
+ "lodash": "^4.17.21",
"mobx": "^6.8.0",
- "type-fest": "^2.19.0"
+ "moment": "^2.29.4",
+ "p-limit": "^3.1.0",
+ "path-to-regexp": "^6.2.1",
+ "react": "^17.0.2",
+ "react-router": "^5.3.4",
+ "readable-stream": "^3.6.2",
+ "semver": "^7.3.8",
+ "tar": "^6.1.13",
+ "type-fest": "^2.19.0",
+ "typed-regex": "^0.0.8"
}
+ },
+ "packages/utility-features/utilities/node_modules/@types/crypto-js": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.1.1.tgz",
+ "integrity": "sha512-BG7fQKZ689HIoc5h+6D2Dgq1fABRa0RbBWKBd9SP/MVRVXROflpm5fhwyATX5duFmbStzyzyycPB8qUYKDH3NA==",
+ "dev": true
}
}
}
diff --git a/package.json b/package.json
index 982724f37f..0a9f693adb 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,7 @@
"clean:node_modules": "lerna clean -y && rimraf node_modules",
"dev": "lerna run dev --stream --skip-nx-cache",
"lint": "lerna run lint --stream",
+ "lint:fix": "lerna run lint:fix --stream",
"mkdocs:serve-local": "docker build -t mkdocs-serve-local:latest mkdocs/ && docker run --rm -it -p 8000:8000 -v ${PWD}:/docs mkdocs-serve-local:latest",
"mkdocs:verify": "docker build -t mkdocs-serve-local:latest mkdocs/ && docker run --rm -v ${PWD}:/docs mkdocs-serve-local:latest build --strict",
"test:unit": "lerna run --stream test:unit",
@@ -28,6 +29,11 @@
"precreate-release-pr": "cd packages/release-tool && npm run build",
"create-release-pr": "node packages/release-tool/dist/index.js"
},
+ "overrides": {
+ "underscore": "^1.12.1",
+ "react": "^17",
+ "@types/react": "^17"
+ },
"devDependencies": {
"adr": "^1.4.3",
"cross-env": "^7.0.3",
diff --git a/packages/cluster-settings/.swcrc b/packages/cluster-settings/.swcrc
new file mode 100644
index 0000000000..8e7a530f16
--- /dev/null
+++ b/packages/cluster-settings/.swcrc
@@ -0,0 +1,9 @@
+{
+ "$schema": "https://json.schemastore.org/swcrc",
+ "jsc": {
+ "parser": {
+ "syntax": "typescript"
+ },
+ "target": "es2022"
+ }
+}
diff --git a/packages/cluster-settings/README.md b/packages/cluster-settings/README.md
new file mode 100644
index 0000000000..c3d3b890f4
--- /dev/null
+++ b/packages/cluster-settings/README.md
@@ -0,0 +1,3 @@
+# Description
+
+The package exports tokens needed for external configuration of Cluster Settings page.
diff --git a/packages/cluster-settings/package.json b/packages/cluster-settings/package.json
new file mode 100644
index 0000000000..199347dcf4
--- /dev/null
+++ b/packages/cluster-settings/package.json
@@ -0,0 +1,31 @@
+{
+ "name": "@k8slens/cluster-settings",
+ "version": "6.5.0-alpha.1",
+ "description": "Injection token exporter for cluster settings configuration",
+ "license": "MIT",
+ "private": false,
+ "mode": "production",
+ "publishConfig": {
+ "access": "public",
+ "registry": "https://registry.npmjs.org/"
+ },
+ "main": "./dist/index.js",
+ "types": "./dist/index.d.ts",
+ "files": [
+ "dist"
+ ],
+ "scripts": {
+ "clean": "rimraf dist/",
+ "generate-types": "tsc --d --declarationDir ./dist --declarationMap --emitDeclarationOnly",
+ "build": "npm run generate-types && swc ./src/index.ts -d ./dist",
+ "prepare:test": "npm run build"
+ },
+ "devDependencies": {
+ "@ogre-tools/injectable": "^15.1.2",
+ "@swc/cli": "^0.1.61",
+ "@swc/core": "^1.3.37",
+ "@types/node": "^16.18.11",
+ "@types/semver": "^7.3.13",
+ "rimraf": "^4.1.2"
+ }
+}
diff --git a/packages/cluster-settings/src/index.ts b/packages/cluster-settings/src/index.ts
new file mode 100644
index 0000000000..181c69d46a
--- /dev/null
+++ b/packages/cluster-settings/src/index.ts
@@ -0,0 +1,30 @@
+import { getInjectionToken } from "@ogre-tools/injectable";
+
+type ClusterPreferences = {
+ clusterName?: string;
+ icon?: string | null;
+}
+
+export interface ClusterIconMenuItem {
+ id: string;
+ title: string;
+ disabled?: (preferences: ClusterPreferences) => boolean;
+ onClick: (preferences: ClusterPreferences) => void;
+}
+
+export interface ClusterIconSettingComponentProps {
+ preferences: ClusterPreferences;
+}
+
+export interface ClusterIconSettingsComponent {
+ id: string;
+ Component: React.ComponentType;
+}
+
+export const clusterIconSettingsMenuInjectionToken = getInjectionToken({
+ id: "cluster-icon-settings-menu-injection-token",
+});
+
+export const clusterIconSettingsComponentInjectionToken = getInjectionToken({
+ id: "cluster-icon-settings-component-injection-token",
+});
\ No newline at end of file
diff --git a/packages/cluster-settings/tsconfig.json b/packages/cluster-settings/tsconfig.json
new file mode 100644
index 0000000000..534a5fd447
--- /dev/null
+++ b/packages/cluster-settings/tsconfig.json
@@ -0,0 +1,18 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "dist/",
+ "paths": {
+ "*": [
+ "node_modules/*",
+ "types/*"
+ ]
+ },
+ },
+ "include": [
+ "src/**/*",
+ ],
+ "exclude": [
+ "node_modules",
+ ]
+}
diff --git a/packages/core/package.json b/packages/core/package.json
index bf304a4c13..ad6e7e45ae 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -116,13 +116,11 @@
}
}
},
- "resolutions": {
- "@astronautlabs/jsonpath/underscore": "^1.12.1"
- },
"dependencies": {
"@astronautlabs/jsonpath": "^1.1.0",
"@hapi/call": "^9.0.1",
"@hapi/subtext": "^7.1.0",
+ "@k8slens/cluster-settings": "^6.5.0-alpha.1",
"@k8slens/node-fetch": "^6.5.0-alpha.1",
"@kubernetes/client-node": "^0.18.1",
"@material-ui/styles": "^4.11.5",
@@ -134,7 +132,6 @@
"@sentry/electron": "^3.0.8",
"@sentry/integrations": "^6.19.3",
"@side/jest-runtime": "^1.1.0",
- "abort-controller": "^3.0.0",
"auto-bind": "^4.0.0",
"await-lock": "^2.2.2",
"byline": "^5.0.0",
@@ -193,6 +190,7 @@
},
"devDependencies": {
"@async-fn/jest": "1.6.4",
+ "@k8slens/messaging-fake-bridge": "^1.0.0-alpha.1",
"@material-ui/core": "^4.12.3",
"@material-ui/icons": "^4.11.2",
"@material-ui/lab": "^4.0.0-alpha.60",
@@ -223,7 +221,6 @@
"@types/marked": "^4.0.8",
"@types/md5-file": "^4.0.2",
"@types/memorystream": "^0.3.0",
- "@types/mini-css-extract-plugin": "^2.4.0",
"@types/mock-fs": "^4.13.1",
"@types/node": "^16.18.11",
"@types/proper-lockfile": "^4.1.2",
@@ -240,7 +237,6 @@
"@types/semver": "^7.3.13",
"@types/tar": "^6.1.4",
"@types/tcp-port-used": "^1.0.1",
- "@types/tempy": "^0.3.0",
"@types/triple-beam": "^1.3.2",
"@types/url-parse": "^1.4.8",
"@types/uuid": "^8.3.4",
@@ -262,7 +258,7 @@
"css-loader": "^6.7.3",
"deepdash": "^5.3.9",
"dompurify": "^2.4.4",
- "electron": "^19.1.9",
+ "electron": "^22.3.3",
"electron-builder": "^23.6.0",
"esbuild": "^0.17.8",
"esbuild-loader": "^2.21.0",
@@ -328,7 +324,11 @@
"@k8slens/application": "^6.5.0-alpha.0",
"@k8slens/application-for-electron-main": "^6.5.0-alpha.0",
"@k8slens/legacy-extensions": "^1.0.0-alpha.0",
+ "@k8slens/messaging": "^1.0.0-alpha.1",
+ "@k8slens/messaging-for-main": "^1.0.0-alpha.1",
+ "@k8slens/messaging-for-renderer": "^1.0.0-alpha.1",
"@k8slens/run-many": "^1.0.0-alpha.1",
+ "@k8slens/startable-stoppable": "^1.0.0-alpha.1",
"@k8slens/test-utils": "^1.0.0-alpha.1",
"@k8slens/utilities": "^1.0.0-alpha.1",
"@types/byline": "^4.2.33",
diff --git a/packages/core/src/common/app-paths/app-path-names.ts b/packages/core/src/common/app-paths/app-path-names.ts
index 8e3d2c440e..b7b829a5e3 100644
--- a/packages/core/src/common/app-paths/app-path-names.ts
+++ b/packages/core/src/common/app-paths/app-path-names.ts
@@ -11,7 +11,7 @@ export const pathNames: PathName[] = [
"home",
"appData",
"userData",
- "cache",
+ "sessionData",
"temp",
"exe",
"module",
diff --git a/packages/core/src/common/app-paths/app-paths-channel.ts b/packages/core/src/common/app-paths/app-paths-channel.ts
index 4502569d3b..e738b4896a 100644
--- a/packages/core/src/common/app-paths/app-paths-channel.ts
+++ b/packages/core/src/common/app-paths/app-paths-channel.ts
@@ -3,11 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { AppPaths } from "./app-path-injection-token";
-import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token";
+import { getRequestChannel } from "@k8slens/messaging";
-export type AppPathsChannel = RequestChannel;
-
-export const appPathsChannel: AppPathsChannel = {
- id: "app-paths",
-};
+export const appPathsChannel = getRequestChannel("app-paths");
diff --git a/packages/core/src/common/app-paths/app-paths.test.ts b/packages/core/src/common/app-paths/app-paths.test.ts
index f847346dad..851ece4390 100644
--- a/packages/core/src/common/app-paths/app-paths.test.ts
+++ b/packages/core/src/common/app-paths/app-paths.test.ts
@@ -21,7 +21,6 @@ describe("app-paths", () => {
const defaultAppPathsStub: AppPaths = {
currentApp: "/some-current-app",
appData: "/some-app-data",
- cache: "/some-cache",
crashDumps: "/some-crash-dumps",
desktop: "/some-desktop",
documents: "/some-documents",
@@ -36,6 +35,7 @@ describe("app-paths", () => {
temp: "/some-temp",
videos: "/some-videos",
userData: "/some-irrelevant-user-data",
+ sessionData: "/some-irrelevant-user-data", // By default this points to userData
};
builder.beforeApplicationStart(({ mainDi }) => {
@@ -73,7 +73,6 @@ describe("app-paths", () => {
expect(actual).toEqual({
currentApp: "/some-current-app",
appData: "/some-app-data",
- cache: "/some-cache",
crashDumps: "/some-crash-dumps",
desktop: "/some-desktop",
documents: "/some-documents",
@@ -88,6 +87,7 @@ describe("app-paths", () => {
temp: "/some-temp",
videos: "/some-videos",
userData: "/some-app-data/some-product-name",
+ sessionData: "/some-app-data/some-product-name",
});
});
@@ -97,7 +97,6 @@ describe("app-paths", () => {
expect(actual).toEqual({
currentApp: "/some-current-app",
appData: "/some-app-data",
- cache: "/some-cache",
crashDumps: "/some-crash-dumps",
desktop: "/some-desktop",
documents: "/some-documents",
@@ -112,6 +111,7 @@ describe("app-paths", () => {
temp: "/some-temp",
videos: "/some-videos",
userData: "/some-app-data/some-product-name",
+ sessionData: "/some-app-data/some-product-name",
});
});
});
diff --git a/packages/core/src/common/base-store/base-store.ts b/packages/core/src/common/base-store/base-store.ts
index be7abf1293..a1dd26f0f7 100644
--- a/packages/core/src/common/base-store/base-store.ts
+++ b/packages/core/src/common/base-store/base-store.ts
@@ -15,7 +15,7 @@ import type { GetConfigurationFileModel } from "../get-configuration-file-model/
import type { Logger } from "../logger";
import type { PersistStateToConfig } from "./save-to-file";
import type { GetBasenameOfPath } from "../path/get-basename.injectable";
-import type { EnlistMessageChannelListener } from "../utils/channel/enlist-message-channel-listener-injection-token";
+import type { EnlistMessageChannelListener } from "@k8slens/messaging";
import { toJS } from "../utils";
export interface BaseStoreParams extends Omit, "migrations"> {
@@ -108,6 +108,7 @@ export abstract class BaseStore {
this.params.syncOptions,
),
this.dependencies.enlistMessageChannelListener({
+ id: this.displayName,
channel: {
id: `${this.dependencies.ipcChannelPrefixes.local}:${config.path}`,
},
diff --git a/packages/core/src/common/certificate/lens-proxy-certificate-channel.ts b/packages/core/src/common/certificate/lens-proxy-certificate-channel.ts
index 7d9652ce5c..9dd339ee65 100644
--- a/packages/core/src/common/certificate/lens-proxy-certificate-channel.ts
+++ b/packages/core/src/common/certificate/lens-proxy-certificate-channel.ts
@@ -4,6 +4,6 @@
*/
import type { SelfSignedCert } from "selfsigned";
-import { getRequestChannel } from "../utils/channel/get-request-channel";
+import { getRequestChannel } from "@k8slens/messaging";
export const lensProxyCertificateChannel = getRequestChannel("request-lens-proxy-certificate");
diff --git a/packages/core/src/common/cluster-store/cluster-store.injectable.ts b/packages/core/src/common/cluster-store/cluster-store.injectable.ts
index ddd811c760..79eb02e36c 100644
--- a/packages/core/src/common/cluster-store/cluster-store.injectable.ts
+++ b/packages/core/src/common/cluster-store/cluster-store.injectable.ts
@@ -16,7 +16,7 @@ import { baseStoreIpcChannelPrefixesInjectionToken } from "../base-store/channel
import { shouldBaseStoreDisableSyncInIpcListenerInjectionToken } from "../base-store/disable-sync";
import { persistStateToConfigInjectionToken } from "../base-store/save-to-file";
import getBasenameOfPathInjectable from "../path/get-basename.injectable";
-import { enlistMessageChannelListenerInjectionToken } from "../utils/channel/enlist-message-channel-listener-injection-token";
+import { enlistMessageChannelListenerInjectionToken } from "@k8slens/messaging";
const clusterStoreInjectable = getInjectable({
id: "cluster-store",
diff --git a/packages/core/src/common/cluster/authorization-review.injectable.ts b/packages/core/src/common/cluster/authorization-review.injectable.ts
deleted file mode 100644
index 3352423377..0000000000
--- a/packages/core/src/common/cluster/authorization-review.injectable.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * Copyright (c) OpenLens Authors. All rights reserved.
- * Licensed under MIT License. See LICENSE in root directory for more information.
- */
-
-import type { KubeConfig, V1ResourceAttributes } from "@kubernetes/client-node";
-import { AuthorizationV1Api } from "@kubernetes/client-node";
-import { getInjectable } from "@ogre-tools/injectable";
-import loggerInjectable from "../logger.injectable";
-
-/**
- * Requests the permissions for actions on the kube cluster
- * @param resourceAttributes The descriptor of the action that is desired to be known if it is allowed
- * @returns `true` if the actions described are allowed
- */
-export type CanI = (resourceAttributes: V1ResourceAttributes) => Promise;
-
-/**
- * @param proxyConfig This config's `currentContext` field must be set, and will be used as the target cluster
- */
-export type CreateAuthorizationReview = (proxyConfig: KubeConfig) => CanI;
-
-const createAuthorizationReviewInjectable = getInjectable({
- id: "authorization-review",
- instantiate: (di): CreateAuthorizationReview => {
- const logger = di.inject(loggerInjectable);
-
- return (proxyConfig) => {
- const api = proxyConfig.makeApiClient(AuthorizationV1Api);
-
- return async (resourceAttributes: V1ResourceAttributes): Promise => {
- try {
- const { body } = await api.createSelfSubjectAccessReview({
- apiVersion: "authorization.k8s.io/v1",
- kind: "SelfSubjectAccessReview",
- spec: { resourceAttributes },
- });
-
- return body.status?.allowed ?? false;
- } catch (error) {
- logger.error(`[AUTHORIZATION-REVIEW]: failed to create access review: ${error}`, { resourceAttributes });
-
- return false;
- }
- };
- };
- },
-});
-
-export default createAuthorizationReviewInjectable;
diff --git a/packages/core/src/common/cluster/create-authorization-api.injectable.ts b/packages/core/src/common/cluster/create-authorization-api.injectable.ts
new file mode 100644
index 0000000000..c0658a4a34
--- /dev/null
+++ b/packages/core/src/common/cluster/create-authorization-api.injectable.ts
@@ -0,0 +1,16 @@
+/**
+ * Copyright (c) OpenLens Authors. All rights reserved.
+ * Licensed under MIT License. See LICENSE in root directory for more information.
+ */
+import { AuthorizationV1Api } from "@kubernetes/client-node";
+import type { KubeConfig } from "@kubernetes/client-node";
+import { getInjectable } from "@ogre-tools/injectable";
+
+export type CreateAuthorizationApi = (config: KubeConfig) => AuthorizationV1Api;
+
+const createAuthorizationApiInjectable = getInjectable({
+ id: "create-authorization-api",
+ instantiate: (): CreateAuthorizationApi => (config) => config.makeApiClient(AuthorizationV1Api),
+});
+
+export default createAuthorizationApiInjectable;
diff --git a/packages/core/src/common/cluster/create-can-i.injectable.ts b/packages/core/src/common/cluster/create-can-i.injectable.ts
new file mode 100644
index 0000000000..59d30dbe77
--- /dev/null
+++ b/packages/core/src/common/cluster/create-can-i.injectable.ts
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) OpenLens Authors. All rights reserved.
+ * Licensed under MIT License. See LICENSE in root directory for more information.
+ */
+
+import type { AuthorizationV1Api, V1ResourceAttributes } from "@kubernetes/client-node";
+import { getInjectable } from "@ogre-tools/injectable";
+import loggerInjectable from "../logger.injectable";
+
+/**
+ * Requests the permissions for actions on the kube cluster
+ * @param resourceAttributes The descriptor of the action that is desired to be known if it is allowed
+ * @returns `true` if the actions described are allowed
+ */
+export type CanI = (resourceAttributes: V1ResourceAttributes) => Promise;
+
+export type CreateCanI = (api: AuthorizationV1Api) => CanI;
+
+const createCanIInjectable = getInjectable({
+ id: "create-can-i",
+ instantiate: (di): CreateCanI => {
+ const logger = di.inject(loggerInjectable);
+
+ return (api) => async (resourceAttributes: V1ResourceAttributes): Promise => {
+ try {
+ const { body } = await api.createSelfSubjectAccessReview({
+ apiVersion: "authorization.k8s.io/v1",
+ kind: "SelfSubjectAccessReview",
+ spec: { resourceAttributes },
+ });
+
+ return body.status?.allowed ?? false;
+ } catch (error) {
+ logger.error(`[AUTHORIZATION-REVIEW]: failed to create access review: ${error}`, { resourceAttributes });
+
+ return false;
+ }
+ };
+ },
+});
+
+export default createCanIInjectable;
diff --git a/packages/core/src/common/cluster/create-core-api.injectable.ts b/packages/core/src/common/cluster/create-core-api.injectable.ts
new file mode 100644
index 0000000000..2389b12478
--- /dev/null
+++ b/packages/core/src/common/cluster/create-core-api.injectable.ts
@@ -0,0 +1,16 @@
+/**
+ * Copyright (c) OpenLens Authors. All rights reserved.
+ * Licensed under MIT License. See LICENSE in root directory for more information.
+ */
+import type { KubeConfig } from "@kubernetes/client-node";
+import { CoreV1Api } from "@kubernetes/client-node";
+import { getInjectable } from "@ogre-tools/injectable";
+
+export type CreateCoreApi = (config: KubeConfig) => CoreV1Api;
+
+const createCoreApiInjectable = getInjectable({
+ id: "create-core-api",
+ instantiate: (): CreateCoreApi => config => config.makeApiClient(CoreV1Api),
+});
+
+export default createCoreApiInjectable;
diff --git a/packages/core/src/common/cluster/create-request-namespace-list-permissions.injectable.ts b/packages/core/src/common/cluster/create-request-namespace-list-permissions.injectable.ts
new file mode 100644
index 0000000000..b3e8875dc1
--- /dev/null
+++ b/packages/core/src/common/cluster/create-request-namespace-list-permissions.injectable.ts
@@ -0,0 +1,57 @@
+/**
+ * Copyright (c) OpenLens Authors. All rights reserved.
+ * Licensed under MIT License. See LICENSE in root directory for more information.
+ */
+
+import type { AuthorizationV1Api } from "@kubernetes/client-node";
+import { getInjectable } from "@ogre-tools/injectable";
+import loggerInjectable from "../logger.injectable";
+import type { KubeApiResource } from "../rbac";
+
+export type CanListResource = (resource: KubeApiResource) => boolean;
+
+/**
+ * Requests the permissions for actions on the kube cluster
+ * @param namespace The namespace of the resources
+ */
+export type RequestNamespaceListPermissions = (namespace: string) => Promise;
+
+export type CreateRequestNamespaceListPermissions = (api: AuthorizationV1Api) => RequestNamespaceListPermissions;
+
+const createRequestNamespaceListPermissionsInjectable = getInjectable({
+ id: "create-request-namespace-list-permissions",
+ instantiate: (di): CreateRequestNamespaceListPermissions => {
+ const logger = di.inject(loggerInjectable);
+
+ return (api) => async (namespace) => {
+ try {
+ const { body: { status }} = await api.createSelfSubjectRulesReview({
+ apiVersion: "authorization.k8s.io/v1",
+ kind: "SelfSubjectRulesReview",
+ spec: { namespace },
+ });
+
+ if (!status || status.incomplete) {
+ logger.warn(`[AUTHORIZATION-NAMESPACE-REVIEW]: allowing all resources in namespace="${namespace}" due to incomplete SelfSubjectRulesReview: ${status?.evaluationError}`);
+
+ return () => true;
+ }
+
+ const { resourceRules } = status;
+
+ return (resource) => (
+ resourceRules
+ .filter(({ apiGroups = ["*"] }) => apiGroups.includes("*") || apiGroups.includes(resource.group))
+ .filter(({ resources = ["*"] }) => resources.includes("*") || resources.includes(resource.apiName))
+ .some(({ verbs }) => verbs.includes("*") || verbs.includes("list"))
+ );
+ } catch (error) {
+ logger.error(`[AUTHORIZATION-NAMESPACE-REVIEW]: failed to create subject rules review`, { namespace, error });
+
+ return () => true;
+ }
+ };
+ },
+});
+
+export default createRequestNamespaceListPermissionsInjectable;
diff --git a/packages/core/src/common/cluster/current-cluster-channel.ts b/packages/core/src/common/cluster/current-cluster-channel.ts
index 957baa6f9c..c16af7832b 100644
--- a/packages/core/src/common/cluster/current-cluster-channel.ts
+++ b/packages/core/src/common/cluster/current-cluster-channel.ts
@@ -4,7 +4,7 @@
*/
import type { ClusterId } from "../cluster-types";
-import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token";
+import type { MessageChannel } from "@k8slens/messaging";
export const currentClusterMessageChannel: MessageChannel = {
id: "current-visible-cluster",
diff --git a/packages/core/src/common/cluster/list-namespaces.injectable.ts b/packages/core/src/common/cluster/list-namespaces.injectable.ts
index 363a10abb1..04acb0671b 100644
--- a/packages/core/src/common/cluster/list-namespaces.injectable.ts
+++ b/packages/core/src/common/cluster/list-namespaces.injectable.ts
@@ -2,27 +2,21 @@
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
-import type { KubeConfig } from "@kubernetes/client-node";
-import { CoreV1Api } from "@kubernetes/client-node";
+import type { CoreV1Api } from "@kubernetes/client-node";
import { getInjectable } from "@ogre-tools/injectable";
import { isDefined } from "@k8slens/utilities";
export type ListNamespaces = () => Promise;
-
-export type CreateListNamespaces = (config: KubeConfig) => ListNamespaces;
+export type CreateListNamespaces = (api: CoreV1Api) => ListNamespaces;
const createListNamespacesInjectable = getInjectable({
id: "create-list-namespaces",
- instantiate: (): CreateListNamespaces => (config) => {
- const coreApi = config.makeApiClient(CoreV1Api);
+ instantiate: (): CreateListNamespaces => (api) => async () => {
+ const { body: { items }} = await api.listNamespace();
- return async () => {
- const { body: { items }} = await coreApi.listNamespace();
-
- return items
- .map(ns => ns.metadata?.name)
- .filter(isDefined);
- };
+ return items
+ .map(ns => ns.metadata?.name)
+ .filter(isDefined);
},
});
diff --git a/packages/core/src/common/cluster/request-namespace-list-permissions.injectable.ts b/packages/core/src/common/cluster/request-namespace-list-permissions.injectable.ts
deleted file mode 100644
index 4b1aadeee6..0000000000
--- a/packages/core/src/common/cluster/request-namespace-list-permissions.injectable.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-/**
- * Copyright (c) OpenLens Authors. All rights reserved.
- * Licensed under MIT License. See LICENSE in root directory for more information.
- */
-
-import type { KubeConfig } from "@kubernetes/client-node";
-import { AuthorizationV1Api } from "@kubernetes/client-node";
-import { getInjectable } from "@ogre-tools/injectable";
-import loggerInjectable from "../logger.injectable";
-import type { KubeApiResource } from "../rbac";
-
-export type CanListResource = (resource: KubeApiResource) => boolean;
-
-/**
- * Requests the permissions for actions on the kube cluster
- * @param namespace The namespace of the resources
- */
-export type RequestNamespaceListPermissions = (namespace: string) => Promise;
-
-/**
- * @param proxyConfig This config's `currentContext` field must be set, and will be used as the target cluster
- */
-export type RequestNamespaceListPermissionsFor = (proxyConfig: KubeConfig) => RequestNamespaceListPermissions;
-
-const requestNamespaceListPermissionsForInjectable = getInjectable({
- id: "request-namespace-list-permissions-for",
- instantiate: (di): RequestNamespaceListPermissionsFor => {
- const logger = di.inject(loggerInjectable);
-
- return (proxyConfig) => {
- const api = proxyConfig.makeApiClient(AuthorizationV1Api);
-
- return async (namespace) => {
- try {
- const { body: { status }} = await api.createSelfSubjectRulesReview({
- apiVersion: "authorization.k8s.io/v1",
- kind: "SelfSubjectRulesReview",
- spec: { namespace },
- });
-
- if (!status || status.incomplete) {
- logger.warn(`[AUTHORIZATION-NAMESPACE-REVIEW]: allowing all resources in namespace="${namespace}" due to incomplete SelfSubjectRulesReview: ${status?.evaluationError}`);
-
- return () => true;
- }
-
- const { resourceRules } = status;
-
- return (resource) => {
- const rules = resourceRules.filter(({
- apiGroups = ["*"],
- resources = ["*"],
- }) => {
- const isAboutRelevantApiGroup = apiGroups.includes("*") || apiGroups.includes(resource.group);
- const isAboutResource = resources.includes("*") || resources.includes(resource.apiName);
-
- return isAboutRelevantApiGroup && isAboutResource;
- });
-
- return rules.some(({ verbs }) => verbs.includes("*") || verbs.includes("list"));
- };
- } catch (error) {
- logger.error(`[AUTHORIZATION-NAMESPACE-REVIEW]: failed to create subject rules review`, { namespace, error });
-
- return () => true;
- }
- };
- };
- },
-});
-
-export default requestNamespaceListPermissionsForInjectable;
diff --git a/packages/core/src/common/cluster/request-namespace-list-permissions.test.ts b/packages/core/src/common/cluster/request-namespace-list-permissions.test.ts
index c62f69ca8e..194b5ce7e5 100644
--- a/packages/core/src/common/cluster/request-namespace-list-permissions.test.ts
+++ b/packages/core/src/common/cluster/request-namespace-list-permissions.test.ts
@@ -3,334 +3,225 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
-import type { V1SubjectRulesReviewStatus } from "@kubernetes/client-node";
+import type { AsyncFnMock } from "@async-fn/jest";
+import asyncFn from "@async-fn/jest";
+import type { AuthorizationV1Api, V1SubjectRulesReviewStatus } from "@kubernetes/client-node";
import type { DiContainer } from "@ogre-tools/injectable";
+import type { IncomingMessage } from "http";
+import { anyObject } from "jest-mock-extended";
import { getDiForUnitTesting } from "../../main/getDiForUnitTesting";
-import type { RequestNamespaceListPermissionsFor } from "./request-namespace-list-permissions.injectable";
-import requestNamespaceListPermissionsForInjectable from "./request-namespace-list-permissions.injectable";
+import { cast } from "../../test-utils/cast";
+import type { KubeApiResource } from "../rbac";
+import type { RequestNamespaceListPermissions } from "./create-request-namespace-list-permissions.injectable";
+import createRequestNamespaceListPermissionsInjectable from "./create-request-namespace-list-permissions.injectable";
-const createStubProxyConfig = (statusResponse: Promise<{ body: { status: V1SubjectRulesReviewStatus }}>) => ({
- makeApiClient: () => ({
- createSelfSubjectRulesReview: (): Promise<{ body: { status: V1SubjectRulesReviewStatus }}> => statusResponse,
- }),
-});
+interface TestCase {
+ description: string;
+ status: V1SubjectRulesReviewStatus;
+ expected: boolean;
+}
describe("requestNamespaceListPermissions", () => {
let di: DiContainer;
- let requestNamespaceListPermissions: RequestNamespaceListPermissionsFor;
+ let createSelfSubjectRulesReviewMock: AsyncFnMock;
+ let requestNamespaceListPermissions: RequestNamespaceListPermissions;
beforeEach(() => {
di = getDiForUnitTesting();
- requestNamespaceListPermissions = di.inject(requestNamespaceListPermissionsForInjectable);
+
+ const createRequestNamespaceListPermissions = di.inject(createRequestNamespaceListPermissionsInjectable);
+
+ createSelfSubjectRulesReviewMock = asyncFn();
+
+ requestNamespaceListPermissions = createRequestNamespaceListPermissions(cast({
+ createSelfSubjectRulesReview: createSelfSubjectRulesReviewMock,
+ }));
});
- describe("when api returns incomplete data", () => {
- it("returns truthy function", async () => {
- const requestPermissions = requestNamespaceListPermissions(createStubProxyConfig(
- new Promise((resolve) => resolve({
- body: {
- status: {
- incomplete: true,
- resourceRules: [],
- nonResourceRules: [],
- },
- },
- })),
- ) as any);
+ describe("when a request for list permissions in a namespace has been started", () => {
+ let request: ReturnType;
- const permissionCheck = await requestPermissions("irrelevant-namespace");
-
- expect(permissionCheck({
- apiName: "pods",
- group: "",
- kind: "Pod",
- namespaced: true,
- })).toBeTruthy();
+ beforeEach(() => {
+ request = requestNamespaceListPermissions("irrelevant-namespace");
});
- });
- describe("when api rejects", () => {
- it("returns truthy function", async () => {
- const requestPermissions = requestNamespaceListPermissions(createStubProxyConfig(
- new Promise((resolve, reject) => reject("unknown error")),
- ) as any);
-
- const permissionCheck = await requestPermissions("irrelevant-namespace");
-
- expect(permissionCheck({
- apiName: "pods",
- group: "",
- kind: "Pod",
- namespaced: true,
- })).toBeTruthy();
+ it("should request the creation of a SelfSubjectRulesReview", () => {
+ expect(createSelfSubjectRulesReviewMock).toBeCalledWith(anyObject({
+ spec: {
+ namespace: "irrelevant-namespace",
+ },
+ }));
});
- });
- describe("when first resourceRule has all permissions for everything", () => {
- it("return truthy function", async () => {
- const requestPermissions = requestNamespaceListPermissions(createStubProxyConfig(
- new Promise((resolve) => resolve({
- body: {
- status: {
- incomplete: false,
- resourceRules: [
- {
- apiGroups: ["*"],
- verbs: ["*"],
- },
- {
- apiGroups: ["*"],
- verbs: ["get"],
- },
- ],
- nonResourceRules: [],
+ ([
+ {
+ description: "incomplete data",
+ status: {
+ incomplete: true,
+ resourceRules: [],
+ nonResourceRules: [],
+ },
+ expected: true,
+ },
+ {
+ description: "first resourceRule has all permissions for everything",
+ status: {
+ incomplete: false,
+ resourceRules: [
+ {
+ apiGroups: ["*"],
+ verbs: ["*"],
},
- },
- })),
- ) as any);
+ {
+ apiGroups: ["*"],
+ verbs: ["get"],
+ },
+ ],
+ nonResourceRules: [],
+ },
+ expected: true,
+ },
+ {
+ description: "first resourceRule has list permissions for everything",
+ status: {
+ incomplete: false,
+ resourceRules: [
+ {
+ apiGroups: ["*"],
+ verbs: ["list"],
+ },
+ {
+ apiGroups: ["*"],
+ verbs: ["get"],
+ },
+ ],
+ nonResourceRules: [],
+ },
+ expected: true,
+ },
+ {
+ description: "first resourceRule has list permissions for asked resource",
+ status: {
+ incomplete: false,
+ resourceRules: [
+ {
+ apiGroups: ["some-api-group"],
+ resources: ["some-kind"],
+ verbs: ["list"],
+ },
+ {
+ apiGroups: ["*"],
+ verbs: ["get"],
+ },
+ ],
+ nonResourceRules: [],
+ },
+ expected: true,
+ },
+ {
+ description: "last resourceRule has all permissions for everything",
+ status: {
+ incomplete: false,
+ resourceRules: [
+ {
+ apiGroups: ["*"],
+ verbs: ["get"],
+ },
+ {
+ apiGroups: ["*"],
+ verbs: ["*"],
+ },
+ ],
+ nonResourceRules: [],
+ },
+ expected: true,
+ },
+ {
+ description: "last resourceRule has list permissions for asked resource",
+ status: {
+ incomplete: false,
+ resourceRules: [
+ {
+ apiGroups: ["*"],
+ verbs: ["get"],
+ },
+ {
+ apiGroups: ["some-api-group"],
+ resources: ["some-kind"],
+ verbs: ["list"],
+ },
+ ],
+ nonResourceRules: [],
+ },
+ expected: true,
+ },
+ {
+ description: "resourceRules has matching resource without list verb",
+ status: {
+ incomplete: false,
+ resourceRules: [
+ {
+ apiGroups: ["some-api-group"],
+ resources: ["some-kind"],
+ verbs: ["get"],
+ },
+ ],
+ nonResourceRules: [],
+ },
+ expected: false,
+ },
+ {
+ description: "resourceRules has no matching resource with list verb",
+ status: {
+ incomplete: false,
+ resourceRules: [
+ {
+ apiGroups: [""],
+ resources: ["services"],
+ verbs: ["list"],
+ },
+ ],
+ nonResourceRules: [],
+ },
+ expected: false,
+ },
+ ] as TestCase[]).forEach(({ description, status, expected }) => {
+ describe(`when api returns ${description}`, () => {
+ beforeEach(async () => {
+ await createSelfSubjectRulesReviewMock.resolve({
+ body: {
+ status,
+ spec: {},
+ },
+ response: null as unknown as IncomingMessage,
+ });
+ });
- const permissionCheck = await requestPermissions("irrelevant-namespace");
+ it(`allows the request to complete, and 'canListResource' will return ${expected}`, async () => {
+ const canListResource = await request;
- expect(permissionCheck({
- apiName: "pods",
- group: "",
- kind: "Pod",
- namespaced: true,
- })).toBeTruthy();
+ expect(canListResource(someKubeResource)).toBe(expected);
+ });
+ });
});
- });
- describe("when first resourceRule has list permissions for everything", () => {
- it("return truthy function", async () => {
- const requestPermissions = requestNamespaceListPermissions(createStubProxyConfig(
- new Promise((resolve) => resolve({
- body: {
- status: {
- incomplete: false,
- resourceRules: [
- {
- apiGroups: ["*"],
- verbs: ["list"],
- },
- {
- apiGroups: ["*"],
- verbs: ["get"],
- },
- ],
- nonResourceRules: [],
- },
- },
- })),
- ) as any);
+ describe("when api rejects", () => {
+ beforeEach(async () => {
+ await createSelfSubjectRulesReviewMock.reject(new Error("unknown error"));
+ });
- const permissionCheck = await requestPermissions("irrelevant-namespace");
+ it("allows the request to complete, and 'canListResource' will return true", async () => {
+ const canListResource = await request;
- expect(permissionCheck({
- apiName: "pods",
- group: "",
- kind: "Pod",
- namespaced: true,
- })).toBeTruthy();
- });
- });
-
- describe("when first resourceRule has list permissions for asked resource", () => {
- it("return truthy function", async () => {
- const requestPermissions = requestNamespaceListPermissions(createStubProxyConfig(
- new Promise((resolve) => resolve({
- body: {
- status: {
- incomplete: false,
- resourceRules: [
- {
- apiGroups: [""],
- resources: ["pods"],
- verbs: ["list"],
- },
- {
- apiGroups: ["*"],
- verbs: ["get"],
- },
- ],
- nonResourceRules: [],
- },
- },
- })),
- ) as any);
-
- const permissionCheck = await requestPermissions("irrelevant-namespace");
-
- expect(permissionCheck({
- apiName: "pods",
- group: "",
- kind: "Pod",
- namespaced: true,
- })).toBeTruthy();
- });
- });
-
- describe("when last resourceRule has all permissions for everything", () => {
- it("return truthy function", async () => {
- const requestPermissions = requestNamespaceListPermissions(createStubProxyConfig(
- new Promise((resolve) => resolve({
- body: {
- status: {
- incomplete: false,
- resourceRules: [
- {
- apiGroups: ["*"],
- verbs: ["get"],
- },
- {
- apiGroups: ["*"],
- verbs: ["*"],
- },
- ],
- nonResourceRules: [],
- },
- },
- })),
- ) as any);
-
- const permissionCheck = await requestPermissions("irrelevant-namespace");
-
- expect(permissionCheck({
- apiName: "pods",
- group: "",
- kind: "Pod",
- namespaced: true,
- })).toBeTruthy();
- });
- });
-
- describe("when last resourceRule has list permissions for everything", () => {
- it("return truthy function", async () => {
- const requestPermissions = requestNamespaceListPermissions(createStubProxyConfig(
- new Promise((resolve) => resolve({
- body: {
- status: {
- incomplete: false,
- resourceRules: [
- {
- apiGroups: ["*"],
- verbs: ["get"],
- },
- {
- apiGroups: ["*"],
- verbs: ["list"],
- },
- ],
- nonResourceRules: [],
- },
- },
- })),
- ) as any);
-
- const permissionCheck = await requestPermissions("irrelevant-namespace");
-
- expect(permissionCheck({
- apiName: "pods",
- group: "",
- kind: "Pod",
- namespaced: true,
- })).toBeTruthy();
- });
- });
-
- describe("when last resourceRule has list permissions for asked resource", () => {
- it("return truthy function", async () => {
- const requestPermissions = requestNamespaceListPermissions(createStubProxyConfig(
- new Promise((resolve) => resolve({
- body: {
- status: {
- incomplete: false,
- resourceRules: [
- {
- apiGroups: ["*"],
- verbs: ["get"],
- },
- {
- apiGroups: [""],
- resources: ["pods"],
- verbs: ["list"],
- },
- ],
- nonResourceRules: [],
- },
- },
- })),
- ) as any);
-
- const permissionCheck = await requestPermissions("irrelevant-namespace");
-
- expect(permissionCheck({
- apiName: "pods",
- group: "",
- kind: "Pod",
- namespaced: true,
- })).toBeTruthy();
- });
- });
-
- describe("when resourceRules has matching resource without list verb", () => {
- it("return falsy function", async () => {
- const requestPermissions = requestNamespaceListPermissions(createStubProxyConfig(
- new Promise((resolve) => resolve({
- body: {
- status: {
- incomplete: false,
- resourceRules: [
- {
- apiGroups: [""],
- resources: ["pods"],
- verbs: ["get"],
- },
- ],
- nonResourceRules: [],
- },
- },
- })),
- ) as any);
-
- const permissionCheck = await requestPermissions("irrelevant-namespace");
-
- expect(permissionCheck({
- apiName: "pods",
- group: "",
- kind: "Pod",
- namespaced: true,
- })).toBeFalsy();
- });
- });
-
- describe("when resourceRules has no matching resource with list verb", () => {
- it("return falsy function", async () => {
- const requestPermissions = requestNamespaceListPermissions(createStubProxyConfig(
- new Promise((resolve) => resolve({
- body: {
- status: {
- incomplete: false,
- resourceRules: [
- {
- apiGroups: [""],
- resources: ["services"],
- verbs: ["list"],
- },
- ],
- nonResourceRules: [],
- },
- },
- })),
- ) as any);
-
- const permissionCheck = await requestPermissions("irrelevant-namespace");
-
- expect(permissionCheck({
- apiName: "pods",
- group: "",
- kind: "Pod",
- namespaced: true,
- })).toBeFalsy();
+ expect(canListResource(someKubeResource)).toBe(true);
+ });
});
});
});
+
+const someKubeResource: KubeApiResource = {
+ apiName: "some-kind",
+ group: "some-api-group",
+ kind: "SomeKind",
+ namespaced: true,
+};
diff --git a/packages/core/src/common/cluster/visibility-channel.ts b/packages/core/src/common/cluster/visibility-channel.ts
index 8a1a297ff2..554217a409 100644
--- a/packages/core/src/common/cluster/visibility-channel.ts
+++ b/packages/core/src/common/cluster/visibility-channel.ts
@@ -4,7 +4,7 @@
*/
import type { ClusterId } from "../cluster-types";
-import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token";
+import type { MessageChannel } from "@k8slens/messaging";
export const clusterVisibilityChannel: MessageChannel = {
id: "cluster-visibility",
diff --git a/packages/core/src/common/error-reporting/initialize-sentry-reporting.injectable.ts b/packages/core/src/common/error-reporting/initialize-sentry-reporting.injectable.ts
index 778f959739..677c18a586 100644
--- a/packages/core/src/common/error-reporting/initialize-sentry-reporting.injectable.ts
+++ b/packages/core/src/common/error-reporting/initialize-sentry-reporting.injectable.ts
@@ -13,7 +13,7 @@ import userStoreInjectable from "../user-store/user-store.injectable";
export type InitializeSentryReportingWith = (initSentry: (opts: BrowserOptions | ElectronMainOptions) => void) => void;
-const mapProcessName = (type: "browser" | "renderer" | "worker") => type === "browser" ? "main" : type;
+const mapProcessName = (type: "browser" | "renderer" | "worker" | "utility") => type === "browser" ? "main" : type;
const initializeSentryReportingWithInjectable = getInjectable({
id: "initialize-sentry-reporting-with",
diff --git a/packages/core/src/common/fetch/timeout-controller.ts b/packages/core/src/common/fetch/timeout-controller.ts
index 702becdc9d..c4688218db 100644
--- a/packages/core/src/common/fetch/timeout-controller.ts
+++ b/packages/core/src/common/fetch/timeout-controller.ts
@@ -3,13 +3,15 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
+import { formatDuration } from "@k8slens/utilities";
+
/**
* Creates an AbortController with an associated timeout
* @param timeout The number of milliseconds before this controller will auto abort
*/
export function withTimeout(timeout: number): AbortController {
const controller = new AbortController();
- const id = setTimeout(() => controller.abort(), timeout);
+ const id = setTimeout(() => controller.abort(`Operation timed out: timeout ${formatDuration(timeout)}`), timeout);
controller.signal.addEventListener("abort", () => clearTimeout(id));
diff --git a/packages/core/src/common/front-end-routing/app-navigation-channel.ts b/packages/core/src/common/front-end-routing/app-navigation-channel.ts
index b3d8f02c66..8670fc4953 100644
--- a/packages/core/src/common/front-end-routing/app-navigation-channel.ts
+++ b/packages/core/src/common/front-end-routing/app-navigation-channel.ts
@@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { IpcRendererNavigationEvents } from "../ipc/navigation-events";
-import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token";
+import type { MessageChannel } from "@k8slens/messaging";
export type AppNavigationChannel = MessageChannel;
diff --git a/packages/core/src/common/front-end-routing/cluster-frame-navigation-channel.ts b/packages/core/src/common/front-end-routing/cluster-frame-navigation-channel.ts
index 2439f523e2..5f96526da4 100644
--- a/packages/core/src/common/front-end-routing/cluster-frame-navigation-channel.ts
+++ b/packages/core/src/common/front-end-routing/cluster-frame-navigation-channel.ts
@@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { IpcRendererNavigationEvents } from "../ipc/navigation-events";
-import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token";
+import type { MessageChannel } from "@k8slens/messaging";
export type ClusterFrameNavigationChannel = MessageChannel;
diff --git a/packages/core/src/common/fs/copy.global-override-for-injectable.ts b/packages/core/src/common/fs/copy.global-override-for-injectable.ts
deleted file mode 100644
index 3799d3b760..0000000000
--- a/packages/core/src/common/fs/copy.global-override-for-injectable.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-/**
- * Copyright (c) OpenLens Authors. All rights reserved.
- * Licensed under MIT License. See LICENSE in root directory for more information.
- */
-
-import { getGlobalOverride } from "@k8slens/test-utils";
-import copyInjectable from "./copy.injectable";
-
-export default getGlobalOverride(copyInjectable, () => async () => {
- throw new Error("tried to copy filepaths without override");
-});
diff --git a/packages/core/src/common/fs/lstat.global-override-for-injectable.ts b/packages/core/src/common/fs/lstat.global-override-for-injectable.ts
deleted file mode 100644
index 155fac7451..0000000000
--- a/packages/core/src/common/fs/lstat.global-override-for-injectable.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-/**
- * Copyright (c) OpenLens Authors. All rights reserved.
- * Licensed under MIT License. See LICENSE in root directory for more information.
- */
-
-import { getGlobalOverride } from "@k8slens/test-utils";
-import lstatInjectable from "./lstat.injectable";
-
-export default getGlobalOverride(lstatInjectable, () => async () => {
- throw new Error("tried to lstat a filepath without override");
-});
diff --git a/packages/core/src/common/fs/read-directory.global-override-for-injectable.ts b/packages/core/src/common/fs/read-directory.global-override-for-injectable.ts
deleted file mode 100644
index 72d9b523f4..0000000000
--- a/packages/core/src/common/fs/read-directory.global-override-for-injectable.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-/**
- * Copyright (c) OpenLens Authors. All rights reserved.
- * Licensed under MIT License. See LICENSE in root directory for more information.
- */
-
-import { getGlobalOverride } from "@k8slens/test-utils";
-import readDirectoryInjectable from "./read-directory.injectable";
-
-export default getGlobalOverride(readDirectoryInjectable, () => async () => {
- throw new Error("tried to read a directory's content without override");
-});
diff --git a/packages/core/src/common/fs/remove.global-override-for-injectable.ts b/packages/core/src/common/fs/remove.global-override-for-injectable.ts
deleted file mode 100644
index 58fb0f9dce..0000000000
--- a/packages/core/src/common/fs/remove.global-override-for-injectable.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-/**
- * Copyright (c) OpenLens Authors. All rights reserved.
- * Licensed under MIT License. See LICENSE in root directory for more information.
- */
-
-import { getGlobalOverride } from "@k8slens/test-utils";
-import removePathInjectable from "./remove.injectable";
-
-export default getGlobalOverride(removePathInjectable, () => async () => {
- throw new Error("tried to remove path without override");
-});
diff --git a/packages/core/src/common/fs/write-file.global-override-for-injectable.ts b/packages/core/src/common/fs/write-file.global-override-for-injectable.ts
deleted file mode 100644
index e87f648305..0000000000
--- a/packages/core/src/common/fs/write-file.global-override-for-injectable.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-/**
- * Copyright (c) OpenLens Authors. All rights reserved.
- * Licensed under MIT License. See LICENSE in root directory for more information.
- */
-
-import { getGlobalOverride } from "@k8slens/test-utils";
-import writeFileInjectable from "./write-file.injectable";
-
-export default getGlobalOverride(writeFileInjectable, () => async () => {
- throw new Error("tried to write file without override");
-});
diff --git a/packages/core/src/common/helm/add-helm-repository-channel.ts b/packages/core/src/common/helm/add-helm-repository-channel.ts
index 258367c7ec..1744192059 100644
--- a/packages/core/src/common/helm/add-helm-repository-channel.ts
+++ b/packages/core/src/common/helm/add-helm-repository-channel.ts
@@ -3,11 +3,10 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { HelmRepo } from "./helm-repo";
-import type { AsyncResult } from "@k8slens/utilities";
-import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token";
+import type { Result } from "@k8slens/utilities";
+import { getRequestChannel } from "@k8slens/messaging";
-export type AddHelmRepositoryChannel = RequestChannel>;
-
-export const addHelmRepositoryChannel: AddHelmRepositoryChannel = {
- id: "add-helm-repository-channel",
-};
+export const addHelmRepositoryChannel = getRequestChannel<
+ HelmRepo,
+ Result
+>("add-helm-repository-channel");
diff --git a/packages/core/src/common/helm/get-active-helm-repositories-channel.ts b/packages/core/src/common/helm/get-active-helm-repositories-channel.ts
index 2ea5a80030..ba4e0ae956 100644
--- a/packages/core/src/common/helm/get-active-helm-repositories-channel.ts
+++ b/packages/core/src/common/helm/get-active-helm-repositories-channel.ts
@@ -4,10 +4,9 @@
*/
import type { HelmRepo } from "./helm-repo";
import type { AsyncResult } from "@k8slens/utilities";
-import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token";
+import { getRequestChannel } from "@k8slens/messaging";
-export type GetActiveHelmRepositoriesChannel = RequestChannel>;
-
-export const getActiveHelmRepositoriesChannel: GetActiveHelmRepositoriesChannel = {
- id: "get-helm-active-list-repositories",
-};
+export const getActiveHelmRepositoriesChannel = getRequestChannel<
+ void,
+ AsyncResult
+>("get-helm-active-list-repositories");
diff --git a/packages/core/src/common/helm/remove-helm-repository-channel.ts b/packages/core/src/common/helm/remove-helm-repository-channel.ts
index f1189cb580..09c7630f34 100644
--- a/packages/core/src/common/helm/remove-helm-repository-channel.ts
+++ b/packages/core/src/common/helm/remove-helm-repository-channel.ts
@@ -3,11 +3,10 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { AsyncResult } from "@k8slens/utilities";
-import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token";
+import { getRequestChannel } from "@k8slens/messaging";
import type { HelmRepo } from "./helm-repo";
-export type RemoveHelmRepositoryChannel = RequestChannel>;
-
-export const removeHelmRepositoryChannel: RemoveHelmRepositoryChannel = {
- id: "remove-helm-repository-channel",
-};
+export const removeHelmRepositoryChannel = getRequestChannel<
+ HelmRepo,
+ AsyncResult
+>("remove-helm-repository-channel");
diff --git a/packages/core/src/common/hotbars/store.injectable.ts b/packages/core/src/common/hotbars/store.injectable.ts
index cc15f93bf8..ea25840e11 100644
--- a/packages/core/src/common/hotbars/store.injectable.ts
+++ b/packages/core/src/common/hotbars/store.injectable.ts
@@ -14,7 +14,7 @@ import { hotbarStoreMigrationInjectionToken } from "./migrations-token";
import getBasenameOfPathInjectable from "../path/get-basename.injectable";
import { baseStoreIpcChannelPrefixesInjectionToken } from "../base-store/channel-prefix";
import { persistStateToConfigInjectionToken } from "../base-store/save-to-file";
-import { enlistMessageChannelListenerInjectionToken } from "../utils/channel/enlist-message-channel-listener-injection-token";
+import { enlistMessageChannelListenerInjectionToken } from "@k8slens/messaging";
import { shouldBaseStoreDisableSyncInIpcListenerInjectionToken } from "../base-store/disable-sync";
const hotbarStoreInjectable = getInjectable({
diff --git a/packages/core/src/common/k8s-api/__tests__/api-manager.test.ts b/packages/core/src/common/k8s-api/__tests__/api-manager.test.ts
index 6ea6327038..48fdb3e544 100644
--- a/packages/core/src/common/k8s-api/__tests__/api-manager.test.ts
+++ b/packages/core/src/common/k8s-api/__tests__/api-manager.test.ts
@@ -4,6 +4,7 @@
*/
import type { DiContainer } from "@ogre-tools/injectable";
+import { getInjectable } from "@ogre-tools/injectable";
import clusterFrameContextForNamespacedResourcesInjectable from "../../../renderer/cluster-frame-context/for-namespaced-resources.injectable";
import hostedClusterInjectable from "../../../renderer/cluster-frame-context/hosted-cluster.injectable";
import { getDiForUnitTesting } from "../../../renderer/getDiForUnitTesting";
@@ -21,6 +22,9 @@ import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
// eslint-disable-next-line no-restricted-imports
import { KubeApi as ExternalKubeApi } from "../../../extensions/common-api/k8s-api";
import { Cluster } from "../../cluster/cluster";
+import { runInAction } from "mobx";
+import { customResourceDefinitionApiInjectionToken } from "../api-manager/crd-api-token";
+import assert from "assert";
class TestApi extends KubeApi {
protected async checkPreferredVersion() {
@@ -117,4 +121,90 @@ describe("ApiManager", () => {
});
});
});
+
+ describe("given than a CRD has a default KubeApi registered for it", () => {
+ const apiBase = "/apis/aquasecurity.github.io/v1alpha1/vulnerabilityreports";
+
+ beforeEach(() => {
+ runInAction(() => {
+ di.register(getInjectable({
+ id: `default-kube-api-for-custom-resource-definition-${apiBase}`,
+ instantiate: (di) => {
+ const objectConstructor = class extends KubeObject {
+ static readonly kind = "VulnerabilityReport";
+ static readonly namespaced = true;
+ static readonly apiBase = apiBase;
+ };
+
+ return Object.assign(
+ new KubeApi({
+ logger: di.inject(loggerInjectable),
+ maybeKubeApi: di.inject(maybeKubeApiInjectable),
+ }, { objectConstructor }),
+ {
+ myField: 1,
+ },
+ );
+ },
+ injectionToken: customResourceDefinitionApiInjectionToken,
+ }));
+ });
+ });
+
+ it("can be retrieved from apiManager", () => {
+ expect(apiManager.getApi(apiBase)).toMatchObject({
+ myField: 1,
+ });
+ });
+
+ it("can have a default KubeObjectStore instance retrieved for it", () => {
+ expect(apiManager.getStore(apiBase)).toBeInstanceOf(KubeObjectStore);
+ });
+
+ describe("given that an extension registers an api with the same apibase", () => {
+ beforeEach(() => {
+ void Object.assign(new ExternalKubeApi({
+ objectConstructor: KubeObject,
+ apiBase,
+ kind: "VulnerabilityReport",
+ }), {
+ myField: 2,
+ });
+ });
+
+ it("the extension's instance is retrievable instead from apiManager", () => {
+ expect(apiManager.getApi(apiBase)).toMatchObject({
+ myField: 2,
+ });
+ });
+
+ it("can have a default KubeObjectStore instance retrieved for it", () => {
+ expect(apiManager.getStore(apiBase)).toBeInstanceOf(KubeObjectStore);
+ });
+
+ describe("given that an extension registers a store for the same apibase", () => {
+ beforeEach(() => {
+ const api = apiManager.getApi(apiBase);
+
+ assert(api);
+
+ apiManager.registerStore(Object.assign(
+ new KubeObjectStore({
+ context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
+ logger: di.inject(loggerInjectable),
+ }, api),
+ {
+ someField: 2,
+ },
+ ));
+ });
+
+ it("can gets the custom KubeObjectStore instance instead", () => {
+ expect(apiManager.getStore(apiBase)).toMatchObject({
+ someField: 2,
+ });
+ });
+ });
+ });
+ });
});
diff --git a/packages/core/src/common/k8s-api/__tests__/kube-api.test.ts b/packages/core/src/common/k8s-api/__tests__/kube-api.test.ts
index fa5b024bd2..e7240895cf 100644
--- a/packages/core/src/common/k8s-api/__tests__/kube-api.test.ts
+++ b/packages/core/src/common/k8s-api/__tests__/kube-api.test.ts
@@ -22,7 +22,6 @@ import { flushPromises } from "@k8slens/test-utils";
import createKubeJsonApiInjectable from "../create-kube-json-api.injectable";
import type { IKubeWatchEvent } from "../kube-watch-event";
import type { KubeJsonApiDataFor, KubeStatusData } from "../kube-object";
-import AbortController from "abort-controller";
import setupAutoRegistrationInjectable
from "../../../renderer/before-frame-starts/runnables/setup-auto-registration.injectable";
import {
diff --git a/packages/core/src/common/k8s-api/api-manager/api-manager.ts b/packages/core/src/common/k8s-api/api-manager/api-manager.ts
index f6c2758921..6b60ba8e7a 100644
--- a/packages/core/src/common/k8s-api/api-manager/api-manager.ts
+++ b/packages/core/src/common/k8s-api/api-manager/api-manager.ts
@@ -10,7 +10,8 @@ import { autorun, action, observable } from "mobx";
import type { KubeApi } from "../kube-api";
import type { KubeObject, ObjectReference } from "../kube-object";
import { parseKubeApi, createKubeApiURL } from "../kube-api-parse";
-import { iter } from "@k8slens/utilities";
+import { getOrInsertWith, iter } from "@k8slens/utilities";
+import type { CreateCustomResourceStore } from "./create-custom-resource-store.injectable";
export type RegisterableStore = Store extends KubeObjectStore
? Store
@@ -26,13 +27,15 @@ export type FindApiCallback = (api: KubeApi) => boolean;
interface Dependencies {
readonly apis: IComputedValue;
+ readonly crdApis: IComputedValue;
readonly stores: IComputedValue;
+ createCustomResourceStore: CreateCustomResourceStore;
}
export class ApiManager {
private readonly externalApis = observable.array();
private readonly externalStores = observable.array();
-
+ private readonly defaultCrdStores = observable.map();
private readonly apis = observable.map();
constructor(private readonly dependencies: Dependencies) {
@@ -56,6 +59,12 @@ export class ApiManager {
}
}
+ for (const crdApi of this.dependencies.crdApis.get()) {
+ if (!newState.has(crdApi.apiBase)) {
+ newState.set(crdApi.apiBase, crdApi);
+ }
+ }
+
this.apis.replace(newState);
});
}
@@ -110,6 +119,16 @@ export class ApiManager {
this.externalStores.push(store);
}
+ private apiIsDefaultCrdApi(api: KubeApi): boolean {
+ for (const crdApi of this.dependencies.crdApis.get()) {
+ if (crdApi.apiBase === api.apiBase) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
getStore(api: string | undefined): KubeObjectStore | undefined;
getStore(api: RegisterableApi): KubeObjectStoreFrom | undefined;
/**
@@ -130,9 +149,19 @@ export class ApiManager {
return undefined;
}
- return iter.chain(this.dependencies.stores.get().values())
+ const defaultResult = iter.chain(this.dependencies.stores.get().values())
.concat(this.externalStores.values())
.find(store => store.api.apiBase === api.apiBase);
+
+ if (defaultResult) {
+ return defaultResult;
+ }
+
+ if (this.apiIsDefaultCrdApi(api)) {
+ return getOrInsertWith(this.defaultCrdStores, api.apiBase, () => this.dependencies.createCustomResourceStore(api));
+ }
+
+ return undefined;
}
lookupApiLink(ref: ObjectReference, parentObject?: KubeObject): string {
diff --git a/packages/core/src/common/k8s-api/api-manager/auto-registration-emitter.injectable.ts b/packages/core/src/common/k8s-api/api-manager/auto-registration-emitter.injectable.ts
index d9a68a988c..714e9d8952 100644
--- a/packages/core/src/common/k8s-api/api-manager/auto-registration-emitter.injectable.ts
+++ b/packages/core/src/common/k8s-api/api-manager/auto-registration-emitter.injectable.ts
@@ -5,11 +5,9 @@
import { getInjectable } from "@ogre-tools/injectable";
import EventEmitter from "events";
import type TypedEventEmitter from "typed-emitter";
-import type { CustomResourceDefinition } from "../endpoints";
import type { KubeApi } from "../kube-api";
export interface LegacyAutoRegistration {
- customResourceDefinition: (crd: CustomResourceDefinition) => void;
kubeApi: (api: KubeApi) => void;
}
diff --git a/packages/core/src/common/k8s-api/api-manager/crd-api-token.ts b/packages/core/src/common/k8s-api/api-manager/crd-api-token.ts
new file mode 100644
index 0000000000..d8f0c918c2
--- /dev/null
+++ b/packages/core/src/common/k8s-api/api-manager/crd-api-token.ts
@@ -0,0 +1,11 @@
+/**
+ * Copyright (c) OpenLens Authors. All rights reserved.
+ * Licensed under MIT License. See LICENSE in root directory for more information.
+ */
+
+import { getInjectionToken } from "@ogre-tools/injectable";
+import type { KubeApi } from "../kube-api";
+
+export const customResourceDefinitionApiInjectionToken = getInjectionToken({
+ id: "custom-resource-definition-api-token",
+});
diff --git a/packages/core/src/common/k8s-api/api-manager/create-custom-resource-store.injectable.ts b/packages/core/src/common/k8s-api/api-manager/create-custom-resource-store.injectable.ts
new file mode 100644
index 0000000000..fbf46e2b42
--- /dev/null
+++ b/packages/core/src/common/k8s-api/api-manager/create-custom-resource-store.injectable.ts
@@ -0,0 +1,27 @@
+/**
+ * Copyright (c) OpenLens Authors. All rights reserved.
+ * Licensed under MIT License. See LICENSE in root directory for more information.
+ */
+import { getInjectable } from "@ogre-tools/injectable";
+import clusterFrameContextForNamespacedResourcesInjectable from "../../../renderer/cluster-frame-context/for-namespaced-resources.injectable";
+import loggerInjectable from "../../logger.injectable";
+import type { KubeApi } from "../kube-api";
+import type { KubeObject } from "../kube-object";
+import type { KubeObjectStoreDependencies } from "../kube-object.store";
+import { CustomResourceStore } from "./resource.store";
+
+export type CreateCustomResourceStore = (api: KubeApi) => CustomResourceStore;
+
+const createCustomResourceStoreInjectable = getInjectable({
+ id: "create-custom-resource-store",
+ instantiate: (di): CreateCustomResourceStore => {
+ const deps: KubeObjectStoreDependencies = {
+ context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
+ logger: di.inject(loggerInjectable),
+ };
+
+ return (api) => new CustomResourceStore(deps, api);
+ },
+});
+
+export default createCustomResourceStoreInjectable;
diff --git a/packages/core/src/common/k8s-api/api-manager/manager.injectable.ts b/packages/core/src/common/k8s-api/api-manager/manager.injectable.ts
index f0b61c28b6..2ffd41a296 100644
--- a/packages/core/src/common/k8s-api/api-manager/manager.injectable.ts
+++ b/packages/core/src/common/k8s-api/api-manager/manager.injectable.ts
@@ -9,6 +9,8 @@ import { computedInjectManyInjectable } from "@ogre-tools/injectable-extension-f
import { kubeObjectStoreInjectionToken } from "./kube-object-store-token";
import { kubeApiInjectionToken } from "../kube-api/kube-api-injection-token";
import { computed } from "mobx";
+import { customResourceDefinitionApiInjectionToken } from "./crd-api-token";
+import createCustomResourceStoreInjectable from "./create-custom-resource-store.injectable";
const apiManagerInjectable = getInjectable({
id: "api-manager",
@@ -23,6 +25,10 @@ const apiManagerInjectable = getInjectable({
stores: storesAndApisCanBeCreated
? computedInjectMany(kubeObjectStoreInjectionToken)
: computed(() => []),
+ crdApis: storesAndApisCanBeCreated
+ ? computedInjectMany(customResourceDefinitionApiInjectionToken)
+ : computed(() => []),
+ createCustomResourceStore: di.inject(createCustomResourceStoreInjectable),
});
},
});
diff --git a/packages/core/src/common/k8s-api/kube-api.ts b/packages/core/src/common/k8s-api/kube-api.ts
index 94fc24be7d..c5ed03abad 100644
--- a/packages/core/src/common/k8s-api/kube-api.ts
+++ b/packages/core/src/common/k8s-api/kube-api.ts
@@ -20,7 +20,6 @@ import type { Patch } from "rfc6902";
import assert from "assert";
import type { PartialDeep } from "type-fest";
import type { Logger } from "../logger";
-import type AbortController from "abort-controller";
import { matches } from "lodash/fp";
import { makeObservable, observable } from "mobx";
diff --git a/packages/core/src/common/k8s-api/kube-object.store.ts b/packages/core/src/common/k8s-api/kube-object.store.ts
index 408794e44b..9effdc8f57 100644
--- a/packages/core/src/common/k8s-api/kube-object.store.ts
+++ b/packages/core/src/common/k8s-api/kube-object.store.ts
@@ -17,7 +17,6 @@ import type { Patch } from "rfc6902";
import type { Logger } from "../logger";
import assert from "assert";
import type { PartialDeep } from "type-fest";
-import AbortController from "abort-controller";
import type { ClusterContext } from "../../renderer/cluster-frame-context/cluster-frame-context";
import autoBind from "auto-bind";
@@ -89,7 +88,7 @@ export interface KubeObjectStoreDependencies {
readonly logger: Logger;
}
-export abstract class KubeObjectStore<
+export class KubeObjectStore<
K extends KubeObject = KubeObject,
A extends KubeApi = KubeApi>,
D extends KubeJsonApiDataFor = KubeApiDataFrom,
diff --git a/packages/core/src/common/kube-helpers/channels.ts b/packages/core/src/common/kube-helpers/channels.ts
index b48f9f1f99..c5df4d7358 100644
--- a/packages/core/src/common/kube-helpers/channels.ts
+++ b/packages/core/src/common/kube-helpers/channels.ts
@@ -4,11 +4,9 @@
*/
import { getInjectionToken } from "@ogre-tools/injectable";
-import type { Asyncify } from "type-fest";
-import type { RequestChannelHandler } from "../../main/utils/channel/channel-listeners/listener-tokens";
import type { ClusterId } from "../cluster-types";
-import type { AsyncResult } from "@k8slens/utilities";
-import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token";
+import type { AsyncResult, Result } from "@k8slens/utilities";
+import { getRequestChannel } from "@k8slens/messaging";
export interface KubectlApplyAllArgs {
clusterId: ClusterId;
@@ -16,11 +14,12 @@ export interface KubectlApplyAllArgs {
extraArgs: string[];
}
-export const kubectlApplyAllChannel: RequestChannel> = {
- id: "kubectl-apply-all",
-};
+export const kubectlApplyAllChannel = getRequestChannel<
+ KubectlApplyAllArgs,
+ Result
+>("kubectl-apply-all");
-export type KubectlApplyAll = Asyncify>;
+export type KubectlApplyAll = (req: KubectlApplyAllArgs) => AsyncResult;
export const kubectlApplyAllInjectionToken = getInjectionToken({
id: "kubectl-apply-all",
@@ -32,11 +31,12 @@ export interface KubectlDeleteAllArgs {
extraArgs: string[];
}
-export const kubectlDeleteAllChannel: RequestChannel> = {
- id: "kubectl-delete-all",
-};
+export const kubectlDeleteAllChannel = getRequestChannel<
+ KubectlDeleteAllArgs,
+ Result
+>("kubectl-delete-all");
-export type KubectlDeleteAll = Asyncify>;
+export type KubectlDeleteAll = (req: KubectlDeleteAllArgs) => AsyncResult;
export const kubectlDeleteAllInjectionToken = getInjectionToken({
id: "kubectl-delete-all",
diff --git a/packages/core/src/common/root-frame/root-frame-rendered-channel.ts b/packages/core/src/common/root-frame/root-frame-rendered-channel.ts
index 060ae8735c..c4dc0cefa6 100644
--- a/packages/core/src/common/root-frame/root-frame-rendered-channel.ts
+++ b/packages/core/src/common/root-frame/root-frame-rendered-channel.ts
@@ -2,7 +2,7 @@
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
-import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token";
+import type { MessageChannel } from "@k8slens/messaging";
export type RootFrameHasRenderedChannel = MessageChannel;
diff --git a/packages/core/src/common/user-store/user-store.injectable.ts b/packages/core/src/common/user-store/user-store.injectable.ts
index 3b45b03b1d..10806007a2 100644
--- a/packages/core/src/common/user-store/user-store.injectable.ts
+++ b/packages/core/src/common/user-store/user-store.injectable.ts
@@ -16,7 +16,7 @@ import { baseStoreIpcChannelPrefixesInjectionToken } from "../base-store/channel
import { shouldBaseStoreDisableSyncInIpcListenerInjectionToken } from "../base-store/disable-sync";
import { persistStateToConfigInjectionToken } from "../base-store/save-to-file";
import getBasenameOfPathInjectable from "../path/get-basename.injectable";
-import { enlistMessageChannelListenerInjectionToken } from "../utils/channel/enlist-message-channel-listener-injection-token";
+import { enlistMessageChannelListenerInjectionToken } from "@k8slens/messaging";
import userStorePreferenceDescriptorsInjectable from "./preference-descriptors.injectable";
const userStoreInjectable = getInjectable({
diff --git a/packages/core/src/common/utils/channel/channel.test.ts b/packages/core/src/common/utils/channel/channel.test.ts
deleted file mode 100644
index bc6043d349..0000000000
--- a/packages/core/src/common/utils/channel/channel.test.ts
+++ /dev/null
@@ -1,245 +0,0 @@
-/**
- * Copyright (c) OpenLens Authors. All rights reserved.
- * Licensed under MIT License. See LICENSE in root directory for more information.
- */
-import type { DiContainer } from "@ogre-tools/injectable";
-import { getInjectable } from "@ogre-tools/injectable";
-import type { SendMessageToChannel } from "./message-to-channel-injection-token";
-import { sendMessageToChannelInjectionToken } from "./message-to-channel-injection-token";
-import type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder";
-import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder";
-import type { LensWindow } from "../../../main/start-main-application/lens-window/application-window/create-lens-window.injectable";
-import type { MessageChannel } from "./message-channel-listener-injection-token";
-import { messageChannelListenerInjectionToken } from "./message-channel-listener-injection-token";
-import type { RequestFromChannel } from "./request-from-channel-injection-token";
-import { requestFromChannelInjectionToken } from "./request-from-channel-injection-token";
-import type { RequestChannel } from "./request-channel-listener-injection-token";
-import type { AsyncFnMock } from "@async-fn/jest";
-import asyncFn from "@async-fn/jest";
-import { getPromiseStatus } from "@k8slens/test-utils";
-import { runInAction } from "mobx";
-import type { RequestChannelHandler } from "../../../main/utils/channel/channel-listeners/listener-tokens";
-import {
- getRequestChannelListenerInjectable,
- requestChannelListenerInjectionToken,
-} from "../../../main/utils/channel/channel-listeners/listener-tokens";
-
-type TestMessageChannel = MessageChannel;
-type TestRequestChannel = RequestChannel;
-
-describe("channel", () => {
- describe("messaging from main to renderer, given listener for channel in a window and application has started", () => {
- let messageListenerInWindowMock: jest.Mock;
- let mainDi: DiContainer;
- let messageToChannel: SendMessageToChannel;
- let builder: ApplicationBuilder;
-
- beforeEach(async () => {
- builder = getApplicationBuilder();
-
- messageListenerInWindowMock = jest.fn();
-
- const testChannelListenerInTestWindowInjectable = getInjectable({
- id: "test-channel-listener-in-test-window",
-
- instantiate: () => ({
- channel: testMessageChannel,
- handler: messageListenerInWindowMock,
- }),
-
- injectionToken: messageChannelListenerInjectionToken,
- });
-
- builder.beforeWindowStart(({ windowDi }) => {
- runInAction(() => {
- windowDi.register(testChannelListenerInTestWindowInjectable);
- });
- });
-
- mainDi = builder.mainDi;
-
- await builder.startHidden();
-
- messageToChannel = mainDi.inject(sendMessageToChannelInjectionToken);
- });
-
- describe("given window is started", () => {
- let someWindowFake: LensWindow;
-
- beforeEach(async () => {
- someWindowFake = builder.applicationWindow.create("some-window");
-
- await someWindowFake.start();
- });
-
- it("when sending message, triggers listener in window", () => {
- messageToChannel(testMessageChannel, "some-message");
-
- expect(messageListenerInWindowMock).toHaveBeenCalledWith("some-message");
- });
-
- it("given window is hidden, when sending message, does not trigger listener in window", () => {
- someWindowFake.close();
-
- messageToChannel(testMessageChannel, "some-message");
-
- expect(messageListenerInWindowMock).not.toHaveBeenCalled();
- });
- });
-
- it("given multiple started windows, when sending message, triggers listeners in all windows", async () => {
- const someWindowFake = builder.applicationWindow.create("some-window");
- const someOtherWindowFake = builder.applicationWindow.create("some-other-window");
-
- await someWindowFake.start();
- await someOtherWindowFake.start();
-
- messageToChannel(testMessageChannel, "some-message");
-
- expect(messageListenerInWindowMock.mock.calls).toEqual([
- ["some-message"],
- ["some-message"],
- ]);
- });
- });
-
- describe("messaging from renderer to main, given listener for channel in a main and application has started", () => {
- let messageListenerInMainMock: jest.Mock;
- let messageToChannel: SendMessageToChannel;
-
- beforeEach(async () => {
- const applicationBuilder = getApplicationBuilder();
-
- messageListenerInMainMock = jest.fn();
-
- const testChannelListenerInMainInjectable = getInjectable({
- id: "test-channel-listener-in-main",
-
- instantiate: () => ({
- channel: testMessageChannel,
- handler: messageListenerInMainMock,
- }),
-
- injectionToken: messageChannelListenerInjectionToken,
- });
-
- applicationBuilder.beforeApplicationStart(({ mainDi }) => {
- runInAction(() => {
- mainDi.register(testChannelListenerInMainInjectable);
- });
- });
-
- await applicationBuilder.render();
-
- const windowDi = applicationBuilder.applicationWindow.only.di;
-
- messageToChannel = windowDi.inject(sendMessageToChannelInjectionToken);
- });
-
- it("when sending message, triggers listener in main", () => {
- messageToChannel(testMessageChannel, "some-message");
-
- expect(messageListenerInMainMock).toHaveBeenCalledWith("some-message");
- });
- });
-
- describe("requesting from main in renderer, given listener for channel in a main and application has started", () => {
- let requestListenerInMainMock: AsyncFnMock>;
- let requestFromChannel: RequestFromChannel;
-
- beforeEach(async () => {
- const applicationBuilder = getApplicationBuilder();
-
- requestListenerInMainMock = asyncFn();
-
- const testChannelListenerInMainInjectable = getRequestChannelListenerInjectable({
- channel: testRequestChannel,
- handler: () => requestListenerInMainMock,
- });
-
- applicationBuilder.beforeApplicationStart(({ mainDi }) => {
- runInAction(() => {
- mainDi.register(testChannelListenerInMainInjectable);
- });
- });
-
- await applicationBuilder.render();
-
- const windowDi = applicationBuilder.applicationWindow.only.di;
-
- requestFromChannel = windowDi.inject(
- requestFromChannelInjectionToken,
- );
- });
-
- describe("when requesting from channel", () => {
- let actualPromise: Promise;
-
- beforeEach(() => {
- actualPromise = requestFromChannel(testRequestChannel, "some-request");
- });
-
- it("triggers listener in main", () => {
- expect(requestListenerInMainMock).toHaveBeenCalledWith("some-request");
- });
-
- it("does not resolve yet", async () => {
- const promiseStatus = await getPromiseStatus(actualPromise);
-
- expect(promiseStatus.fulfilled).toBe(false);
- });
-
- it("when main resolves with response, resolves with response", async () => {
- await requestListenerInMainMock.resolve("some-response");
-
- const actual = await actualPromise;
-
- expect(actual).toBe("some-response");
- });
- });
- });
-
- it("when registering multiple handlers for the same channel, throws", async () => {
- const applicationBuilder = getApplicationBuilder();
-
- const someChannelListenerInjectable = getInjectable({
- id: "some-channel-listener",
-
- instantiate: () => ({
- channel: testRequestChannel,
- handler: () => () => "irrelevant",
- }),
-
- injectionToken: requestChannelListenerInjectionToken,
- });
-
- const someOtherChannelListenerInjectable = getInjectable({
- id: "some-other-channel-listener",
-
- instantiate: () => ({
- channel: testRequestChannel,
- handler: () => () => "irrelevant",
- }),
-
- injectionToken: requestChannelListenerInjectionToken,
- });
-
- applicationBuilder.beforeApplicationStart(({ mainDi }) => {
- runInAction(() => {
- mainDi.register(someChannelListenerInjectable);
- mainDi.register(someOtherChannelListenerInjectable);
- });
- });
-
- await expect(applicationBuilder.render()).rejects.toThrow('Tried to register a multiple channel handlers for "some-request-channel-id", only one handler is supported for a request channel.');
- });
-});
-
-const testMessageChannel: TestMessageChannel = {
- id: "some-message-channel-id",
-};
-
-const testRequestChannel: TestRequestChannel = {
- id: "some-request-channel-id",
-};
-
diff --git a/packages/core/src/common/utils/channel/enlist-message-channel-listener-injection-token.ts b/packages/core/src/common/utils/channel/enlist-message-channel-listener-injection-token.ts
deleted file mode 100644
index d6db37cea2..0000000000
--- a/packages/core/src/common/utils/channel/enlist-message-channel-listener-injection-token.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-/**
- * Copyright (c) OpenLens Authors. All rights reserved.
- * Licensed under MIT License. See LICENSE in root directory for more information.
- */
-import { getInjectionToken } from "@ogre-tools/injectable";
-import type { Disposer } from "@k8slens/utilities";
-import type { MessageChannel, MessageChannelListener } from "./message-channel-listener-injection-token";
-
-export type EnlistMessageChannelListener = (listener: MessageChannelListener>) => Disposer;
-
-export const enlistMessageChannelListenerInjectionToken = getInjectionToken({
- id: "enlist-message-channel-listener",
-});
diff --git a/packages/core/src/common/utils/channel/get-request-channel.ts b/packages/core/src/common/utils/channel/get-request-channel.ts
deleted file mode 100644
index 4dc5b4914e..0000000000
--- a/packages/core/src/common/utils/channel/get-request-channel.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-/**
- * Copyright (c) OpenLens Authors. All rights reserved.
- * Licensed under MIT License. See LICENSE in root directory for more information.
- */
-import type { RequestChannel } from "./request-channel-listener-injection-token";
-
-export const getRequestChannel = (id: string): RequestChannel => ({
- id,
-});
diff --git a/packages/core/src/common/utils/channel/listening-on-message-channels.injectable.ts b/packages/core/src/common/utils/channel/listening-on-message-channels.injectable.ts
deleted file mode 100644
index 6ebc9ca7c1..0000000000
--- a/packages/core/src/common/utils/channel/listening-on-message-channels.injectable.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * Copyright (c) OpenLens Authors. All rights reserved.
- * Licensed under MIT License. See LICENSE in root directory for more information.
- */
-import { getInjectable } from "@ogre-tools/injectable";
-import { getStartableStoppable } from "../get-startable-stoppable";
-import { messageChannelListenerInjectionToken } from "./message-channel-listener-injection-token";
-import { enlistMessageChannelListenerInjectionToken } from "./enlist-message-channel-listener-injection-token";
-import { disposer } from "@k8slens/utilities";
-
-const listeningOnMessageChannelsInjectable = getInjectable({
- id: "listening-on-message-channels",
-
- instantiate: (di) => {
- const enlistMessageChannelListener = di.inject(enlistMessageChannelListenerInjectionToken);
- const messageChannelListeners = di.injectMany(messageChannelListenerInjectionToken);
-
- return getStartableStoppable("listening-on-channels", () => (
- disposer(messageChannelListeners.map(enlistMessageChannelListener))
- ));
- },
-});
-
-
-export default listeningOnMessageChannelsInjectable;
diff --git a/packages/core/src/common/utils/channel/message-channel-listener-injection-token.ts b/packages/core/src/common/utils/channel/message-channel-listener-injection-token.ts
deleted file mode 100644
index 5bfc45a82d..0000000000
--- a/packages/core/src/common/utils/channel/message-channel-listener-injection-token.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- * Copyright (c) OpenLens Authors. All rights reserved.
- * Licensed under MIT License. See LICENSE in root directory for more information.
- */
-import type { DiContainerForInjection } from "@ogre-tools/injectable";
-import { getInjectable, getInjectionToken } from "@ogre-tools/injectable";
-
-export interface MessageChannel {
- id: string;
- _messageSignature?: Message; // only used to mark `Message` as used
-}
-
-export type MessageChannelHandler = Channel extends MessageChannel
- ? (message: Message) => void
- : never;
-
-export interface MessageChannelListener {
- channel: Channel;
- handler: MessageChannelHandler;
-}
-
-export const messageChannelListenerInjectionToken = getInjectionToken>>(
- {
- id: "message-channel-listener",
- },
-);
-
-export interface GetMessageChannelListenerInfo<
- Channel extends MessageChannel,
- Message,
-> {
- id: string;
- channel: Channel;
- handler: (di: DiContainerForInjection) => MessageChannelHandler;
- causesSideEffects?: boolean;
-}
-
-export function getMessageChannelListenerInjectable<
- Channel extends MessageChannel,
- Message,
->(info: GetMessageChannelListenerInfo) {
- return getInjectable({
- id: `${info.channel.id}-listener-${info.id}`,
- instantiate: (di) => ({
- channel: info.channel,
- handler: info.handler(di),
- }),
- injectionToken: messageChannelListenerInjectionToken,
- causesSideEffects: info.causesSideEffects,
- });
-}
diff --git a/packages/core/src/common/utils/channel/request-channel-listener-injection-token.ts b/packages/core/src/common/utils/channel/request-channel-listener-injection-token.ts
deleted file mode 100644
index 2f0b84a3cc..0000000000
--- a/packages/core/src/common/utils/channel/request-channel-listener-injection-token.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-/**
- * Copyright (c) OpenLens Authors. All rights reserved.
- * Licensed under MIT License. See LICENSE in root directory for more information.
- */
-
-export interface RequestChannel {
- id: string;
- _requestSignature?: Request; // used only to mark `Request` as "used"
- _responseSignature?: Response; // used only to mark `Response` as "used"
-}
diff --git a/packages/core/src/common/utils/registrator-helper.ts b/packages/core/src/common/utils/registrator-helper.ts
new file mode 100644
index 0000000000..4a9cc5c2d2
--- /dev/null
+++ b/packages/core/src/common/utils/registrator-helper.ts
@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) OpenLens Authors. All rights reserved.
+ * Licensed under MIT License. See LICENSE in root directory for more information.
+ */
+
+import { iter } from "@k8slens/utilities";
+import type { DiContainerForInjection, Injectable } from "@ogre-tools/injectable";
+
+// Register new injectables and deregister removed injectables by id
+
+export const injectableDifferencingRegistratorWith = (di: DiContainerForInjection) => (
+ (rawCurrent: Injectable[], rawPrevious: Injectable[] = []) => {
+ const current = new Map(rawCurrent.map(inj => [inj.id, inj]));
+ const previous = new Map(rawPrevious.map(inj => [inj.id, inj]));
+ const toAdd = iter.chain(current.entries())
+ .filter(([id]) => !previous.has(id))
+ .collect(entries => new Map(entries));
+ const toRemove = iter.chain(previous.entries())
+ .filter(([id]) => !current.has(id))
+ .collect(entries => new Map(entries));
+
+ di.deregister(...toRemove.values());
+ di.register(...toAdd.values());
+ }
+);
diff --git a/packages/core/src/common/utils/resolve-system-proxy/resolve-system-proxy-channel.ts b/packages/core/src/common/utils/resolve-system-proxy/resolve-system-proxy-channel.ts
index c823a8a8f9..210112c0b7 100644
--- a/packages/core/src/common/utils/resolve-system-proxy/resolve-system-proxy-channel.ts
+++ b/packages/core/src/common/utils/resolve-system-proxy/resolve-system-proxy-channel.ts
@@ -2,10 +2,8 @@
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
-import type { RequestChannel } from "../channel/request-channel-listener-injection-token";
+import { getRequestChannel } from "@k8slens/messaging";
-export type ResolveSystemProxyChannel = RequestChannel;
-
-export const resolveSystemProxyChannel: ResolveSystemProxyChannel = {
- id: "resolve-system-proxy-channel",
-};
+export const resolveSystemProxyChannel = getRequestChannel(
+ "resolve-system-proxy-channel",
+);
diff --git a/packages/core/src/common/utils/sync-box/channel-listener.injectable.ts b/packages/core/src/common/utils/sync-box/channel-listener.injectable.ts
index a97d95d726..482886d178 100644
--- a/packages/core/src/common/utils/sync-box/channel-listener.injectable.ts
+++ b/packages/core/src/common/utils/sync-box/channel-listener.injectable.ts
@@ -3,13 +3,13 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { syncBoxChannel } from "./channels";
-import { getMessageChannelListenerInjectable } from "../channel/message-channel-listener-injection-token";
+import { getMessageChannelListenerInjectable } from "@k8slens/messaging";
import syncBoxStateInjectable from "./sync-box-state.injectable";
const syncBoxChannelListenerInjectable = getMessageChannelListenerInjectable({
id: "init",
channel: syncBoxChannel,
- handler: (di) => ({ id, value }) => di.inject(syncBoxStateInjectable, id).set(value),
+ getHandler: (di) => ({ id, value }) => di.inject(syncBoxStateInjectable, id).set(value),
});
export default syncBoxChannelListenerInjectable;
diff --git a/packages/core/src/common/utils/sync-box/channels.ts b/packages/core/src/common/utils/sync-box/channels.ts
index 4df0462dc3..5178ff013c 100644
--- a/packages/core/src/common/utils/sync-box/channels.ts
+++ b/packages/core/src/common/utils/sync-box/channels.ts
@@ -2,20 +2,12 @@
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
-import type { MessageChannel } from "../channel/message-channel-listener-injection-token";
-import type { RequestChannel } from "../channel/request-channel-listener-injection-token";
+import { getMessageChannel, getRequestChannel } from "@k8slens/messaging";
-export type SyncBoxChannel = MessageChannel<{ id: string; value: any }>;
+export const syncBoxChannel =
+ getMessageChannel<{ id: string; value: any }>("sync-box-channel");
-export const syncBoxChannel: SyncBoxChannel = {
- id: "sync-box-channel",
-};
-
-export type SyncBoxInitialValueChannel = RequestChannel<
+export const syncBoxInitialValueChannel = getRequestChannel<
void,
{ id: string; value: any }[]
->;
-
-export const syncBoxInitialValueChannel: SyncBoxInitialValueChannel = {
- id: "sync-box-initial-value-channel",
-};
+>("sync-box-initial-value-channel");
diff --git a/packages/core/src/common/utils/sync-box/create-sync-box.injectable.ts b/packages/core/src/common/utils/sync-box/create-sync-box.injectable.ts
index 4a01fe71a0..2a142dc573 100644
--- a/packages/core/src/common/utils/sync-box/create-sync-box.injectable.ts
+++ b/packages/core/src/common/utils/sync-box/create-sync-box.injectable.ts
@@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
import type { IObservableValue } from "mobx";
import { computed } from "mobx";
import { syncBoxChannel } from "./channels";
-import { sendMessageToChannelInjectionToken } from "../channel/message-to-channel-injection-token";
+import { sendMessageToChannelInjectionToken } from "@k8slens/messaging";
import syncBoxStateInjectable from "./sync-box-state.injectable";
import type { SyncBox } from "./sync-box-injection-token";
import { toJS } from "../toJS";
diff --git a/packages/core/src/common/utils/sync-box/handler.injectable.ts b/packages/core/src/common/utils/sync-box/handler.injectable.ts
deleted file mode 100644
index f520585474..0000000000
--- a/packages/core/src/common/utils/sync-box/handler.injectable.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) OpenLens Authors. All rights reserved.
- * Licensed under MIT License. See LICENSE in root directory for more information.
- */
-import { getInjectable } from "@ogre-tools/injectable";
-import type { MessageChannelHandler } from "../channel/message-channel-listener-injection-token";
-import type { SyncBoxChannel } from "./channels";
-import syncBoxStateInjectable from "./sync-box-state.injectable";
-
-const syncBoxChannelHandlerInjectable = getInjectable({
- id: "sync-box-channel-handler",
- instantiate: (di): MessageChannelHandler => {
- const getSyncBoxState = (id: string) => di.inject(syncBoxStateInjectable, id);
-
- return ({ id, value }) => getSyncBoxState(id)?.set(value);
- },
-});
-
-export default syncBoxChannelHandlerInjectable;
diff --git a/packages/core/src/common/vars/build-semantic-version.injectable.ts b/packages/core/src/common/vars/build-semantic-version.injectable.ts
index 2a49327480..402fb9d442 100644
--- a/packages/core/src/common/vars/build-semantic-version.injectable.ts
+++ b/packages/core/src/common/vars/build-semantic-version.injectable.ts
@@ -7,7 +7,7 @@ import { getInjectionToken } from "@ogre-tools/injectable";
import { SemVer } from "semver";
import type { InitializableState } from "../initializable-state/create";
import { createInitializableState } from "../initializable-state/create";
-import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token";
+import type { RequestChannel } from "@k8slens/messaging";
export const buildVersionInjectionToken = getInjectionToken>({
id: "build-version-token",
diff --git a/packages/core/src/common/weblinks-store/weblink-store.injectable.ts b/packages/core/src/common/weblinks-store/weblink-store.injectable.ts
index cf793a2e58..843c8716e5 100644
--- a/packages/core/src/common/weblinks-store/weblink-store.injectable.ts
+++ b/packages/core/src/common/weblinks-store/weblink-store.injectable.ts
@@ -11,7 +11,7 @@ import { persistStateToConfigInjectionToken } from "../base-store/save-to-file";
import getConfigurationFileModelInjectable from "../get-configuration-file-model/get-configuration-file-model.injectable";
import loggerInjectable from "../logger.injectable";
import getBasenameOfPathInjectable from "../path/get-basename.injectable";
-import { enlistMessageChannelListenerInjectionToken } from "../utils/channel/enlist-message-channel-listener-injection-token";
+import { enlistMessageChannelListenerInjectionToken } from "@k8slens/messaging";
import storeMigrationVersionInjectable from "../vars/store-migration-version.injectable";
import { weblinkStoreMigrationInjectionToken } from "./migration-token";
import { WeblinkStore } from "./weblink-store";
diff --git a/packages/core/src/extensions/extension-loader/extension/extension.injectable.ts b/packages/core/src/extensions/extension-loader/extension/extension.injectable.ts
index 07f054d3fd..d54d997d09 100644
--- a/packages/core/src/extensions/extension-loader/extension/extension.injectable.ts
+++ b/packages/core/src/extensions/extension-loader/extension/extension.injectable.ts
@@ -2,29 +2,18 @@
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
-import type { Injectable } from "@ogre-tools/injectable";
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
-import { difference, find, map } from "lodash";
import { reaction, runInAction } from "mobx";
import { disposer } from "@k8slens/utilities";
import type { LensExtension } from "../../lens-extension";
import { extensionRegistratorInjectionToken } from "../extension-registrator-injection-token";
+import { injectableDifferencingRegistratorWith } from "../../../common/utils/registrator-helper";
export interface Extension {
register: () => void;
deregister: () => void;
}
-const idsToInjectables = (ids: string[], injectables: Injectable[]) => ids.map(id => {
- const injectable = find(injectables, { id });
-
- if (!injectable) {
- throw new Error(`Injectable ${id} not found`);
- }
-
- return injectable;
-});
-
const extensionInjectable = getInjectable({
id: "extension",
@@ -35,36 +24,27 @@ const extensionInjectable = getInjectable({
instantiate: (childDi) => {
const extensionRegistrators = childDi.injectMany(extensionRegistratorInjectionToken);
const reactionDisposer = disposer();
+ const injectableDifferencingRegistrator = injectableDifferencingRegistratorWith(childDi);
return {
register: () => {
- extensionRegistrators.forEach((getInjectablesOfExtension) => {
- const injectables = getInjectablesOfExtension(instance);
+ for (const extensionRegistrator of extensionRegistrators) {
+ const injectables = extensionRegistrator(instance);
- reactionDisposer.push(
- // injectables is either an array or a computed array, in which case
- // we need to update the registered injectables with a reaction every time they change
- reaction(
- () => Array.isArray(injectables) ? injectables : injectables.get(),
- (currentInjectables, previousInjectables = []) => {
- // Register new injectables and deregister removed injectables by id
- const currentIds = map(currentInjectables, "id");
- const previousIds = map(previousInjectables, "id");
- const idsToAdd = difference(currentIds, previousIds);
- const idsToRemove = previousIds.filter(previousId => !currentIds.includes(previousId));
-
- if (idsToRemove.length > 0) {
- childDi.deregister(...idsToInjectables(idsToRemove, previousInjectables));
- }
-
- if (idsToAdd.length > 0) {
- childDi.register(...idsToInjectables(idsToAdd, currentInjectables));
- }
- }, {
+ if (Array.isArray(injectables)) {
+ runInAction(() => {
+ injectableDifferencingRegistrator(injectables);
+ });
+ } else {
+ reactionDisposer.push(reaction(
+ () => injectables.get(),
+ injectableDifferencingRegistrator,
+ {
fireImmediately: true,
},
));
- });
+ }
+ }
},
deregister: () => {
diff --git a/packages/core/src/extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store.injectable.ts b/packages/core/src/extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store.injectable.ts
index 847ae37f03..2295608520 100644
--- a/packages/core/src/extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store.injectable.ts
+++ b/packages/core/src/extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store.injectable.ts
@@ -12,7 +12,7 @@ import { baseStoreIpcChannelPrefixesInjectionToken } from "../../../common/base-
import { shouldBaseStoreDisableSyncInIpcListenerInjectionToken } from "../../../common/base-store/disable-sync";
import { persistStateToConfigInjectionToken } from "../../../common/base-store/save-to-file";
import getBasenameOfPathInjectable from "../../../common/path/get-basename.injectable";
-import { enlistMessageChannelListenerInjectionToken } from "../../../common/utils/channel/enlist-message-channel-listener-injection-token";
+import { enlistMessageChannelListenerInjectionToken } from "@k8slens/messaging";
import ensureHashedDirectoryForExtensionInjectable from "./ensure-hashed-directory-for-extension.injectable";
import { registeredExtensionsInjectable } from "./registered-extensions.injectable";
diff --git a/packages/core/src/extensions/extension-store.ts b/packages/core/src/extensions/extension-store.ts
index cf435fb474..fe9cff2a02 100644
--- a/packages/core/src/extensions/extension-store.ts
+++ b/packages/core/src/extensions/extension-store.ts
@@ -20,7 +20,7 @@ import { baseStoreIpcChannelPrefixesInjectionToken } from "../common/base-store/
import { shouldBaseStoreDisableSyncInIpcListenerInjectionToken } from "../common/base-store/disable-sync";
import { persistStateToConfigInjectionToken } from "../common/base-store/save-to-file";
import getBasenameOfPathInjectable from "../common/path/get-basename.injectable";
-import { enlistMessageChannelListenerInjectionToken } from "../common/utils/channel/enlist-message-channel-listener-injection-token";
+import { enlistMessageChannelListenerInjectionToken } from "@k8slens/messaging";
export interface ExtensionStoreParams extends BaseStoreParams {
migrations?: Migrations;
diff --git a/packages/core/src/extensions/extensions-store/extensions-store.injectable.ts b/packages/core/src/extensions/extensions-store/extensions-store.injectable.ts
index 9f5ff83270..9e08a96aac 100644
--- a/packages/core/src/extensions/extensions-store/extensions-store.injectable.ts
+++ b/packages/core/src/extensions/extensions-store/extensions-store.injectable.ts
@@ -10,7 +10,7 @@ import { persistStateToConfigInjectionToken } from "../../common/base-store/save
import getConfigurationFileModelInjectable from "../../common/get-configuration-file-model/get-configuration-file-model.injectable";
import loggerInjectable from "../../common/logger.injectable";
import getBasenameOfPathInjectable from "../../common/path/get-basename.injectable";
-import { enlistMessageChannelListenerInjectionToken } from "../../common/utils/channel/enlist-message-channel-listener-injection-token";
+import { enlistMessageChannelListenerInjectionToken } from "@k8slens/messaging";
import storeMigrationVersionInjectable from "../../common/vars/store-migration-version.injectable";
import { ExtensionsStore } from "./extensions-store";
diff --git a/packages/core/src/features/application-menu/main/application-menu-reactivity.injectable.ts b/packages/core/src/features/application-menu/main/application-menu-reactivity.injectable.ts
index 80bfd108fd..e5d95bf7d8 100644
--- a/packages/core/src/features/application-menu/main/application-menu-reactivity.injectable.ts
+++ b/packages/core/src/features/application-menu/main/application-menu-reactivity.injectable.ts
@@ -4,7 +4,7 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import { autorun } from "mobx";
-import { getStartableStoppable } from "../../../common/utils/get-startable-stoppable";
+import { getStartableStoppable } from "@k8slens/startable-stoppable";
import populateApplicationMenuInjectable from "./populate-application-menu.injectable";
import applicationMenuItemCompositeInjectable from "./application-menu-item-composite.injectable";
diff --git a/packages/core/src/features/application-update/child-features/application-update-using-application-menu/main/check-for-updates-menu-item.injectable.ts b/packages/core/src/features/application-update/child-features/application-update-using-application-menu/main/check-for-updates-menu-item.injectable.ts
index fe997e62fb..97b9acf9f8 100644
--- a/packages/core/src/features/application-update/child-features/application-update-using-application-menu/main/check-for-updates-menu-item.injectable.ts
+++ b/packages/core/src/features/application-update/child-features/application-update-using-application-menu/main/check-for-updates-menu-item.injectable.ts
@@ -28,7 +28,7 @@ const checkForUpdatesMenuItemInjectable = getInjectable({
id: "check-for-updates",
parentId: isMac ? "mac" : "help",
orderNumber: isMac ? 20 : 50,
- label: "Check for updates",
+ label: "Check for Updates...",
isShown: updatingIsEnabled,
onClick: () => {
diff --git a/packages/core/src/features/application-update/child-features/application-update-using-tray/installing-update-using-tray.test.ts b/packages/core/src/features/application-update/child-features/application-update-using-tray/installing-update-using-tray.test.ts
index d5caa63149..f18f288469 100644
--- a/packages/core/src/features/application-update/child-features/application-update-using-tray/installing-update-using-tray.test.ts
+++ b/packages/core/src/features/application-update/child-features/application-update-using-tray/installing-update-using-tray.test.ts
@@ -146,7 +146,7 @@ describe("installing update using tray", () => {
it("name of tray item for checking updates indicates that checking is happening", () => {
expect(
builder.tray.get("check-for-updates")?.label,
- ).toBe("Checking for updates...");
+ ).toBe("Checking for Updates...");
});
it("user cannot install update yet", () => {
@@ -177,7 +177,7 @@ describe("installing update using tray", () => {
it("name of tray item for checking updates no longer indicates that checking is happening", () => {
expect(
builder.tray.get("check-for-updates")?.label,
- ).toBe("Check for updates");
+ ).toBe("Check for Updates...");
});
it("renders", () => {
@@ -241,7 +241,7 @@ describe("installing update using tray", () => {
it("name of tray item for checking updates no longer indicates that downloading is happening", () => {
expect(
builder.tray.get("check-for-updates")?.label,
- ).toBe("Check for updates");
+ ).toBe("Check for Updates...");
});
it("renders", () => {
@@ -269,7 +269,7 @@ describe("installing update using tray", () => {
it("name of tray item for checking updates no longer indicates that downloading is happening", () => {
expect(
builder.tray.get("check-for-updates")?.label,
- ).toBe("Check for updates");
+ ).toBe("Check for Updates...");
});
it("renders", () => {
diff --git a/packages/core/src/features/application-update/child-features/application-update-using-tray/main/tray-items/check-for-updates-tray-item.injectable.ts b/packages/core/src/features/application-update/child-features/application-update-using-tray/main/tray-items/check-for-updates-tray-item.injectable.ts
index e904abaa99..3f05ddb71e 100644
--- a/packages/core/src/features/application-update/child-features/application-update-using-tray/main/tray-items/check-for-updates-tray-item.injectable.ts
+++ b/packages/core/src/features/application-update/child-features/application-update-using-tray/main/tray-items/check-for-updates-tray-item.injectable.ts
@@ -47,10 +47,10 @@ const checkForUpdatesTrayItemInjectable = getInjectable({
}
if (checkingForUpdatesState.value.get()) {
- return "Checking for updates...";
+ return "Checking for Updates...";
}
- return "Check for updates";
+ return "Check for Updates...";
}),
enabled: computed(() => !checkingForUpdatesState.value.get() && !downloadingUpdateState.value.get()),
diff --git a/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/periodical-check-for-updates.injectable.ts b/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/periodical-check-for-updates.injectable.ts
index 85c687e478..953aa2b45a 100644
--- a/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/periodical-check-for-updates.injectable.ts
+++ b/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/periodical-check-for-updates.injectable.ts
@@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
-import { getStartableStoppable } from "../../../../../common/utils/get-startable-stoppable";
+import { getStartableStoppable } from "@k8slens/startable-stoppable";
import processCheckingForUpdatesInjectable from "../../../main/process-checking-for-updates.injectable";
import withOrphanPromiseInjectable from "../../../../../common/utils/with-orphan-promise/with-orphan-promise.injectable";
diff --git a/packages/core/src/features/application-update/common/restart-and-install-update-channel.ts b/packages/core/src/features/application-update/common/restart-and-install-update-channel.ts
index 470debf981..87b8f76cf3 100644
--- a/packages/core/src/features/application-update/common/restart-and-install-update-channel.ts
+++ b/packages/core/src/features/application-update/common/restart-and-install-update-channel.ts
@@ -2,7 +2,7 @@
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
-import type { MessageChannel } from "../../../common/utils/channel/message-channel-listener-injection-token";
+import type { MessageChannel } from "@k8slens/messaging";
export type RestartAndInstallUpdateChannel = MessageChannel;
diff --git a/packages/core/src/features/application-update/main/restart-and-install-update/restart-and-install-update-listener.injectable.ts b/packages/core/src/features/application-update/main/restart-and-install-update/restart-and-install-update-listener.injectable.ts
index 940856ad3b..768ad50ffd 100644
--- a/packages/core/src/features/application-update/main/restart-and-install-update/restart-and-install-update-listener.injectable.ts
+++ b/packages/core/src/features/application-update/main/restart-and-install-update/restart-and-install-update-listener.injectable.ts
@@ -3,13 +3,13 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { restartAndInstallUpdateChannel } from "../../common/restart-and-install-update-channel";
-import { getMessageChannelListenerInjectable } from "../../../../common/utils/channel/message-channel-listener-injection-token";
+import { getMessageChannelListenerInjectable } from "@k8slens/messaging";
import quitAndInstallUpdateInjectable from "../quit-and-install-update.injectable";
const restartAndInstallUpdateListenerInjectable = getMessageChannelListenerInjectable({
id: "restart",
channel: restartAndInstallUpdateChannel,
- handler: (di) => di.inject(quitAndInstallUpdateInjectable),
+ getHandler: (di) => di.inject(quitAndInstallUpdateInjectable),
});
export default restartAndInstallUpdateListenerInjectable;
diff --git a/packages/core/src/features/application-update/main/watch-if-update-should-happen-on-quit/watch-if-update-should-happen-on-quit.injectable.ts b/packages/core/src/features/application-update/main/watch-if-update-should-happen-on-quit/watch-if-update-should-happen-on-quit.injectable.ts
index bcad45a0ac..bd949194e6 100644
--- a/packages/core/src/features/application-update/main/watch-if-update-should-happen-on-quit/watch-if-update-should-happen-on-quit.injectable.ts
+++ b/packages/core/src/features/application-update/main/watch-if-update-should-happen-on-quit/watch-if-update-should-happen-on-quit.injectable.ts
@@ -4,7 +4,7 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import { autorun } from "mobx";
-import { getStartableStoppable } from "../../../../common/utils/get-startable-stoppable";
+import { getStartableStoppable } from "@k8slens/startable-stoppable";
import setUpdateOnQuitInjectable from "../../../../main/electron-app/features/set-update-on-quit.injectable";
import selectedUpdateChannelInjectable from "../../common/selected-update-channel/selected-update-channel.injectable";
import type { ReleaseChannel, UpdateChannel } from "../../common/update-channels";
diff --git a/packages/core/src/features/application-update/renderer/restart-and-install-update.injectable.ts b/packages/core/src/features/application-update/renderer/restart-and-install-update.injectable.ts
index 2502a599a2..d60f8da909 100644
--- a/packages/core/src/features/application-update/renderer/restart-and-install-update.injectable.ts
+++ b/packages/core/src/features/application-update/renderer/restart-and-install-update.injectable.ts
@@ -4,13 +4,13 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import { restartAndInstallUpdateChannel } from "../common/restart-and-install-update-channel";
-import messageToChannelInjectable from "../../../renderer/utils/channel/message-to-channel.injectable";
+import { sendMessageToChannelInjectionToken } from "@k8slens/messaging";
const restartAndInstallUpdateInjectable = getInjectable({
id: "restart-and-install-update",
instantiate: (di) => {
- const messageToChannel = di.inject(messageToChannelInjectable);
+ const messageToChannel = di.inject(sendMessageToChannelInjectionToken);
return () => {
messageToChannel(restartAndInstallUpdateChannel);
diff --git a/packages/core/src/features/catalog/__snapshots__/entity-running.test.tsx.snap b/packages/core/src/features/catalog/__snapshots__/entity-running.test.tsx.snap
index 2d5653372c..8586d4538c 100644
--- a/packages/core/src/features/catalog/__snapshots__/entity-running.test.tsx.snap
+++ b/packages/core/src/features/catalog/__snapshots__/entity-running.test.tsx.snap
@@ -490,10 +490,10 @@ exports[`entity running technical tests when navigated to catalog renders 1`] =
style="position: relative; height: 420000px; width: 100%; overflow: auto; will-change: transform; direction: ltr;"
>
("certificate-authorities");
diff --git a/packages/core/src/features/certificate-authorities/main/channel-handler.global-override-for-injectable.ts b/packages/core/src/features/certificate-authorities/main/channel-handler.global-override-for-injectable.ts
index 62882fb49f..a7c52503c5 100644
--- a/packages/core/src/features/certificate-authorities/main/channel-handler.global-override-for-injectable.ts
+++ b/packages/core/src/features/certificate-authorities/main/channel-handler.global-override-for-injectable.ts
@@ -8,6 +8,7 @@ import { casChannel } from "../common/channel";
import certificateAuthoritiesChannelListenerInjectable from "./channel-handler.injectable";
export default getGlobalOverride(certificateAuthoritiesChannelListenerInjectable, () => ({
+ id: "certificate-authorities-channel-listener",
channel: casChannel,
handler: () => [],
}));
diff --git a/packages/core/src/features/certificate-authorities/main/channel-handler.injectable.ts b/packages/core/src/features/certificate-authorities/main/channel-handler.injectable.ts
index 206a68ba94..d776e9fcce 100644
--- a/packages/core/src/features/certificate-authorities/main/channel-handler.injectable.ts
+++ b/packages/core/src/features/certificate-authorities/main/channel-handler.injectable.ts
@@ -2,14 +2,15 @@
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
-import { getRequestChannelListenerInjectable } from "../../../main/utils/channel/channel-listeners/listener-tokens";
+import { getRequestChannelListenerInjectable } from "@k8slens/messaging";
import { casChannel } from "../common/channel";
import { globalAgent } from "https";
import { isString } from "@k8slens/utilities";
const certificateAuthoritiesChannelListenerInjectable = getRequestChannelListenerInjectable({
+ id: "certificate-authorities-channel-listener",
channel: casChannel,
- handler: () => () => {
+ getHandler: () => () => {
if (Array.isArray(globalAgent.options.ca)) {
return globalAgent.options.ca.filter(isString);
}
diff --git a/packages/core/src/features/certificate-authorities/renderer/request-system-cas.injectable.ts b/packages/core/src/features/certificate-authorities/renderer/request-system-cas.injectable.ts
index e3c840a95a..e9ac074989 100644
--- a/packages/core/src/features/certificate-authorities/renderer/request-system-cas.injectable.ts
+++ b/packages/core/src/features/certificate-authorities/renderer/request-system-cas.injectable.ts
@@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
-import { requestFromChannelInjectionToken } from "../../../common/utils/channel/request-from-channel-injection-token";
+import { requestFromChannelInjectionToken } from "@k8slens/messaging";
import { casChannel } from "../common/channel";
import { requestSystemCAsInjectionToken } from "../common/request-system-cas-token";
diff --git a/packages/core/src/features/cluster/activation/common/channels.ts b/packages/core/src/features/cluster/activation/common/channels.ts
index 3631c4d9b8..55172e75fc 100644
--- a/packages/core/src/features/cluster/activation/common/channels.ts
+++ b/packages/core/src/features/cluster/activation/common/channels.ts
@@ -4,7 +4,7 @@
*/
import type { ClusterId } from "../../../../common/cluster-types";
-import { getRequestChannel } from "../../../../common/utils/channel/get-request-channel";
+import { getRequestChannel } from "@k8slens/messaging";
export interface ActivateCluster {
clusterId: ClusterId;
diff --git a/packages/core/src/features/cluster/activation/common/request-token.ts b/packages/core/src/features/cluster/activation/common/request-token.ts
index 5bee44208f..0abe5775b3 100644
--- a/packages/core/src/features/cluster/activation/common/request-token.ts
+++ b/packages/core/src/features/cluster/activation/common/request-token.ts
@@ -4,7 +4,7 @@
*/
import { getInjectionToken } from "@ogre-tools/injectable";
-import type { ChannelRequester } from "../../../../common/utils/channel/request-from-channel-injection-token";
+import type { ChannelRequester } from "@k8slens/messaging";
import type { activateClusterChannel, deactivateClusterChannel } from "./channels";
export type RequestClusterActivation = ChannelRequester
;
diff --git a/packages/core/src/features/cluster/activation/main/activate-listener.injectable.ts b/packages/core/src/features/cluster/activation/main/activate-listener.injectable.ts
index 4ce22e6311..08b068abef 100644
--- a/packages/core/src/features/cluster/activation/main/activate-listener.injectable.ts
+++ b/packages/core/src/features/cluster/activation/main/activate-listener.injectable.ts
@@ -2,13 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
-import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens";
+import { getRequestChannelListenerInjectable } from "@k8slens/messaging";
import { activateClusterChannel } from "../common/channels";
import requestClusterActivationInjectable from "./request-activation.injectable";
const activateClusterRequestChannelListenerInjectable = getRequestChannelListenerInjectable({
+ id: "activate-cluster-request-channel-listener",
channel: activateClusterChannel,
- handler: (di) => di.inject(requestClusterActivationInjectable),
+ getHandler: (di) => di.inject(requestClusterActivationInjectable),
});
export default activateClusterRequestChannelListenerInjectable;
diff --git a/packages/core/src/features/cluster/activation/main/deactivate-listener.injectable.ts b/packages/core/src/features/cluster/activation/main/deactivate-listener.injectable.ts
index e24ce48ba6..bbfe79a41d 100644
--- a/packages/core/src/features/cluster/activation/main/deactivate-listener.injectable.ts
+++ b/packages/core/src/features/cluster/activation/main/deactivate-listener.injectable.ts
@@ -2,13 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
-import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens";
+import { getRequestChannelListenerInjectable } from "@k8slens/messaging";
import { deactivateClusterChannel } from "../common/channels";
import requestClusterDeactivationInjectable from "./request-deactivation.injectable";
const clusterDeactivationRequestChannelListenerInjectable = getRequestChannelListenerInjectable({
+ id: "cluster-deactivation-request-channel-listener",
channel: deactivateClusterChannel,
- handler: (di) => di.inject(requestClusterDeactivationInjectable),
+ getHandler: (di) => di.inject(requestClusterDeactivationInjectable),
});
export default clusterDeactivationRequestChannelListenerInjectable;
diff --git a/packages/core/src/features/cluster/activation/renderer/request-activation.injectable.ts b/packages/core/src/features/cluster/activation/renderer/request-activation.injectable.ts
index 1677d67792..6609516918 100644
--- a/packages/core/src/features/cluster/activation/renderer/request-activation.injectable.ts
+++ b/packages/core/src/features/cluster/activation/renderer/request-activation.injectable.ts
@@ -3,14 +3,14 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
-import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable";
+import { requestFromChannelInjectionToken } from "@k8slens/messaging";
import { activateClusterChannel } from "../common/channels";
import { requestClusterActivationInjectionToken } from "../common/request-token";
const requestClusterActivationInjectable = getInjectable({
id: "request-cluster-activation",
instantiate: (di) => {
- const requestFromChannel = di.inject(requestFromChannelInjectable);
+ const requestFromChannel = di.inject(requestFromChannelInjectionToken);
return (req) => requestFromChannel(activateClusterChannel, req);
},
diff --git a/packages/core/src/features/cluster/activation/renderer/request-deactivation.injectable.ts b/packages/core/src/features/cluster/activation/renderer/request-deactivation.injectable.ts
index 362784e91b..e019b8b615 100644
--- a/packages/core/src/features/cluster/activation/renderer/request-deactivation.injectable.ts
+++ b/packages/core/src/features/cluster/activation/renderer/request-deactivation.injectable.ts
@@ -3,14 +3,14 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
-import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable";
+import { requestFromChannelInjectionToken } from "@k8slens/messaging";
import { deactivateClusterChannel } from "../common/channels";
import { requestClusterDeactivationInjectionToken } from "../common/request-token";
const requestClusterDeactivationInjectable = getInjectable({
id: "request-cluster-deactivation",
instantiate: (di) => {
- const requestFromChannel = di.inject(requestFromChannelInjectable);
+ const requestFromChannel = di.inject(requestFromChannelInjectionToken);
return (clusterId) => requestFromChannel(deactivateClusterChannel, clusterId);
},
diff --git a/packages/core/src/features/cluster/delete-dialog/common/clear-as-deleting-channel.ts b/packages/core/src/features/cluster/delete-dialog/common/clear-as-deleting-channel.ts
index bf33a23165..f6bdc1d072 100644
--- a/packages/core/src/features/cluster/delete-dialog/common/clear-as-deleting-channel.ts
+++ b/packages/core/src/features/cluster/delete-dialog/common/clear-as-deleting-channel.ts
@@ -3,10 +3,8 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { ClusterId } from "../../../../common/cluster-types";
-import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token";
+import { getRequestChannel } from "@k8slens/messaging";
-export type ClearClusterAsDeletingChannel = RequestChannel;
-
-export const clearClusterAsDeletingChannel: ClearClusterAsDeletingChannel = {
- id: "clear-cluster-as-deleting",
-};
+export const clearClusterAsDeletingChannel = getRequestChannel(
+ "clear-cluster-as-deleting",
+);
diff --git a/packages/core/src/features/cluster/delete-dialog/common/delete-channel.ts b/packages/core/src/features/cluster/delete-dialog/common/delete-channel.ts
index 0e9142fcd3..b3a007b1bd 100644
--- a/packages/core/src/features/cluster/delete-dialog/common/delete-channel.ts
+++ b/packages/core/src/features/cluster/delete-dialog/common/delete-channel.ts
@@ -3,10 +3,11 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { ClusterId } from "../../../../common/cluster-types";
-import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token";
+import type { RequestChannel } from "@k8slens/messaging";
+import { getRequestChannel } from "@k8slens/messaging";
export type DeleteClusterChannel = RequestChannel;
-export const deleteClusterChannel: DeleteClusterChannel = {
- id: "delete-cluster",
-};
+export const deleteClusterChannel = getRequestChannel(
+ "delete-cluster",
+);
diff --git a/packages/core/src/features/cluster/delete-dialog/common/set-as-deleting-channel.ts b/packages/core/src/features/cluster/delete-dialog/common/set-as-deleting-channel.ts
index 57ef2e3a8d..7b93b292d5 100644
--- a/packages/core/src/features/cluster/delete-dialog/common/set-as-deleting-channel.ts
+++ b/packages/core/src/features/cluster/delete-dialog/common/set-as-deleting-channel.ts
@@ -3,10 +3,8 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { ClusterId } from "../../../../common/cluster-types";
-import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token";
+import { getRequestChannel } from "@k8slens/messaging";
-export type SetClusterAsDeletingChannel = RequestChannel;
-
-export const setClusterAsDeletingChannel: SetClusterAsDeletingChannel = {
- id: "set-cluster-as-deleting",
-};
+export const setClusterAsDeletingChannel = getRequestChannel(
+ "set-cluster-as-deleting",
+);
diff --git a/packages/core/src/features/cluster/delete-dialog/main/clear-as-deleting-channel-listener.injectable.ts b/packages/core/src/features/cluster/delete-dialog/main/clear-as-deleting-channel-listener.injectable.ts
index a8dd2a80b0..a83de06acb 100644
--- a/packages/core/src/features/cluster/delete-dialog/main/clear-as-deleting-channel-listener.injectable.ts
+++ b/packages/core/src/features/cluster/delete-dialog/main/clear-as-deleting-channel-listener.injectable.ts
@@ -3,12 +3,13 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import clustersThatAreBeingDeletedInjectable from "../../../../main/cluster/are-being-deleted.injectable";
-import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens";
+import { getRequestChannelListenerInjectable } from "@k8slens/messaging";
import { clearClusterAsDeletingChannel } from "../common/clear-as-deleting-channel";
const clearClusterAsDeletingChannelListenerInjectable = getRequestChannelListenerInjectable({
+ id: "clear-cluster-as-deleting-channel-listener",
channel: clearClusterAsDeletingChannel,
- handler: (di) => {
+ getHandler: (di) => {
const clustersThatAreBeingDeleted = di.inject(clustersThatAreBeingDeletedInjectable);
return (clusterId) => {
diff --git a/packages/core/src/features/cluster/delete-dialog/main/delete-channel-listener.injectable.ts b/packages/core/src/features/cluster/delete-dialog/main/delete-channel-listener.injectable.ts
index 94caf169ba..30d976c59c 100644
--- a/packages/core/src/features/cluster/delete-dialog/main/delete-channel-listener.injectable.ts
+++ b/packages/core/src/features/cluster/delete-dialog/main/delete-channel-listener.injectable.ts
@@ -10,12 +10,13 @@ import removePathInjectable from "../../../../common/fs/remove.injectable";
import joinPathsInjectable from "../../../../common/path/join-paths.injectable";
import clusterConnectionInjectable from "../../../../main/cluster/cluster-connection.injectable";
import { noop } from "@k8slens/utilities";
-import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens";
+import { getRequestChannelListenerInjectable } from "@k8slens/messaging";
import { deleteClusterChannel } from "../common/delete-channel";
const deleteClusterChannelListenerInjectable = getRequestChannelListenerInjectable({
+ id: "delete-cluster-channel-listener",
channel: deleteClusterChannel,
- handler: (di) => {
+ getHandler: (di) => {
const emitAppEvent = di.inject(emitAppEventInjectable);
const clusterStore = di.inject(clusterStoreInjectable);
const clusterFrames = di.inject(clusterFramesInjectable);
diff --git a/packages/core/src/features/cluster/delete-dialog/main/set-as-deleteing-channel-listener.injectable.ts b/packages/core/src/features/cluster/delete-dialog/main/set-as-deleteing-channel-listener.injectable.ts
index f532b4a81f..74bd168723 100644
--- a/packages/core/src/features/cluster/delete-dialog/main/set-as-deleteing-channel-listener.injectable.ts
+++ b/packages/core/src/features/cluster/delete-dialog/main/set-as-deleteing-channel-listener.injectable.ts
@@ -3,12 +3,13 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import clustersThatAreBeingDeletedInjectable from "../../../../main/cluster/are-being-deleted.injectable";
-import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens";
+import { getRequestChannelListenerInjectable } from "@k8slens/messaging";
import { setClusterAsDeletingChannel } from "../common/set-as-deleting-channel";
const setClusterAsDeletingChannelHandlerInjectable = getRequestChannelListenerInjectable({
+ id: "set-cluster-as-deleting-channel-handler",
channel: setClusterAsDeletingChannel,
- handler: (di) => {
+ getHandler: (di) => {
const clustersThatAreBeingDeleted = di.inject(clustersThatAreBeingDeletedInjectable);
return (clusterId) => {
diff --git a/packages/core/src/features/cluster/delete-dialog/renderer/request-clear-as-deleting.injectable.ts b/packages/core/src/features/cluster/delete-dialog/renderer/request-clear-as-deleting.injectable.ts
index e476998ca0..1e3125a52a 100644
--- a/packages/core/src/features/cluster/delete-dialog/renderer/request-clear-as-deleting.injectable.ts
+++ b/packages/core/src/features/cluster/delete-dialog/renderer/request-clear-as-deleting.injectable.ts
@@ -4,7 +4,7 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { ClusterId } from "../../../../common/cluster-types";
-import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable";
+import { requestFromChannelInjectionToken } from "@k8slens/messaging";
import { clearClusterAsDeletingChannel } from "../common/clear-as-deleting-channel";
export type RequestClearClusterAsDeleting = (clusterId: ClusterId) => Promise;
@@ -12,7 +12,7 @@ export type RequestClearClusterAsDeleting = (clusterId: ClusterId) => Promise {
- const requestChannel = di.inject(requestFromChannelInjectable);
+ const requestChannel = di.inject(requestFromChannelInjectionToken);
return (clusterId) => requestChannel(clearClusterAsDeletingChannel, clusterId);
},
diff --git a/packages/core/src/features/cluster/delete-dialog/renderer/request-delete.injectable.ts b/packages/core/src/features/cluster/delete-dialog/renderer/request-delete.injectable.ts
index c1286e3103..9e415e79d0 100644
--- a/packages/core/src/features/cluster/delete-dialog/renderer/request-delete.injectable.ts
+++ b/packages/core/src/features/cluster/delete-dialog/renderer/request-delete.injectable.ts
@@ -4,7 +4,7 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { ClusterId } from "../../../../common/cluster-types";
-import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable";
+import { requestFromChannelInjectionToken } from "@k8slens/messaging";
import { deleteClusterChannel } from "../common/delete-channel";
export type RequestDeleteCluster = (clusterId: ClusterId) => Promise;
@@ -12,7 +12,7 @@ export type RequestDeleteCluster = (clusterId: ClusterId) => Promise;
const requestDeleteClusterInjectable = getInjectable({
id: "request-delete-cluster",
instantiate: (di): RequestDeleteCluster => {
- const requestChannel = di.inject(requestFromChannelInjectable);
+ const requestChannel = di.inject(requestFromChannelInjectionToken);
return (clusterId) => requestChannel(deleteClusterChannel, clusterId);
},
diff --git a/packages/core/src/features/cluster/delete-dialog/renderer/request-set-as-deleting.injectable.ts b/packages/core/src/features/cluster/delete-dialog/renderer/request-set-as-deleting.injectable.ts
index de3a6393b3..0e86632f89 100644
--- a/packages/core/src/features/cluster/delete-dialog/renderer/request-set-as-deleting.injectable.ts
+++ b/packages/core/src/features/cluster/delete-dialog/renderer/request-set-as-deleting.injectable.ts
@@ -4,7 +4,7 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { ClusterId } from "../../../../common/cluster-types";
-import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable";
+import { requestFromChannelInjectionToken } from "@k8slens/messaging";
import { setClusterAsDeletingChannel } from "../common/set-as-deleting-channel";
export type RequestSetClusterAsDeleting = (clusterId: ClusterId) => Promise;
@@ -12,7 +12,7 @@ export type RequestSetClusterAsDeleting = (clusterId: ClusterId) => Promise {
- const requestChannel = di.inject(requestFromChannelInjectable);
+ const requestChannel = di.inject(requestFromChannelInjectionToken);
return (clusterId) => requestChannel(setClusterAsDeletingChannel, clusterId);
},
diff --git a/packages/core/src/features/cluster/refresh-accessibility-technical.test.ts b/packages/core/src/features/cluster/refresh-accessibility-technical.test.ts
new file mode 100644
index 0000000000..73ff6151b9
--- /dev/null
+++ b/packages/core/src/features/cluster/refresh-accessibility-technical.test.ts
@@ -0,0 +1,637 @@
+/**
+ * Copyright (c) OpenLens Authors. All rights reserved.
+ * Licensed under MIT License. See LICENSE in root directory for more information.
+ */
+
+import type { AsyncFnMock } from "@async-fn/jest";
+import asyncFn from "@async-fn/jest";
+import type { AuthorizationV1Api, CoreV1Api, V1APIGroupList, V1APIVersions, V1NamespaceList, V1SelfSubjectAccessReview, V1SelfSubjectRulesReview } from "@kubernetes/client-node";
+import clusterStoreInjectable from "../../common/cluster-store/cluster-store.injectable";
+import type { Cluster } from "../../common/cluster/cluster";
+import createAuthorizationApiInjectable from "../../common/cluster/create-authorization-api.injectable";
+import writeJsonFileInjectable from "../../common/fs/write-json-file.injectable";
+import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
+import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
+import broadcastMessageInjectable from "../../common/ipc/broadcast-message.injectable";
+import type { PartialDeep } from "type-fest";
+import { anyObject } from "jest-mock-extended";
+import createCoreApiInjectable from "../../common/cluster/create-core-api.injectable";
+import type { K8sRequest } from "../../main/k8s-request.injectable";
+import k8sRequestInjectable from "../../main/k8s-request.injectable";
+import type { DetectClusterMetadata } from "../../main/cluster-detectors/detect-cluster-metadata.injectable";
+import detectClusterMetadataInjectable from "../../main/cluster-detectors/detect-cluster-metadata.injectable";
+import type { ClusterConnection } from "../../main/cluster/cluster-connection.injectable";
+import clusterConnectionInjectable from "../../main/cluster/cluster-connection.injectable";
+import type { KubeAuthProxy } from "../../main/kube-auth-proxy/create-kube-auth-proxy.injectable";
+import createKubeAuthProxyInjectable from "../../main/kube-auth-proxy/create-kube-auth-proxy.injectable";
+import type { Mocked } from "../../test-utils/mock-interface";
+import { flushPromises } from "@k8slens/test-utils";
+
+describe("Refresh Cluster Accessibility Technical Tests", () => {
+ let builder: ApplicationBuilder;
+ let createSelfSubjectRulesReviewMock: AsyncFnMock;
+ let createSelfSubjectAccessReviewMock: AsyncFnMock;
+ let listNamespaceMock: AsyncFnMock;
+ let k8sRequestMock: AsyncFnMock;
+ let detectClusterMetadataMock: AsyncFnMock;
+ let kubeAuthProxyMock: Mocked;
+
+ beforeEach(async () => {
+ builder = getApplicationBuilder();
+
+ const mainDi = builder.mainDi;
+
+ mainDi.override(broadcastMessageInjectable, () => async () => {});
+
+ kubeAuthProxyMock = {
+ apiPrefix: "/some-api-prefix",
+ port: 0,
+ exit: jest.fn(),
+ run: asyncFn(),
+ };
+ mainDi.override(createKubeAuthProxyInjectable, () => () => kubeAuthProxyMock);
+
+ detectClusterMetadataMock = asyncFn();
+ mainDi.override(detectClusterMetadataInjectable, () => detectClusterMetadataMock);
+
+ k8sRequestMock = asyncFn();
+ mainDi.override(k8sRequestInjectable, () => k8sRequestMock);
+
+ createSelfSubjectRulesReviewMock = asyncFn();
+ createSelfSubjectAccessReviewMock = asyncFn();
+ mainDi.override(createAuthorizationApiInjectable, () => () => ({
+ createSelfSubjectRulesReview: createSelfSubjectRulesReviewMock,
+ createSelfSubjectAccessReview: createSelfSubjectAccessReviewMock,
+ } as any));
+
+ listNamespaceMock = asyncFn();
+ mainDi.override(createCoreApiInjectable, () => () => ({
+ listNamespace: listNamespaceMock,
+ } as any));
+
+ await builder.render();
+ });
+
+ describe("given a cluster with no configured preferences", () => {
+ let cluster: Cluster;
+ let clusterConnection: ClusterConnection;
+ let refreshPromise: Promise;
+
+ beforeEach(async () => {
+ const mainDi = builder.mainDi;
+ const clusterStore = mainDi.inject(clusterStoreInjectable);
+ const writeJsonFile = mainDi.inject(writeJsonFileInjectable);
+
+ await writeJsonFile("/some-kube-config-path", {
+ apiVersion: "v1",
+ kind: "Config",
+ clusters: [{
+ name: "some-cluster-name",
+ cluster: {
+ server: "https://localhost:8989",
+ },
+ }],
+ users: [{
+ name: "some-user-name",
+ }],
+ contexts: [{
+ name: "some-cluster-context",
+ context: {
+ user: "some-user-name",
+ cluster: "some-cluster-name",
+ },
+ }],
+ });
+
+ clusterStore.addCluster({
+ contextName: "some-cluster-context",
+ id: "some-cluster-id",
+ kubeConfigPath: "/some-kube-config-path",
+ });
+
+ cluster = clusterStore.getById("some-cluster-id") ?? (() => { throw new Error("missing cluster"); })();
+ clusterConnection = mainDi.inject(clusterConnectionInjectable, cluster);
+ refreshPromise = clusterConnection.refreshAccessibilityAndMetadata();
+ });
+
+ it("starts kubeAuthProxy", () => {
+ expect(kubeAuthProxyMock.run).toBeCalled();
+ });
+
+ describe("when kubeAuthProxy has started running and its port is found", () => {
+ beforeEach(async () => {
+ kubeAuthProxyMock.port = 1235;
+ await kubeAuthProxyMock.run.resolve();
+ await flushPromises();
+ });
+
+ it("requests if cluster has admin permissions", async () => {
+ expect(createSelfSubjectAccessReviewMock).toBeCalledWith(anyObject({
+ spec: {
+ namespace: "kube-system",
+ resource: "*",
+ verb: "create",
+ },
+ }));
+ });
+
+ describe.each([ true, false ])("when cluster admin request resolves to %p", (isAdmin) => {
+ beforeEach(async () => {
+ await createSelfSubjectAccessReviewMock.resolve({
+ body: {
+ status: {
+ allowed: isAdmin,
+ },
+ } as PartialDeep,
+ } as any);
+ });
+
+ it("requests if cluster has global watch permissions", () => {
+ expect(createSelfSubjectAccessReviewMock).toBeCalledWith(anyObject({
+ spec: {
+ verb: "watch",
+ resource: "*",
+ },
+ }));
+ });
+
+ describe.each([ true, false ])("when cluster global watch request resolves with %p", (globalWatch) => {
+ beforeEach(async () => {
+ await createSelfSubjectAccessReviewMock.resolve({
+ body: {
+ status: {
+ allowed: globalWatch,
+ },
+ } as PartialDeep,
+ } as any);
+ });
+
+ it("requests namespaces", () => {
+ expect(listNamespaceMock).toBeCalled();
+ });
+
+ describe("when list namespaces resolves", () => {
+ beforeEach(async () => {
+ await listNamespaceMock.resolve(listNamespaceResponse);
+ });
+
+ it("requests core api versions", () => {
+ expect(k8sRequestMock).toBeCalledWith(
+ anyObject({ id: "some-cluster-id" }),
+ "/api",
+ );
+ });
+
+ describe("when core api versions request resolves", () => {
+ beforeEach(async () => {
+ await k8sRequestMock.resolve({
+ serverAddressByClientCIDRs: [],
+ versions: [
+ "v1",
+ ],
+ } as V1APIVersions);
+ });
+
+ it("requests non-core api resource kinds", () => {
+ expect(k8sRequestMock).toBeCalledWith(
+ anyObject({ id: "some-cluster-id" }),
+ "/apis",
+ );
+ });
+
+ describe("when non-core api resource kinds request resolves", () => {
+ beforeEach(async () => {
+ await k8sRequestMock.resolve(nonCoreApiResponse);
+ });
+
+ it("requests specific resource kinds in core", () => {
+ expect(k8sRequestMock).toBeCalledWith(
+ anyObject({ id: "some-cluster-id" }),
+ "/api/v1",
+ );
+ });
+
+ describe("when core specific resource kinds request resolves", () => {
+ beforeEach(async () => {
+ await k8sRequestMock.resolve(coreApiKindsResponse);
+ });
+
+ it("requests specific resources kinds from the first non-core response", () => {
+ expect(k8sRequestMock).toBeCalledWith(
+ anyObject({ id: "some-cluster-id" }),
+ "/apis/node.k8s.io/v1",
+ );
+ });
+
+ describe("when first specific resource kinds request resolves", () => {
+ beforeEach(async () => {
+ await k8sRequestMock.resolve(nodeK8sIoKindsResponse);
+ });
+
+ it("requests specific resources kinds from the second non-core response", () => {
+ expect(k8sRequestMock).toBeCalledWith(
+ anyObject({ id: "some-cluster-id" }),
+ "/apis/discovery.k8s.io/v1",
+ );
+ });
+
+ describe("when second specific resource kinds request resolves", () => {
+ beforeEach(async () => {
+ await k8sRequestMock.resolve(discoveryK8sIoKindsResponse);
+ });
+
+ it("requests namespace list permissions for 'default' namespace", () => {
+ expect(createSelfSubjectRulesReviewMock).toBeCalledWith(anyObject({
+ spec: {
+ namespace: "default",
+ },
+ }));
+ });
+
+ describe("when the permissions are incomplete", () => {
+ beforeEach(async () => {
+ await createSelfSubjectRulesReviewMock.resolve(defaultIncompletePermissions);
+ });
+
+ it("requests namespace list permissions for 'my-namespace' namespace", () => {
+ expect(createSelfSubjectRulesReviewMock).toBeCalledWith(anyObject({
+ spec: {
+ namespace: "my-namespace",
+ },
+ }));
+ });
+
+ describe("when the permissions request for 'my-namespace' resolves as empty", () => {
+ beforeEach(async () => {
+ await createSelfSubjectRulesReviewMock.resolve(emptyPermissions);
+ });
+
+ it("requests cluster metadata", () => {
+ expect(detectClusterMetadataMock).toBeCalledWith(anyObject({ id: "some-cluster-id" }));
+ });
+
+ describe("when cluster metadata request resolves", () => {
+ beforeEach(async () => {
+ await detectClusterMetadataMock.resolve({});
+ });
+
+ it("allows the call to refreshAccessibilityAndMetadata to resolve", async () => {
+ await refreshPromise;
+ });
+
+ it("should have the cluster displaying 'pods'", () => {
+ expect(cluster.resourcesToShow.has("pods")).toBe(true);
+ });
+
+ it("should have the cluster displaying 'namespaces'", () => {
+ expect(cluster.resourcesToShow.has("namespaces")).toBe(true);
+ });
+ });
+ });
+
+ describe.skip("when the permissions are incomplete", () => {});
+ describe.skip("when the permissions resolve to a single entry with 'list' verb", () => {});
+ describe.skip("when the permissions resolve to multiple entries with the 'list' verb not on the first entry", () => {});
+ });
+
+ describe("when the permissions resolve to an empty list", () => {
+ beforeEach(async () => {
+ await createSelfSubjectRulesReviewMock.resolve(emptyPermissions);
+ });
+
+ it("requests namespace list permissions for 'my-namespace' namespace", () => {
+ expect(createSelfSubjectRulesReviewMock).toBeCalledWith(anyObject({
+ spec: {
+ namespace: "my-namespace",
+ },
+ }));
+ });
+
+ describe("when the permissions request for 'my-namespace' resolves as empty", () => {
+ beforeEach(async () => {
+ await createSelfSubjectRulesReviewMock.resolve(emptyPermissions);
+ });
+
+ it("requests cluster metadata", () => {
+ expect(detectClusterMetadataMock).toBeCalledWith(anyObject({ id: "some-cluster-id" }));
+ });
+
+ describe("when cluster metadata request resolves", () => {
+ beforeEach(async () => {
+ await detectClusterMetadataMock.resolve({});
+ });
+
+ it("allows the call to refreshAccessibilityAndMetadata to resolve", async () => {
+ await refreshPromise;
+ });
+
+ it("should have the cluster displaying 'pods'", () => {
+ expect(cluster.resourcesToShow.has("pods")).toBe(false);
+ });
+
+ it("should have the cluster not displaying 'namespaces'", () => {
+ expect(cluster.resourcesToShow.has("namespaces")).toBe(false);
+ });
+ });
+ });
+
+ describe.skip("when the permissions are incomplete", () => {});
+ describe.skip("when the permissions resolve to a single entry with 'list' verb", () => {});
+ describe.skip("when the permissions resolve to multiple entries with the 'list' verb not on the first entry", () => {});
+ });
+
+ describe("when the permissions resolve to a single entry with 'list' verb", () => {
+ beforeEach(async () => {
+ await createSelfSubjectRulesReviewMock.resolve(defaultSingleListPermissions);
+ });
+
+ it("requests namespace list permissions for 'my-namespace' namespace", () => {
+ expect(createSelfSubjectRulesReviewMock).toBeCalledWith(anyObject({
+ spec: {
+ namespace: "my-namespace",
+ },
+ }));
+ });
+
+ describe("when the permissions request for 'my-namespace' resolves as empty", () => {
+ beforeEach(async () => {
+ await createSelfSubjectRulesReviewMock.resolve(emptyPermissions);
+ });
+
+ it("requests cluster metadata", () => {
+ expect(detectClusterMetadataMock).toBeCalledWith(anyObject({ id: "some-cluster-id" }));
+ });
+
+ describe("when cluster metadata request resolves", () => {
+ beforeEach(async () => {
+ await detectClusterMetadataMock.resolve({});
+ });
+
+ it("allows the call to refreshAccessibilityAndMetadata to resolve", async () => {
+ await refreshPromise;
+ });
+
+ it("should have the cluster displaying 'pods'", () => {
+ expect(cluster.resourcesToShow.has("pods")).toBe(true);
+ });
+
+ it("should have the cluster not displaying 'namespaces'", () => {
+ expect(cluster.resourcesToShow.has("namespaces")).toBe(false);
+ });
+ });
+ });
+
+ describe.skip("when the permissions are incomplete", () => {});
+ describe.skip("when the permissions resolve to a single entry with 'list' verb", () => {});
+ describe.skip("when the permissions resolve to multiple entries with the 'list' verb not on the first entry", () => {});
+ });
+
+ describe("when the permissions resolve to multiple entries with the 'list' verb not on the first entry", () => {
+ beforeEach(async () => {
+ await createSelfSubjectRulesReviewMock.resolve(defaultMultipleListPermissions);
+ });
+
+ it("requests namespace list permissions for 'my-namespace' namespace", () => {
+ expect(createSelfSubjectRulesReviewMock).toBeCalledWith(anyObject({
+ spec: {
+ namespace: "my-namespace",
+ },
+ }));
+ });
+
+ describe("when the permissions request for 'my-namespace' resolves as empty", () => {
+ beforeEach(async () => {
+ await createSelfSubjectRulesReviewMock.resolve(emptyPermissions);
+ });
+
+ it("requests cluster metadata", () => {
+ expect(detectClusterMetadataMock).toBeCalledWith(anyObject({ id: "some-cluster-id" }));
+ });
+
+ describe("when cluster metadata request resolves", () => {
+ beforeEach(async () => {
+ await detectClusterMetadataMock.resolve({});
+ });
+
+ it("allows the call to refreshAccessibilityAndMetadata to resolve", async () => {
+ await refreshPromise;
+ });
+
+ it("should have the cluster displaying 'pods'", () => {
+ expect(cluster.resourcesToShow.has("pods")).toBe(true);
+ });
+
+ it("should have the cluster not displaying 'namespaces'", () => {
+ expect(cluster.resourcesToShow.has("namespaces")).toBe(false);
+ });
+ });
+ });
+
+ describe.skip("when the permissions are incomplete", () => {});
+ describe.skip("when the permissions resolve to a single entry with 'list' verb", () => {});
+ describe.skip("when the permissions resolve to multiple entries with the 'list' verb not on the first entry", () => {});
+ });
+ });
+
+ describe.skip("when second specific resource kinds rejects", () => {});
+ });
+ });
+
+ describe.skip("when first specific resource kinds rejects", () => {});
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+});
+
+const nonCoreApiResponse = {
+ groups: [
+ {
+ name: "node.k8s.io",
+ versions: [
+ {
+ groupVersion: "node.k8s.io/v1",
+ version: "v1",
+ },
+ ],
+ preferredVersion: {
+ groupVersion: "node.k8s.io/v1",
+ version: "v1",
+ },
+ },
+ {
+ name: "discovery.k8s.io",
+ versions: [
+ {
+ groupVersion: "discovery.k8s.io/v1",
+ version: "v1",
+ },
+ ],
+ preferredVersion: {
+ groupVersion: "discovery.k8s.io/v1",
+ version: "v1",
+ },
+ },
+ ],
+} as V1APIGroupList;
+
+const listNamespaceResponse = {
+ body: {
+ items: [
+ {
+ metadata: {
+ name: "default",
+ },
+ },
+ {
+ metadata: {
+ name: "my-namespace",
+ },
+ },
+ ],
+ } as PartialDeep,
+} as Awaited>;
+
+const coreApiKindsResponse = {
+ kind: "APIResourceList",
+ groupVersion: "v1",
+ resources: [
+ {
+ name: "namespaces",
+ singularName: "",
+ namespaced: false,
+ kind: "Namespace",
+ verbs: ["create", "delete", "get", "list", "patch", "update", "watch"],
+ shortNames: ["ns"],
+ storageVersionHash: "Q3oi5N2YM8M=",
+ },
+ {
+ name: "pods",
+ singularName: "",
+ namespaced: true,
+ kind: "Pod",
+ verbs: [
+ "create",
+ "delete",
+ "deletecollection",
+ "get",
+ "list",
+ "patch",
+ "update",
+ "watch",
+ ],
+ shortNames: ["po"],
+ categories: ["all"],
+ storageVersionHash: "xPOwRZ+Yhw8=",
+ },
+ {
+ name: "pods/attach",
+ singularName: "",
+ namespaced: true,
+ kind: "PodAttachOptions",
+ verbs: ["create", "get"],
+ },
+ ],
+};
+
+const nodeK8sIoKindsResponse = {
+ kind: "APIResourceList",
+ apiVersion: "v1",
+ groupVersion: "node.k8s.io/v1",
+ resources: [
+ {
+ name: "runtimeclasses",
+ singularName: "",
+ namespaced: false,
+ kind: "RuntimeClass",
+ verbs: [
+ "create",
+ "delete",
+ "deletecollection",
+ "get",
+ "list",
+ "patch",
+ "update",
+ "watch",
+ ],
+ storageVersionHash: "WQTu1GL3T2Q=",
+ },
+ ],
+};
+
+const discoveryK8sIoKindsResponse = {
+ kind: "APIResourceList",
+ apiVersion: "v1",
+ groupVersion: "discovery.k8s.io/v1",
+ resources: [
+ {
+ name: "endpointslices",
+ singularName: "",
+ namespaced: true,
+ kind: "EndpointSlice",
+ verbs: [
+ "create",
+ "delete",
+ "deletecollection",
+ "get",
+ "list",
+ "patch",
+ "update",
+ "watch",
+ ],
+ storageVersionHash: "Nx3SIv6I0mE=",
+ },
+ ],
+};
+
+type CreateSelfSubjectRulesReviewRes = Awaited>;
+
+const defaultIncompletePermissions = {
+ body: {
+ status: {
+ incomplete: true,
+ },
+ } as PartialDeep,
+} as CreateSelfSubjectRulesReviewRes;
+
+const emptyPermissions = {
+ body: {
+ status: {
+ resourceRules: [],
+ },
+ } as PartialDeep,
+} as CreateSelfSubjectRulesReviewRes;
+
+const defaultSingleListPermissions = {
+ body: {
+ status: {
+ resourceRules: [{
+ apiGroups: [""],
+ resources: ["pods"],
+ verbs: ["list"],
+ }],
+ },
+ } as PartialDeep,
+} as CreateSelfSubjectRulesReviewRes;
+
+const defaultMultipleListPermissions = {
+ body: {
+ status: {
+ resourceRules: [
+ {
+ apiGroups: [""],
+ resources: ["pods"],
+ verbs: ["get"],
+ },
+ {
+ apiGroups: [""],
+ resources: ["pods"],
+ verbs: ["list"],
+ },
+ ],
+ },
+ } as PartialDeep,
+} as CreateSelfSubjectRulesReviewRes;
diff --git a/packages/core/src/features/cluster/state-sync/common/channels.ts b/packages/core/src/features/cluster/state-sync/common/channels.ts
index 7ceeb82f84..66ce718955 100644
--- a/packages/core/src/features/cluster/state-sync/common/channels.ts
+++ b/packages/core/src/features/cluster/state-sync/common/channels.ts
@@ -4,8 +4,7 @@
*/
import type { ClusterId, ClusterState } from "../../../../common/cluster-types";
-import type { MessageChannel } from "../../../../common/utils/channel/message-channel-listener-injection-token";
-import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token";
+import type { MessageChannel, RequestChannel } from "@k8slens/messaging";
export interface ClusterStateSync {
clusterId: ClusterId;
diff --git a/packages/core/src/features/cluster/state-sync/main/emit-update.injectable.ts b/packages/core/src/features/cluster/state-sync/main/emit-update.injectable.ts
index 8cadd32864..4499d2ac66 100644
--- a/packages/core/src/features/cluster/state-sync/main/emit-update.injectable.ts
+++ b/packages/core/src/features/cluster/state-sync/main/emit-update.injectable.ts
@@ -3,18 +3,16 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
-import type { MessageChannelHandler } from "../../../../common/utils/channel/message-channel-listener-injection-token";
-import { sendMessageToChannelInjectionToken } from "../../../../common/utils/channel/message-to-channel-injection-token";
+import { sendMessageToChannelInjectionToken } from "@k8slens/messaging";
+import type { ClusterStateSync } from "../common/channels";
import { clusterStateSyncChannel } from "../common/channels";
-export type EmitClusterStateUpdate = MessageChannelHandler;
-
const emitClusterStateUpdateInjectable = getInjectable({
id: "emit-cluster-state-update",
- instantiate: (di): EmitClusterStateUpdate => {
+ instantiate: (di) => {
const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken);
- return (message) => sendMessageToChannel(clusterStateSyncChannel, message);
+ return (message: ClusterStateSync) => sendMessageToChannel(clusterStateSyncChannel, message);
},
});
diff --git a/packages/core/src/features/cluster/state-sync/main/handle-initial.injectable.ts b/packages/core/src/features/cluster/state-sync/main/handle-initial.injectable.ts
index 708f032d48..db65024973 100644
--- a/packages/core/src/features/cluster/state-sync/main/handle-initial.injectable.ts
+++ b/packages/core/src/features/cluster/state-sync/main/handle-initial.injectable.ts
@@ -3,12 +3,13 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import clusterStoreInjectable from "../../../../common/cluster-store/cluster-store.injectable";
-import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens";
+import { getRequestChannelListenerInjectable } from "@k8slens/messaging";
import { initialClusterStatesChannel } from "../common/channels";
const handleInitialClusterStateSyncInjectable = getRequestChannelListenerInjectable({
+ id: "handle-initial-cluster-state-sync",
channel: initialClusterStatesChannel,
- handler: (di) => {
+ getHandler: (di) => {
const clusterStore = di.inject(clusterStoreInjectable);
return () => clusterStore.clustersList.map(cluster => ({
diff --git a/packages/core/src/features/cluster/state-sync/renderer/listener.injectable.ts b/packages/core/src/features/cluster/state-sync/renderer/listener.injectable.ts
index 9863a391e8..a3778d096e 100644
--- a/packages/core/src/features/cluster/state-sync/renderer/listener.injectable.ts
+++ b/packages/core/src/features/cluster/state-sync/renderer/listener.injectable.ts
@@ -3,13 +3,13 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import getClusterByIdInjectable from "../../../../common/cluster-store/get-by-id.injectable";
-import { getMessageChannelListenerInjectable } from "../../../../common/utils/channel/message-channel-listener-injection-token";
+import { getMessageChannelListenerInjectable } from "@k8slens/messaging";
import { clusterStateSyncChannel } from "../common/channels";
const clusterStateListenerInjectable = getMessageChannelListenerInjectable({
channel: clusterStateSyncChannel,
id: "main",
- handler: (di) => {
+ getHandler: (di) => {
const getClusterById = di.inject(getClusterByIdInjectable);
return ({ clusterId, state }) => getClusterById(clusterId)?.setState(state);
diff --git a/packages/core/src/features/cluster/state-sync/renderer/request-initial.injectable.ts b/packages/core/src/features/cluster/state-sync/renderer/request-initial.injectable.ts
index 89f72fbcf5..497d2c5aaf 100644
--- a/packages/core/src/features/cluster/state-sync/renderer/request-initial.injectable.ts
+++ b/packages/core/src/features/cluster/state-sync/renderer/request-initial.injectable.ts
@@ -3,8 +3,8 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
-import type { RequestChannelHandler } from "../../../../main/utils/channel/channel-listeners/listener-tokens";
-import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable";
+import type { RequestChannelHandler } from "@k8slens/messaging";
+import { requestFromChannelInjectionToken } from "@k8slens/messaging";
import { initialClusterStatesChannel } from "../common/channels";
export type RequestInitialClusterStates = RequestChannelHandler;
@@ -12,7 +12,7 @@ export type RequestInitialClusterStates = RequestChannelHandler {
- const requestFromChannel = di.inject(requestFromChannelInjectable);
+ const requestFromChannel = di.inject(requestFromChannelInjectionToken);
return () => requestFromChannel(initialClusterStatesChannel);
},
diff --git a/packages/core/src/features/extension-special-characters-in-page-registrations.test.tsx b/packages/core/src/features/extension-special-characters-in-page-registrations.test.tsx
index ac038a5743..b9760eba79 100644
--- a/packages/core/src/features/extension-special-characters-in-page-registrations.test.tsx
+++ b/packages/core/src/features/extension-special-characters-in-page-registrations.test.tsx
@@ -31,8 +31,7 @@ describe("extension special characters in page registrations", () => {
describe("when navigating to route with ID having special characters", () => {
beforeEach(() => {
- const testExtension =
- builder.extensions.get("some-extension-id").applicationWindows.only;
+ const testExtension = builder.extensions.get("some-extension-id").applicationWindows.only;
testExtension.navigate("/some-page-id/");
});
diff --git a/packages/core/src/features/extensions/navigate/common/channel.ts b/packages/core/src/features/extensions/navigate/common/channel.ts
index 4c6892e6cb..ec7bc967dc 100644
--- a/packages/core/src/features/extensions/navigate/common/channel.ts
+++ b/packages/core/src/features/extensions/navigate/common/channel.ts
@@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
-import type { MessageChannel } from "../../../../common/utils/channel/message-channel-listener-injection-token";
+import type { MessageChannel } from "@k8slens/messaging";
export interface NavigateForExtensionArgs {
extId: string;
diff --git a/packages/core/src/features/extensions/navigate/renderer/listener.injectable.ts b/packages/core/src/features/extensions/navigate/renderer/listener.injectable.ts
index fccf0efca6..2397def4f6 100644
--- a/packages/core/src/features/extensions/navigate/renderer/listener.injectable.ts
+++ b/packages/core/src/features/extensions/navigate/renderer/listener.injectable.ts
@@ -2,15 +2,15 @@
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
-import { getMessageChannelListenerInjectable } from "../../../../common/utils/channel/message-channel-listener-injection-token";
+import { getMessageChannelListenerInjectable } from "@k8slens/messaging";
import extensionLoaderInjectable from "../../../../extensions/extension-loader/extension-loader.injectable";
import type { LensRendererExtension } from "../../../../extensions/lens-renderer-extension";
import { navigateForExtensionChannel } from "../common/channel";
const navigateForExtensionListenerInjectable = getMessageChannelListenerInjectable({
channel: navigateForExtensionChannel,
- id: "main",
- handler: (di) => {
+ id: "renderer",
+ getHandler: (di) => {
const extensionLoader = di.inject(extensionLoaderInjectable);
return ({ extId, pageId, params }) => {
diff --git a/packages/core/src/features/helm-charts/child-features/preferences/renderer/active-helm-repositories.injectable.ts b/packages/core/src/features/helm-charts/child-features/preferences/renderer/active-helm-repositories.injectable.ts
index 7a0d5e6b47..b4195a876f 100644
--- a/packages/core/src/features/helm-charts/child-features/preferences/renderer/active-helm-repositories.injectable.ts
+++ b/packages/core/src/features/helm-charts/child-features/preferences/renderer/active-helm-repositories.injectable.ts
@@ -5,7 +5,7 @@
import { getInjectable } from "@ogre-tools/injectable";
import { asyncComputed } from "@ogre-tools/injectable-react";
import { getActiveHelmRepositoriesChannel } from "../../../../../common/helm/get-active-helm-repositories-channel";
-import { requestFromChannelInjectionToken } from "../../../../../common/utils/channel/request-from-channel-injection-token";
+import { requestFromChannelInjectionToken } from "@k8slens/messaging";
import showErrorNotificationInjectable from "../../../../../renderer/components/notifications/show-error-notification.injectable";
import helmRepositoriesErrorStateInjectable from "./helm-repositories-error-state.injectable";
import { runInAction } from "mobx";
diff --git a/packages/core/src/features/helm-charts/child-features/preferences/renderer/adding-of-public-helm-repository/select-helm-repository/add-helm-repository.injectable.ts b/packages/core/src/features/helm-charts/child-features/preferences/renderer/adding-of-public-helm-repository/select-helm-repository/add-helm-repository.injectable.ts
index 6b39d8dddf..3c2199c490 100644
--- a/packages/core/src/features/helm-charts/child-features/preferences/renderer/adding-of-public-helm-repository/select-helm-repository/add-helm-repository.injectable.ts
+++ b/packages/core/src/features/helm-charts/child-features/preferences/renderer/adding-of-public-helm-repository/select-helm-repository/add-helm-repository.injectable.ts
@@ -4,7 +4,7 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { HelmRepo } from "../../../../../../../common/helm/helm-repo";
-import { requestFromChannelInjectionToken } from "../../../../../../../common/utils/channel/request-from-channel-injection-token";
+import { requestFromChannelInjectionToken } from "@k8slens/messaging";
import activeHelmRepositoriesInjectable from "../../active-helm-repositories.injectable";
import showErrorNotificationInjectable from "../../../../../../../renderer/components/notifications/show-error-notification.injectable";
import showSuccessNotificationInjectable from "../../../../../../../renderer/components/notifications/show-success-notification.injectable";
diff --git a/packages/core/src/features/helm-charts/child-features/preferences/renderer/remove-helm-repository.injectable.ts b/packages/core/src/features/helm-charts/child-features/preferences/renderer/remove-helm-repository.injectable.ts
index 3aa56a4b04..4af5543c28 100644
--- a/packages/core/src/features/helm-charts/child-features/preferences/renderer/remove-helm-repository.injectable.ts
+++ b/packages/core/src/features/helm-charts/child-features/preferences/renderer/remove-helm-repository.injectable.ts
@@ -4,7 +4,7 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { HelmRepo } from "../../../../../common/helm/helm-repo";
-import { requestFromChannelInjectionToken } from "../../../../../common/utils/channel/request-from-channel-injection-token";
+import { requestFromChannelInjectionToken } from "@k8slens/messaging";
import activeHelmRepositoriesInjectable from "./active-helm-repositories.injectable";
import { removeHelmRepositoryChannel } from "../../../../../common/helm/remove-helm-repository-channel";
diff --git a/packages/core/src/features/navigation/reload-page/common/channel.ts b/packages/core/src/features/navigation/reload-page/common/channel.ts
index b920067a4d..50cdaa8918 100644
--- a/packages/core/src/features/navigation/reload-page/common/channel.ts
+++ b/packages/core/src/features/navigation/reload-page/common/channel.ts
@@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
-import type { MessageChannel } from "../../../../common/utils/channel/message-channel-listener-injection-token";
+import type { MessageChannel } from "@k8slens/messaging";
export type ReloadPageChannel = MessageChannel;
diff --git a/packages/core/src/features/navigation/reload-page/renderer/register-listener.global-override-for-injectable.ts b/packages/core/src/features/navigation/reload-page/renderer/register-listener.global-override-for-injectable.ts
index 9953ddcbf9..4b9842cf7d 100644
--- a/packages/core/src/features/navigation/reload-page/renderer/register-listener.global-override-for-injectable.ts
+++ b/packages/core/src/features/navigation/reload-page/renderer/register-listener.global-override-for-injectable.ts
@@ -8,6 +8,7 @@ import { reloadPageChannel } from "../common/channel";
import reloadPageChannelListenerInjectable from "./register-listener.injectable";
export default getGlobalOverride(reloadPageChannelListenerInjectable, () => ({
+ id: "reload-page-channel-listener",
channel: reloadPageChannel,
handler: () => {},
}));
diff --git a/packages/core/src/features/navigation/reload-page/renderer/register-listener.injectable.ts b/packages/core/src/features/navigation/reload-page/renderer/register-listener.injectable.ts
index a42d818729..f71096bebf 100644
--- a/packages/core/src/features/navigation/reload-page/renderer/register-listener.injectable.ts
+++ b/packages/core/src/features/navigation/reload-page/renderer/register-listener.injectable.ts
@@ -2,13 +2,13 @@
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
-import { getMessageChannelListenerInjectable } from "../../../../common/utils/channel/message-channel-listener-injection-token";
+import { getMessageChannelListenerInjectable } from "@k8slens/messaging";
import { reloadPageChannel } from "../common/channel";
const reloadPageChannelListenerInjectable = getMessageChannelListenerInjectable({
id: "handler",
channel: reloadPageChannel,
- handler: () => () => location.reload(),
+ getHandler: () => () => location.reload(),
causesSideEffects: true,
});
diff --git a/packages/core/src/features/path-picking-dialog/common/channel.ts b/packages/core/src/features/path-picking-dialog/common/channel.ts
index 98c19b4ad6..c5e8b9386d 100644
--- a/packages/core/src/features/path-picking-dialog/common/channel.ts
+++ b/packages/core/src/features/path-picking-dialog/common/channel.ts
@@ -4,7 +4,7 @@
*/
import type { OpenDialogOptions } from "electron";
-import type { RequestChannel } from "../../../common/utils/channel/request-channel-listener-injection-token";
+import type { RequestChannel } from "@k8slens/messaging";
export type PathPickingResponse = {
canceled: true;
diff --git a/packages/core/src/features/path-picking-dialog/main/handle-pick-paths.injectable.ts b/packages/core/src/features/path-picking-dialog/main/handle-pick-paths.injectable.ts
index d566ac9728..dded293c83 100644
--- a/packages/core/src/features/path-picking-dialog/main/handle-pick-paths.injectable.ts
+++ b/packages/core/src/features/path-picking-dialog/main/handle-pick-paths.injectable.ts
@@ -4,12 +4,13 @@
*/
import askUserForFilePathsInjectable from "../../../main/ipc/ask-user-for-file-paths.injectable";
-import { getRequestChannelListenerInjectable } from "../../../main/utils/channel/channel-listeners/listener-tokens";
+import { getRequestChannelListenerInjectable } from "@k8slens/messaging";
import { openPathPickingDialogChannel } from "../common/channel";
const openPathPickingDialogListener = getRequestChannelListenerInjectable({
+ id: "open-path-picking-dialog",
channel: openPathPickingDialogChannel,
- handler: (di) => di.inject(askUserForFilePathsInjectable),
+ getHandler: (di) => di.inject(askUserForFilePathsInjectable),
});
export default openPathPickingDialogListener;
diff --git a/packages/core/src/features/path-picking-dialog/renderer/pick-paths.injectable.ts b/packages/core/src/features/path-picking-dialog/renderer/pick-paths.injectable.ts
index 5dde31f46d..528bffc634 100644
--- a/packages/core/src/features/path-picking-dialog/renderer/pick-paths.injectable.ts
+++ b/packages/core/src/features/path-picking-dialog/renderer/pick-paths.injectable.ts
@@ -4,7 +4,7 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { PathPickOpts } from "../../../renderer/components/path-picker";
-import requestFromChannelInjectable from "../../../renderer/utils/channel/request-from-channel.injectable";
+import { requestFromChannelInjectionToken } from "@k8slens/messaging";
import { openPathPickingDialogChannel } from "../common/channel";
export type OpenPathPickingDialog = (options: PathPickOpts) => Promise;
@@ -12,7 +12,7 @@ export type OpenPathPickingDialog = (options: PathPickOpts) => Promise;
const openPathPickingDialogInjectable = getInjectable({
id: "open-path-picking-dialog",
instantiate: (di): OpenPathPickingDialog => {
- const requestFromChannel = di.inject(requestFromChannelInjectable);
+ const requestFromChannel = di.inject(requestFromChannelInjectionToken);
return async (options) => {
const { onPick, onCancel, ...dialogOptions } = options;
diff --git a/packages/core/src/features/shell-sync/common/failure-channel.ts b/packages/core/src/features/shell-sync/common/failure-channel.ts
index aed25b0da0..268640fe89 100644
--- a/packages/core/src/features/shell-sync/common/failure-channel.ts
+++ b/packages/core/src/features/shell-sync/common/failure-channel.ts
@@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
-import type { MessageChannel } from "../../../common/utils/channel/message-channel-listener-injection-token";
+import type { MessageChannel } from "@k8slens/messaging";
export const shellSyncFailedChannel: MessageChannel = {
id: "shell-sync-failed-channel",
diff --git a/packages/core/src/features/shell-sync/main/emit-failure.injectable.ts b/packages/core/src/features/shell-sync/main/emit-failure.injectable.ts
index 5abdfafa52..7dbfb094f2 100644
--- a/packages/core/src/features/shell-sync/main/emit-failure.injectable.ts
+++ b/packages/core/src/features/shell-sync/main/emit-failure.injectable.ts
@@ -3,16 +3,15 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
-import type { MessageChannelSender } from "../../../common/utils/channel/message-to-channel-injection-token";
-import { sendMessageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token";
+import { sendMessageToChannelInjectionToken } from "@k8slens/messaging";
import { shellSyncFailedChannel } from "../common/failure-channel";
const emitShellSyncFailedInjectable = getInjectable({
id: "emit-shell-sync-failed",
- instantiate: (di): MessageChannelSender => {
+ instantiate: (di) => {
const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken);
- return (error) => sendMessageToChannel(shellSyncFailedChannel, error);
+ return (error: string) => sendMessageToChannel(shellSyncFailedChannel, error);
},
});
diff --git a/packages/core/src/features/shell-sync/renderer/failure-listener.injectable.ts b/packages/core/src/features/shell-sync/renderer/failure-listener.injectable.ts
index 2014397fad..135143b3a6 100644
--- a/packages/core/src/features/shell-sync/renderer/failure-listener.injectable.ts
+++ b/packages/core/src/features/shell-sync/renderer/failure-listener.injectable.ts
@@ -2,14 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
-import { getMessageChannelListenerInjectable } from "../../../common/utils/channel/message-channel-listener-injection-token";
+import { getMessageChannelListenerInjectable } from "@k8slens/messaging";
import showErrorNotificationInjectable from "../../../renderer/components/notifications/show-error-notification.injectable";
import { shellSyncFailedChannel } from "../common/failure-channel";
const shellSyncFailureListenerInjectable = getMessageChannelListenerInjectable({
id: "notification",
channel: shellSyncFailedChannel,
- handler: (di) => {
+ getHandler: (di) => {
const showErrorNotification = di.inject(showErrorNotificationInjectable);
return (errorMessage) => showErrorNotification(`Failed to sync shell environment: ${errorMessage}`);
diff --git a/packages/core/src/features/theme/system-type/common/channels.ts b/packages/core/src/features/theme/system-type/common/channels.ts
index 3134f20378..49fb96ef0a 100644
--- a/packages/core/src/features/theme/system-type/common/channels.ts
+++ b/packages/core/src/features/theme/system-type/common/channels.ts
@@ -3,8 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
-import type { MessageChannel } from "../../../../common/utils/channel/message-channel-listener-injection-token";
-import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token";
+import type { MessageChannel, RequestChannel } from "@k8slens/messaging";
export type SystemThemeType = "dark" | "light";
diff --git a/packages/core/src/features/theme/system-type/main/emit-update.injectable.ts b/packages/core/src/features/theme/system-type/main/emit-update.injectable.ts
index c085e6615a..d078e81e33 100644
--- a/packages/core/src/features/theme/system-type/main/emit-update.injectable.ts
+++ b/packages/core/src/features/theme/system-type/main/emit-update.injectable.ts
@@ -3,18 +3,16 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
-import type { MessageChannelHandler } from "../../../../common/utils/channel/message-channel-listener-injection-token";
-import { sendMessageToChannelInjectionToken } from "../../../../common/utils/channel/message-to-channel-injection-token";
+import { sendMessageToChannelInjectionToken } from "@k8slens/messaging";
+import type { SystemThemeType } from "../common/channels";
import { systemThemeTypeUpdateChannel } from "../common/channels";
-export type EmitSystemThemeTypeUpdate = MessageChannelHandler;
-
const emitSystemThemeTypeUpdateInjectable = getInjectable({
id: "emit-system-theme-type-update",
- instantiate: (di): EmitSystemThemeTypeUpdate => {
+ instantiate: (di) => {
const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken);
- return (type) => sendMessageToChannel(systemThemeTypeUpdateChannel, type);
+ return (type: SystemThemeType) => sendMessageToChannel(systemThemeTypeUpdateChannel, type);
},
});
diff --git a/packages/core/src/features/theme/system-type/main/handle-initial.injectable.ts b/packages/core/src/features/theme/system-type/main/handle-initial.injectable.ts
index 1468b1eeda..7af8a0a069 100644
--- a/packages/core/src/features/theme/system-type/main/handle-initial.injectable.ts
+++ b/packages/core/src/features/theme/system-type/main/handle-initial.injectable.ts
@@ -4,12 +4,13 @@
*/
import operatingSystemThemeInjectable from "../../../../main/theme/operating-system-theme.injectable";
-import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens";
+import { getRequestChannelListenerInjectable } from "@k8slens/messaging";
import { initialSystemThemeTypeChannel } from "../common/channels";
const initialSystemThemeTypeHandler = getRequestChannelListenerInjectable({
+ id: "initial-system-theme-type-listener",
channel: initialSystemThemeTypeChannel,
- handler: (di) => {
+ getHandler: (di) => {
const operatingSystemTheme = di.inject(operatingSystemThemeInjectable);
return () => operatingSystemTheme.get();
diff --git a/packages/core/src/features/theme/system-type/renderer/request-initial.injectable.ts b/packages/core/src/features/theme/system-type/renderer/request-initial.injectable.ts
index 74fe73cf03..fd84d7f90c 100644
--- a/packages/core/src/features/theme/system-type/renderer/request-initial.injectable.ts
+++ b/packages/core/src/features/theme/system-type/renderer/request-initial.injectable.ts
@@ -3,8 +3,8 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
-import type { RequestChannelHandler } from "../../../../main/utils/channel/channel-listeners/listener-tokens";
-import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable";
+import type { RequestChannelHandler } from "@k8slens/messaging";
+import { requestFromChannelInjectionToken } from "@k8slens/messaging";
import { initialSystemThemeTypeChannel } from "../common/channels";
export type RequestInitialSystemThemeType = RequestChannelHandler;
@@ -12,7 +12,7 @@ export type RequestInitialSystemThemeType = RequestChannelHandler {
- const requestFromChannel = di.inject(requestFromChannelInjectable);
+ const requestFromChannel = di.inject(requestFromChannelInjectionToken);
return () => requestFromChannel(initialSystemThemeTypeChannel);
},
diff --git a/packages/core/src/features/theme/system-type/renderer/update-listener.injectable.ts b/packages/core/src/features/theme/system-type/renderer/update-listener.injectable.ts
index 4eb57c9b85..dac9061c28 100644
--- a/packages/core/src/features/theme/system-type/renderer/update-listener.injectable.ts
+++ b/packages/core/src/features/theme/system-type/renderer/update-listener.injectable.ts
@@ -2,14 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
-import { getMessageChannelListenerInjectable } from "../../../../common/utils/channel/message-channel-listener-injection-token";
+import { getMessageChannelListenerInjectable } from "@k8slens/messaging";
import systemThemeConfigurationInjectable from "../../../../renderer/themes/system-theme.injectable";
import { systemThemeTypeUpdateChannel } from "../common/channels";
const systemThemeTypeUpdateListenerInjectable = getMessageChannelListenerInjectable({
channel: systemThemeTypeUpdateChannel,
id: "main",
- handler: (di) => {
+ getHandler: (di) => {
const systemThemeConfiguration = di.inject(systemThemeConfigurationInjectable);
return (type) => systemThemeConfiguration.set(type);
diff --git a/packages/core/src/jest-after-env.setup.ts b/packages/core/src/jest-after-env.setup.ts
index 69b18161a8..df0fcfff4d 100644
--- a/packages/core/src/jest-after-env.setup.ts
+++ b/packages/core/src/jest-after-env.setup.ts
@@ -4,3 +4,8 @@
*/
import "@testing-library/jest-dom";
+
+// Note: This is a kludge to prevent "Hooks cannot be defined inside tests" error
+// when importing a test util inside a test suite.
+import { render } from "@testing-library/react";
+void render;
diff --git a/packages/core/src/main/__test__/cluster.test.ts b/packages/core/src/main/__test__/cluster.test.ts
index bb495af847..205a23d5ab 100644
--- a/packages/core/src/main/__test__/cluster.test.ts
+++ b/packages/core/src/main/__test__/cluster.test.ts
@@ -5,10 +5,6 @@
import { Cluster } from "../../common/cluster/cluster";
import { Kubectl } from "../kubectl/kubectl";
import { getDiForUnitTesting } from "../getDiForUnitTesting";
-import createAuthorizationReviewInjectable from "../../common/cluster/authorization-review.injectable";
-import requestNamespaceListPermissionsForInjectable from "../../common/cluster/request-namespace-list-permissions.injectable";
-import createListNamespacesInjectable from "../../common/cluster/list-namespaces.injectable";
-import prometheusHandlerInjectable from "../cluster/prometheus-handler/prometheus-handler.injectable";
import directoryForUserDataInjectable from "../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
import directoryForTempInjectable from "../../common/app-paths/directory-for-temp/directory-for-temp.injectable";
import normalizedPlatformInjectable from "../../common/vars/normalized-platform.injectable";
@@ -19,6 +15,10 @@ import clusterConnectionInjectable from "../cluster/cluster-connection.injectabl
import kubeconfigManagerInjectable from "../kubeconfig-manager/kubeconfig-manager.injectable";
import type { KubeconfigManager } from "../kubeconfig-manager/kubeconfig-manager";
import broadcastConnectionUpdateInjectable from "../cluster/broadcast-connection-update.injectable";
+import createCanIInjectable from "../../common/cluster/create-can-i.injectable";
+import createRequestNamespaceListPermissionsInjectable from "../../common/cluster/create-request-namespace-list-permissions.injectable";
+import createListNamespacesInjectable from "../../common/cluster/list-namespaces.injectable";
+import prometheusHandlerInjectable from "../cluster/prometheus-handler/prometheus-handler.injectable";
describe("create clusters", () => {
let cluster: Cluster;
@@ -34,8 +34,8 @@ describe("create clusters", () => {
di.override(kubectlDownloadingNormalizedArchInjectable, () => "amd64");
di.override(normalizedPlatformInjectable, () => "darwin");
di.override(broadcastConnectionUpdateInjectable, () => async () => {});
- di.override(createAuthorizationReviewInjectable, () => () => () => Promise.resolve(true));
- di.override(requestNamespaceListPermissionsForInjectable, () => () => async () => () => true);
+ di.override(createCanIInjectable, () => () => () => Promise.resolve(true));
+ di.override(createRequestNamespaceListPermissionsInjectable, () => () => async () => () => true);
di.override(createListNamespacesInjectable, () => () => () => Promise.resolve([ "default" ]));
di.override(prometheusHandlerInjectable, () => ({
getPrometheusDetails: jest.fn(),
diff --git a/packages/core/src/main/__test__/context-handler.test.ts b/packages/core/src/main/__test__/context-handler.test.ts
deleted file mode 100644
index 61bd12398d..0000000000
--- a/packages/core/src/main/__test__/context-handler.test.ts
+++ /dev/null
@@ -1,203 +0,0 @@
-/**
- * Copyright (c) OpenLens Authors. All rights reserved.
- * Licensed under MIT License. See LICENSE in root directory for more information.
- */
-
-import { getDiForUnitTesting } from "../getDiForUnitTesting";
-import { Cluster } from "../../common/cluster/cluster";
-import createKubeAuthProxyInjectable from "../kube-auth-proxy/create-kube-auth-proxy.injectable";
-import type { DiContainer } from "@ogre-tools/injectable";
-import { getInjectable } from "@ogre-tools/injectable";
-import type { PrometheusProvider } from "../prometheus/provider";
-import { prometheusProviderInjectionToken } from "../prometheus/provider";
-import { runInAction } from "mobx";
-import prometheusHandlerInjectable from "../cluster/prometheus-handler/prometheus-handler.injectable";
-import directoryForTempInjectable from "../../common/app-paths/directory-for-temp/directory-for-temp.injectable";
-import lensProxyPortInjectable from "../lens-proxy/lens-proxy-port.injectable";
-import type { KubeAuthProxy } from "../kube-auth-proxy/kube-auth-proxy";
-import loadProxyKubeconfigInjectable from "../cluster/load-proxy-kubeconfig.injectable";
-import type { KubeConfig } from "@kubernetes/client-node";
-
-enum ServiceResult {
- Success,
- Failure,
-}
-
-const createTestPrometheusProvider = (kind: string, alwaysFail: ServiceResult): PrometheusProvider => ({
- kind,
- name: "TestProvider1",
- isConfigurable: false,
- getQuery: () => {
- throw new Error("getQuery is not implemented.");
- },
- getPrometheusService: async () => {
- switch (alwaysFail) {
- case ServiceResult.Success:
- return {
- kind,
- namespace: "default",
- port: 7000,
- service: "",
- };
- case ServiceResult.Failure:
- throw new Error("does fail");
- }
- },
-});
-
-describe("ContextHandler", () => {
- let di: DiContainer;
- let cluster: Cluster;
-
- beforeEach(() => {
- di = getDiForUnitTesting();
-
- di.override(loadProxyKubeconfigInjectable, () => async () => ({
- makeApiClient: () => ({} as any),
- } as Partial));
-
- di.override(createKubeAuthProxyInjectable, () => () => ({
- run: async () => {},
- } as KubeAuthProxy));
- di.override(directoryForTempInjectable, () => "/some-directory-for-tmp");
- di.inject(lensProxyPortInjectable).set(9968);
-
- cluster = new Cluster({
- contextName: "some-context-name",
- id: "some-cluster-id",
- kubeConfigPath: "/some-kubeconfig-path",
- }, {
- clusterServerUrl: "https://some-website.com",
- });
- });
-
- describe("getPrometheusService", () => {
- it.each([
- [0],
- [1],
- [2],
- [3],
- ])("should throw after %d failure(s)", async (failures) => {
- runInAction(() => {
- for (let i = 0; i < failures; i += 1) {
- di.register(getInjectable({
- id: `test-prometheus-provider-failure-${i}`,
- injectionToken: prometheusProviderInjectionToken,
- instantiate: () => createTestPrometheusProvider(`id_failure_${i}`, ServiceResult.Failure),
- }));
- }
- });
-
- expect(() => di.inject(prometheusHandlerInjectable, cluster).getPrometheusDetails()).rejects.toThrowError();
- });
-
- it.each([
- [1, 0],
- [1, 1],
- [1, 2],
- [1, 3],
- [2, 0],
- [2, 1],
- [2, 2],
- [2, 3],
- ])("should pick the first provider of %d success(es) after %d failure(s)", async (successes, failures) => {
- runInAction(() => {
- for (let i = 0; i < failures; i += 1) {
- di.register(getInjectable({
- id: `test-prometheus-provider-failure-${i}`,
- injectionToken: prometheusProviderInjectionToken,
- instantiate: () => createTestPrometheusProvider(`id_failure_${i}`, ServiceResult.Failure),
- }));
- }
-
- for (let i = 0; i < successes; i += 1) {
- di.register(getInjectable({
- id: `test-prometheus-provider-success-${i}`,
- injectionToken: prometheusProviderInjectionToken,
- instantiate: () => createTestPrometheusProvider(`id_success_${i}`, ServiceResult.Success),
- }));
- }
- });
-
- const details = await di.inject(prometheusHandlerInjectable, cluster).getPrometheusDetails();
-
- expect(details.provider.kind === `id_failure_${failures}`);
- });
-
- it.each([
- [1, 0],
- [1, 1],
- [1, 2],
- [1, 3],
- [2, 0],
- [2, 1],
- [2, 2],
- [2, 3],
- ])("should pick the first provider of %d success(es) before %d failure(s)", async (successes, failures) => {
- runInAction(() => {
- for (let i = 0; i < failures; i += 1) {
- di.register(getInjectable({
- id: `test-prometheus-provider-failure-${i}`,
- injectionToken: prometheusProviderInjectionToken,
- instantiate: () => createTestPrometheusProvider(`id_failure_${i}`, ServiceResult.Failure),
- }));
- }
-
- for (let i = 0; i < successes; i += 1) {
- di.register(getInjectable({
- id: `test-prometheus-provider-success-${i}`,
- injectionToken: prometheusProviderInjectionToken,
- instantiate: () => createTestPrometheusProvider(`id_success_${i}`, ServiceResult.Success),
- }));
- }
- });
-
- const details = await di.inject(prometheusHandlerInjectable, cluster).getPrometheusDetails();
-
- expect(details.provider.kind === "id_failure_0");
- });
-
- it.each([
- [1, 0],
- [1, 1],
- [1, 2],
- [1, 3],
- [2, 0],
- [2, 1],
- [2, 2],
- [2, 3],
- ])("should pick the first provider of %d success(es) between %d failure(s)", async (successes, failures) => {
- const beforeSuccesses = Math.floor(successes / 2);
-
- runInAction(() => {
- for (let i = 0; i < beforeSuccesses; i += 1) {
- di.register(getInjectable({
- id: `test-prometheus-provider-success-${i}`,
- injectionToken: prometheusProviderInjectionToken,
- instantiate: () => createTestPrometheusProvider(`id_success_${i}`, ServiceResult.Success),
- }));
- }
-
- for (let i = 0; i < failures; i += 1) {
- di.register(getInjectable({
- id: `test-prometheus-provider-failure-${i}`,
- injectionToken: prometheusProviderInjectionToken,
- instantiate: () => createTestPrometheusProvider(`id_failure_${i}`, ServiceResult.Failure),
- }));
- }
-
- for (let i = beforeSuccesses; i < successes; i += 1) {
- di.register(getInjectable({
- id: `test-prometheus-provider-success-${i}`,
- injectionToken: prometheusProviderInjectionToken,
- instantiate: () => createTestPrometheusProvider(`id_success_${i}`, ServiceResult.Success),
- }));
- }
- });
-
- const details = await di.inject(prometheusHandlerInjectable, cluster).getPrometheusDetails();
-
- expect(details.provider.kind === "id_success_0");
- });
- });
-});
diff --git a/packages/core/src/main/__test__/kube-auth-proxy.test.ts b/packages/core/src/main/__test__/kube-auth-proxy.test.ts
index 8fa8a175a5..dc4878f806 100644
--- a/packages/core/src/main/__test__/kube-auth-proxy.test.ts
+++ b/packages/core/src/main/__test__/kube-auth-proxy.test.ts
@@ -5,7 +5,6 @@
import waitUntilPortIsUsedInjectable from "../kube-auth-proxy/wait-until-port-is-used/wait-until-port-is-used.injectable";
import { Cluster } from "../../common/cluster/cluster";
-import type { KubeAuthProxy } from "../kube-auth-proxy/kube-auth-proxy";
import type { ChildProcess } from "child_process";
import { Kubectl } from "../kubectl/kubectl";
import type { DeepMockProxy } from "jest-mock-extended";
@@ -13,6 +12,7 @@ import { mockDeep, mock } from "jest-mock-extended";
import type { Readable } from "stream";
import { EventEmitter } from "stream";
import { getDiForUnitTesting } from "../getDiForUnitTesting";
+import type { CreateKubeAuthProxy, KubeAuthProxy } from "../kube-auth-proxy/create-kube-auth-proxy.injectable";
import createKubeAuthProxyInjectable from "../kube-auth-proxy/create-kube-auth-proxy.injectable";
import spawnInjectable from "../child-process/spawn.injectable";
import directoryForUserDataInjectable from "../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
@@ -29,7 +29,7 @@ import getBasenameOfPathInjectable from "../../common/path/get-basename.injectab
const clusterServerUrl = "https://192.168.64.3:8443";
describe("kube auth proxy tests", () => {
- let createKubeAuthProxy: (cluster: Cluster, environmentVariables: NodeJS.ProcessEnv) => KubeAuthProxy;
+ let createKubeAuthProxy: CreateKubeAuthProxy;
let spawnMock: jest.Mock;
let waitUntilPortIsUsedMock: jest.Mock;
let broadcastMessageMock: jest.Mock;
diff --git a/packages/core/src/main/__test__/prometheus-handler.test.ts b/packages/core/src/main/__test__/prometheus-handler.test.ts
index 59671553bb..74cab1ea74 100644
--- a/packages/core/src/main/__test__/prometheus-handler.test.ts
+++ b/packages/core/src/main/__test__/prometheus-handler.test.ts
@@ -43,7 +43,7 @@ const createTestPrometheusProvider = (kind: string, alwaysFail: ServiceResult):
},
});
-describe("ContextHandler", () => {
+describe("PrometheusHandler", () => {
let di: DiContainer;
let cluster: Cluster;
diff --git a/packages/core/src/main/app-paths/app-paths-request-channel-listener.injectable.ts b/packages/core/src/main/app-paths/app-paths-request-channel-listener.injectable.ts
index 568d63f1ea..ccf8be5054 100644
--- a/packages/core/src/main/app-paths/app-paths-request-channel-listener.injectable.ts
+++ b/packages/core/src/main/app-paths/app-paths-request-channel-listener.injectable.ts
@@ -4,11 +4,12 @@
*/
import { appPathsChannel } from "../../common/app-paths/app-paths-channel";
import appPathsInjectable from "../../common/app-paths/app-paths.injectable";
-import { getRequestChannelListenerInjectable } from "../utils/channel/channel-listeners/listener-tokens";
+import { getRequestChannelListenerInjectable } from "@k8slens/messaging";
const appPathsRequestChannelListenerInjectable = getRequestChannelListenerInjectable({
+ id: "app-paths-request-channel-listener",
channel: appPathsChannel,
- handler: (di) => {
+ getHandler: (di) => {
const appPaths = di.inject(appPathsInjectable);
return () => appPaths;
diff --git a/packages/core/src/main/app-paths/setup-app-paths.injectable.ts b/packages/core/src/main/app-paths/setup-app-paths.injectable.ts
index 34178547c3..255beffae0 100644
--- a/packages/core/src/main/app-paths/setup-app-paths.injectable.ts
+++ b/packages/core/src/main/app-paths/setup-app-paths.injectable.ts
@@ -34,6 +34,7 @@ const setupAppPathsInjectable = getInjectable({
const appDataPath = getElectronAppPath("appData");
setElectronAppPath("userData", joinPaths(appDataPath, appName));
+ setElectronAppPath("sessionData", getElectronAppPath("userData"));
const appPaths = pipeline(
pathNames,
diff --git a/packages/core/src/main/build-version/setup-channel.injectable.ts b/packages/core/src/main/build-version/setup-channel.injectable.ts
index 05da92db6e..88661c899f 100644
--- a/packages/core/src/main/build-version/setup-channel.injectable.ts
+++ b/packages/core/src/main/build-version/setup-channel.injectable.ts
@@ -3,12 +3,13 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { buildVersionChannel } from "../../common/vars/build-semantic-version.injectable";
-import { getRequestChannelListenerInjectable } from "../utils/channel/channel-listeners/listener-tokens";
+import { getRequestChannelListenerInjectable } from "@k8slens/messaging";
import buildVersionInjectable from "../vars/build-version/build-version.injectable";
const buildVersionChannelListenerInjectable = getRequestChannelListenerInjectable({
+ id: "build-version-channel-listener",
channel: buildVersionChannel,
- handler: (di) => {
+ getHandler: (di) => {
const buildVersion = di.inject(buildVersionInjectable);
return () => buildVersion.get();
diff --git a/packages/core/src/main/catalog-sync-to-renderer/catalog-sync-to-renderer.injectable.ts b/packages/core/src/main/catalog-sync-to-renderer/catalog-sync-to-renderer.injectable.ts
index cd77332185..a2fe077c1d 100644
--- a/packages/core/src/main/catalog-sync-to-renderer/catalog-sync-to-renderer.injectable.ts
+++ b/packages/core/src/main/catalog-sync-to-renderer/catalog-sync-to-renderer.injectable.ts
@@ -7,7 +7,7 @@ import { reaction } from "mobx";
import ipcMainInjectionToken from "../../common/ipc/ipc-main-injection-token";
import { catalogInitChannel } from "../../common/ipc/catalog";
import { disposer } from "@k8slens/utilities";
-import { getStartableStoppable } from "../../common/utils/get-startable-stoppable";
+import { getStartableStoppable } from "@k8slens/startable-stoppable";
import catalogEntityRegistryInjectable from "../catalog/entity-registry.injectable";
import catalogSyncBroadcasterInjectable from "./broadcaster.injectable";
import { toJS } from "../../common/utils";
diff --git a/packages/core/src/main/cluster/request-api-versions.ts b/packages/core/src/main/cluster/api-versions-requester.ts
similarity index 64%
rename from packages/core/src/main/cluster/request-api-versions.ts
rename to packages/core/src/main/cluster/api-versions-requester.ts
index a9b5074549..0bb2c65f6c 100644
--- a/packages/core/src/main/cluster/request-api-versions.ts
+++ b/packages/core/src/main/cluster/api-versions-requester.ts
@@ -15,8 +15,11 @@ export interface ClusterData {
readonly id: string;
}
-export type RequestApiVersions = (cluster: ClusterData) => AsyncResult;
+export interface ApiVersionsRequester {
+ request(cluster: ClusterData): AsyncResult;
+ readonly orderNumber: number;
+}
-export const requestApiVersionsInjectionToken = getInjectionToken({
+export const apiVersionsRequesterInjectionToken = getInjectionToken({
id: "request-api-versions-token",
});
diff --git a/packages/core/src/main/cluster/cluster-connection.injectable.ts b/packages/core/src/main/cluster/cluster-connection.injectable.ts
index c5d9a5f165..3f40898fc7 100644
--- a/packages/core/src/main/cluster/cluster-connection.injectable.ts
+++ b/packages/core/src/main/cluster/cluster-connection.injectable.ts
@@ -6,10 +6,7 @@
import { type KubeConfig, HttpError } from "@kubernetes/client-node";
import { reaction, comparer, runInAction } from "mobx";
import { ClusterStatus } from "../../common/cluster-types";
-import type { CreateAuthorizationReview } from "../../common/cluster/authorization-review.injectable";
-import type { Cluster } from "../../common/cluster/cluster";
import type { CreateListNamespaces } from "../../common/cluster/list-namespaces.injectable";
-import type { RequestNamespaceListPermissionsFor, RequestNamespaceListPermissions } from "../../common/cluster/request-namespace-list-permissions.injectable";
import type { BroadcastMessage } from "../../common/ipc/broadcast-message.injectable";
import { clusterListNamespaceForbiddenChannel } from "../../common/ipc/cluster";
import type { Logger } from "../../common/logger";
@@ -25,7 +22,6 @@ import type { RequestApiResources } from "./request-api-resources.injectable";
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
import broadcastConnectionUpdateInjectable from "./broadcast-connection-update.injectable";
import broadcastMessageInjectable from "../../common/ipc/broadcast-message.injectable";
-import createAuthorizationReviewInjectable from "../../common/cluster/authorization-review.injectable";
import createListNamespacesInjectable from "../../common/cluster/list-namespaces.injectable";
import kubeAuthProxyServerInjectable from "./kube-auth-proxy-server.injectable";
import loadProxyKubeconfigInjectable from "./load-proxy-kubeconfig.injectable";
@@ -33,21 +29,31 @@ import loggerInjectable from "../../common/logger.injectable";
import prometheusHandlerInjectable from "./prometheus-handler/prometheus-handler.injectable";
import removeProxyKubeconfigInjectable from "./remove-proxy-kubeconfig.injectable";
import requestApiResourcesInjectable from "./request-api-resources.injectable";
-import requestNamespaceListPermissionsForInjectable from "../../common/cluster/request-namespace-list-permissions.injectable";
import type { DetectClusterMetadata } from "../cluster-detectors/detect-cluster-metadata.injectable";
import type { FallibleOnlyClusterMetadataDetector } from "../cluster-detectors/token";
import clusterVersionDetectorInjectable from "../cluster-detectors/cluster-version-detector.injectable";
import detectClusterMetadataInjectable from "../cluster-detectors/detect-cluster-metadata.injectable";
import { replaceObservableObject } from "../../common/utils/replace-observable-object";
+import type { CreateAuthorizationApi } from "../../common/cluster/create-authorization-api.injectable";
+import type { CreateCanI } from "../../common/cluster/create-can-i.injectable";
+import type { CreateRequestNamespaceListPermissions, RequestNamespaceListPermissions } from "../../common/cluster/create-request-namespace-list-permissions.injectable";
+import type { Cluster } from "../../common/cluster/cluster";
+import createAuthorizationApiInjectable from "../../common/cluster/create-authorization-api.injectable";
+import createCanIInjectable from "../../common/cluster/create-can-i.injectable";
+import createRequestNamespaceListPermissionsInjectable from "../../common/cluster/create-request-namespace-list-permissions.injectable";
+import type { CreateCoreApi } from "../../common/cluster/create-core-api.injectable";
+import createCoreApiInjectable from "../../common/cluster/create-core-api.injectable";
interface Dependencies {
readonly logger: Logger;
readonly prometheusHandler: ClusterPrometheusHandler;
readonly kubeAuthProxyServer: KubeAuthProxyServer;
readonly clusterVersionDetector: FallibleOnlyClusterMetadataDetector;
- createAuthorizationReview: CreateAuthorizationReview;
+ createCanI: CreateCanI;
requestApiResources: RequestApiResources;
- requestNamespaceListPermissionsFor: RequestNamespaceListPermissionsFor;
+ createRequestNamespaceListPermissions: CreateRequestNamespaceListPermissions;
+ createAuthorizationApi: CreateAuthorizationApi;
+ createCoreApi: CreateCoreApi;
createListNamespaces: CreateListNamespaces;
detectClusterMetadata: DetectClusterMetadata;
broadcastMessage: BroadcastMessage;
@@ -224,8 +230,9 @@ class ClusterConnection {
private async refreshAccessibility(): Promise {
this.dependencies.logger.info(`[CLUSTER]: refreshAccessibility`, this.cluster.getMeta());
const proxyConfig = await this.dependencies.loadProxyKubeconfig();
- const canI = this.dependencies.createAuthorizationReview(proxyConfig);
- const requestNamespaceListPermissions = this.dependencies.requestNamespaceListPermissionsFor(proxyConfig);
+ const api = this.dependencies.createAuthorizationApi(proxyConfig);
+ const canI = this.dependencies.createCanI(api);
+ const requestNamespaceListPermissions = this.dependencies.createRequestNamespaceListPermissions(api);
const isAdmin = await canI({
namespace: "kube-system",
@@ -360,7 +367,8 @@ class ClusterConnection {
}
try {
- const listNamespaces = this.dependencies.createListNamespaces(proxyConfig);
+ const api = this.dependencies.createCoreApi(proxyConfig);
+ const listNamespaces = this.dependencies.createListNamespaces(api);
return await listNamespaces();
} catch (error) {
@@ -403,13 +411,15 @@ const clusterConnectionInjectable = getInjectable({
prometheusHandler: di.inject(prometheusHandlerInjectable, cluster),
broadcastConnectionUpdate: di.inject(broadcastConnectionUpdateInjectable, cluster),
broadcastMessage: di.inject(broadcastMessageInjectable),
- createAuthorizationReview: di.inject(createAuthorizationReviewInjectable),
createListNamespaces: di.inject(createListNamespacesInjectable),
detectClusterMetadata: di.inject(detectClusterMetadataInjectable),
loadProxyKubeconfig: di.inject(loadProxyKubeconfigInjectable, cluster),
removeProxyKubeconfig: di.inject(removeProxyKubeconfigInjectable, cluster),
requestApiResources: di.inject(requestApiResourcesInjectable),
- requestNamespaceListPermissionsFor: di.inject(requestNamespaceListPermissionsForInjectable),
+ createAuthorizationApi: di.inject(createAuthorizationApiInjectable),
+ createCoreApi: di.inject(createCoreApiInjectable),
+ createCanI: di.inject(createCanIInjectable),
+ createRequestNamespaceListPermissions: di.inject(createRequestNamespaceListPermissionsInjectable),
},
cluster,
),
diff --git a/packages/core/src/main/cluster/kube-auth-proxy-server.injectable.ts b/packages/core/src/main/cluster/kube-auth-proxy-server.injectable.ts
index 9942c40168..ff70af3a7b 100644
--- a/packages/core/src/main/cluster/kube-auth-proxy-server.injectable.ts
+++ b/packages/core/src/main/cluster/kube-auth-proxy-server.injectable.ts
@@ -8,7 +8,7 @@ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
import type { Cluster } from "../../common/cluster/cluster";
import createKubeAuthProxyInjectable from "../kube-auth-proxy/create-kube-auth-proxy.injectable";
import kubeAuthProxyCertificateInjectable from "../kube-auth-proxy/kube-auth-proxy-certificate.injectable";
-import type { KubeAuthProxy } from "../kube-auth-proxy/kube-auth-proxy";
+import type { KubeAuthProxy } from "../kube-auth-proxy/create-kube-auth-proxy.injectable";
export interface KubeAuthProxyServer {
getApiTarget(isLongRunningRequest?: boolean): Promise;
diff --git a/packages/core/src/main/cluster/request-api-resources.injectable.ts b/packages/core/src/main/cluster/request-api-resources.injectable.ts
index d6a21e3ce4..14776bb93a 100644
--- a/packages/core/src/main/cluster/request-api-resources.injectable.ts
+++ b/packages/core/src/main/cluster/request-api-resources.injectable.ts
@@ -7,11 +7,12 @@ import { getInjectable } from "@ogre-tools/injectable";
import loggerInjectable from "../../common/logger.injectable";
import type { KubeApiResource } from "../../common/rbac";
import type { Cluster } from "../../common/cluster/cluster";
-import { requestApiVersionsInjectionToken } from "./request-api-versions";
+import { apiVersionsRequesterInjectionToken } from "./api-versions-requester";
import { backoffCaller, withConcurrencyLimit } from "@k8slens/utilities";
import requestKubeApiResourcesForInjectable from "./request-kube-api-resources-for.injectable";
import type { AsyncResult } from "@k8slens/utilities";
import broadcastConnectionUpdateInjectable from "./broadcast-connection-update.injectable";
+import { byOrderNumber } from "../../common/utils/composable-responsibilities/orderable/orderable";
export type RequestApiResources = (cluster: Cluster) => AsyncResult;
@@ -24,7 +25,8 @@ const requestApiResourcesInjectable = getInjectable({
id: "request-api-resources",
instantiate: (di): RequestApiResources => {
const logger = di.inject(loggerInjectable);
- const apiVersionRequesters = di.injectMany(requestApiVersionsInjectionToken);
+ const apiVersionRequesters = di.injectMany(apiVersionsRequesterInjectionToken)
+ .sort(byOrderNumber);
const requestKubeApiResourcesFor = di.inject(requestKubeApiResourcesForInjectable);
return async (...args) => {
@@ -35,7 +37,7 @@ const requestApiResourcesInjectable = getInjectable({
const groupLists: KubeResourceListGroup[] = [];
for (const apiVersionRequester of apiVersionRequesters) {
- const result = await backoffCaller(() => apiVersionRequester(cluster), {
+ const result = await backoffCaller(() => apiVersionRequester.request(cluster), {
onIntermediateError: (error, attempt) => {
broadcastConnectionUpdate({
message: `Failed to list kube API resource kinds, attempt ${attempt}: ${error}`,
diff --git a/packages/core/src/main/cluster/request-core-api-versions.injectable.ts b/packages/core/src/main/cluster/request-core-api-versions.injectable.ts
index b709eb9356..5b059d6f7f 100644
--- a/packages/core/src/main/cluster/request-core-api-versions.injectable.ts
+++ b/packages/core/src/main/cluster/request-core-api-versions.injectable.ts
@@ -5,33 +5,36 @@
import type { V1APIVersions } from "@kubernetes/client-node";
import { getInjectable } from "@ogre-tools/injectable";
import k8sRequestInjectable from "../k8s-request.injectable";
-import { requestApiVersionsInjectionToken } from "./request-api-versions";
+import { apiVersionsRequesterInjectionToken } from "./api-versions-requester";
const requestCoreApiVersionsInjectable = getInjectable({
id: "request-core-api-versions",
instantiate: (di) => {
const k8sRequest = di.inject(k8sRequestInjectable);
- return async (cluster) => {
- try {
- const { versions } = await k8sRequest(cluster, "/api") as V1APIVersions;
+ return {
+ request: async (cluster) => {
+ try {
+ const { versions } = await k8sRequest(cluster, "/api") as V1APIVersions;
- return {
- callWasSuccessful: true,
- response: versions.map(version => ({
- group: "",
- path: `/api/${version}`,
- })),
- };
- } catch (error) {
- return {
- callWasSuccessful: false,
- error: error as Error,
- };
- }
+ return {
+ callWasSuccessful: true,
+ response: versions.map(version => ({
+ group: "",
+ path: `/api/${version}`,
+ })),
+ };
+ } catch (error) {
+ return {
+ callWasSuccessful: false,
+ error: error as Error,
+ };
+ }
+ },
+ orderNumber: 10,
};
},
- injectionToken: requestApiVersionsInjectionToken,
+ injectionToken: apiVersionsRequesterInjectionToken,
});
export default requestCoreApiVersionsInjectable;
diff --git a/packages/core/src/main/cluster/request-kube-api-resources-for.injectable.ts b/packages/core/src/main/cluster/request-kube-api-resources-for.injectable.ts
index 65e326eed7..80720a9ef1 100644
--- a/packages/core/src/main/cluster/request-kube-api-resources-for.injectable.ts
+++ b/packages/core/src/main/cluster/request-kube-api-resources-for.injectable.ts
@@ -8,7 +8,7 @@ import type { Cluster } from "../../common/cluster/cluster";
import type { KubeApiResource } from "../../common/rbac";
import type { AsyncResult } from "@k8slens/utilities";
import k8sRequestInjectable from "../k8s-request.injectable";
-import type { KubeResourceListGroup } from "./request-api-versions";
+import type { KubeResourceListGroup } from "./api-versions-requester";
export type RequestKubeApiResources = (grouping: KubeResourceListGroup) => AsyncResult;
diff --git a/packages/core/src/main/cluster/request-non-core-api-versions.injectable.ts b/packages/core/src/main/cluster/request-non-core-api-versions.injectable.ts
index 84e62f6b80..7e5abbc44d 100644
--- a/packages/core/src/main/cluster/request-non-core-api-versions.injectable.ts
+++ b/packages/core/src/main/cluster/request-non-core-api-versions.injectable.ts
@@ -6,35 +6,40 @@ import type { V1APIGroupList } from "@kubernetes/client-node";
import { getInjectable } from "@ogre-tools/injectable";
import { iter } from "@k8slens/utilities";
import k8sRequestInjectable from "../k8s-request.injectable";
-import { requestApiVersionsInjectionToken } from "./request-api-versions";
+import { apiVersionsRequesterInjectionToken } from "./api-versions-requester";
const requestNonCoreApiVersionsInjectable = getInjectable({
id: "request-non-core-api-versions",
instantiate: (di) => {
const k8sRequest = di.inject(k8sRequestInjectable);
- return async (cluster) => {
- try {
- const { groups } = await k8sRequest(cluster, "/apis") as V1APIGroupList;
+ return {
+ request: async (cluster) => {
+ try {
+ const { groups } = (await k8sRequest(cluster, "/apis")) as V1APIGroupList;
- return {
- callWasSuccessful: true,
- response: iter.chain(groups.values())
- .flatMap(group => group.versions.map(version => ({
- group: group.name,
- path: `/apis/${version.groupVersion}`,
- })))
- .collect(v => [...v]),
- };
- } catch (error) {
- return {
- callWasSuccessful: false,
- error: error as Error,
- };
- }
+ return {
+ callWasSuccessful: true,
+ response: iter.chain(groups.values())
+ .flatMap((group) =>
+ group.versions.map((version) => ({
+ group: group.name,
+ path: `/apis/${version.groupVersion}`,
+ })),
+ )
+ .collect((v) => [...v]),
+ };
+ } catch (error) {
+ return {
+ callWasSuccessful: false,
+ error: error as Error,
+ };
+ }
+ },
+ orderNumber: 20,
};
},
- injectionToken: requestApiVersionsInjectionToken,
+ injectionToken: apiVersionsRequesterInjectionToken,
});
export default requestNonCoreApiVersionsInjectable;
diff --git a/packages/core/src/main/cluster/request-non-core-api-versions.test.ts b/packages/core/src/main/cluster/request-non-core-api-versions.test.ts
index c38359b6a5..ca4dcd01b7 100644
--- a/packages/core/src/main/cluster/request-non-core-api-versions.test.ts
+++ b/packages/core/src/main/cluster/request-non-core-api-versions.test.ts
@@ -10,13 +10,13 @@ import type { DiContainer } from "@ogre-tools/injectable";
import { getDiForUnitTesting } from "../getDiForUnitTesting";
import type { K8sRequest } from "../k8s-request.injectable";
import k8sRequestInjectable from "../k8s-request.injectable";
-import type { RequestApiVersions } from "./request-api-versions";
+import type { ApiVersionsRequester } from "./api-versions-requester";
import requestNonCoreApiVersionsInjectable from "./request-non-core-api-versions.injectable";
describe("requestNonCoreApiVersions", () => {
let di: DiContainer;
let k8sRequestMock: AsyncFnMock;
- let requestNonCoreApiVersions: RequestApiVersions;
+ let requestNonCoreApiVersions: ApiVersionsRequester;
beforeEach(() => {
di = getDiForUnitTesting();
@@ -28,10 +28,10 @@ describe("requestNonCoreApiVersions", () => {
});
describe("when called", () => {
- let versionsRequest: ReturnType;
+ let versionsRequest: ReturnType;
beforeEach(() => {
- versionsRequest = requestNonCoreApiVersions({ id: "some-cluster-id" });
+ versionsRequest = requestNonCoreApiVersions.request({ id: "some-cluster-id" });
});
it("should request all api groups", () => {
diff --git a/packages/core/src/main/cluster/visibility-handler.injectable.ts b/packages/core/src/main/cluster/visibility-handler.injectable.ts
index 31f6ff13ec..ef4277e905 100644
--- a/packages/core/src/main/cluster/visibility-handler.injectable.ts
+++ b/packages/core/src/main/cluster/visibility-handler.injectable.ts
@@ -3,13 +3,13 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { clusterVisibilityChannel } from "../../common/cluster/visibility-channel";
-import { getMessageChannelListenerInjectable } from "../../common/utils/channel/message-channel-listener-injection-token";
+import { getMessageChannelListenerInjectable } from "@k8slens/messaging";
import visibleClusterInjectable from "./visible-cluster.injectable";
const clusterVisibilityHandlerInjectable = getMessageChannelListenerInjectable({
channel: clusterVisibilityChannel,
id: "base",
- handler: (di) => {
+ getHandler: (di) => {
const visibleCluster = di.inject(visibleClusterInjectable);
return (clusterId) => visibleCluster.set(clusterId);
diff --git a/packages/core/src/main/electron-app/features/sync-theme-from-operating-system.injectable.ts b/packages/core/src/main/electron-app/features/sync-theme-from-operating-system.injectable.ts
index 818bf938ec..02f0c916b6 100644
--- a/packages/core/src/main/electron-app/features/sync-theme-from-operating-system.injectable.ts
+++ b/packages/core/src/main/electron-app/features/sync-theme-from-operating-system.injectable.ts
@@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
-import { getStartableStoppable } from "../../../common/utils/get-startable-stoppable";
+import { getStartableStoppable } from "@k8slens/startable-stoppable";
import operatingSystemThemeStateInjectable from "../../theme/operating-system-theme-state.injectable";
import nativeThemeInjectable from "./native-theme.injectable";
import getElectronThemeInjectable from "./get-electron-theme.injectable";
diff --git a/packages/core/src/main/getDiForUnitTesting.ts b/packages/core/src/main/getDiForUnitTesting.ts
index b71ab53239..b374eec1ca 100644
--- a/packages/core/src/main/getDiForUnitTesting.ts
+++ b/packages/core/src/main/getDiForUnitTesting.ts
@@ -22,7 +22,6 @@ import electronQuitAndInstallUpdateInjectable from "./electron-app/features/elec
import electronUpdaterIsActiveInjectable from "./electron-app/features/electron-updater-is-active.injectable";
import setUpdateOnQuitInjectable from "./electron-app/features/set-update-on-quit.injectable";
import waitUntilBundledExtensionsAreLoadedInjectable from "./start-main-application/lens-window/application-window/wait-until-bundled-extensions-are-loaded.injectable";
-import electronInjectable from "./utils/resolve-system-proxy/electron.injectable";
import initializeClusterManagerInjectable from "./cluster/initialize-manager.injectable";
import type { GlobalOverride } from "@k8slens/test-utils";
import { getOverrideFsWithFakes } from "../test-utils/override-fs-with-fakes";
@@ -30,6 +29,8 @@ import {
setLegacyGlobalDiForExtensionApi,
} from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx";
+import { registerFeature } from "@k8slens/feature-core";
+import { messagingFeature, testUtils as messagingTestUtils } from "@k8slens/messaging";
export function getDiForUnitTesting() {
const di = createContainer("main");
@@ -37,6 +38,11 @@ export function getDiForUnitTesting() {
registerMobX(di);
setLegacyGlobalDiForExtensionApi(di, "main");
+ runInAction(() => {
+ registerFeature(di, messagingFeature, messagingTestUtils.messagingFeatureForUnitTesting);
+
+ });
+
di.preventSideEffects();
runInAction(() => {
@@ -56,7 +62,6 @@ export function getDiForUnitTesting() {
di.override(globalOverride.injectable, globalOverride.overridingInstantiate);
}
- di.override(electronInjectable, () => ({}));
di.override(waitUntilBundledExtensionsAreLoadedInjectable, () => async () => {});
overrideRunnablesHavingSideEffects(di);
diff --git a/packages/core/src/main/helm/repositories/add-helm-repository/add-helm-repository-channel-listener.injectable.ts b/packages/core/src/main/helm/repositories/add-helm-repository/add-helm-repository-channel-listener.injectable.ts
index 1c68bf6fd7..d5343b1d4f 100644
--- a/packages/core/src/main/helm/repositories/add-helm-repository/add-helm-repository-channel-listener.injectable.ts
+++ b/packages/core/src/main/helm/repositories/add-helm-repository/add-helm-repository-channel-listener.injectable.ts
@@ -3,12 +3,14 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { addHelmRepositoryChannel } from "../../../../common/helm/add-helm-repository-channel";
-import { getRequestChannelListenerInjectable } from "../../../utils/channel/channel-listeners/listener-tokens";
+import { getRequestChannelListenerInjectable } from "@k8slens/messaging";
import addHelmRepositoryInjectable from "./add-helm-repository.injectable";
-const addHelmRepositoryChannelListenerInjectable = getRequestChannelListenerInjectable({
- channel: addHelmRepositoryChannel,
- handler: (di) => di.inject(addHelmRepositoryInjectable),
-});
+const addHelmRepositoryChannelListenerInjectable =
+ getRequestChannelListenerInjectable({
+ id: "add-helm-repository-channel-listener",
+ channel: addHelmRepositoryChannel,
+ getHandler: (di) => di.inject(addHelmRepositoryInjectable),
+ });
export default addHelmRepositoryChannelListenerInjectable;
diff --git a/packages/core/src/main/helm/repositories/add-helm-repository/add-helm-repository.injectable.ts b/packages/core/src/main/helm/repositories/add-helm-repository/add-helm-repository.injectable.ts
index 5292f8a662..27272a76f3 100644
--- a/packages/core/src/main/helm/repositories/add-helm-repository/add-helm-repository.injectable.ts
+++ b/packages/core/src/main/helm/repositories/add-helm-repository/add-helm-repository.injectable.ts
@@ -5,17 +5,16 @@
import { getInjectable } from "@ogre-tools/injectable";
import execHelmInjectable from "../../exec-helm/exec-helm.injectable";
import loggerInjectable from "../../../../common/logger.injectable";
-import type { AddHelmRepositoryChannel } from "../../../../common/helm/add-helm-repository-channel";
-import type { RequestChannelHandler } from "../../../utils/channel/channel-listeners/listener-tokens";
+import type { HelmRepo } from "../../../../common/helm/helm-repo";
const addHelmRepositoryInjectable = getInjectable({
id: "add-helm-repository",
- instantiate: (di): RequestChannelHandler => {
+ instantiate: (di) => {
const execHelm = di.inject(execHelmInjectable);
const logger = di.inject(loggerInjectable);
- return async (repo) => {
+ return async (repo: HelmRepo) => {
const {
name,
url,
@@ -59,12 +58,12 @@ const addHelmRepositoryInjectable = getInjectable({
if (result.callWasSuccessful) {
return {
- callWasSuccessful: true,
+ callWasSuccessful: true as const,
};
}
return {
- callWasSuccessful: false,
+ callWasSuccessful: false as const,
error: result.error.stderr || result.error.message,
};
};
diff --git a/packages/core/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories-channel-listener.injectable.ts b/packages/core/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories-channel-listener.injectable.ts
index 5ef0f2b5a4..a3cd9f2529 100644
--- a/packages/core/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories-channel-listener.injectable.ts
+++ b/packages/core/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories-channel-listener.injectable.ts
@@ -3,12 +3,13 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getActiveHelmRepositoriesChannel } from "../../../../common/helm/get-active-helm-repositories-channel";
-import { getRequestChannelListenerInjectable } from "../../../utils/channel/channel-listeners/listener-tokens";
+import { getRequestChannelListenerInjectable } from "@k8slens/messaging";
import getActiveHelmRepositoriesInjectable from "./get-active-helm-repositories.injectable";
const getActiveHelmRepositoriesChannelListenerInjectable = getRequestChannelListenerInjectable({
+ id: "get-active-helm-repositories-channel-listener",
channel: getActiveHelmRepositoriesChannel,
- handler: (di) => di.inject(getActiveHelmRepositoriesInjectable),
+ getHandler: (di) => di.inject(getActiveHelmRepositoriesInjectable),
});
export default getActiveHelmRepositoriesChannelListenerInjectable;
diff --git a/packages/core/src/main/helm/repositories/remove-helm-repository/remove-helm-repository-channel-listener.injectable.ts b/packages/core/src/main/helm/repositories/remove-helm-repository/remove-helm-repository-channel-listener.injectable.ts
index 8a4e04b87c..84b147fed1 100644
--- a/packages/core/src/main/helm/repositories/remove-helm-repository/remove-helm-repository-channel-listener.injectable.ts
+++ b/packages/core/src/main/helm/repositories/remove-helm-repository/remove-helm-repository-channel-listener.injectable.ts
@@ -4,11 +4,12 @@
*/
import removeHelmRepositoryInjectable from "./remove-helm-repository.injectable";
import { removeHelmRepositoryChannel } from "../../../../common/helm/remove-helm-repository-channel";
-import { getRequestChannelListenerInjectable } from "../../../utils/channel/channel-listeners/listener-tokens";
+import { getRequestChannelListenerInjectable } from "@k8slens/messaging";
const removeHelmRepositoryChannelListenerInjectable = getRequestChannelListenerInjectable({
+ id: "remove-helm-repository-channel-listener",
channel: removeHelmRepositoryChannel,
- handler: (di) => di.inject(removeHelmRepositoryInjectable),
+ getHandler: (di) => di.inject(removeHelmRepositoryInjectable),
});
export default removeHelmRepositoryChannelListenerInjectable;
diff --git a/packages/core/src/main/ipc/ask-user-for-file-paths.injectable.ts b/packages/core/src/main/ipc/ask-user-for-file-paths.injectable.ts
index f8a0685d7c..3d0326711e 100644
--- a/packages/core/src/main/ipc/ask-user-for-file-paths.injectable.ts
+++ b/packages/core/src/main/ipc/ask-user-for-file-paths.injectable.ts
@@ -5,7 +5,7 @@
import { getInjectable } from "@ogre-tools/injectable";
import showApplicationWindowInjectable from "../start-main-application/lens-window/show-application-window.injectable";
-import type { RequestChannelHandler } from "../utils/channel/channel-listeners/listener-tokens";
+import type { RequestChannelHandler } from "@k8slens/messaging";
import type { openPathPickingDialogChannel } from "../../features/path-picking-dialog/common/channel";
import showOpenDialogInjectable from "../electron-app/features/show-open-dialog.injectable";
diff --git a/packages/core/src/main/k8s-request.injectable.ts b/packages/core/src/main/k8s-request.injectable.ts
index 70ca3c3b6e..efa9df1fe7 100644
--- a/packages/core/src/main/k8s-request.injectable.ts
+++ b/packages/core/src/main/k8s-request.injectable.ts
@@ -34,8 +34,8 @@ const k8sRequestInjectable = getInjectable({
) => {
const controller = timeout ? withTimeout(timeout) : undefined;
- if (controller) {
- signal?.addEventListener("abort", () => controller.abort());
+ if (controller && signal) {
+ signal.addEventListener("abort", () => controller.abort());
}
const response = await lensFetch(`/${cluster.id}${pathnameAndQuery}`, {
diff --git a/packages/core/src/main/kube-auth-proxy/create-kube-auth-proxy.injectable.ts b/packages/core/src/main/kube-auth-proxy/create-kube-auth-proxy.injectable.ts
index 56260347bf..fd4acf0d7a 100644
--- a/packages/core/src/main/kube-auth-proxy/create-kube-auth-proxy.injectable.ts
+++ b/packages/core/src/main/kube-auth-proxy/create-kube-auth-proxy.injectable.ts
@@ -4,7 +4,7 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { KubeAuthProxyDependencies } from "./kube-auth-proxy";
-import { KubeAuthProxy } from "./kube-auth-proxy";
+import { KubeAuthProxyImpl } from "./kube-auth-proxy";
import type { Cluster } from "../../common/cluster/cluster";
import spawnInjectable from "../child-process/spawn.injectable";
import kubeAuthProxyCertificateInjectable from "./kube-auth-proxy-certificate.injectable";
@@ -15,6 +15,13 @@ import getPortFromStreamInjectable from "../utils/get-port-from-stream.injectabl
import getDirnameOfPathInjectable from "../../common/path/get-dirname.injectable";
import broadcastConnectionUpdateInjectable from "../cluster/broadcast-connection-update.injectable";
+export interface KubeAuthProxy {
+ readonly apiPrefix: string;
+ readonly port: number;
+ run: () => Promise;
+ exit: () => void;
+}
+
export type CreateKubeAuthProxy = (cluster: Cluster, env: NodeJS.ProcessEnv) => KubeAuthProxy;
const createKubeAuthProxyInjectable = getInjectable({
@@ -33,7 +40,7 @@ const createKubeAuthProxyInjectable = getInjectable({
return (cluster, env) => {
const clusterUrl = new URL(cluster.apiUrl.get());
- return new KubeAuthProxy({
+ return new KubeAuthProxyImpl({
...dependencies,
proxyCert: di.inject(kubeAuthProxyCertificateInjectable, clusterUrl.hostname),
broadcastConnectionUpdate: di.inject(broadcastConnectionUpdateInjectable, cluster),
diff --git a/packages/core/src/main/kube-auth-proxy/kube-auth-proxy.ts b/packages/core/src/main/kube-auth-proxy/kube-auth-proxy.ts
index 9a9b5a249f..160566c3a5 100644
--- a/packages/core/src/main/kube-auth-proxy/kube-auth-proxy.ts
+++ b/packages/core/src/main/kube-auth-proxy/kube-auth-proxy.ts
@@ -16,6 +16,7 @@ import type { Logger } from "../../common/logger";
import type { WaitUntilPortIsUsed } from "./wait-until-port-is-used/wait-until-port-is-used.injectable";
import type { GetDirnameOfPath } from "../../common/path/get-dirname.injectable";
import type { BroadcastConnectionUpdate } from "../cluster/broadcast-connection-update.injectable";
+import type { KubeAuthProxy } from "./create-kube-auth-proxy.injectable";
const startingServeMatcher = "starting to serve on (?.+)";
const startingServeRegex = Object.assign(TypedRegEx(startingServeMatcher, "i"), {
@@ -33,7 +34,7 @@ export interface KubeAuthProxyDependencies {
broadcastConnectionUpdate: BroadcastConnectionUpdate;
}
-export class KubeAuthProxy {
+export class KubeAuthProxyImpl implements KubeAuthProxy {
public readonly apiPrefix = `/${randomBytes(8).toString("hex")}`;
public get port(): number {
diff --git a/packages/core/src/main/kubeconfig-manager/kubeconfig-manager.ts b/packages/core/src/main/kubeconfig-manager/kubeconfig-manager.ts
index 9d28306bbf..276692c500 100644
--- a/packages/core/src/main/kubeconfig-manager/kubeconfig-manager.ts
+++ b/packages/core/src/main/kubeconfig-manager/kubeconfig-manager.ts
@@ -85,7 +85,7 @@ export class KubeconfigManager {
return this.tempFilePath = await this.createProxyKubeconfig();
} catch (error) {
- throw new Error(`Failed to creat temp config for auth-proxy: ${error}`);
+ throw new Error(`Failed to create temp config for auth-proxy: ${error}`);
}
}
diff --git a/packages/core/src/main/kubectl/apply-all-handler.injectable.ts b/packages/core/src/main/kubectl/apply-all-handler.injectable.ts
index 7f62ca14fc..00f58e5e3f 100644
--- a/packages/core/src/main/kubectl/apply-all-handler.injectable.ts
+++ b/packages/core/src/main/kubectl/apply-all-handler.injectable.ts
@@ -6,11 +6,12 @@ import emitAppEventInjectable from "../../common/app-event-bus/emit-event.inject
import getClusterByIdInjectable from "../../common/cluster-store/get-by-id.injectable";
import { kubectlApplyAllChannel } from "../../common/kube-helpers/channels";
import resourceApplierInjectable from "../resource-applier/create-resource-applier.injectable";
-import { getRequestChannelListenerInjectable } from "../utils/channel/channel-listeners/listener-tokens";
+import { getRequestChannelListenerInjectable } from "@k8slens/messaging";
const kubectlApplyAllChannelHandlerInjectable = getRequestChannelListenerInjectable({
+ id: "kubectl-apply-all-channel-handler-listener",
channel: kubectlApplyAllChannel,
- handler: (di) => {
+ getHandler: (di) => {
const getClusterById = di.inject(getClusterByIdInjectable);
const emitAppEvent = di.inject(emitAppEventInjectable);
diff --git a/packages/core/src/main/kubectl/delete-all-handler.injectable.ts b/packages/core/src/main/kubectl/delete-all-handler.injectable.ts
index 715eb0caf9..5d207be482 100644
--- a/packages/core/src/main/kubectl/delete-all-handler.injectable.ts
+++ b/packages/core/src/main/kubectl/delete-all-handler.injectable.ts
@@ -6,11 +6,12 @@ import emitAppEventInjectable from "../../common/app-event-bus/emit-event.inject
import getClusterByIdInjectable from "../../common/cluster-store/get-by-id.injectable";
import { kubectlDeleteAllChannel } from "../../common/kube-helpers/channels";
import resourceApplierInjectable from "../resource-applier/create-resource-applier.injectable";
-import { getRequestChannelListenerInjectable } from "../utils/channel/channel-listeners/listener-tokens";
+import { getRequestChannelListenerInjectable } from "@k8slens/messaging";
const kubectlDeleteAllChannelHandlerInjectable = getRequestChannelListenerInjectable({
+ id: "kubectl-delete-all-channel-handler-listener",
channel: kubectlDeleteAllChannel,
- handler: (di) => {
+ getHandler: (di) => {
const emitAppEvent = di.inject(emitAppEventInjectable);
const getClusterById = di.inject(getClusterByIdInjectable);
diff --git a/packages/core/src/main/lens-proxy/lens-proxy-certificate-request-handler.injectable.ts b/packages/core/src/main/lens-proxy/lens-proxy-certificate-request-handler.injectable.ts
index 5f6938912a..6f35450273 100644
--- a/packages/core/src/main/lens-proxy/lens-proxy-certificate-request-handler.injectable.ts
+++ b/packages/core/src/main/lens-proxy/lens-proxy-certificate-request-handler.injectable.ts
@@ -3,12 +3,13 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { lensProxyCertificateChannel } from "../../common/certificate/lens-proxy-certificate-channel";
-import { getRequestChannelListenerInjectable } from "../utils/channel/channel-listeners/listener-tokens";
+import { getRequestChannelListenerInjectable } from "@k8slens/messaging";
import lensProxyCertificateInjectable from "../../common/certificate/lens-proxy-certificate.injectable";
const lensProxyCertificateRequestHandlerInjectable = getRequestChannelListenerInjectable({
+ id: "lens-proxy-certificate-request-handler-listener",
channel: lensProxyCertificateChannel,
- handler: (di) => {
+ getHandler: (di) => {
const lensProxyCertificate = di.inject(lensProxyCertificateInjectable).get();
return () => ({
diff --git a/packages/core/src/main/start-main-application/lens-window/current-cluster-frame/listener.injectable.ts b/packages/core/src/main/start-main-application/lens-window/current-cluster-frame/listener.injectable.ts
index d29210cda1..11d23e6a4f 100644
--- a/packages/core/src/main/start-main-application/lens-window/current-cluster-frame/listener.injectable.ts
+++ b/packages/core/src/main/start-main-application/lens-window/current-cluster-frame/listener.injectable.ts
@@ -3,17 +3,17 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { currentClusterMessageChannel } from "../../../../common/cluster/current-cluster-channel";
-import { getMessageChannelListenerInjectable } from "../../../../common/utils/channel/message-channel-listener-injection-token";
+import { getMessageChannelListenerInjectable } from "@k8slens/messaging";
import currentClusterFrameClusterIdStateInjectable from "./current-cluster-frame-cluster-id-state.injectable";
-const currentVisibileClusterListenerInjectable = getMessageChannelListenerInjectable({
- id: "current-visibile-cluster",
+const currentVisibleClusterListenerInjectable = getMessageChannelListenerInjectable({
+ id: "current-visible-cluster",
channel: currentClusterMessageChannel,
- handler: (di) => {
+ getHandler: (di) => {
const currentClusterFrameState = di.inject(currentClusterFrameClusterIdStateInjectable);
return clusterId => currentClusterFrameState.set(clusterId);
},
});
-export default currentVisibileClusterListenerInjectable;
+export default currentVisibleClusterListenerInjectable;
diff --git a/packages/core/src/main/start-main-application/runnables/root-frame-has-rendered/channel-listener.injectable.ts b/packages/core/src/main/start-main-application/runnables/root-frame-has-rendered/channel-listener.injectable.ts
index 8b906c79e9..4769c12256 100644
--- a/packages/core/src/main/start-main-application/runnables/root-frame-has-rendered/channel-listener.injectable.ts
+++ b/packages/core/src/main/start-main-application/runnables/root-frame-has-rendered/channel-listener.injectable.ts
@@ -2,7 +2,7 @@
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
-import { getMessageChannelListenerInjectable } from "../../../../common/utils/channel/message-channel-listener-injection-token";
+import { getMessageChannelListenerInjectable } from "@k8slens/messaging";
import { rootFrameHasRenderedChannel } from "../../../../common/root-frame/root-frame-rendered-channel";
import { runManyFor } from "@k8slens/run-many";
import { afterRootFrameIsReadyInjectionToken } from "../../runnable-tokens/phases";
@@ -10,7 +10,7 @@ import { afterRootFrameIsReadyInjectionToken } from "../../runnable-tokens/phase
const rootFrameRenderedChannelListenerInjectable = getMessageChannelListenerInjectable({
id: "action",
channel: rootFrameHasRenderedChannel,
- handler: (di) => {
+ getHandler: (di) => {
const runMany = runManyFor(di);
return runMany(afterRootFrameIsReadyInjectionToken);
diff --git a/packages/core/src/main/tray/menu-icon/reactive.injectable.ts b/packages/core/src/main/tray/menu-icon/reactive.injectable.ts
index 8c6d358477..4fbc8c2448 100644
--- a/packages/core/src/main/tray/menu-icon/reactive.injectable.ts
+++ b/packages/core/src/main/tray/menu-icon/reactive.injectable.ts
@@ -4,7 +4,7 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import { reaction } from "mobx";
-import { getStartableStoppable } from "../../../common/utils/get-startable-stoppable";
+import { getStartableStoppable } from "@k8slens/startable-stoppable";
import electronTrayInjectable from "../electron-tray/electron-tray.injectable";
import trayIconInjectable from "./tray-icon.injectable";
diff --git a/packages/core/src/main/tray/reactive-tray-menu-items/reactive-tray-menu-items.injectable.ts b/packages/core/src/main/tray/reactive-tray-menu-items/reactive-tray-menu-items.injectable.ts
index 378bceafd9..a216675b01 100644
--- a/packages/core/src/main/tray/reactive-tray-menu-items/reactive-tray-menu-items.injectable.ts
+++ b/packages/core/src/main/tray/reactive-tray-menu-items/reactive-tray-menu-items.injectable.ts
@@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
-import { getStartableStoppable } from "../../../common/utils/get-startable-stoppable";
+import { getStartableStoppable } from "@k8slens/startable-stoppable";
import { reaction } from "mobx";
import type { MinimalTrayMenuItem } from "../electron-tray/electron-tray.injectable";
import electronTrayInjectable from "../electron-tray/electron-tray.injectable";
diff --git a/packages/core/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts b/packages/core/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts
deleted file mode 100644
index db6435ea56..0000000000
--- a/packages/core/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- * Copyright (c) OpenLens Authors. All rights reserved.
- * Licensed under MIT License. See LICENSE in root directory for more information.
- */
-import { getInjectable } from "@ogre-tools/injectable";
-import type { IpcMainEvent } from "electron";
-import { enlistMessageChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-message-channel-listener-injection-token";
-import ipcMainInjectionToken from "../../../../common/ipc/ipc-main-injection-token";
-
-const enlistMessageChannelListenerInjectable = getInjectable({
- id: "enlist-message-channel-listener-for-main",
-
- instantiate: (di) => {
- const ipcMain = di.inject(ipcMainInjectionToken);
-
- return ({ channel, handler }) => {
- const nativeOnCallback = (_: IpcMainEvent, message: unknown) => {
- handler(message);
- };
-
- ipcMain.on(channel.id, nativeOnCallback);
-
- return () => {
- ipcMain.off(channel.id, nativeOnCallback);
- };
- };
- },
-
- injectionToken: enlistMessageChannelListenerInjectionToken,
-});
-
-export default enlistMessageChannelListenerInjectable;
diff --git a/packages/core/src/main/utils/channel/channel-listeners/listening-on-request-channels.injectable.ts b/packages/core/src/main/utils/channel/channel-listeners/listening-on-request-channels.injectable.ts
deleted file mode 100644
index 1e6d0f296c..0000000000
--- a/packages/core/src/main/utils/channel/channel-listeners/listening-on-request-channels.injectable.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * Copyright (c) OpenLens Authors. All rights reserved.
- * Licensed under MIT License. See LICENSE in root directory for more information.
- */
-import { getInjectable } from "@ogre-tools/injectable";
-import { disposer } from "@k8slens/utilities";
-import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token";
-import { getStartableStoppable } from "../../../../common/utils/get-startable-stoppable";
-import enlistRequestChannelListenerInjectable from "./enlist-request-channel-listener.injectable";
-import { requestChannelListenerInjectionToken } from "./listener-tokens";
-
-const listeningOnRequestChannelsInjectable = getInjectable({
- id: "listening-on-request-channels",
- instantiate: (di) => {
- const enlistRequestChannelListener = di.inject(enlistRequestChannelListenerInjectable);
- const requestChannelListeners = di.injectMany(requestChannelListenerInjectionToken);
-
- return getStartableStoppable("listening-on-request-channels", () => {
- const seenChannels = new Set>();
-
- for (const listener of requestChannelListeners) {
- if (seenChannels.has(listener.channel)) {
- throw new Error(`Tried to register a multiple channel handlers for "${listener.channel.id}", only one handler is supported for a request channel.`);
- }
-
- seenChannels.add(listener.channel);
- }
-
- return disposer(requestChannelListeners.map(enlistRequestChannelListener));
- });
- },
-});
-
-export default listeningOnRequestChannelsInjectable;
diff --git a/packages/core/src/main/utils/channel/channel-listeners/start-listening-on-channels.injectable.ts b/packages/core/src/main/utils/channel/channel-listeners/start-listening-on-channels.injectable.ts
deleted file mode 100644
index c83425109c..0000000000
--- a/packages/core/src/main/utils/channel/channel-listeners/start-listening-on-channels.injectable.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * Copyright (c) OpenLens Authors. All rights reserved.
- * Licensed under MIT License. See LICENSE in root directory for more information.
- */
-import { getInjectable } from "@ogre-tools/injectable";
-import { onLoadOfApplicationInjectionToken } from "@k8slens/application";
-import listeningOnMessageChannelsInjectable from "../../../../common/utils/channel/listening-on-message-channels.injectable";
-import listeningOnRequestChannelsInjectable from "./listening-on-request-channels.injectable";
-
-const startListeningOnChannelsInjectable = getInjectable({
- id: "start-listening-on-channels-main",
-
- instantiate: (di) => ({
- run: () => {
- const listeningOnMessageChannels = di.inject(listeningOnMessageChannelsInjectable);
- const listeningOnRequestChannels = di.inject(listeningOnRequestChannelsInjectable);
-
- listeningOnMessageChannels.start();
- listeningOnRequestChannels.start();
- },
- }),
-
- injectionToken: onLoadOfApplicationInjectionToken,
-});
-
-export default startListeningOnChannelsInjectable;
diff --git a/packages/core/src/main/utils/channel/message-to-channel.injectable.ts b/packages/core/src/main/utils/channel/message-to-channel.injectable.ts
deleted file mode 100644
index 392120509d..0000000000
--- a/packages/core/src/main/utils/channel/message-to-channel.injectable.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- * Copyright (c) OpenLens Authors. All rights reserved.
- * Licensed under MIT License. See LICENSE in root directory for more information.
- */
-import { getInjectable } from "@ogre-tools/injectable";
-import type { SendMessageToChannel } from "../../../common/utils/channel/message-to-channel-injection-token";
-import { sendMessageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token";
-import getVisibleWindowsInjectable from "../../start-main-application/lens-window/get-visible-windows.injectable";
-import clusterFramesInjectable from "../../../common/cluster-frames.injectable";
-
-const messageToChannelInjectable = getInjectable({
- id: "message-to-channel",
-
- instantiate: (di) => {
- const getVisibleWindows = di.inject(getVisibleWindowsInjectable);
- const clusterFrames = di.inject(clusterFramesInjectable);
-
- return ((channel, data) => {
- for (const window of getVisibleWindows()) {
- window.send({ channel: channel.id, data });
-
- clusterFrames.forEach(frameInfo => {
- window.send({ channel: channel.id, data, frameInfo });
- });
- }
- }) as SendMessageToChannel;
- },
-
- injectionToken: sendMessageToChannelInjectionToken,
-});
-
-export default messageToChannelInjectable;
diff --git a/packages/core/src/main/utils/channel/message-to-channel.test.ts b/packages/core/src/main/utils/channel/message-to-channel.test.ts
deleted file mode 100644
index 8e544c47dd..0000000000
--- a/packages/core/src/main/utils/channel/message-to-channel.test.ts
+++ /dev/null
@@ -1,115 +0,0 @@
-/**
- * Copyright (c) OpenLens Authors. All rights reserved.
- * Licensed under MIT License. See LICENSE in root directory for more information.
- */
-import { getDiForUnitTesting } from "../../getDiForUnitTesting";
-import getVisibleWindowsInjectable from "../../start-main-application/lens-window/get-visible-windows.injectable";
-import clusterFramesInjectable from "../../../common/cluster-frames.injectable";
-import type { MessageChannel } from "../../../common/utils/channel/message-channel-listener-injection-token";
-import { sendMessageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token";
-import type { DiContainer } from "@ogre-tools/injectable";
-import type { ClusterFrameInfo } from "../../../common/cluster-frames.injectable";
-
-describe("message-to-channel", () => {
- let di: DiContainer;
- let sendToWindowMock: jest.Mock;
-
- beforeEach(() => {
- di = getDiForUnitTesting();
-
- sendToWindowMock = jest.fn();
-
- di.override(getVisibleWindowsInjectable, () => () => [
- {
- id: "some-window",
- send: sendToWindowMock,
- show: () => {},
- reload: () => {},
- isStarting: false,
- start: async () => {},
- close: () => {},
- isVisible: true,
- },
-
- {
- id: "some-other-window",
- send: sendToWindowMock,
- show: () => {},
- reload: () => {},
- isStarting: false,
- start: async () => {},
- close: () => {},
- isVisible: true,
- },
- ]);
-
- di.override(
- clusterFramesInjectable,
- () =>
- new Map([
- [
- "some-cluster-id",
- { frameId: 42, processId: 84 },
- ],
- [
- "some-other-cluster-id",
- { frameId: 126, processId: 168 },
- ],
- ]),
- );
- });
-
- describe("when sending message", () => {
- beforeEach(() => {
- const sendMessageToChannel = di.inject(
- sendMessageToChannelInjectionToken,
- );
-
- sendMessageToChannel(someChannel, 42);
- });
-
- it("sends to each window and cluster frames", () => {
- expect(sendToWindowMock.mock.calls).toEqual([
- [{ channel: "some-channel-id", data: 42 }],
-
- [
- {
- channel: "some-channel-id",
- data: 42,
- frameInfo: { frameId: 42, processId: 84 },
- },
- ],
-
- [
- {
- channel: "some-channel-id",
- data: 42,
- frameInfo: { frameId: 126, processId: 168 },
- },
- ],
-
- [{ channel: "some-channel-id", data: 42 }],
-
- [
- {
- channel: "some-channel-id",
- data: 42,
- frameInfo: { frameId: 42, processId: 84 },
- },
- ],
-
- [
- {
- channel: "some-channel-id",
- data: 42,
- frameInfo: { frameId: 126, processId: 168 },
- },
- ],
- ]);
- });
- });
-});
-
-const someChannel: MessageChannel = {
- id: "some-channel-id",
-};
diff --git a/packages/core/src/main/utils/resolve-system-proxy/electron.injectable.ts b/packages/core/src/main/utils/resolve-system-proxy/electron.injectable.ts
deleted file mode 100644
index a5999c9e59..0000000000
--- a/packages/core/src/main/utils/resolve-system-proxy/electron.injectable.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-/**
- * Copyright (c) OpenLens Authors. All rights reserved.
- * Licensed under MIT License. See LICENSE in root directory for more information.
- */
-import { getInjectable } from "@ogre-tools/injectable";
-import electron from "electron";
-
-const electronInjectable = getInjectable({
- id: "electron",
- instantiate: () => electron,
- causesSideEffects: true,
-});
-
-export default electronInjectable;
diff --git a/packages/core/src/main/utils/resolve-system-proxy/resolve-system-proxy-channel-responder.injectable.ts b/packages/core/src/main/utils/resolve-system-proxy/resolve-system-proxy-channel-responder.injectable.ts
index a2cd605633..16229a0fb7 100644
--- a/packages/core/src/main/utils/resolve-system-proxy/resolve-system-proxy-channel-responder.injectable.ts
+++ b/packages/core/src/main/utils/resolve-system-proxy/resolve-system-proxy-channel-responder.injectable.ts
@@ -3,12 +3,13 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { resolveSystemProxyChannel } from "../../../common/utils/resolve-system-proxy/resolve-system-proxy-channel";
-import { getRequestChannelListenerInjectable } from "../channel/channel-listeners/listener-tokens";
+import { getRequestChannelListenerInjectable } from "@k8slens/messaging";
import resolveSystemProxyInjectable from "./resolve-system-proxy.injectable";
const resolveSystemProxyChannelResponderInjectable = getRequestChannelListenerInjectable({
+ id: "resolve-system-proxy-channel-responder-listener",
channel: resolveSystemProxyChannel,
- handler: (di) => di.inject(resolveSystemProxyInjectable),
+ getHandler: (di) => di.inject(resolveSystemProxyInjectable),
});
export default resolveSystemProxyChannelResponderInjectable;
diff --git a/packages/core/src/main/utils/resolve-system-proxy/resolve-system-proxy-from-electron.injectable.ts b/packages/core/src/main/utils/resolve-system-proxy/resolve-system-proxy-from-electron.injectable.ts
index c663d59fde..4ad2da39b8 100644
--- a/packages/core/src/main/utils/resolve-system-proxy/resolve-system-proxy-from-electron.injectable.ts
+++ b/packages/core/src/main/utils/resolve-system-proxy/resolve-system-proxy-from-electron.injectable.ts
@@ -3,28 +3,19 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
-import electronInjectable from "./electron.injectable";
import withErrorLoggingInjectable from "../../../common/utils/with-error-logging/with-error-logging.injectable";
+import resolveSystemProxyWindowInjectable from "./resolve-system-proxy-window.injectable";
const resolveSystemProxyFromElectronInjectable = getInjectable({
id: "resolve-system-proxy-from-electron",
instantiate: (di) => {
- const electron = di.inject(electronInjectable);
+ const helperWindow = di.inject(resolveSystemProxyWindowInjectable);
const withErrorLoggingFor = di.inject(withErrorLoggingInjectable);
-
const withErrorLogging = withErrorLoggingFor(() => "Error resolving proxy");
-
+
return withErrorLogging(async (url: string) => {
- const webContent = electron.webContents
- .getAllWebContents()
- .find((x) => !x.isDestroyed());
-
- if (!webContent) {
- throw new Error(`Tried to resolve proxy for "${url}", but no browser window was available`);
- }
-
- return await webContent.session.resolveProxy(url);
+ return await helperWindow.webContents.session.resolveProxy(url);
});
},
});
diff --git a/packages/core/src/main/utils/resolve-system-proxy/resolve-system-proxy-from-electron.test.ts b/packages/core/src/main/utils/resolve-system-proxy/resolve-system-proxy-from-electron.test.ts
index c197566a10..a2e6d01627 100644
--- a/packages/core/src/main/utils/resolve-system-proxy/resolve-system-proxy-from-electron.test.ts
+++ b/packages/core/src/main/utils/resolve-system-proxy/resolve-system-proxy-from-electron.test.ts
@@ -5,13 +5,13 @@
import { getDiForUnitTesting } from "../../getDiForUnitTesting";
import resolveSystemProxyFromElectronInjectable from "./resolve-system-proxy-from-electron.injectable";
-import electronInjectable from "./electron.injectable";
+import resolveSystemProxyWindowInjectable from "./resolve-system-proxy-window.injectable";
import type { AsyncFnMock } from "@async-fn/jest";
import asyncFn from "@async-fn/jest";
-import type electron from "electron";
import { getPromiseStatus } from "@k8slens/test-utils";
import logErrorInjectable from "../../../common/log-error.injectable";
import type { DiContainer } from "@ogre-tools/injectable";
+import type { BrowserWindow, Session, WebContents } from "electron";
describe("technical: resolve-system-proxy-from-electron", () => {
let resolveSystemProxyMock: AsyncFnMock<(url: string) => Promise>;
@@ -26,44 +26,19 @@ describe("technical: resolve-system-proxy-from-electron", () => {
di.override(logErrorInjectable, () => logErrorMock);
});
- describe("given there are non-destroyed Lens windows, when called with URL", () => {
+ describe("given there are no unexpected issues, when called with URL", () => {
beforeEach(() => {
resolveSystemProxyMock = asyncFn();
di.override(
- electronInjectable,
-
- () =>
- ({
- webContents: {
- getAllWebContents: () => [
- {
- isDestroyed: () => true,
-
- session: {
- resolveProxy: () => {
- throw new Error("should never come here");
- },
- },
- },
-
- {
- isDestroyed: () => false,
- session: { resolveProxy: resolveSystemProxyMock },
- },
-
- {
- isDestroyed: () => false,
-
- session: {
- resolveProxy: () => {
- throw new Error("should never come here");
- },
- },
- },
- ],
- },
- } as unknown as typeof electron),
+ resolveSystemProxyWindowInjectable,
+ () => ({
+ webContents: {
+ session: {
+ resolveProxy: resolveSystemProxyMock,
+ } as unknown as Session,
+ } as unknown as WebContents,
+ } as unknown as BrowserWindow),
);
const resolveSystemProxyFromElectron = di.inject(
@@ -73,7 +48,7 @@ describe("technical: resolve-system-proxy-from-electron", () => {
actualPromise = resolveSystemProxyFromElectron("some-url");
});
- it("calls to resolve proxy from the first window", () => {
+ it("calls to resolve proxy from the browser window", () => {
expect(resolveSystemProxyMock).toHaveBeenCalledWith("some-url");
});
@@ -90,28 +65,23 @@ describe("technical: resolve-system-proxy-from-electron", () => {
});
});
- describe("given there are only destroyed Lens windows, when called with URL", () => {
+ describe("given there are unexpected issues, when called with URL", () => {
let error: any;
beforeEach(async () => {
- di.override(
- electronInjectable,
- () =>
- ({
- webContents: {
- getAllWebContents: () => [
- {
- isDestroyed: () => true,
+ resolveSystemProxyMock = asyncFn();
- session: {
- resolveProxy: () => {
- throw new Error("should never come here");
- },
- },
- },
- ],
- },
- } as unknown as typeof electron),
+ di.override(
+ resolveSystemProxyWindowInjectable,
+ () => ({
+ webContents: {
+ session: {
+ resolveProxy: () => {
+ throw new Error("unexpected error");
+ },
+ } as unknown as Session,
+ } as unknown as WebContents,
+ } as unknown as BrowserWindow),
);
resolveSystemProxyMock = asyncFn();
@@ -128,7 +98,7 @@ describe("technical: resolve-system-proxy-from-electron", () => {
});
it("throws error", () => {
- expect(error.message).toBe('Tried to resolve proxy for "some-url", but no browser window was available');
+ expect(error.message).toBe("unexpected error");
});
it("logs error", () => {
diff --git a/packages/core/src/main/utils/resolve-system-proxy/resolve-system-proxy-window.global-override-for-injectable.ts b/packages/core/src/main/utils/resolve-system-proxy/resolve-system-proxy-window.global-override-for-injectable.ts
new file mode 100644
index 0000000000..4bf1ada952
--- /dev/null
+++ b/packages/core/src/main/utils/resolve-system-proxy/resolve-system-proxy-window.global-override-for-injectable.ts
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) OpenLens Authors. All rights reserved.
+ * Licensed under MIT License. See LICENSE in root directory for more information.
+ */
+
+import { getGlobalOverride } from "@k8slens/test-utils";
+import type { BrowserWindow, Session, WebContents } from "electron";
+import resolveSystemProxyWindowInjectable from "./resolve-system-proxy-window.injectable";
+
+export default getGlobalOverride(
+ resolveSystemProxyWindowInjectable,
+ () => ({
+ webContents: {
+ session: {
+ resolveProxy: () => "DIRECT",
+ } as unknown as Session,
+ } as unknown as WebContents,
+ } as unknown as BrowserWindow),
+);
diff --git a/packages/core/src/main/utils/resolve-system-proxy/resolve-system-proxy-window.injectable.ts b/packages/core/src/main/utils/resolve-system-proxy/resolve-system-proxy-window.injectable.ts
new file mode 100644
index 0000000000..baa0da6c39
--- /dev/null
+++ b/packages/core/src/main/utils/resolve-system-proxy/resolve-system-proxy-window.injectable.ts
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) OpenLens Authors. All rights reserved.
+ * Licensed under MIT License. See LICENSE in root directory for more information.
+ */
+import { getInjectable } from "@ogre-tools/injectable";
+import { BrowserWindow } from "electron";
+
+const resolveSystemProxyWindowInjectable = getInjectable({
+ id: "resolve-system-proxy-window",
+ instantiate: () => {
+ const window = new BrowserWindow({ show: false });
+
+ window.hide();
+
+ return window;
+ },
+ causesSideEffects: true,
+});
+
+export default resolveSystemProxyWindowInjectable;
diff --git a/packages/core/src/main/utils/sync-box/sync-box-initial-value-channel-listener.injectable.ts b/packages/core/src/main/utils/sync-box/sync-box-initial-value-channel-listener.injectable.ts
index da78d76c36..fafb32e7e9 100644
--- a/packages/core/src/main/utils/sync-box/sync-box-initial-value-channel-listener.injectable.ts
+++ b/packages/core/src/main/utils/sync-box/sync-box-initial-value-channel-listener.injectable.ts
@@ -4,11 +4,12 @@
*/
import { syncBoxInitialValueChannel } from "../../../common/utils/sync-box/channels";
import { syncBoxInjectionToken } from "../../../common/utils/sync-box/sync-box-injection-token";
-import { getRequestChannelListenerInjectable } from "../channel/channel-listeners/listener-tokens";
+import { getRequestChannelListenerInjectable } from "@k8slens/messaging";
const syncBoxInitialValueChannelListenerInjectable = getRequestChannelListenerInjectable({
+ id: "sync-box-initial-value-channel-listener",
channel: syncBoxInitialValueChannel,
- handler: (di) => {
+ getHandler: (di) => {
const syncBoxes = di.injectMany(syncBoxInjectionToken);
return () => syncBoxes.map((box) => ({
diff --git a/packages/core/src/renderer/app-paths/setup-app-paths.injectable.ts b/packages/core/src/renderer/app-paths/setup-app-paths.injectable.ts
index d80cc668ac..af5c3cebc6 100644
--- a/packages/core/src/renderer/app-paths/setup-app-paths.injectable.ts
+++ b/packages/core/src/renderer/app-paths/setup-app-paths.injectable.ts
@@ -4,9 +4,9 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import appPathsStateInjectable from "../../common/app-paths/app-paths-state.injectable";
-import { beforeFrameStartsFirstInjectionToken } from "../before-frame-starts/tokens";
import { appPathsChannel } from "../../common/app-paths/app-paths-channel";
-import { requestFromChannelInjectionToken } from "../../common/utils/channel/request-from-channel-injection-token";
+import { requestFromChannelInjectionToken } from "@k8slens/messaging";
+import { beforeApplicationIsLoadingInjectionToken } from "@k8slens/application";
const setupAppPathsInjectable = getInjectable({
id: "setup-app-paths",
@@ -21,7 +21,7 @@ const setupAppPathsInjectable = getInjectable({
},
}),
- injectionToken: beforeFrameStartsFirstInjectionToken,
+ injectionToken: beforeApplicationIsLoadingInjectionToken,
});
export default setupAppPathsInjectable;
diff --git a/packages/core/src/renderer/before-frame-starts/runnables/setup-auto-crd-api-creations.injectable.ts b/packages/core/src/renderer/before-frame-starts/runnables/setup-auto-crd-api-creations.injectable.ts
new file mode 100644
index 0000000000..c23a34d767
--- /dev/null
+++ b/packages/core/src/renderer/before-frame-starts/runnables/setup-auto-crd-api-creations.injectable.ts
@@ -0,0 +1,53 @@
+/**
+ * Copyright (c) OpenLens Authors. All rights reserved.
+ * Licensed under MIT License. See LICENSE in root directory for more information.
+ */
+import { getInjectable } from "@ogre-tools/injectable";
+import { reaction } from "mobx";
+import { customResourceDefinitionApiInjectionToken } from "../../../common/k8s-api/api-manager/crd-api-token";
+import type { CustomResourceDefinition } from "../../../common/k8s-api/endpoints";
+import { KubeApi } from "../../../common/k8s-api/kube-api";
+import { KubeObject } from "../../../common/k8s-api/kube-object";
+import maybeKubeApiInjectable from "../../../common/k8s-api/maybe-kube-api.injectable";
+import loggerInjectable from "../../../common/logger.injectable";
+import { injectableDifferencingRegistratorWith } from "../../../common/utils/registrator-helper";
+import customResourceDefinitionStoreInjectable from "../../components/+custom-resources/definition.store.injectable";
+import { beforeClusterFrameStartsSecondInjectionToken } from "../tokens";
+
+const setupAutoCrdApiCreationsInjectable = getInjectable({
+ id: "setup-auto-crd-api-creations",
+ instantiate: (di) => ({
+ run: () => {
+ const customResourceDefinitionStore = di.inject(customResourceDefinitionStoreInjectable);
+ const injectableDifferencingRegistrator = injectableDifferencingRegistratorWith(di);
+
+ reaction(
+ () => customResourceDefinitionStore.getItems().map(toCrdApiInjectable),
+ injectableDifferencingRegistrator,
+ {
+ fireImmediately: true,
+ },
+ );
+ },
+ }),
+ injectionToken: beforeClusterFrameStartsSecondInjectionToken,
+});
+
+export default setupAutoCrdApiCreationsInjectable;
+
+const toCrdApiInjectable = (crd: CustomResourceDefinition) => getInjectable({
+ id: `default-kube-api-for-custom-resource-definition-${crd.getResourceApiBase()}`,
+ instantiate: (di) => {
+ const objectConstructor = class extends KubeObject {
+ static readonly kind = crd.getResourceKind();
+ static readonly namespaced = crd.isNamespaced();
+ static readonly apiBase = crd.getResourceApiBase();
+ };
+
+ return new KubeApi({
+ logger: di.inject(loggerInjectable),
+ maybeKubeApi: di.inject(maybeKubeApiInjectable),
+ }, { objectConstructor });
+ },
+ injectionToken: customResourceDefinitionApiInjectionToken,
+});
diff --git a/packages/core/src/renderer/before-frame-starts/runnables/setup-auto-registration.injectable.ts b/packages/core/src/renderer/before-frame-starts/runnables/setup-auto-registration.injectable.ts
index dbc77a92b8..78b1f90015 100644
--- a/packages/core/src/renderer/before-frame-starts/runnables/setup-auto-registration.injectable.ts
+++ b/packages/core/src/renderer/before-frame-starts/runnables/setup-auto-registration.injectable.ts
@@ -5,71 +5,22 @@
import { getInjectable } from "@ogre-tools/injectable";
import autoRegistrationEmitterInjectable from "../../../common/k8s-api/api-manager/auto-registration-emitter.injectable";
import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable";
-import { CustomResourceStore } from "../../../common/k8s-api/api-manager/resource.store";
-import type { CustomResourceDefinition } from "../../../common/k8s-api/endpoints";
-import type { KubeApiDependencies } from "../../../common/k8s-api/kube-api";
-import { KubeApi } from "../../../common/k8s-api/kube-api";
-import { KubeObject } from "../../../common/k8s-api/kube-object";
+import type { KubeApi } from "../../../common/k8s-api/kube-api";
import { beforeClusterFrameStartsSecondInjectionToken } from "../tokens";
-import type { KubeObjectStoreDependencies } from "../../../common/k8s-api/kube-object.store";
-import clusterFrameContextForNamespacedResourcesInjectable from "../../cluster-frame-context/for-namespaced-resources.injectable";
-import loggerInjectable from "../../../common/logger.injectable";
-import maybeKubeApiInjectable from "../../../common/k8s-api/maybe-kube-api.injectable";
const setupAutoRegistrationInjectable = getInjectable({
id: "setup-auto-registration",
instantiate: (di) => ({
run: () => {
const autoRegistrationEmitter = di.inject(autoRegistrationEmitterInjectable);
- const beforeApiManagerInitializationCrds: CustomResourceDefinition[] = [];
const beforeApiManagerInitializationApis: KubeApi[] = [];
- const kubeApiDependencies: KubeApiDependencies = {
- logger: di.inject(loggerInjectable),
- maybeKubeApi: di.inject(maybeKubeApiInjectable),
- };
- const kubeObjectStoreDependencies: KubeObjectStoreDependencies = {
- context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
- logger: di.inject(loggerInjectable),
- };
let initialized = false;
- const autoInitCustomResourceStore = (crd: CustomResourceDefinition) => {
- const objectConstructor = class extends KubeObject {
- static readonly kind = crd.getResourceKind();
- static readonly namespaced = crd.isNamespaced();
- static readonly apiBase = crd.getResourceApiBase();
- };
-
- const api = (() => {
- const rawApi = apiManager.getApi(objectConstructor.apiBase);
-
- if (rawApi) {
- return rawApi;
- }
-
- const api = new KubeApi(kubeApiDependencies, { objectConstructor });
-
- apiManager.registerApi(api);
-
- return api;
- })();
-
- if (!apiManager.getStore(api)) {
- apiManager.registerStore(new CustomResourceStore(kubeObjectStoreDependencies, api));
- }
- };
const autoInitKubeApi = (api: KubeApi) => {
apiManager.registerApi(api);
};
autoRegistrationEmitter
- .on("customResourceDefinition", (crd) => {
- if (initialized) {
- autoInitCustomResourceStore(crd);
- } else {
- beforeApiManagerInitializationCrds.push(crd);
- }
- })
.on("kubeApi", (api) => {
if (initialized) {
autoInitKubeApi(api);
@@ -81,7 +32,6 @@ const setupAutoRegistrationInjectable = getInjectable({
// NOTE: this MUST happen after the event emitter listeners are registered
const apiManager = di.inject(apiManagerInjectable);
- beforeApiManagerInitializationCrds.forEach(autoInitCustomResourceStore);
beforeApiManagerInitializationApis.forEach(autoInitKubeApi);
initialized = true;
},
diff --git a/packages/core/src/renderer/before-frame-starts/runnables/setup-current-cluster-broadcast.injectable.ts b/packages/core/src/renderer/before-frame-starts/runnables/setup-current-cluster-broadcast.injectable.ts
index 0d9c8bc65a..e60eb3fae1 100644
--- a/packages/core/src/renderer/before-frame-starts/runnables/setup-current-cluster-broadcast.injectable.ts
+++ b/packages/core/src/renderer/before-frame-starts/runnables/setup-current-cluster-broadcast.injectable.ts
@@ -5,7 +5,7 @@
import { getInjectable } from "@ogre-tools/injectable";
import { reaction } from "mobx";
import { currentClusterMessageChannel } from "../../../common/cluster/current-cluster-channel";
-import { sendMessageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token";
+import { sendMessageToChannelInjectionToken } from "@k8slens/messaging";
import matchedClusterIdInjectable from "../../navigation/matched-cluster-id.injectable";
import { beforeMainFrameStartsFirstInjectionToken } from "../tokens";
diff --git a/packages/core/src/renderer/certificate/request-lens-proxy-certificate.injectable.ts b/packages/core/src/renderer/certificate/request-lens-proxy-certificate.injectable.ts
index e1322096bf..f80911c7a5 100644
--- a/packages/core/src/renderer/certificate/request-lens-proxy-certificate.injectable.ts
+++ b/packages/core/src/renderer/certificate/request-lens-proxy-certificate.injectable.ts
@@ -4,12 +4,12 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import { lensProxyCertificateChannel } from "../../common/certificate/lens-proxy-certificate-channel";
-import requestFromChannelInjectable from "../utils/channel/request-from-channel.injectable";
+import { requestFromChannelInjectionToken } from "@k8slens/messaging";
const requestLensProxyCertificateInjectable = getInjectable({
id: "request-lens-proxy-certificate",
instantiate: (di) => {
- const requestFromChannel = di.inject(requestFromChannelInjectable);
+ const requestFromChannel = di.inject(requestFromChannelInjectionToken);
return () => requestFromChannel(lensProxyCertificateChannel);
},
diff --git a/packages/core/src/renderer/components/+catalog/catalog.module.scss b/packages/core/src/renderer/components/+catalog/catalog.module.scss
index 4fe31c4f27..85976301ba 100644
--- a/packages/core/src/renderer/components/+catalog/catalog.module.scss
+++ b/packages/core/src/renderer/components/+catalog/catalog.module.scss
@@ -8,6 +8,10 @@
opacity: 1;
}
+ :global(.TableCell) {
+ padding: 6px 8px;
+ }
+
flex-grow: 1;
}
diff --git a/packages/core/src/renderer/components/+catalog/catalog.tsx b/packages/core/src/renderer/components/+catalog/catalog.tsx
index b521f39730..1d385d78c4 100644
--- a/packages/core/src/renderer/components/+catalog/catalog.tsx
+++ b/packages/core/src/renderer/components/+catalog/catalog.tsx
@@ -276,6 +276,9 @@ class NonInjectedCatalog extends React.Component {
{...getCategoryColumns({ activeCategory })}
onDetails={this.props.onCatalogEntityListClick}
renderItemMenu={this.renderItemMenu}
+ tableProps={{
+ customRowHeights: () => 36, // Entity avatar size + padding
+ }}
data-testid={`catalog-list-for-${activeCategory?.metadata.name ?? "browse-all"}`}
/>
);
diff --git a/packages/core/src/renderer/components/+config-horizontal-pod-autoscalers/hpa-details.test.tsx b/packages/core/src/renderer/components/+config-horizontal-pod-autoscalers/hpa-details.test.tsx
index 48c2183055..aa2d2a3b32 100644
--- a/packages/core/src/renderer/components/+config-horizontal-pod-autoscalers/hpa-details.test.tsx
+++ b/packages/core/src/renderer/components/+config-horizontal-pod-autoscalers/hpa-details.test.tsx
@@ -4,8 +4,13 @@
*/
import type { RenderResult } from "@testing-library/react";
import React from "react";
+import directoryForKubeConfigsInjectable from "../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable";
+import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
+import { Cluster } from "../../../common/cluster/cluster";
import { HorizontalPodAutoscaler, HpaMetricType } from "../../../common/k8s-api/endpoints";
+import hostedClusterInjectable from "../../cluster-frame-context/hosted-cluster.injectable";
import { getDiForUnitTesting } from "../../getDiForUnitTesting";
+import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
import type { DiRender } from "../test-utils/renderFor";
import { renderFor } from "../test-utils/renderFor";
import { HpaDetails } from "./hpa-details";
@@ -41,6 +46,17 @@ describe("", () => {
beforeEach(() => {
const di = getDiForUnitTesting();
+ di.override(directoryForUserDataInjectable, () => "/some-user-store-path");
+ di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs");
+ di.override(storesAndApisCanBeCreatedInjectable, () => true);
+ di.override(hostedClusterInjectable, () => new Cluster({
+ contextName: "some-context-name",
+ id: "some-cluster-id",
+ kubeConfigPath: "/some-path-to-a-kubeconfig",
+ }, {
+ clusterServerUrl: "https://localhost:8080",
+ }));
+
render = renderFor(di);
});
diff --git a/packages/core/src/renderer/components/+custom-resources/definition.store.injectable.ts b/packages/core/src/renderer/components/+custom-resources/definition.store.injectable.ts
index f1d8f635b8..dbbd2460aa 100644
--- a/packages/core/src/renderer/components/+custom-resources/definition.store.injectable.ts
+++ b/packages/core/src/renderer/components/+custom-resources/definition.store.injectable.ts
@@ -4,7 +4,6 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert";
-import autoRegistrationEmitterInjectable from "../../../common/k8s-api/api-manager/auto-registration-emitter.injectable";
import { kubeObjectStoreInjectionToken } from "../../../common/k8s-api/api-manager/kube-object-store-token";
import customResourceDefinitionApiInjectable from "../../../common/k8s-api/endpoints/custom-resource-definition.api.injectable";
import loggerInjectable from "../../../common/logger.injectable";
@@ -20,7 +19,6 @@ const customResourceDefinitionStoreInjectable = getInjectable({
const api = di.inject(customResourceDefinitionApiInjectable);
return new CustomResourceDefinitionStore({
- autoRegistration: di.inject(autoRegistrationEmitterInjectable),
context: di.inject(clusterFrameContextForClusterScopedResourcesInjectable),
logger: di.inject(loggerInjectable),
}, api);
diff --git a/packages/core/src/renderer/components/+custom-resources/definition.store.ts b/packages/core/src/renderer/components/+custom-resources/definition.store.ts
index 310e51709a..78ef3982a9 100644
--- a/packages/core/src/renderer/components/+custom-resources/definition.store.ts
+++ b/packages/core/src/renderer/components/+custom-resources/definition.store.ts
@@ -3,37 +3,22 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
-import { computed, reaction, makeObservable } from "mobx";
+import { computed, makeObservable } from "mobx";
import type { KubeObjectStoreDependencies, KubeObjectStoreOptions } from "../../../common/k8s-api/kube-object.store";
import { KubeObjectStore } from "../../../common/k8s-api/kube-object.store";
import type { CustomResourceDefinition, CustomResourceDefinitionApi } from "../../../common/k8s-api/endpoints/custom-resource-definition.api";
import type { KubeObject } from "../../../common/k8s-api/kube-object";
-import type TypedEventEmitter from "typed-emitter";
-import type { LegacyAutoRegistration } from "../../../common/k8s-api/api-manager/auto-registration-emitter.injectable";
import autoBind from "auto-bind";
-export interface CustomResourceDefinitionStoreDependencies extends KubeObjectStoreDependencies {
- readonly autoRegistration: TypedEventEmitter;
-}
-
export class CustomResourceDefinitionStore extends KubeObjectStore {
constructor(
- protected readonly dependencies: CustomResourceDefinitionStoreDependencies,
+ dependencies: KubeObjectStoreDependencies,
api: CustomResourceDefinitionApi,
opts?: KubeObjectStoreOptions,
) {
super(dependencies, api, opts);
makeObservable(this);
autoBind(this);
-
- reaction(
- () => this.getItems(),
- crds => {
- for (const crd of crds) {
- this.dependencies.autoRegistration.emit("customResourceDefinition", crd);
- }
- },
- );
}
protected sortItems(items: CustomResourceDefinition[]) {
diff --git a/packages/core/src/renderer/components/+extensions/attempt-install-by-info.injectable.tsx b/packages/core/src/renderer/components/+extensions/attempt-install-by-info.injectable.tsx
index 523a91596e..8f2e5692d1 100644
--- a/packages/core/src/renderer/components/+extensions/attempt-install-by-info.injectable.tsx
+++ b/packages/core/src/renderer/components/+extensions/attempt-install-by-info.injectable.tsx
@@ -26,6 +26,7 @@ export interface ExtensionInfo {
requireConfirmation?: boolean;
}
+// @ts-ignore
interface NpmPackageVersionDescriptor extends PackageJson {
dist: {
integrity: string;
diff --git a/packages/core/src/renderer/components/+network-ingresses/ingresses.scss b/packages/core/src/renderer/components/+network-ingresses/ingresses.scss
index 4c6d5a75c1..f0b754d03d 100644
--- a/packages/core/src/renderer/components/+network-ingresses/ingresses.scss
+++ b/packages/core/src/renderer/components/+network-ingresses/ingresses.scss
@@ -12,7 +12,7 @@
&.rules {
flex-grow: 3.0;
overflow-x: scroll;
- text-overflow: unset;
+ flex-wrap: wrap;
&::-webkit-scrollbar {
display: none;
@@ -20,7 +20,6 @@
.ingressRule {
overflow: hidden;
- text-overflow: ellipsis;
}
.ingressRule + .ingressRule {
diff --git a/packages/core/src/renderer/components/+workloads-pods/pods.tsx b/packages/core/src/renderer/components/+workloads-pods/pods.tsx
index 849a101ae1..1132c00a0c 100644
--- a/packages/core/src/renderer/components/+workloads-pods/pods.tsx
+++ b/packages/core/src/renderer/components/+workloads-pods/pods.tsx
@@ -29,6 +29,7 @@ import nodeApiInjectable from "../../../common/k8s-api/endpoints/node.api.inject
import eventStoreInjectable from "../+events/store.injectable";
import podStoreInjectable from "./store.injectable";
import { NamespaceSelectBadge } from "../+namespaces/namespace-select-badge";
+import { Tooltip } from "../tooltip";
enum columnId {
name = "name",
@@ -163,13 +164,14 @@ class NonInjectedPods extends React.Component {
{ title: "Status", className: "status", sortBy: columnId.status, id: columnId.status },
]}
renderTableContents={pod => [
- ,
+ <>
+
+ {pod.getName()}
+
+
+ {pod.getName()}
+
+ >,
,
void;
}
export class ClusterFrameHandler {
diff --git a/packages/core/src/renderer/components/cluster-manager/emit-cluster-visibility.injectable.ts b/packages/core/src/renderer/components/cluster-manager/emit-cluster-visibility.injectable.ts
index 261582d136..5c941c60e6 100644
--- a/packages/core/src/renderer/components/cluster-manager/emit-cluster-visibility.injectable.ts
+++ b/packages/core/src/renderer/components/cluster-manager/emit-cluster-visibility.injectable.ts
@@ -3,18 +3,16 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
-import type { MessageChannelHandler } from "../../../common/utils/channel/message-channel-listener-injection-token";
-import { sendMessageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token";
+import { sendMessageToChannelInjectionToken } from "@k8slens/messaging";
import { clusterVisibilityChannel } from "../../../common/cluster/visibility-channel";
-
-export type EmitClusterVisibility = MessageChannelHandler;
+import type { ClusterId } from "../../../common/cluster-types";
const emitClusterVisibilityInjectable = getInjectable({
id: "emit-cluster-visibility",
- instantiate: (di): EmitClusterVisibility => {
+ instantiate: (di) => {
const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken);
- return (id) => sendMessageToChannel(clusterVisibilityChannel, id);
+ return (id: ClusterId | null) => sendMessageToChannel(clusterVisibilityChannel, id);
},
});
diff --git a/packages/core/src/renderer/components/cluster-settings/__tests__/__snapshots__/icon-settings.test.tsx.snap b/packages/core/src/renderer/components/cluster-settings/__tests__/__snapshots__/icon-settings.test.tsx.snap
index 97eac8fca2..6c22436089 100644
--- a/packages/core/src/renderer/components/cluster-settings/__tests__/__snapshots__/icon-settings.test.tsx.snap
+++ b/packages/core/src/renderer/components/cluster-settings/__tests__/__snapshots__/icon-settings.test.tsx.snap
@@ -51,3 +51,55 @@ exports[`Icon settings given no external registrations for cluster settings menu
+
+