diff --git a/package-lock.json b/package-lock.json index 8eb60c76ad..655fe9d8e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -114,13 +114,50 @@ "semver": "bin/semver.js" } }, - "node_modules/@babel/generator": { - "version": "7.20.14", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.14.tgz", - "integrity": "sha512-AEmuXHdcD3A52HHXxaTmYlb8q/xMEhoRP67B3T4Oq7lbmSoqroMZzjnGj3+i1io3pdnF8iBYVu4Ilj+c4hBxYg==", + "node_modules/@babel/eslint-parser": { + "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": { - "@babel/types": "^7.20.7", + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.11.0", + "eslint": "^7.5.0 || ^8.0.0" + } + }, + "node_modules/@babel/eslint-parser/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@babel/eslint-parser/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "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.0", "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" }, "engines": { @@ -140,6 +177,31 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "peer": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", + "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", + "peer": true, + "dependencies": { + "@babel/helper-explode-assignable-expression": "^7.18.6", + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-compilation-targets": { "version": "7.20.7", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", @@ -166,6 +228,70 @@ "semver": "bin/semver.js" } }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.0.tgz", + "integrity": "sha512-Q8wNiMIdwsv5la5SPxNYzzkPnjgC0Sy0i7jLkVOCdllu/xcVNkr3TeZzbHBJrj+XXRqzX5uCyCoV9eu6xUG7KQ==", + "peer": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.21.0", + "@babel/helper-member-expression-to-functions": "^7.21.0", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.20.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/helper-split-export-declaration": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.21.0.tgz", + "integrity": "sha512-N+LaFW/auRSWdx7SHD/HiARwXQju1vXTW4fKr4u5SgBUTm51OKEjKgj+cs00ggW3kEvNqwErnlwuq7Y3xBe4eg==", + "peer": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "regexpu-core": "^5.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz", + "integrity": "sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==", + "peer": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.17.7", + "@babel/helper-plugin-utils": "^7.16.7", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0-0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/helper-environment-visitor": { "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", @@ -174,13 +300,25 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-function-name": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "node_modules/@babel/helper-explode-assignable-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", + "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", + "peer": true, "dependencies": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", + "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", + "dependencies": { + "@babel/template": "^7.20.7", + "@babel/types": "^7.21.0" }, "engines": { "node": ">=6.9.0" @@ -197,6 +335,18 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.21.0.tgz", + "integrity": "sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q==", + "peer": true, + "dependencies": { + "@babel/types": "^7.21.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-module-imports": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", @@ -209,9 +359,9 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz", - "integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", + "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", @@ -219,8 +369,20 @@ "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1", "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.10", - "@babel/types": "^7.20.7" + "@babel/traverse": "^7.21.2", + "@babel/types": "^7.21.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", + "peer": true, + "dependencies": { + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -234,6 +396,41 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz", + "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==", + "peer": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-wrap-function": "^7.18.9", + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz", + "integrity": "sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==", + "peer": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.20.7", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.7", + "@babel/types": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-simple-access": { "version": "7.20.2", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", @@ -245,6 +442,18 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz", + "integrity": "sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==", + "peer": true, + "dependencies": { + "@babel/types": "^7.20.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-split-export-declaration": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", @@ -273,9 +482,24 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", + "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz", + "integrity": "sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q==", + "peer": true, + "dependencies": { + "@babel/helper-function-name": "^7.19.0", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.20.5", + "@babel/types": "^7.20.5" + }, "engines": { "node": ">=6.9.0" } @@ -371,9 +595,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.20.15", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.15.tgz", - "integrity": "sha512-DI4a1oZuf8wC+oAJA9RW6ga3Zbe8RZFt7kD9i4qAspz3I/yHet1VvC3DiSy/fsUvv5pvJuNPh0LPOdCcqinDPg==", + "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" }, @@ -381,6 +605,306 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz", + "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.20.7.tgz", + "integrity": "sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/plugin-proposal-optional-chaining": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-proposal-async-generator-functions": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", + "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", + "peer": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-remap-async-to-generator": "^7.18.9", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "peer": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-static-block": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.21.0.tgz", + "integrity": "sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw==", + "peer": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-proposal-decorators": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.21.0.tgz", + "integrity": "sha512-MfgX49uRrFUTL/HvWtmx3zmpyzMMr4MTj3d527MLlr/4RTT9G/ytFFP7qet2uM2Ve03b+BkpWUpK+lRXnQ+v9w==", + "peer": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-replace-supers": "^7.20.7", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/plugin-syntax-decorators": "^7.21.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-dynamic-import": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", + "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-export-namespace-from": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", + "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-json-strings": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", + "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz", + "integrity": "sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-numeric-separator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", + "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", + "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", + "peer": true, + "dependencies": { + "@babel/compat-data": "^7.20.5", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-catch-binding": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", + "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", + "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-methods": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "peer": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0.tgz", + "integrity": "sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw==", + "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-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-unicode-property-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", + "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-async-generators": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", @@ -414,6 +938,90 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-decorators": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.21.0.tgz", + "integrity": "sha512-tIoPpGBR8UuM4++ccWN3gifhVvQu7ZizuR1fklhRJrd5ewgbkUS+0KVFeWWxELtn18NTLoW32XV7zyOgIAiz+w==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.18.6.tgz", + "integrity": "sha512-LUbR+KNTBWCUAqRG9ex5Gnzu2IOkt8jRJbHHXFT9q+L9zm7M/QQbEqXyw1n1pohYvOyWC8CjeyjrSaIwiYjK7A==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.20.0.tgz", + "integrity": "sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-import-meta": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", @@ -516,6 +1124,21 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-top-level-await": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", @@ -544,6 +1167,797 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.20.7.tgz", + "integrity": "sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.20.7.tgz", + "integrity": "sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==", + "peer": true, + "dependencies": { + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-remap-async-to-generator": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", + "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.21.0.tgz", + "integrity": "sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.21.0.tgz", + "integrity": "sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ==", + "peer": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.21.0", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-replace-supers": "^7.20.7", + "@babel/helper-split-export-declaration": "^7.18.6", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.20.7.tgz", + "integrity": "sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/template": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "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" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", + "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz", + "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", + "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", + "peer": true, + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.21.0.tgz", + "integrity": "sha512-FlFA2Mj87a6sDkW4gfGrQQqwY/dLlBAyJa2dJEZ+FHXUVHBflO2wyKvg+OOEzXfrKYIa4HWl0mgmbCzt0cMb7w==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-flow": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.21.0.tgz", + "integrity": "sha512-LlUYlydgDkKpIY7mcBWvyPPmMcOphEyYA27Ef4xpbh1IiDNLr0kZsos2nf92vz3IccvJI25QUwp86Eo5s6HmBQ==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz", + "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==", + "peer": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz", + "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", + "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.20.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.20.11.tgz", + "integrity": "sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==", + "peer": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.20.11", + "@babel/helper-plugin-utils": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.2.tgz", + "integrity": "sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA==", + "peer": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.21.2", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-simple-access": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.20.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.20.11.tgz", + "integrity": "sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==", + "peer": true, + "dependencies": { + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-module-transforms": "^7.20.11", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-validator-identifier": "^7.19.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", + "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", + "peer": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.20.5.tgz", + "integrity": "sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.20.5", + "@babel/helper-plugin-utils": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", + "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", + "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "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" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", + "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz", + "integrity": "sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.21.0.tgz", + "integrity": "sha512-6OAWljMvQrZjR2DaNhVfRz6dkCAVV+ymcLUmaf8bccGOHn2v5rHJK3tTpij0BuhdYWP4LLaqj5lwcdlpAAPuvg==", + "peer": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-jsx": "^7.18.6", + "@babel/types": "^7.21.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz", + "integrity": "sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==", + "peer": true, + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz", + "integrity": "sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ==", + "peer": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz", + "integrity": "sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "regenerator-transform": "^0.15.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", + "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.21.0.tgz", + "integrity": "sha512-ReY6pxwSzEU0b3r2/T/VhqMKg/AkceBT19X0UptA3/tYi5Pe2eXgEUH+NNMC5nok6c6XQz5tyVTUpuezRfSMSg==", + "peer": true, + "dependencies": { + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.20.2", + "babel-plugin-polyfill-corejs2": "^0.3.3", + "babel-plugin-polyfill-corejs3": "^0.6.0", + "babel-plugin-polyfill-regenerator": "^0.4.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", + "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.20.7.tgz", + "integrity": "sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", + "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz", + "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz", + "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "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-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-typescript": "^7.20.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", + "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", + "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.20.2.tgz", + "integrity": "sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg==", + "peer": true, + "dependencies": { + "@babel/compat-data": "^7.20.1", + "@babel/helper-compilation-targets": "^7.20.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-async-generator-functions": "^7.20.1", + "@babel/plugin-proposal-class-properties": "^7.18.6", + "@babel/plugin-proposal-class-static-block": "^7.18.6", + "@babel/plugin-proposal-dynamic-import": "^7.18.6", + "@babel/plugin-proposal-export-namespace-from": "^7.18.9", + "@babel/plugin-proposal-json-strings": "^7.18.6", + "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", + "@babel/plugin-proposal-numeric-separator": "^7.18.6", + "@babel/plugin-proposal-object-rest-spread": "^7.20.2", + "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", + "@babel/plugin-proposal-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-private-methods": "^7.18.6", + "@babel/plugin-proposal-private-property-in-object": "^7.18.6", + "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.20.0", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-transform-arrow-functions": "^7.18.6", + "@babel/plugin-transform-async-to-generator": "^7.18.6", + "@babel/plugin-transform-block-scoped-functions": "^7.18.6", + "@babel/plugin-transform-block-scoping": "^7.20.2", + "@babel/plugin-transform-classes": "^7.20.2", + "@babel/plugin-transform-computed-properties": "^7.18.9", + "@babel/plugin-transform-destructuring": "^7.20.2", + "@babel/plugin-transform-dotall-regex": "^7.18.6", + "@babel/plugin-transform-duplicate-keys": "^7.18.9", + "@babel/plugin-transform-exponentiation-operator": "^7.18.6", + "@babel/plugin-transform-for-of": "^7.18.8", + "@babel/plugin-transform-function-name": "^7.18.9", + "@babel/plugin-transform-literals": "^7.18.9", + "@babel/plugin-transform-member-expression-literals": "^7.18.6", + "@babel/plugin-transform-modules-amd": "^7.19.6", + "@babel/plugin-transform-modules-commonjs": "^7.19.6", + "@babel/plugin-transform-modules-systemjs": "^7.19.6", + "@babel/plugin-transform-modules-umd": "^7.18.6", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.19.1", + "@babel/plugin-transform-new-target": "^7.18.6", + "@babel/plugin-transform-object-super": "^7.18.6", + "@babel/plugin-transform-parameters": "^7.20.1", + "@babel/plugin-transform-property-literals": "^7.18.6", + "@babel/plugin-transform-regenerator": "^7.18.6", + "@babel/plugin-transform-reserved-words": "^7.18.6", + "@babel/plugin-transform-shorthand-properties": "^7.18.6", + "@babel/plugin-transform-spread": "^7.19.0", + "@babel/plugin-transform-sticky-regex": "^7.18.6", + "@babel/plugin-transform-template-literals": "^7.18.9", + "@babel/plugin-transform-typeof-symbol": "^7.18.9", + "@babel/plugin-transform-unicode-escapes": "^7.18.10", + "@babel/plugin-transform-unicode-regex": "^7.18.6", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.20.2", + "babel-plugin-polyfill-corejs2": "^0.3.3", + "babel-plugin-polyfill-corejs3": "^0.6.0", + "babel-plugin-polyfill-regenerator": "^0.4.1", + "core-js-compat": "^3.25.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", + "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.18.6.tgz", + "integrity": "sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-transform-react-display-name": "^7.18.6", + "@babel/plugin-transform-react-jsx": "^7.18.6", + "@babel/plugin-transform-react-jsx-development": "^7.18.6", + "@babel/plugin-transform-react-pure-annotations": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.21.0.tgz", + "integrity": "sha512-myc9mpoVA5m1rF8K8DgLEatOYFDpwC+RkMkjZ0Du6uI62YvDe8uxIEYVs/VCdSJ097nlALiU/yBC7//3nI+hNg==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-validator-option": "^7.21.0", + "@babel/plugin-transform-typescript": "^7.21.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "peer": true + }, "node_modules/@babel/runtime": { "version": "7.20.13", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz", @@ -556,9 +1970,9 @@ } }, "node_modules/@babel/runtime-corejs3": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.21.0.tgz", - "integrity": "sha512-TDD4UJzos3JJtM+tHX+w2Uc+KWj7GV+VKKFdMVd2Rx8sdA19hcc3P3AHFYd5LVOw+pYuSd5lICC3gm52B6Rwxw==", + "version": "7.20.13", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.20.13.tgz", + "integrity": "sha512-p39/6rmY9uvlzRiLZBIB3G9/EBr66LBMcYm7fIDeSBNdRjF2AGD3rFZucUyAgGHC2N+7DdLvVi33uTjSE44FIw==", "dev": true, "dependencies": { "core-js-pure": "^3.25.1", @@ -582,18 +1996,18 @@ } }, "node_modules/@babel/traverse": { - "version": "7.20.13", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.13.tgz", - "integrity": "sha512-kMJXfF0T6DIS9E8cgdLCSAL+cuCK+YEZHWiLK0SXpTo8YRj5lpJu3CDNKiIBCne4m9hhTIqUg6SYTAI39tAiVQ==", + "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.20.7", + "@babel/generator": "^7.21.1", "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", + "@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.20.13", - "@babel/types": "^7.20.7", + "@babel/parser": "^7.21.2", + "@babel/types": "^7.21.2", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -602,9 +2016,9 @@ } }, "node_modules/@babel/types": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz", - "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==", + "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", @@ -945,9 +2359,9 @@ } }, "node_modules/@electron/rebuild/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.16.1.tgz", + "integrity": "sha512-9kkuMZHnLH/8qXARvYSjNvq8S1GYFFzynQTAfKeaJ0sIrR3PUPuu37Z+EiIANiZBvpfTf2B5y8ecDLSMWlLv+w==", "dev": true, "engines": { "node": ">=12" @@ -1270,9 +2684,9 @@ "dev": true }, "node_modules/@esbuild/android-arm": { - "version": "0.17.11", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.11.tgz", - "integrity": "sha512-CdyX6sRVh1NzFCsf5vw3kULwlAhfy9wVt8SZlrhQ7eL2qBjGbFhRBWkkAzuZm9IIEOCKJw4DXA6R85g+qc8RDw==", + "version": "0.17.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.9.tgz", + "integrity": "sha512-efHnZVJldh2e18fK40RYzYTTRDzZ0QgL9V/73PSsAH43BauvjVwkqSHPhbcn77H0EQOUM2JPuO/XCg7jcKt94A==", "cpu": [ "arm" ], @@ -1286,9 +2700,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.17.11", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.11.tgz", - "integrity": "sha512-QnK4d/zhVTuV4/pRM4HUjcsbl43POALU2zvBynmrrqZt9LPcLA3x1fTZPBg2RRguBQnJcnU059yKr+bydkntjg==", + "version": "0.17.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.9.tgz", + "integrity": "sha512-bqds/6lXsCA7JhHGKIM/R80sy3BAIBR0HWyeas0bW57QVHT3Rz5sf4oUVS4ZsmN+J+8IgNnaIT2PXZ0pnRcLKg==", "cpu": [ "arm64" ], @@ -1302,9 +2716,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.17.11", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.11.tgz", - "integrity": "sha512-3PL3HKtsDIXGQcSCKtWD/dy+mgc4p2Tvo2qKgKHj9Yf+eniwFnuoQ0OUhlSfAEpKAFzF9N21Nwgnap6zy3L3MQ==", + "version": "0.17.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.9.tgz", + "integrity": "sha512-pP+MLR/k8BAYZuOqEkjAaQd9/pzbNS52pNFiXgdiCHb/16u6o7s0rPF8vPlVg+1s8ii+M6HrymL4534xYwCQCA==", "cpu": [ "x64" ], @@ -1318,9 +2732,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.17.11", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.11.tgz", - "integrity": "sha512-pJ950bNKgzhkGNO3Z9TeHzIFtEyC2GDQL3wxkMApDEghYx5Qers84UTNc1bAxWbRkuJOgmOha5V0WUeh8G+YGw==", + "version": "0.17.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.9.tgz", + "integrity": "sha512-Gdbnu/RCIGHE/zqLHZwujTXnHz0lBQxK9+llrbxm5tO46CMhqiOhUuA5Zt6q2imULNoPJtxmhspHSAQtcx2pkw==", "cpu": [ "arm64" ], @@ -1334,9 +2748,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.17.11", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.11.tgz", - "integrity": "sha512-iB0dQkIHXyczK3BZtzw1tqegf0F0Ab5texX2TvMQjiJIWXAfM4FQl7D909YfXWnB92OQz4ivBYQ2RlxBJrMJOw==", + "version": "0.17.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.9.tgz", + "integrity": "sha512-GEZsUsDjJnCTVWuaq1cJ1Y3oV9GmNj/h4j6jA29VYSip7S7nSSiAo4dQFBJg734QKZZFos8fHc4abJpoN2ebGw==", "cpu": [ "x64" ], @@ -1350,9 +2764,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.17.11", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.11.tgz", - "integrity": "sha512-7EFzUADmI1jCHeDRGKgbnF5sDIceZsQGapoO6dmw7r/ZBEKX7CCDnIz8m9yEclzr7mFsd+DyasHzpjfJnmBB1Q==", + "version": "0.17.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.9.tgz", + "integrity": "sha512-l3v6bZdpZIG4RpNKObqNqJhDvqQO5JqQlU2S+KyMCbf0xQhYCbTuhu5kKY8hndM1oKhmqq6VfPWhOSf6P3XT/g==", "cpu": [ "arm64" ], @@ -1366,9 +2780,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.17.11", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.11.tgz", - "integrity": "sha512-iPgenptC8i8pdvkHQvXJFzc1eVMR7W2lBPrTE6GbhR54sLcF42mk3zBOjKPOodezzuAz/KSu8CPyFSjcBMkE9g==", + "version": "0.17.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.9.tgz", + "integrity": "sha512-o/qhS0gbIdS0AjgiT0mbdiRIyNVRD31N81c1H7NNM4p6jVkSvScqo0v9eYJ+30mPhJsL26BwSNiuFJzD/SCyuw==", "cpu": [ "x64" ], @@ -1382,9 +2796,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.17.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.11.tgz", - "integrity": "sha512-M9iK/d4lgZH0U5M1R2p2gqhPV/7JPJcRz+8O8GBKVgqndTzydQ7B2XGDbxtbvFkvIs53uXTobOhv+RyaqhUiMg==", + "version": "0.17.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.9.tgz", + "integrity": "sha512-AhSVW1uIbcXssQ1D+Mn0txGgcxU32ikvIxuqkmjLC7dUpcX0JuwkPgdqTOicuBjG06GV4WvXSHcKCBUjN+oBxA==", "cpu": [ "arm" ], @@ -1398,9 +2812,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.17.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.11.tgz", - "integrity": "sha512-Qxth3gsWWGKz2/qG2d5DsW/57SeA2AmpSMhdg9TSB5Svn2KDob3qxfQSkdnWjSd42kqoxIPy3EJFs+6w1+6Qjg==", + "version": "0.17.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.9.tgz", + "integrity": "sha512-o3bvDJn9txfMxrCVJATbL3NeksMT9MGqSN7vTeG9g+387rDzfUiWpF5CN/L0MoI3QTicTydEDOx0PVX8/q+nCA==", "cpu": [ "arm64" ], @@ -1414,9 +2828,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.17.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.11.tgz", - "integrity": "sha512-dB1nGaVWtUlb/rRDHmuDQhfqazWE0LMro/AIbT2lWM3CDMHJNpLckH+gCddQyhhcLac2OYw69ikUMO34JLt3wA==", + "version": "0.17.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.9.tgz", + "integrity": "sha512-fh3Eb+jMHDJUd08vEYL8swRT7zJo4lhrcG8NYuosHVeT49XQ0Bn9xLMtgtYXjCw5aB11aphAUwnzawvDqJCqTQ==", "cpu": [ "ia32" ], @@ -1430,9 +2844,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.17.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.11.tgz", - "integrity": "sha512-aCWlq70Q7Nc9WDnormntGS1ar6ZFvUpqr8gXtO+HRejRYPweAFQN615PcgaSJkZjhHp61+MNLhzyVALSF2/Q0g==", + "version": "0.17.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.9.tgz", + "integrity": "sha512-+DvqOzQLkXonfQTHo4PTlbiTCfz0Rx6oYn3fQrUlPX2PffGOth4HjuP4jHeFbw0YFfOErhjM6n481nB4VTmmFQ==", "cpu": [ "loong64" ], @@ -1446,9 +2860,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.17.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.11.tgz", - "integrity": "sha512-cGeGNdQxqY8qJwlYH1BP6rjIIiEcrM05H7k3tR7WxOLmD1ZxRMd6/QIOWMb8mD2s2YJFNRuNQ+wjMhgEL2oCEw==", + "version": "0.17.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.9.tgz", + "integrity": "sha512-9O0HhtxRzx9OOqavv7kIONncJXxhzrbDFmOD+cJ/3UUsy8dn52J6X2xCeUOxbmEOXYP2K+uha7b1AXG/URhF5Q==", "cpu": [ "mips64el" ], @@ -1462,9 +2876,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.17.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.11.tgz", - "integrity": "sha512-BdlziJQPW/bNe0E8eYsHB40mYOluS+jULPCjlWiHzDgr+ZBRXPtgMV1nkLEGdpjrwgmtkZHEGEPaKdS/8faLDA==", + "version": "0.17.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.9.tgz", + "integrity": "sha512-tOwSTDZ0X5rcYK3OyfJVf4fFlvYLv3HGCOJxdE9gZVeRkXXd6O9CJ/A4Li1Tt9JQs9kJcFWCXxCwhY70h+t9iw==", "cpu": [ "ppc64" ], @@ -1478,9 +2892,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.17.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.11.tgz", - "integrity": "sha512-MDLwQbtF+83oJCI1Cixn68Et/ME6gelmhssPebC40RdJaect+IM+l7o/CuG0ZlDs6tZTEIoxUe53H3GmMn8oMA==", + "version": "0.17.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.9.tgz", + "integrity": "sha512-mmirCaZItLSPw7loFPHvdDXO0A2I+cYOQ96eerbWEjqi9V4u+vvYSoUR3Or7HLe1JUZS+T0YWN+jPUASc1hqzg==", "cpu": [ "riscv64" ], @@ -1494,9 +2908,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.17.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.11.tgz", - "integrity": "sha512-4N5EMESvws0Ozr2J94VoUD8HIRi7X0uvUv4c0wpTHZyZY9qpaaN7THjosdiW56irQ4qnJ6Lsc+i+5zGWnyqWqQ==", + "version": "0.17.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.9.tgz", + "integrity": "sha512-zuL5TDhxstsvxYVZ1McsnfNrO6vlpZmxiNShJmYuYPt8COBJ/4iRkwHZ5Rbf1OkEVazB3/WASNtopv1/Gq19IQ==", "cpu": [ "s390x" ], @@ -1510,9 +2924,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.17.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.11.tgz", - "integrity": "sha512-rM/v8UlluxpytFSmVdbCe1yyKQd/e+FmIJE2oPJvbBo+D0XVWi1y/NQ4iTNx+436WmDHQBjVLrbnAQLQ6U7wlw==", + "version": "0.17.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.9.tgz", + "integrity": "sha512-jVa5NKqwBmq57aNDZOSnNuRTV5GrI93HdjTlyQyRrOs7OSEQq2r9NyaGd6KmzuxLz19XTanFt4WeGoLnjFT1Ug==", "cpu": [ "x64" ], @@ -1526,9 +2940,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.17.11", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.11.tgz", - "integrity": "sha512-4WaAhuz5f91h3/g43VBGdto1Q+X7VEZfpcWGtOFXnggEuLvjV+cP6DyLRU15IjiU9fKLLk41OoJfBFN5DhPvag==", + "version": "0.17.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.9.tgz", + "integrity": "sha512-BRoQyPJ7aiQ7USFCtGmmrYTbRDa9muZAwoYchfqspd+ef8n2kKcXGQ0K2OqcLEqNFOwhLpAY4y4YAl22FbP+BA==", "cpu": [ "x64" ], @@ -1542,9 +2956,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.17.11", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.11.tgz", - "integrity": "sha512-UBj135Nx4FpnvtE+C8TWGp98oUgBcmNmdYgl5ToKc0mBHxVVqVE7FUS5/ELMImOp205qDAittL6Ezhasc2Ev/w==", + "version": "0.17.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.9.tgz", + "integrity": "sha512-gDCVw9M2k8tyA9GokQEeh+L2gl0EZeGIIj5WB5H97Mb0ADq5Ea8vWyQs2iY1Q/tebcuP8cUoOZWxkCsmlyl1NA==", "cpu": [ "x64" ], @@ -1558,9 +2972,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.17.11", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.11.tgz", - "integrity": "sha512-1/gxTifDC9aXbV2xOfCbOceh5AlIidUrPsMpivgzo8P8zUtczlq1ncFpeN1ZyQJ9lVs2hILy1PG5KPp+w8QPPg==", + "version": "0.17.9", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.9.tgz", + "integrity": "sha512-f89/xt0Hzp7POTDJYSJvotyFXatxXBGXJyFFTQGJW+NTYhFHaMcrrb41OB3L8sfzYi3PSlM3pZnwlEk1QiBX2g==", "cpu": [ "x64" ], @@ -1574,9 +2988,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.17.11", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.11.tgz", - "integrity": "sha512-vtSfyx5yRdpiOW9yp6Ax0zyNOv9HjOAw8WaZg3dF5djEHKKm3UnoohftVvIJtRh0Ec7Hso0RIdTqZvPXJ7FdvQ==", + "version": "0.17.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.9.tgz", + "integrity": "sha512-jrU/SBHXc3NPS5mPgYeL8pgIrBTwdrnaoLtygkQtuPzz0oBjsTyxV46tZoOctv4Q1Jq06+4zsJWkTzVaoik8FQ==", "cpu": [ "arm64" ], @@ -1590,9 +3004,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.17.11", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.11.tgz", - "integrity": "sha512-GFPSLEGQr4wHFTiIUJQrnJKZhZjjq4Sphf+mM76nQR6WkQn73vm7IsacmBRPkALfpOCHsopSvLgqdd4iUW2mYw==", + "version": "0.17.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.9.tgz", + "integrity": "sha512-/oVEu7DurNFM0E6qA18R8xkbYU6xilaTnqG65rqm4XJo8ONuqTzLnj/93bQps7RJIxPI+yKPl0Zx2KifvWUa5A==", "cpu": [ "ia32" ], @@ -1606,9 +3020,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.17.11", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.11.tgz", - "integrity": "sha512-N9vXqLP3eRL8BqSy8yn4Y98cZI2pZ8fyuHx6lKjiG2WABpT2l01TXdzq5Ma2ZUBzfB7tx5dXVhge8X9u0S70ZQ==", + "version": "0.17.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.9.tgz", + "integrity": "sha512-PLKuXKwlPljFrzzsUO6hHNWcYeE4a8FOX/6AJ7U7PajgKqtBGw2mGYxsfJHGb+UdfgdOapIOsYPgzMTG+SGDrg==", "cpu": [ "x64" ], @@ -1622,10 +3036,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz", - "integrity": "sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==", - "dev": true, + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", + "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -1648,7 +3061,6 @@ "version": "13.20.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", - "dev": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -1663,7 +3075,6 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, "engines": { "node": ">=10" }, @@ -1671,34 +3082,37 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@eslint/js": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz", - "integrity": "sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, "node_modules/@floating-ui/core": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.2.2.tgz", - "integrity": "sha512-FaO9KVLFnxknZaGWGmNtjD2CVFuc0u4yeGEofoyXO2wgRA7fLtkngT6UB0vtWQWuhH3iMTZZ/Y89CMeyGfn8pA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.2.1.tgz", + "integrity": "sha512-LSqwPZkK3rYfD7GKoIeExXOyYx6Q1O4iqZWwIehDNuv3Dv425FIAE8PRwtAx1imEolFTHgBEcoFHm9MDnYgPCg==", "dev": true }, "node_modules/@floating-ui/dom": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.2.3.tgz", - "integrity": "sha512-lK9cZUrHSJLMVAdCvDqs6Ug8gr0wmqksYiaoj/bxj2gweRQkSuhg2/V6Jswz2KiQ0RAULbqw1oQDJIMpQ5GfGA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.2.1.tgz", + "integrity": "sha512-Rt45SmRiV8eU+xXSB9t0uMYiQ/ZWGE/jumse2o3i5RGlyvcbqOF4q+1qBnzLE2kZ5JGhq0iMkcGXUKbFe7MpTA==", "dev": true, "dependencies": { - "@floating-ui/core": "^1.2.2" + "@floating-ui/core": "^1.2.1" } }, "node_modules/@gar/promisify": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==" + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "dev": true + }, + "node_modules/@hapi/address": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/address/-/address-5.1.0.tgz", + "integrity": "sha512-b/OicomrGhG+aRgAhtxqOArHDH7kE2sY0IQ5MwIU6EkzUIOmsfi4YfYPZxGSauHLgVzcwk2rseCi7fjeMpQh+w==", + "dependencies": { + "@hapi/hoek": "^11.0.2" + }, + "engines": { + "node": ">=14.0.0" + } }, "node_modules/@hapi/b64": { "version": "5.0.0", @@ -1761,6 +3175,11 @@ "resolved": "https://registry.npmjs.org/@hapi/file/-/file-2.0.0.tgz", "integrity": "sha512-WSrlgpvEqgPWkI18kkGELEZfXr0bYLtr16iIN4Krh9sRnzBZN6nnWxHFxtsnP684wueEySBbXPDg/WfA9xJdBQ==" }, + "node_modules/@hapi/formula": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@hapi/formula/-/formula-3.0.2.tgz", + "integrity": "sha512-hY5YPNXzw1He7s0iqkRQi+uMGh383CGdyyIGYtB+W5N3KHPXoqychklvHhKCC9M3Xtv0OCs/IHw+r4dcHtBYWw==" + }, "node_modules/@hapi/hoek": { "version": "11.0.2", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-11.0.2.tgz", @@ -1808,6 +3227,11 @@ "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" }, + "node_modules/@hapi/pinpoint": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@hapi/pinpoint/-/pinpoint-2.0.1.tgz", + "integrity": "sha512-EKQmr16tM8s16vTT3cA5L0kZZcTMU5DUOZTuvpnY738m+jyP3JIUj+Mm1xc1rsLkGBQ/gVnfKYPwOmPg1tUR4Q==" + }, "node_modules/@hapi/subtext": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@hapi/subtext/-/subtext-7.1.0.tgz", @@ -1835,18 +3259,21 @@ "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" }, - "node_modules/@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", - "dependencies": { - "@hapi/hoek": "^9.0.0" + "node_modules/@hapi/tlds": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@hapi/tlds/-/tlds-1.0.1.tgz", + "integrity": "sha512-OXs5OliWsLTmvzQKZtb3KhfEz30WuuaizwAn95GLfeK+JpGnBxR55lALv3kA4T1RRb3wlrNjnboBg6ur1Czvig==", + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@hapi/topo/node_modules/@hapi/hoek": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + "node_modules/@hapi/topo": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-6.0.1.tgz", + "integrity": "sha512-JioWUZL1Bm7r8bnCDx2AUggiPwpV7djFfDTWT1aZSyHjN++fVz7XPdW8YVCxvyv9bSWcbbOLV/h4U1zGdwrN3w==", + "dependencies": { + "@hapi/hoek": "^11.0.2" + } }, "node_modules/@hapi/vise": { "version": "4.0.0", @@ -1888,7 +3315,6 @@ "version": "0.11.8", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", - "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", @@ -1902,7 +3328,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, "engines": { "node": ">=12.22" }, @@ -1914,8 +3339,7 @@ "node_modules/@humanwhocodes/object-schema": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" }, "node_modules/@hutson/parse-repository-url": { "version": "3.0.2", @@ -1929,7 +3353,8 @@ "node_modules/@isaacs/string-locale-compare": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz", - "integrity": "sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==" + "integrity": "sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==", + "dev": true }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", @@ -3262,6 +4687,10 @@ "resolved": "packages/ensure-binaries", "link": true }, + "node_modules/@k8slens/eslint-config": { + "resolved": "packages/infrastructure/eslint-config", + "link": true + }, "node_modules/@k8slens/extensions": { "resolved": "packages/extension-api", "link": true @@ -3286,14 +4715,26 @@ "resolved": "packages/release-tool", "link": true }, + "node_modules/@k8slens/run-many": { + "resolved": "packages/utility-features/run-many", + "link": true + }, "node_modules/@k8slens/semver": { "resolved": "packages/semver", "link": true }, + "node_modules/@k8slens/test-utils": { + "resolved": "packages/utility-features/test-utils", + "link": true + }, "node_modules/@k8slens/typescript": { "resolved": "packages/infrastructure/typescript", "link": true }, + "node_modules/@k8slens/utilities": { + "resolved": "packages/utility-features/utilities", + "link": true + }, "node_modules/@k8slens/webpack": { "resolved": "packages/infrastructure/webpack", "link": true @@ -3686,6 +5127,15 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "peer": true, + "dependencies": { + "eslint-scope": "5.1.1" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -3722,6 +5172,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-5.3.0.tgz", "integrity": "sha512-+rZ9zgL1lnbl8Xbb1NQdMjveOMwj4lIYfcDtyJHHi5x4X8jtR6m8SXooJMZy5vmFVZ8w7A2Bnd/oX9eTuU8w5A==", + "dev": true, "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", "@npmcli/installed-package-contents": "^1.0.7", @@ -3769,6 +5220,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", + "dev": true, "dependencies": { "lru-cache": "^7.5.1" }, @@ -3780,6 +5232,7 @@ "version": "7.16.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.16.1.tgz", "integrity": "sha512-9kkuMZHnLH/8qXARvYSjNvq8S1GYFFzynQTAfKeaJ0sIrR3PUPuu37Z+EiIANiZBvpfTf2B5y8ecDLSMWlLv+w==", + "dev": true, "engines": { "node": ">=12" } @@ -3788,6 +5241,7 @@ "version": "9.1.2", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.2.tgz", "integrity": "sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg==", + "dev": true, "dependencies": { "hosted-git-info": "^5.0.0", "proc-log": "^2.0.1", @@ -3802,6 +5256,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -3816,6 +5271,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "dev": true, "dependencies": { "@gar/promisify": "^1.1.3", "semver": "^7.3.5" @@ -3828,6 +5284,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-3.0.2.tgz", "integrity": "sha512-CAcd08y3DWBJqJDpfuVL0uijlq5oaXaOJEKHKc4wqrjd00gkvTZB+nFuLn+doOOKddaQS9JfqtNoFCO2LCvA3w==", + "dev": true, "dependencies": { "@npmcli/promise-spawn": "^3.0.0", "lru-cache": "^7.4.4", @@ -3847,6 +5304,7 @@ "version": "7.16.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.16.1.tgz", "integrity": "sha512-9kkuMZHnLH/8qXARvYSjNvq8S1GYFFzynQTAfKeaJ0sIrR3PUPuu37Z+EiIANiZBvpfTf2B5y8ecDLSMWlLv+w==", + "dev": true, "engines": { "node": ">=12" } @@ -3855,6 +5313,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz", "integrity": "sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw==", + "dev": true, "dependencies": { "npm-bundled": "^1.1.1", "npm-normalize-package-bin": "^1.0.1" @@ -3870,6 +5329,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-2.0.4.tgz", "integrity": "sha512-bMo0aAfwhVwqoVM5UzX1DJnlvVvzDCHae821jv48L1EsrYwfOZChlqWYXEtto/+BkBXetPbEWgau++/brh4oVg==", + "dev": true, "dependencies": { "@npmcli/name-from-folder": "^1.0.1", "glob": "^8.0.1", @@ -3884,6 +5344,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -3892,6 +5353,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -3910,6 +5372,7 @@ "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -3921,6 +5384,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/@npmcli/metavuln-calculator/-/metavuln-calculator-3.1.1.tgz", "integrity": "sha512-n69ygIaqAedecLeVH3KnO39M6ZHiJ2dEv5A7DGvcqCB8q17BGUgW8QaanIkbWUo2aYGZqJaOORTLAlIvKjNDKA==", + "dev": true, "dependencies": { "cacache": "^16.0.0", "json-parse-even-better-errors": "^2.3.1", @@ -3936,6 +5400,7 @@ "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", "deprecated": "This functionality has been moved to @npmcli/fs", + "dev": true, "dependencies": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" @@ -3948,6 +5413,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -3961,12 +5427,14 @@ "node_modules/@npmcli/name-from-folder": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-1.0.1.tgz", - "integrity": "sha512-qq3oEfcLFwNfEYOQ8HLimRGKlD8WSeGEdtUa7hmzpR8Sa7haL1KVQrvgO6wqMjhWFFVjgtrh1gIxDz+P8sjUaA==" + "integrity": "sha512-qq3oEfcLFwNfEYOQ8HLimRGKlD8WSeGEdtUa7hmzpR8Sa7haL1KVQrvgO6wqMjhWFFVjgtrh1gIxDz+P8sjUaA==", + "dev": true }, "node_modules/@npmcli/node-gyp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-2.0.0.tgz", "integrity": "sha512-doNI35wIe3bBaEgrlPfdJPaCpUR89pJWep4Hq3aRdh6gKazIVWfs0jHttvSSoq47ZXgC7h73kDsUl8AoIQUB+A==", + "dev": true, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } @@ -3975,6 +5443,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-2.0.0.tgz", "integrity": "sha512-42jnZ6yl16GzjWSH7vtrmWyJDGVa/LXPdpN2rcUWolFjc9ON2N3uz0qdBbQACfmhuJZ2lbKYtmK5qx68ZPLHMA==", + "dev": true, "dependencies": { "json-parse-even-better-errors": "^2.3.1" }, @@ -3986,6 +5455,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-3.0.0.tgz", "integrity": "sha512-s9SgS+p3a9Eohe68cSI3fi+hpcZUmXq5P7w0kMlAsWVtR7XbK3ptkZqKT2cK1zLDObJ3sR+8P59sJE0w/KTL1g==", + "dev": true, "dependencies": { "infer-owner": "^1.0.4" }, @@ -3997,6 +5467,7 @@ "version": "4.1.7", "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-4.1.7.tgz", "integrity": "sha512-WXr/MyM4tpKA4BotB81NccGAv8B48lNH0gRoILucbcAhTQXLCoi6HflMV3KdXubIqvP9SuLsFn68Z7r4jl+ppw==", + "dev": true, "dependencies": { "@npmcli/node-gyp": "^2.0.0", "@npmcli/promise-spawn": "^3.0.0", @@ -4012,6 +5483,7 @@ "version": "7.16.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.16.1.tgz", "integrity": "sha512-9kkuMZHnLH/8qXARvYSjNvq8S1GYFFzynQTAfKeaJ0sIrR3PUPuu37Z+EiIANiZBvpfTf2B5y8ecDLSMWlLv+w==", + "dev": true, "engines": { "node": ">=12" } @@ -4020,6 +5492,7 @@ "version": "10.2.1", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "dev": true, "dependencies": { "agentkeepalive": "^4.2.1", "cacache": "^16.1.0", @@ -4046,6 +5519,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -4057,6 +5531,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "dev": true, "dependencies": { "minipass": "^3.1.6", "minipass-sized": "^1.0.3", @@ -4073,6 +5548,7 @@ "version": "9.3.1", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.3.1.tgz", "integrity": "sha512-4Q16ZCqq3g8awk6UplT7AuxQ35XN4R/yf/+wSAwcBUAjg7l58RTactWaP8fIDTi0FzI7YcVLujwExakZlfWkXg==", + "dev": true, "dependencies": { "env-paths": "^2.2.0", "glob": "^7.1.4", @@ -4096,6 +5572,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "dev": true, "dependencies": { "abbrev": "^1.0.0" }, @@ -4110,6 +5587,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -4124,6 +5602,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "dev": true, "dependencies": { "agent-base": "^6.0.2", "debug": "^4.3.3", @@ -4136,7 +5615,8 @@ "node_modules/@npmcli/run-script/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/@nrwl/cli": { "version": "15.7.2", @@ -4641,16 +6121,6 @@ "react-dom": "^17 || ^18" } }, - "node_modules/@ogre-tools/injectable-utils": { - "version": "15.1.2", - "resolved": "https://registry.npmjs.org/@ogre-tools/injectable-utils/-/injectable-utils-15.1.2.tgz", - "integrity": "sha512-2MjkmA2HRFQ6Czz8BWtujosFDgPO6OXnzkbWYvDFYT7W8zLJHmeXzt4mWjw90+vIfwAPOQWOlBP6T4yau9tSug==", - "peerDependencies": { - "@ogre-tools/fp": "*", - "@ogre-tools/injectable": "*", - "lodash": "^4.17.21" - } - }, "node_modules/@ogre-tools/test-utils": { "version": "15.1.2", "resolved": "https://registry.npmjs.org/@ogre-tools/test-utils/-/test-utils-15.1.2.tgz", @@ -4766,6 +6236,12 @@ } } }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz", + "integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==", + "peer": true + }, "node_modules/@sentry/browser": { "version": "6.19.2", "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.19.2.tgz", @@ -5003,29 +6479,6 @@ "jest-runtime": ">=28" } }, - "node_modules/@sideway/address": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", - "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@sideway/address/node_modules/@hapi/hoek": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" - }, - "node_modules/@sideway/formula": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", - "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" - }, - "node_modules/@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" - }, "node_modules/@sinclair/typebox": { "version": "0.25.23", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.23.tgz", @@ -5827,9 +7280,9 @@ "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" }, "node_modules/@types/http-proxy": { - "version": "1.17.10", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.10.tgz", - "integrity": "sha512-Qs5aULi+zV1bwKAg5z1PWnDXWmsn+LxIvUGv6E2+OOMYhclZMO+OXd9pYVf2gLykf2I7IV2u7oTHwChPNsvJ7g==", + "version": "1.17.9", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz", + "integrity": "sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw==", "dev": true, "dependencies": { "@types/node": "*" @@ -5973,9 +7426,9 @@ "dev": true }, "node_modules/@types/memorystream": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@types/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha512-eSkOeBPwr0godOTPV4hQTzXZElnpyHhhCCscrcN6teFLbSPC8Xyb/rxsU2r6tg+eNzIuVX4miav3KhY6NUpgMw==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@types/memorystream/-/memorystream-0.3.0.tgz", + "integrity": "sha512-gzh6mqZcLryYHn4g2MuMWjo9J1+Py/XYwITyZmUxV7ZoBIi7bTbBgSiuC5tcm3UL3gmaiYssQFDlXr/3fK94cw==", "dev": true, "dependencies": { "@types/node": "*" @@ -6286,9 +7739,9 @@ } }, "node_modules/@types/serve-static": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.1.tgz", - "integrity": "sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==", "dev": true, "dependencies": { "@types/mime": "*", @@ -6463,14 +7916,13 @@ "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.54.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.54.1.tgz", - "integrity": "sha512-a2RQAkosH3d3ZIV08s3DcL/mcGc2M/UC528VkPULFxR9VnVPT8pBu0IyBAJJmVsCmhVfwQX1v6q+QGnmSe1bew==", - "dev": true, + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.52.0.tgz", + "integrity": "sha512-lHazYdvYVsBokwCdKOppvYJKaJ4S41CgKBcPvyd0xjZNbvQdhn/pnJlGtQksQ/NhInzdaeaSarlBjDXHuclEbg==", "dependencies": { - "@typescript-eslint/scope-manager": "5.54.1", - "@typescript-eslint/type-utils": "5.54.1", - "@typescript-eslint/utils": "5.54.1", + "@typescript-eslint/scope-manager": "5.52.0", + "@typescript-eslint/type-utils": "5.52.0", + "@typescript-eslint/utils": "5.52.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -6496,15 +7948,133 @@ } } }, - "node_modules/@typescript-eslint/parser": { - "version": "5.54.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.54.1.tgz", - "integrity": "sha512-8zaIXJp/nG9Ff9vQNh7TI+C3nA6q6iIsGJ4B4L6MhZ7mHnTMR4YP5vp2xydmFXIy8rpyIVbNAG44871LMt6ujg==", - "dev": true, + "node_modules/@typescript-eslint/experimental-utils": { + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.54.0.tgz", + "integrity": "sha512-rRYECOTh5V3iWsrOzXi7h1jp3Bi9OkJHrb3wECi3DVqMGTilo9wAYmCbT+6cGdrzUY3MWcAa2mESM6FMik6tVw==", + "peer": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.54.1", - "@typescript-eslint/types": "5.54.1", - "@typescript-eslint/typescript-estree": "5.54.1", + "@typescript-eslint/utils": "5.54.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/scope-manager": { + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.0.tgz", + "integrity": "sha512-VTPYNZ7vaWtYna9M4oD42zENOBrb+ZYyCNdFs949GcN8Miwn37b8b7eMj+EZaq7VK9fx0Jd+JhmkhjFhvnovhg==", + "peer": true, + "dependencies": { + "@typescript-eslint/types": "5.54.0", + "@typescript-eslint/visitor-keys": "5.54.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/types": { + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.0.tgz", + "integrity": "sha512-nExy+fDCBEgqblasfeE3aQ3NuafBUxZxgxXcYfzYRZFHdVvk5q60KhCSkG0noHgHRo/xQ/BOzURLZAafFpTkmQ==", + "peer": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.0.tgz", + "integrity": "sha512-X2rJG97Wj/VRo5YxJ8Qx26Zqf0RRKsVHd4sav8NElhbZzhpBI8jU54i6hfo9eheumj4oO4dcRN1B/zIVEqR/MQ==", + "peer": true, + "dependencies": { + "@typescript-eslint/types": "5.54.0", + "@typescript-eslint/visitor-keys": "5.54.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/utils": { + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.54.0.tgz", + "integrity": "sha512-cuwm8D/Z/7AuyAeJ+T0r4WZmlnlxQ8wt7C7fLpFlKMR+dY6QO79Cq1WpJhvZbMA4ZeZGHiRWnht7ZJ8qkdAunw==", + "peer": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.54.0", + "@typescript-eslint/types": "5.54.0", + "@typescript-eslint/typescript-estree": "5.54.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.0.tgz", + "integrity": "sha512-xu4wT7aRCakGINTLGeyGqDn+78BwFlggwBjnHa1ar/KaGagnmwLYmlrXIrgAaQ3AE1Vd6nLfKASm7LrFHNbKGA==", + "peer": true, + "dependencies": { + "@typescript-eslint/types": "5.54.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.52.0.tgz", + "integrity": "sha512-e2KiLQOZRo4Y0D/b+3y08i3jsekoSkOYStROYmPUnGMEoA0h+k2qOH5H6tcjIc68WDvGwH+PaOrP1XRzLJ6QlA==", + "dependencies": { + "@typescript-eslint/scope-manager": "5.52.0", + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/typescript-estree": "5.52.0", "debug": "^4.3.4" }, "engines": { @@ -6524,13 +8094,12 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.54.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.1.tgz", - "integrity": "sha512-zWKuGliXxvuxyM71UA/EcPxaviw39dB2504LqAmFDjmkpO8qNLHcmzlh6pbHs1h/7YQ9bnsO8CCcYCSA8sykUg==", - "dev": true, + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.52.0.tgz", + "integrity": "sha512-AR7sxxfBKiNV0FWBSARxM8DmNxrwgnYMPwmpkC1Pl1n+eT8/I2NAUPuwDy/FmDcC6F8pBfmOcaxcxRHspgOBMw==", "dependencies": { - "@typescript-eslint/types": "5.54.1", - "@typescript-eslint/visitor-keys": "5.54.1" + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/visitor-keys": "5.52.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -6541,13 +8110,12 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.54.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.54.1.tgz", - "integrity": "sha512-WREHsTz0GqVYLIbzIZYbmUUr95DKEKIXZNH57W3s+4bVnuF1TKe2jH8ZNH8rO1CeMY3U4j4UQeqPNkHMiGem3g==", - "dev": true, + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.52.0.tgz", + "integrity": "sha512-tEKuUHfDOv852QGlpPtB3lHOoig5pyFQN/cUiZtpw99D93nEBjexRLre5sQZlkMoHry/lZr8qDAt2oAHLKA6Jw==", "dependencies": { - "@typescript-eslint/typescript-estree": "5.54.1", - "@typescript-eslint/utils": "5.54.1", + "@typescript-eslint/typescript-estree": "5.52.0", + "@typescript-eslint/utils": "5.52.0", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -6568,10 +8136,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.54.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.1.tgz", - "integrity": "sha512-G9+1vVazrfAfbtmCapJX8jRo2E4MDXxgm/IMOF4oGh3kq7XuK3JRkOg6y2Qu1VsTRmWETyTkWt1wxy7X7/yLkw==", - "dev": true, + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.52.0.tgz", + "integrity": "sha512-oV7XU4CHYfBhk78fS7tkum+/Dpgsfi91IIDy7fjCyq2k6KB63M6gMC0YIvy+iABzmXThCRI6xpCEyVObBdWSDQ==", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -6581,13 +8148,12 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.54.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.1.tgz", - "integrity": "sha512-bjK5t+S6ffHnVwA0qRPTZrxKSaFYocwFIkZx5k7pvWfsB1I57pO/0M0Skatzzw1sCkjJ83AfGTL0oFIFiDX3bg==", - "dev": true, + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.52.0.tgz", + "integrity": "sha512-WeWnjanyEwt6+fVrSR0MYgEpUAuROxuAH516WPjUblIrClzYJj0kBbjdnbQXLpgAN8qbEuGywiQsXUVDiAoEuQ==", "dependencies": { - "@typescript-eslint/types": "5.54.1", - "@typescript-eslint/visitor-keys": "5.54.1", + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/visitor-keys": "5.52.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -6608,16 +8174,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.54.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.54.1.tgz", - "integrity": "sha512-IY5dyQM8XD1zfDe5X8jegX6r2EVU5o/WJnLu/znLPWCBF7KNGC+adacXnt5jEYS9JixDcoccI6CvE4RCjHMzCQ==", - "dev": true, + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.52.0.tgz", + "integrity": "sha512-As3lChhrbwWQLNk2HC8Ree96hldKIqk98EYvypd3It8Q1f8d5zWyIoaZEp2va5667M4ZyE7X8UUR+azXrFl+NA==", "dependencies": { "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.54.1", - "@typescript-eslint/types": "5.54.1", - "@typescript-eslint/typescript-estree": "5.54.1", + "@typescript-eslint/scope-manager": "5.52.0", + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/typescript-estree": "5.52.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0", "semver": "^7.3.7" @@ -6634,12 +8199,11 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.54.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.1.tgz", - "integrity": "sha512-q8iSoHTgwCfgcRJ2l2x+xCbu8nBlRAlsQ33k24Adj8eoVBE0f8dUeI+bAa8F84Mv05UGbAx57g2zrRsYIooqQg==", - "dev": true, + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.52.0.tgz", + "integrity": "sha512-qMwpw6SU5VHCPr99y274xhbm+PRViK/NATY6qzt+Et7+mThGuFSl/ompj2/hrBlRP/kq+BFdgagnOSgw9TB0eA==", "dependencies": { - "@typescript-eslint/types": "5.54.1", + "@typescript-eslint/types": "5.52.0", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -6910,7 +8474,8 @@ "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true }, "node_modules/abort-controller": { "version": "3.0.0", @@ -6968,7 +8533,6 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -7064,6 +8628,7 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz", "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==", + "dev": true, "dependencies": { "debug": "^4.1.0", "depd": "^1.1.2", @@ -7334,7 +8899,8 @@ "node_modules/aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true }, "node_modules/arch": { "version": "2.2.0", @@ -7360,6 +8926,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "dev": true, "dependencies": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" @@ -7424,7 +8991,6 @@ "version": "3.1.6", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -7451,7 +9017,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -7469,7 +9034,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -7487,7 +9051,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -7508,7 +9071,8 @@ "node_modules/asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true }, "node_modules/asar": { "version": "3.2.0", @@ -7548,6 +9112,12 @@ "node": ">=0.8" } }, + "node_modules/ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", + "peer": true + }, "node_modules/astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", @@ -7686,6 +9256,15 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" }, + "node_modules/axe-core": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.6.3.tgz", + "integrity": "sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg==", + "peer": true, + "engines": { + "node": ">=4" + } + }, "node_modules/axios": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.3.tgz", @@ -7711,6 +9290,15 @@ "node": ">= 6" } }, + "node_modules/axobject-query": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", + "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "peer": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, "node_modules/b4a": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.1.tgz", @@ -7879,7 +9467,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", - "dev": true, "dependencies": { "@babel/runtime": "^7.12.5", "cosmiconfig": "^7.0.0", @@ -7890,6 +9477,60 @@ "npm": ">=6" } }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz", + "integrity": "sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==", + "peer": true, + "dependencies": { + "@babel/compat-data": "^7.17.7", + "@babel/helper-define-polyfill-provider": "^0.3.3", + "semver": "^6.1.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz", + "integrity": "sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==", + "peer": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.3", + "core-js-compat": "^3.25.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz", + "integrity": "sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==", + "peer": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-transform-react-remove-prop-types": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", + "integrity": "sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==", + "peer": true + }, "node_modules/babel-preset-current-node-syntax": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", @@ -7927,6 +9568,30 @@ "@babel/core": "^7.0.0" } }, + "node_modules/babel-preset-react-app": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-react-app/-/babel-preset-react-app-10.0.1.tgz", + "integrity": "sha512-b0D9IZ1WhhCWkrTXyFuIIgqGzSkRIH5D5AmB0bXbzYAB1OBAwHcUeyWW2LorutLWF5btNo/N7r/cIdmvvKJlYg==", + "peer": true, + "dependencies": { + "@babel/core": "^7.16.0", + "@babel/plugin-proposal-class-properties": "^7.16.0", + "@babel/plugin-proposal-decorators": "^7.16.4", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.0", + "@babel/plugin-proposal-numeric-separator": "^7.16.0", + "@babel/plugin-proposal-optional-chaining": "^7.16.0", + "@babel/plugin-proposal-private-methods": "^7.16.0", + "@babel/plugin-transform-flow-strip-types": "^7.16.0", + "@babel/plugin-transform-react-display-name": "^7.16.0", + "@babel/plugin-transform-runtime": "^7.16.4", + "@babel/preset-env": "^7.16.4", + "@babel/preset-react": "^7.16.0", + "@babel/preset-typescript": "^7.16.0", + "@babel/runtime": "^7.16.3", + "babel-plugin-macros": "^3.1.0", + "babel-plugin-transform-react-remove-prop-types": "^0.4.24" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -7997,6 +9662,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/bin-links/-/bin-links-3.0.3.tgz", "integrity": "sha512-zKdnMPWEdh4F5INR07/eBrodC7QrF5JKvqskjz/ZZRXg5YSAZIbn8zGhbhUrElzHBZ2fvEQdOU59RHcTG3GiwA==", + "dev": true, "dependencies": { "cmd-shim": "^5.0.0", "mkdirp-infer-owner": "^2.0.0", @@ -8013,6 +9679,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz", "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==", + "dev": true, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } @@ -8021,6 +9688,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -8467,6 +10135,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "dev": true, "dependencies": { "semver": "^7.0.0" } @@ -8501,6 +10170,7 @@ "version": "16.1.3", "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", + "dev": true, "dependencies": { "@npmcli/fs": "^2.1.0", "@npmcli/move-file": "^2.0.0", @@ -8529,6 +10199,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -8537,6 +10208,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -8555,6 +10227,7 @@ "version": "7.16.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.16.1.tgz", "integrity": "sha512-9kkuMZHnLH/8qXARvYSjNvq8S1GYFFzynQTAfKeaJ0sIrR3PUPuu37Z+EiIANiZBvpfTf2B5y8ecDLSMWlLv+w==", + "dev": true, "engines": { "node": ">=12" } @@ -8563,6 +10236,7 @@ "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -8574,6 +10248,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -8585,6 +10260,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -8599,6 +10275,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -8608,6 +10285,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -8627,6 +10305,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -8637,7 +10316,8 @@ "node_modules/cacache/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/cacheable-lookup": { "version": "5.0.4", @@ -9162,6 +10842,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-5.0.0.tgz", "integrity": "sha512-qkCtZ59BidfEwHltnJwkyVZn+XQojdAySM1D1gSeh11Z4pW1Kpolkyo53L5noc0nrxmIvyFwTmJRo4xs7FFLPw==", + "dev": true, "dependencies": { "mkdirp-infer-owner": "^2.0.0" }, @@ -9235,6 +10916,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, "bin": { "color-support": "bin.js" } @@ -9279,6 +10961,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.6.0.tgz", "integrity": "sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==", + "dev": true, "dependencies": { "strip-ansi": "^6.0.1", "wcwidth": "^1.0.0" @@ -9324,7 +11007,8 @@ "node_modules/common-ancestor-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz", - "integrity": "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==" + "integrity": "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==", + "dev": true }, "node_modules/common-path-prefix": { "version": "3.0.0", @@ -9535,6 +11219,12 @@ "proto-list": "~1.2.1" } }, + "node_modules/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", + "peer": true + }, "node_modules/connect-history-api-fallback": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", @@ -9547,7 +11237,8 @@ "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true }, "node_modules/content-disposition": { "version": "0.5.4", @@ -9916,10 +11607,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/core-js-pure": { + "node_modules/core-js-compat": { "version": "3.29.0", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.29.0.tgz", - "integrity": "sha512-v94gUjN5UTe1n0yN/opTihJ8QBWD2O8i19RfTZR7foONPWArnjB96QA/wk5ozu1mm6ja3udQCzOzwQXTxi3xOQ==", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.29.0.tgz", + "integrity": "sha512-ScMn3uZNAFhK2DGoEfErguoiAHhV2Ju+oJo/jK08p7B3f3UhocUrCCkTvnZaiS+edl5nlIoiBXKcwMc6elv4KQ==", + "peer": true, + "dependencies": { + "browserslist": "^4.21.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-pure": { + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.28.0.tgz", + "integrity": "sha512-DSOVleA9/v3LNj/vFxAPfUHttKTzrB2RXhAPvR5TPXn4vrra3Z2ssytvRyt8eruJwAfwAiFADEbrjcRdcvPLQQ==", "dev": true, "hasInstallScript": true, "funding": { @@ -10162,6 +11866,12 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==" }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "peer": true + }, "node_modules/dargs": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", @@ -10259,6 +11969,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", "integrity": "sha512-syBZ+rnAK3EgMsH2aYEOLUW7mZSY9Gb+0wUMCFsZvcmiz+HigA0LOcq/HoQqVuGG+EKykunc7QG2bzrponfaSw==", + "dev": true, "engines": { "node": "*" } @@ -10567,12 +12278,14 @@ "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true }, "node_modules/depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -10645,6 +12358,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, "dependencies": { "asap": "^2.0.0", "wrappy": "1" @@ -10826,7 +12540,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, "dependencies": { "esutils": "^2.0.2" }, @@ -10924,9 +12637,9 @@ } }, "node_modules/dompurify": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.5.tgz", - "integrity": "sha512-jggCCd+8Iqp4Tsz0nIvpcb22InKEBrGz5dw3EQJMs8HPJDsKbFIO3STYtAvCfDx26Muevn1MHVI0XxjgFfmiSA==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.4.tgz", + "integrity": "sha512-1e2SpqHiRx4DPvmRuXU5J0di3iQACwJM+mFGE2HAkkK7Tbnfk9WcghcAmyWc9CRrjyRRUpmuhPUH6LphQQR3EQ==", "dev": true }, "node_modules/domutils": { @@ -11006,9 +12719,9 @@ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, "node_modules/duplexify/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==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -11343,9 +13056,9 @@ } }, "node_modules/electron/node_modules/@types/node": { - "version": "16.18.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.14.tgz", - "integrity": "sha512-wvzClDGQXOCVNU4APPopC2KtMYukaF1MN/W3xAmslx22Z4/IF1/izDMekuyoUlwfnDHYCIZGaj7jMwnJKBTxKw==" + "version": "16.18.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.12.tgz", + "integrity": "sha512-vzLe5NaNMjIE3mcddFVGlAXN1LEWueUsMsOJWaT6wWMJGyljHAWHznqfnKUQWGzu7TLPrGvWdNAsvQYW+C0xtw==" }, "node_modules/emittery": { "version": "0.10.2", @@ -11390,6 +13103,7 @@ "version": "0.1.13", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dev": true, "optional": true, "dependencies": { "iconv-lite": "^0.6.2" @@ -11466,7 +13180,8 @@ "node_modules/err-code": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==" + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true }, "node_modules/errno": { "version": "0.1.8", @@ -11501,7 +13216,6 @@ "version": "1.21.1", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.1.tgz", "integrity": "sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg==", - "dev": true, "dependencies": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", @@ -11572,7 +13286,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", - "dev": true, "dependencies": { "get-intrinsic": "^1.1.3", "has": "^1.0.3", @@ -11586,7 +13299,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", - "dev": true, "dependencies": { "has": "^1.0.3" } @@ -11595,7 +13307,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, "dependencies": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -11616,9 +13327,9 @@ "peer": true }, "node_modules/esbuild": { - "version": "0.17.11", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.11.tgz", - "integrity": "sha512-pAMImyokbWDtnA/ufPxjQg0fYo2DDuzAlqwnDvbXqHLphe+m80eF++perYKVm8LeTuj2zUuFXC+xgSVxyoHUdg==", + "version": "0.17.9", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.9.tgz", + "integrity": "sha512-m3b2MR76QkwKPw/KQBlBJVaIncfQhhXsDMCFPoyqEOIziV+O7BAKqOYT1NbHsnFUX0/98CLWxUfM5stzh4yq4Q==", "dev": true, "hasInstallScript": true, "bin": { @@ -11628,28 +13339,28 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.17.11", - "@esbuild/android-arm64": "0.17.11", - "@esbuild/android-x64": "0.17.11", - "@esbuild/darwin-arm64": "0.17.11", - "@esbuild/darwin-x64": "0.17.11", - "@esbuild/freebsd-arm64": "0.17.11", - "@esbuild/freebsd-x64": "0.17.11", - "@esbuild/linux-arm": "0.17.11", - "@esbuild/linux-arm64": "0.17.11", - "@esbuild/linux-ia32": "0.17.11", - "@esbuild/linux-loong64": "0.17.11", - "@esbuild/linux-mips64el": "0.17.11", - "@esbuild/linux-ppc64": "0.17.11", - "@esbuild/linux-riscv64": "0.17.11", - "@esbuild/linux-s390x": "0.17.11", - "@esbuild/linux-x64": "0.17.11", - "@esbuild/netbsd-x64": "0.17.11", - "@esbuild/openbsd-x64": "0.17.11", - "@esbuild/sunos-x64": "0.17.11", - "@esbuild/win32-arm64": "0.17.11", - "@esbuild/win32-ia32": "0.17.11", - "@esbuild/win32-x64": "0.17.11" + "@esbuild/android-arm": "0.17.9", + "@esbuild/android-arm64": "0.17.9", + "@esbuild/android-x64": "0.17.9", + "@esbuild/darwin-arm64": "0.17.9", + "@esbuild/darwin-x64": "0.17.9", + "@esbuild/freebsd-arm64": "0.17.9", + "@esbuild/freebsd-x64": "0.17.9", + "@esbuild/linux-arm": "0.17.9", + "@esbuild/linux-arm64": "0.17.9", + "@esbuild/linux-ia32": "0.17.9", + "@esbuild/linux-loong64": "0.17.9", + "@esbuild/linux-mips64el": "0.17.9", + "@esbuild/linux-ppc64": "0.17.9", + "@esbuild/linux-riscv64": "0.17.9", + "@esbuild/linux-s390x": "0.17.9", + "@esbuild/linux-x64": "0.17.9", + "@esbuild/netbsd-x64": "0.17.9", + "@esbuild/openbsd-x64": "0.17.9", + "@esbuild/sunos-x64": "0.17.9", + "@esbuild/win32-arm64": "0.17.9", + "@esbuild/win32-ia32": "0.17.9", + "@esbuild/win32-x64": "0.17.9" } }, "node_modules/esbuild-loader": { @@ -12079,7 +13790,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "devOptional": true, "engines": { "node": ">=10" }, @@ -12177,13 +13887,11 @@ } }, "node_modules/eslint": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz", - "integrity": "sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==", - "dev": true, + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.34.0.tgz", + "integrity": "sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg==", "dependencies": { - "@eslint/eslintrc": "^2.0.0", - "@eslint/js": "8.35.0", + "@eslint/eslintrc": "^1.4.1", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -12197,7 +13905,7 @@ "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.3.0", "espree": "^9.4.0", - "esquery": "^1.4.2", + "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", @@ -12233,11 +13941,117 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint-config-airbnb-base": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", + "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", + "peer": true, + "dependencies": { + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5", + "semver": "^6.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.2" + } + }, + "node_modules/eslint-config-airbnb-base/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-config-airbnb-typescript": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-17.0.0.tgz", + "integrity": "sha512-elNiuzD0kPAPTXjFWg+lE24nMdHMtuxgYoD30OyMD6yrW1AhFZPAg27VX7d3tzOErw+dgJTNWfRSDqEcXb4V0g==", + "peer": true, + "dependencies": { + "eslint-config-airbnb-base": "^15.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^5.13.0", + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.3" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.7.0.tgz", + "integrity": "sha512-HHVXLSlVUhMSmyW4ZzEuvjpwqamgmlfkutD53cYXLikh4pt/modINRcCIApJ84czDxM4GZInwUrromsDdTImTA==", + "peer": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-config-react-app": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-7.0.1.tgz", + "integrity": "sha512-K6rNzvkIeHaTd8m/QEh1Zko0KI7BACWkkneSs6s9cKZC/J27X3eZR6Upt1jkmZ/4FK+XUOPPxMEN7+lbUXfSlA==", + "peer": true, + "dependencies": { + "@babel/core": "^7.16.0", + "@babel/eslint-parser": "^7.16.3", + "@rushstack/eslint-patch": "^1.1.0", + "@typescript-eslint/eslint-plugin": "^5.5.0", + "@typescript-eslint/parser": "^5.5.0", + "babel-preset-react-app": "^10.0.1", + "confusing-browser-globals": "^1.0.11", + "eslint-plugin-flowtype": "^8.0.3", + "eslint-plugin-import": "^2.25.3", + "eslint-plugin-jest": "^25.3.0", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-react": "^7.27.1", + "eslint-plugin-react-hooks": "^4.3.0", + "eslint-plugin-testing-library": "^5.0.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "eslint": "^8.0.0" + } + }, + "node_modules/eslint-config-react-app/node_modules/eslint-plugin-jest": { + "version": "25.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz", + "integrity": "sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==", + "peer": true, + "dependencies": { + "@typescript-eslint/experimental-utils": "^5.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^4.0.0 || ^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } + } + }, "node_modules/eslint-import-resolver-node": { "version": "0.3.7", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", - "dev": true, "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.11.0", @@ -12248,7 +14062,6 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, "dependencies": { "ms": "^2.1.1" } @@ -12313,7 +14126,6 @@ "version": "2.7.4", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", - "dev": true, "dependencies": { "debug": "^3.2.7" }, @@ -12330,11 +14142,28 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, "dependencies": { "ms": "^2.1.1" } }, + "node_modules/eslint-plugin-flowtype": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz", + "integrity": "sha512-dX8l6qUL6O+fYPtpNRideCFSpmWOUVx5QcaGLVqe/vlDiBSe4vYljDWDETwnyFzpl7By/WVIu6rcrniCgH9BqQ==", + "peer": true, + "dependencies": { + "lodash": "^4.17.21", + "string-natural-compare": "^3.0.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@babel/plugin-syntax-flow": "^7.14.5", + "@babel/plugin-transform-react-jsx": "^7.14.9", + "eslint": "^8.1.0" + } + }, "node_modules/eslint-plugin-header": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/eslint-plugin-header/-/eslint-plugin-header-3.1.1.tgz", @@ -12348,7 +14177,6 @@ "version": "2.27.5", "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", - "dev": true, "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", @@ -12377,7 +14205,6 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, "dependencies": { "ms": "^2.1.1" } @@ -12386,7 +14213,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, "dependencies": { "esutils": "^2.0.2" }, @@ -12398,16 +14224,122 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, "bin": { "semver": "bin/semver.js" } }, + "node_modules/eslint-plugin-jest": { + "version": "27.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.1.tgz", + "integrity": "sha512-l067Uxx7ZT8cO9NJuf+eJHvt6bqJyz2Z29wykyEdz/OtmcELQl2MQGQLX8J94O1cSJWAwUSEvCjwjA7KEK3Hmg==", + "peer": true, + "dependencies": { + "@typescript-eslint/utils": "^5.10.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^5.0.0", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz", + "integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.20.7", + "aria-query": "^5.1.3", + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "ast-types-flow": "^0.0.7", + "axe-core": "^4.6.2", + "axobject-query": "^3.1.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "has": "^1.0.3", + "jsx-ast-utils": "^3.3.3", + "language-tags": "=1.0.5", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "peer": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "peer": true + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-no-unsanitized": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-4.0.2.tgz", + "integrity": "sha512-Pry0S9YmHoz8NCEMRQh7N0Yexh2MYCNPIlrV52hTmS7qXnTghWsjXouF08bgsrrZqaW9tt1ZiK3j5NEmPE+EjQ==", + "peer": true, + "peerDependencies": { + "eslint": "^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "peer": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, "node_modules/eslint-plugin-react": { "version": "7.32.2", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==", - "dev": true, "dependencies": { "array-includes": "^3.1.6", "array.prototype.flatmap": "^1.3.1", @@ -12436,7 +14368,6 @@ "version": "4.6.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", - "dev": true, "engines": { "node": ">=10" }, @@ -12448,7 +14379,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, "dependencies": { "esutils": "^2.0.2" }, @@ -12460,7 +14390,6 @@ "version": "2.0.0-next.4", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", - "dev": true, "dependencies": { "is-core-module": "^2.9.0", "path-parse": "^1.0.7", @@ -12477,16 +14406,48 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, "bin": { "semver": "bin/semver.js" } }, + "node_modules/eslint-plugin-security": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-1.7.1.tgz", + "integrity": "sha512-sMStceig8AFglhhT2LqlU5r+/fn9OwsA72O5bBuQVTssPCdQAOQzL+oMn/ZcpeUY6KcNfLJArgcrsSULNjYYdQ==", + "peer": true, + "dependencies": { + "safe-regex": "^2.1.1" + } + }, + "node_modules/eslint-plugin-simple-import-sort": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-10.0.0.tgz", + "integrity": "sha512-AeTvO9UCMSNzIHRkg8S6c3RPy5YEwKWSQPx3DYghLedo2ZQxowPFLGDN1AZ2evfg6r6mjBSZSLxLFsWSu3acsw==", + "peer": true, + "peerDependencies": { + "eslint": ">=5.0.0" + } + }, + "node_modules/eslint-plugin-testing-library": { + "version": "5.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.10.2.tgz", + "integrity": "sha512-f1DmDWcz5SDM+IpCkEX0lbFqrrTs8HRsEElzDEqN/EBI0hpRj8Cns5+IVANXswE8/LeybIJqPAOQIFu2j5Y5sw==", + "peer": true, + "dependencies": { + "@typescript-eslint/utils": "^5.43.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0", + "npm": ">=6" + }, + "peerDependencies": { + "eslint": "^7.5.0 || ^8.0.0" + } + }, "node_modules/eslint-plugin-unused-imports": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-2.0.0.tgz", "integrity": "sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==", - "dev": true, "dependencies": { "eslint-rule-composer": "^0.3.0" }, @@ -12503,11 +14464,22 @@ } } }, + "node_modules/eslint-plugin-xss": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/eslint-plugin-xss/-/eslint-plugin-xss-0.1.12.tgz", + "integrity": "sha512-L5oYaD//ZE7fKNtWUfVgYTRW19jrZlvaHe2swyFLxXQ5pwVQLivi5m92rtXd/ww8yqg4Drasqyi0hlBmhf9YQg==", + "peer": true, + "dependencies": { + "requireindex": "~1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/eslint-rule-composer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz", "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==", - "dev": true, "engines": { "node": ">=4.0.0" } @@ -12536,7 +14508,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, "dependencies": { "eslint-visitor-keys": "^2.0.0" }, @@ -12554,7 +14525,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, "engines": { "node": ">=10" } @@ -12563,7 +14533,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } @@ -12572,7 +14541,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -12585,7 +14553,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, "dependencies": { "is-glob": "^4.0.3" }, @@ -12597,7 +14564,6 @@ "version": "13.20.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", - "dev": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -12612,7 +14578,6 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, "engines": { "node": ">=10" }, @@ -12624,7 +14589,6 @@ "version": "9.4.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", - "dev": true, "dependencies": { "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", @@ -12653,7 +14617,6 @@ "version": "1.4.2", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.2.tgz", "integrity": "sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng==", - "dev": true, "dependencies": { "estraverse": "^5.1.0" }, @@ -13172,6 +15135,12 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, + "node_modules/fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "peer": true + }, "node_modules/fast-fifo": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.1.0.tgz", @@ -13306,7 +15275,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, "dependencies": { "flat-cache": "^3.0.4" }, @@ -13549,7 +15517,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -13589,7 +15556,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, "dependencies": { "flatted": "^3.1.0", "rimraf": "^3.0.2" @@ -13602,7 +15568,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -13616,8 +15581,7 @@ "node_modules/flatted": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" }, "node_modules/fn.name": { "version": "1.1.0", @@ -13853,7 +15817,6 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.3", @@ -13879,6 +15842,7 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "dev": true, "dependencies": { "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.3", @@ -14034,7 +15998,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.1.1" @@ -14243,7 +16206,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "devOptional": true, "dependencies": { "define-properties": "^1.1.3" }, @@ -14553,7 +16515,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -14589,7 +16550,8 @@ "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true }, "node_modules/he": { "version": "1.2.0", @@ -14630,6 +16592,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -14641,6 +16604,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -14651,7 +16615,8 @@ "node_modules/hosted-git-info/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/hpack.js": { "version": "2.1.6", @@ -14672,9 +16637,9 @@ "dev": true }, "node_modules/hpack.js/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==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "dependencies": { "core-util-is": "~1.0.0", @@ -14960,6 +16925,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dev": true, "dependencies": { "ms": "^2.0.0" } @@ -15062,6 +17028,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-5.0.1.tgz", "integrity": "sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==", + "dev": true, "dependencies": { "minimatch": "^5.0.1" }, @@ -15073,6 +17040,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -15081,6 +17049,7 @@ "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -15185,7 +17154,8 @@ "node_modules/infer-owner": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true }, "node_modules/inflight": { "version": "1.0.6", @@ -15210,6 +17180,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/init-package-json/-/init-package-json-3.0.2.tgz", "integrity": "sha512-YhlQPEjNFqlGdzrBfDNRLhvoSgX7iQRgSxgsNknRQ9ITXFT7UMfVMWhBTOh2Y+25lRnGrv5Xz8yZwQ3ACR6T3A==", + "dev": true, "dependencies": { "npm-package-arg": "^9.0.1", "promzard": "^0.3.0", @@ -15227,6 +17198,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", + "dev": true, "dependencies": { "lru-cache": "^7.5.1" }, @@ -15238,6 +17210,7 @@ "version": "7.16.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.16.1.tgz", "integrity": "sha512-9kkuMZHnLH/8qXARvYSjNvq8S1GYFFzynQTAfKeaJ0sIrR3PUPuu37Z+EiIANiZBvpfTf2B5y8ecDLSMWlLv+w==", + "dev": true, "engines": { "node": ">=12" } @@ -15246,6 +17219,7 @@ "version": "9.1.2", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.2.tgz", "integrity": "sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg==", + "dev": true, "dependencies": { "hosted-git-info": "^5.0.0", "proc-log": "^2.0.1", @@ -15322,7 +17296,8 @@ "node_modules/ip": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "dev": true }, "node_modules/ip-regex": { "version": "4.3.0", @@ -15486,9 +17461,9 @@ } }, "node_modules/is-electron": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-electron/-/is-electron-2.2.2.tgz", - "integrity": "sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==" + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-electron/-/is-electron-2.2.1.tgz", + "integrity": "sha512-r8EEQQsqT+Gn0aXFx7lTFygYQhILLCB+wn0WCDL5LZRINeLH/Rvw1j2oKodELLXYNImQ3CRlVsY8wW4cGOsyuw==" }, "node_modules/is-extendable": { "version": "0.1.1", @@ -15559,7 +17534,8 @@ "node_modules/is-lambda": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==" + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "dev": true }, "node_modules/is-map": { "version": "2.0.2", @@ -15573,7 +17549,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -15810,7 +17785,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, "dependencies": { "call-bind": "^1.0.2" }, @@ -18858,26 +20832,22 @@ "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==" }, "node_modules/joi": { - "version": "17.8.3", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.8.3.tgz", - "integrity": "sha512-q5Fn6Tj/jR8PfrLrx4fpGH4v9qM6o+vDUfD4/3vxxyg34OmKcNqYZ1qn2mpLza96S8tL0p0rIw2gOZX+/cTg9w==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.8.1.tgz", + "integrity": "sha512-Zoafe6E2kQ+hkkJQSBnOxA8beb2LF33keCxZP3vSy7qTHj9/2GAEQ9KLwfe+PR35WvspwNz0jWajDIHLnCKfpg==", "dependencies": { - "@hapi/hoek": "^9.0.0", - "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.3", - "@sideway/formula": "^3.0.1", - "@sideway/pinpoint": "^2.0.0" + "@hapi/address": "^5.1.0", + "@hapi/formula": "^3.0.2", + "@hapi/hoek": "^11.0.2", + "@hapi/pinpoint": "^2.0.1", + "@hapi/tlds": "^1.0.1", + "@hapi/topo": "^6.0.1" } }, - "node_modules/joi/node_modules/@hapi/hoek": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" - }, "node_modules/jose": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/jose/-/jose-4.13.1.tgz", - "integrity": "sha512-MSJQC5vXco5Br38mzaQKiq9mwt7lwj2eXpgpRyQYNHYt2lq1PjkWa7DLXX0WVcQLE9HhMh3jPiufS7fhJf+CLQ==", + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.12.0.tgz", + "integrity": "sha512-wW1u3cK81b+SFcHjGC8zw87yuyUweEFe0UJirrXEw1NasW00eF7sZjeG3SLBGz001ozxQ46Y9sofDvhBmWFtXQ==", "optional": true, "funding": { "url": "https://github.com/sponsors/panva" @@ -18896,7 +20866,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", - "dev": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/js-sdsl" @@ -19025,13 +20994,13 @@ "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" }, "node_modules/json-stringify-nice": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz", "integrity": "sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw==", + "dev": true, "funding": { "url": "https://github.com/sponsors/isaacs" } @@ -19072,6 +21041,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "dev": true, "engines": [ "node >= 0.2.0" ] @@ -19218,7 +21188,6 @@ "version": "3.3.3", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", - "dev": true, "dependencies": { "array-includes": "^3.1.5", "object.assign": "^4.1.3" @@ -19257,9 +21226,9 @@ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" }, "node_modules/jszip/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==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -19281,12 +21250,14 @@ "node_modules/just-diff": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/just-diff/-/just-diff-5.2.0.tgz", - "integrity": "sha512-6ufhP9SHjb7jibNFrNxyFZ6od3g+An6Ai9mhGRvcYe8UJlH0prseN64M+6ZBBUoKYHZsitDP42gAJ8+eVWr3lw==" + "integrity": "sha512-6ufhP9SHjb7jibNFrNxyFZ6od3g+An6Ai9mhGRvcYe8UJlH0prseN64M+6ZBBUoKYHZsitDP42gAJ8+eVWr3lw==", + "dev": true }, "node_modules/just-diff-apply": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/just-diff-apply/-/just-diff-apply-5.5.0.tgz", - "integrity": "sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw==" + "integrity": "sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw==", + "dev": true }, "node_modules/keyv": { "version": "4.5.2", @@ -19325,6 +21296,21 @@ "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" }, + "node_modules/language-subtag-registry": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", + "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==", + "peer": true + }, + "node_modules/language-tags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", + "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", + "peer": true, + "dependencies": { + "language-subtag-registry": "~0.3.2" + } + }, "node_modules/lazy-cache": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", @@ -19858,7 +21844,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -19871,6 +21856,7 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/libnpmaccess/-/libnpmaccess-6.0.3.tgz", "integrity": "sha512-4tkfUZprwvih2VUZYMozL7EMKgQ5q9VW2NtRyxWtQWlkLTAWHRklcAvBN49CVqEkhUw7vTX2fNgB5LzgUucgYg==", + "dev": true, "dependencies": { "aproba": "^2.0.0", "minipass": "^3.1.1", @@ -19885,6 +21871,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", + "dev": true, "dependencies": { "lru-cache": "^7.5.1" }, @@ -19896,6 +21883,7 @@ "version": "7.16.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.16.1.tgz", "integrity": "sha512-9kkuMZHnLH/8qXARvYSjNvq8S1GYFFzynQTAfKeaJ0sIrR3PUPuu37Z+EiIANiZBvpfTf2B5y8ecDLSMWlLv+w==", + "dev": true, "engines": { "node": ">=12" } @@ -19904,6 +21892,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -19915,6 +21904,7 @@ "version": "9.1.2", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.2.tgz", "integrity": "sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg==", + "dev": true, "dependencies": { "hosted-git-info": "^5.0.0", "proc-log": "^2.0.1", @@ -19928,12 +21918,14 @@ "node_modules/libnpmaccess/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/libnpmpublish": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/libnpmpublish/-/libnpmpublish-6.0.4.tgz", "integrity": "sha512-lvAEYW8mB8QblL6Q/PI/wMzKNvIrF7Kpujf/4fGS/32a2i3jzUXi04TNyIBcK6dQJ34IgywfaKGh+Jq4HYPFmg==", + "dev": true, "dependencies": { "normalize-package-data": "^4.0.0", "npm-package-arg": "^9.0.1", @@ -19949,6 +21941,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", + "dev": true, "dependencies": { "lru-cache": "^7.5.1" }, @@ -19960,6 +21953,7 @@ "version": "7.16.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.16.1.tgz", "integrity": "sha512-9kkuMZHnLH/8qXARvYSjNvq8S1GYFFzynQTAfKeaJ0sIrR3PUPuu37Z+EiIANiZBvpfTf2B5y8ecDLSMWlLv+w==", + "dev": true, "engines": { "node": ">=12" } @@ -19968,6 +21962,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-4.0.1.tgz", "integrity": "sha512-EBk5QKKuocMJhB3BILuKhmaPjI8vNRSpIfO9woLC6NyHVkKKdVEdAO1mrT0ZfxNR1lKwCcTkuZfmGIFdizZ8Pg==", + "dev": true, "dependencies": { "hosted-git-info": "^5.0.0", "is-core-module": "^2.8.1", @@ -19982,6 +21977,7 @@ "version": "9.1.2", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.2.tgz", "integrity": "sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg==", + "dev": true, "dependencies": { "hosted-git-info": "^5.0.0", "proc-log": "^2.0.1", @@ -20090,7 +22086,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -20123,6 +22118,12 @@ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "peer": true + }, "node_modules/lodash.escaperegexp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", @@ -20147,8 +22148,7 @@ "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, "node_modules/lodash.template": { "version": "4.5.0", @@ -20308,6 +22308,7 @@ "version": "9.1.0", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "dev": true, "dependencies": { "agentkeepalive": "^4.1.3", "cacache": "^15.2.0", @@ -20334,6 +22335,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "dev": true, "dependencies": { "@gar/promisify": "^1.0.1", "semver": "^7.3.5" @@ -20344,6 +22346,7 @@ "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", "deprecated": "This functionality has been moved to @npmcli/fs", + "dev": true, "dependencies": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" @@ -20356,6 +22359,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true, "engines": { "node": ">= 6" } @@ -20364,6 +22368,7 @@ "version": "15.3.0", "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "dev": true, "dependencies": { "@npmcli/fs": "^1.0.0", "@npmcli/move-file": "^1.0.1", @@ -20392,6 +22397,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, "dependencies": { "@tootallnate/once": "1", "agent-base": "6", @@ -20405,6 +22411,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -20416,6 +22423,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -20427,6 +22435,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -20441,6 +22450,7 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "dev": true, "dependencies": { "minipass": "^3.1.1" }, @@ -20452,6 +22462,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, "dependencies": { "unique-slug": "^2.0.0" } @@ -20460,6 +22471,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, "dependencies": { "imurmurhash": "^0.1.4" } @@ -20467,7 +22479,8 @@ "node_modules/make-fetch-happen/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/make-plural": { "version": "6.2.2", @@ -21080,6 +23093,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, "dependencies": { "minipass": "^3.0.0" }, @@ -21091,6 +23105,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -21101,12 +23116,14 @@ "node_modules/minipass-collect/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/minipass-fetch": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "dev": true, "dependencies": { "minipass": "^3.1.0", "minipass-sized": "^1.0.3", @@ -21123,6 +23140,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -21133,12 +23151,14 @@ "node_modules/minipass-fetch/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/minipass-flush": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, "dependencies": { "minipass": "^3.0.0" }, @@ -21150,6 +23170,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -21160,12 +23181,14 @@ "node_modules/minipass-flush/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/minipass-json-stream": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", + "dev": true, "dependencies": { "jsonparse": "^1.3.1", "minipass": "^3.0.0" @@ -21175,6 +23198,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -21185,12 +23209,14 @@ "node_modules/minipass-json-stream/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/minipass-pipeline": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, "dependencies": { "minipass": "^3.0.0" }, @@ -21202,6 +23228,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -21212,12 +23239,14 @@ "node_modules/minipass-pipeline/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/minipass-sized": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, "dependencies": { "minipass": "^3.0.0" }, @@ -21229,6 +23258,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -21239,7 +23269,8 @@ "node_modules/minipass-sized/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/minizlib": { "version": "2.1.2", @@ -21326,6 +23357,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/mkdirp-infer-owner/-/mkdirp-infer-owner-2.0.0.tgz", "integrity": "sha512-sdqtiFt3lkOaYvTXSRIUjkIdPTcxgv5+fgqYE/5qgwdw12cOrAuzzgzvVExIkH/ul1oeHN3bCLOWSG3XOqbKKw==", + "dev": true, "dependencies": { "chownr": "^2.0.0", "infer-owner": "^1.0.4", @@ -21379,9 +23411,9 @@ } }, "node_modules/mobx-react-lite": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/mobx-react-lite/-/mobx-react-lite-3.4.2.tgz", - "integrity": "sha512-wOFI6qhMBucYNy00aSDoee23L2//wKYJp4z5k+YOhOCY303prwLaWiEhJU0H2c//oIEEswGqUHtVV2qptk/g5g==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/mobx-react-lite/-/mobx-react-lite-3.4.0.tgz", + "integrity": "sha512-bRuZp3C0itgLKHu/VNxi66DN/XVkQG7xtoBVWxpvC5FhAqbOCP21+nPhULjnzEqd7xBMybp6KwytdUpZKEgpIQ==", "funding": { "type": "opencollective", "url": "https://opencollective.com/mobx" @@ -21437,11 +23469,11 @@ } }, "node_modules/moment-timezone": { - "version": "0.5.41", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.41.tgz", - "integrity": "sha512-e0jGNZDOHfBXJGz8vR/sIMXvBIGJJcqFjmlg9lmE+5KX1U7/RZNMswfD8nKnNCnQdKTIj50IaRKwl1fvMLyyRg==", + "version": "0.5.40", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.40.tgz", + "integrity": "sha512-tWfmNkRYmBkPJz5mr9GVDn9vRlVZOTe6yqY92rFxiOdWXbjaR0+9LwQnZGGuNR63X456NqmEkbskte8tWL5ePg==", "dependencies": { - "moment": "^2.29.4" + "moment": ">= 2.9.0" }, "engines": { "node": "*" @@ -21561,8 +23593,7 @@ "node_modules/natural-compare-lite": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==" }, "node_modules/needle": { "version": "3.2.0", @@ -21594,6 +23625,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -21692,6 +23724,7 @@ "version": "8.4.1", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "dev": true, "dependencies": { "env-paths": "^2.2.0", "glob": "^7.1.4", @@ -21726,6 +23759,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -21775,9 +23809,9 @@ "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==" }, "node_modules/nodemon": { - "version": "2.0.21", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.21.tgz", - "integrity": "sha512-djN/n2549DUtY33S7o1djRCd7dEm0kBnj9c7S9XVXqRUbuggN1MZH/Nqa+5RFQr63Fbefq37nFXAE9VU86yL1A==", + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", + "integrity": "sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==", "dev": true, "dependencies": { "chokidar": "^3.5.2", @@ -21845,6 +23879,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dev": true, "dependencies": { "abbrev": "1" }, @@ -22064,6 +24099,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", + "dev": true, "dependencies": { "npm-normalize-package-bin": "^1.0.1" } @@ -22096,6 +24132,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-5.0.0.tgz", "integrity": "sha512-65lUsMI8ztHCxFz5ckCEC44DRvEGdZX5usQFriauxHEwt7upv1FKaQEmAtU0YnOAdwuNWCmk64xYiQABNrEyLA==", + "dev": true, "dependencies": { "semver": "^7.1.1" }, @@ -22106,12 +24143,14 @@ "node_modules/npm-normalize-package-bin": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", + "dev": true }, "node_modules/npm-package-arg": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.1.tgz", "integrity": "sha512-CsP95FhWQDwNqiYS+Q0mZ7FAEDytDZAkNxQqea6IaAFJTAY9Lhhqyl0irU/6PMc7BGfUmnsbHcqxJD7XuVM/rg==", + "dev": true, "dependencies": { "hosted-git-info": "^3.0.6", "semver": "^7.0.0", @@ -22124,12 +24163,14 @@ "node_modules/npm-package-arg/node_modules/builtins": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", - "integrity": "sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==" + "integrity": "sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==", + "dev": true }, "node_modules/npm-package-arg/node_modules/hosted-git-info": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz", "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==", + "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -22141,6 +24182,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -22152,6 +24194,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", "integrity": "sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==", + "dev": true, "dependencies": { "builtins": "^1.0.3" } @@ -22159,12 +24202,14 @@ "node_modules/npm-package-arg/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/npm-packlist": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-5.1.1.tgz", "integrity": "sha512-UfpSvQ5YKwctmodvPPkK6Fwk603aoVsf8AEbmVKAEECrfvL8SSe1A2YIwrJ6xmTHAITKPwwZsWo7WwEbNk0kxw==", + "dev": true, "dependencies": { "glob": "^8.0.1", "ignore-walk": "^5.0.1", @@ -22182,6 +24227,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -22190,6 +24236,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -22208,6 +24255,7 @@ "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -22219,6 +24267,7 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-7.0.2.tgz", "integrity": "sha512-gk37SyRmlIjvTfcYl6RzDbSmS9Y4TOBXfsPnoYqTHARNgWbyDiCSMLUpmALDj4jjcTZpURiEfsSHJj9k7EV4Rw==", + "dev": true, "dependencies": { "npm-install-checks": "^5.0.0", "npm-normalize-package-bin": "^2.0.0", @@ -22233,6 +24282,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", + "dev": true, "dependencies": { "lru-cache": "^7.5.1" }, @@ -22244,6 +24294,7 @@ "version": "7.16.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.16.1.tgz", "integrity": "sha512-9kkuMZHnLH/8qXARvYSjNvq8S1GYFFzynQTAfKeaJ0sIrR3PUPuu37Z+EiIANiZBvpfTf2B5y8ecDLSMWlLv+w==", + "dev": true, "engines": { "node": ">=12" } @@ -22252,6 +24303,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz", "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==", + "dev": true, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } @@ -22260,6 +24312,7 @@ "version": "9.1.2", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.2.tgz", "integrity": "sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg==", + "dev": true, "dependencies": { "hosted-git-info": "^5.0.0", "proc-log": "^2.0.1", @@ -22274,6 +24327,7 @@ "version": "13.3.0", "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-13.3.0.tgz", "integrity": "sha512-10LJQ/1+VhKrZjIuY9I/+gQTvumqqlgnsCufoXETHAPFTS3+M+Z5CFhZRDHGavmJ6rOye3UvNga88vl8n1r6gg==", + "dev": true, "dependencies": { "make-fetch-happen": "^10.0.6", "minipass": "^3.1.6", @@ -22291,6 +24345,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", + "dev": true, "dependencies": { "lru-cache": "^7.5.1" }, @@ -22302,6 +24357,7 @@ "version": "7.16.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.16.1.tgz", "integrity": "sha512-9kkuMZHnLH/8qXARvYSjNvq8S1GYFFzynQTAfKeaJ0sIrR3PUPuu37Z+EiIANiZBvpfTf2B5y8ecDLSMWlLv+w==", + "dev": true, "engines": { "node": ">=12" } @@ -22310,6 +24366,7 @@ "version": "10.2.1", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "dev": true, "dependencies": { "agentkeepalive": "^4.2.1", "cacache": "^16.1.0", @@ -22336,6 +24393,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -22347,6 +24405,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "dev": true, "dependencies": { "minipass": "^3.1.6", "minipass-sized": "^1.0.3", @@ -22363,6 +24422,7 @@ "version": "9.1.2", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.2.tgz", "integrity": "sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg==", + "dev": true, "dependencies": { "hosted-git-info": "^5.0.0", "proc-log": "^2.0.1", @@ -22377,6 +24437,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "dev": true, "dependencies": { "agent-base": "^6.0.2", "debug": "^4.3.3", @@ -22389,7 +24450,8 @@ "node_modules/npm-registry-fetch/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/npm-run-path": { "version": "2.0.2", @@ -24609,6 +26671,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "dev": true, "dependencies": { "are-we-there-yet": "^3.0.0", "console-control-strings": "^1.1.0", @@ -24962,7 +27025,6 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -24976,7 +27038,6 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -24993,7 +27054,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", - "dev": true, "dependencies": { "define-properties": "^1.1.4", "es-abstract": "^1.20.4" @@ -25018,7 +27078,6 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -25179,7 +27238,6 @@ "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -25279,7 +27337,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -25417,6 +27474,7 @@ "version": "13.6.1", "resolved": "https://registry.npmjs.org/pacote/-/pacote-13.6.1.tgz", "integrity": "sha512-L+2BI1ougAPsFjXRyBhcKmfT016NscRFLv6Pz5EiNf1CCFJFU0pSKKQwsZTyAQB+sTuUL4TyFyp6J1Ork3dOqw==", + "dev": true, "dependencies": { "@npmcli/git": "^3.0.0", "@npmcli/installed-package-contents": "^1.0.7", @@ -25451,6 +27509,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", + "dev": true, "dependencies": { "lru-cache": "^7.5.1" }, @@ -25462,6 +27521,7 @@ "version": "7.16.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.16.1.tgz", "integrity": "sha512-9kkuMZHnLH/8qXARvYSjNvq8S1GYFFzynQTAfKeaJ0sIrR3PUPuu37Z+EiIANiZBvpfTf2B5y8ecDLSMWlLv+w==", + "dev": true, "engines": { "node": ">=12" } @@ -25470,6 +27530,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -25481,6 +27542,7 @@ "version": "9.1.2", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.2.tgz", "integrity": "sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg==", + "dev": true, "dependencies": { "hosted-git-info": "^5.0.0", "proc-log": "^2.0.1", @@ -25495,6 +27557,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -25508,7 +27571,8 @@ "node_modules/pacote/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/pako": { "version": "0.2.9", @@ -25540,6 +27604,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/parse-conflict-json/-/parse-conflict-json-2.0.2.tgz", "integrity": "sha512-jDbRGb00TAPFsKWCpZZOT93SxVP9nONOSgES3AevqRq/CHvavEBvKAjxX9p5Y5F0RZLxH9Ufd9+RwtCsa+lFDA==", + "dev": true, "dependencies": { "json-parse-even-better-errors": "^2.3.1", "just-diff": "^5.0.1", @@ -25660,6 +27725,7 @@ "version": "1.6.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.6.1.tgz", "integrity": "sha512-OW+5s+7cw6253Q4E+8qQ/u1fVvcJQCJo/VFD8pje+dbJCF1n5ZRMV2AEHbGp+5Q7jxQIYJxkHopnj6nzdGeZLA==", + "dev": true, "dependencies": { "lru-cache": "^7.14.1", "minipass": "^4.0.2" @@ -25675,6 +27741,7 @@ "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, "engines": { "node": ">=12" } @@ -25885,13 +27952,13 @@ } }, "node_modules/playwright": { - "version": "1.31.2", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.31.2.tgz", - "integrity": "sha512-jpC47n2PKQNtzB7clmBuWh6ftBRS/Bt5EGLigJ9k2QAKcNeYXZkEaDH5gmvb6+AbcE0DO6GnXdbl9ogG6Eh+og==", + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.30.0.tgz", + "integrity": "sha512-ENbW5o75HYB3YhnMTKJLTErIBExrSlX2ZZ1C/FzmHjUYIfxj/UnI+DWpQr992m+OQVSg0rCExAOlRwB+x+yyIg==", "dev": true, "hasInstallScript": true, "dependencies": { - "playwright-core": "1.31.2" + "playwright-core": "1.30.0" }, "bin": { "playwright": "cli.js" @@ -25901,9 +27968,9 @@ } }, "node_modules/playwright-core": { - "version": "1.31.2", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.31.2.tgz", - "integrity": "sha512-a1dFgCNQw4vCsG7bnojZjDnPewZcw7tZUNFN0ZkcLYKj+mPmXvg4MpaaKZ5SgqPsOmqIf2YsVRkgqiRDxD+fDQ==", + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.30.0.tgz", + "integrity": "sha512-7AnRmTCf+GVYhHbLJsGUtskWTE33SwMZkybJ0v6rqR1boxq2x36U7p1vDRV7HO2IwTZgmycracLxPEJI49wu4g==", "dev": true, "bin": { "playwright": "cli.js" @@ -26474,7 +28541,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, "engines": { "node": ">= 0.8.0" } @@ -26487,6 +28553,33 @@ "node": ">=4" } }, + "node_modules/prettier": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.4.tgz", + "integrity": "sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw==", + "peer": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "peer": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/pretty-error": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", @@ -26541,6 +28634,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-2.0.1.tgz", "integrity": "sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==", + "dev": true, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } @@ -26570,6 +28664,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz", "integrity": "sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==", + "dev": true, "funding": { "url": "https://github.com/sponsors/isaacs" } @@ -26578,6 +28673,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-call-limit/-/promise-call-limit-1.0.1.tgz", "integrity": "sha512-3+hgaa19jzCGLuSCbieeRsu5C2joKfYn8pY6JAuXFRVfF4IO+L7UPpFWNTeWT9pM7uhskvbPPd/oEOktCn317Q==", + "dev": true, "funding": { "url": "https://github.com/sponsors/isaacs" } @@ -26585,12 +28681,14 @@ "node_modules/promise-inflight": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==" + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "dev": true }, "node_modules/promise-retry": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, "dependencies": { "err-code": "^2.0.2", "retry": "^0.12.0" @@ -26615,6 +28713,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/promzard/-/promzard-0.3.0.tgz", "integrity": "sha512-JZeYqd7UAcHCwI+sTOeUDYkvEU+1bQ7iE0UT1MgB/tERkAPkesW46MrpIySzODi+owTjZtiF8Ay5j9m60KmMBw==", + "dev": true, "dependencies": { "read": "1" } @@ -27229,6 +29328,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", + "dev": true, "dependencies": { "mute-stream": "~0.0.4" }, @@ -27249,6 +29349,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-3.0.0.tgz", "integrity": "sha512-KQDVjGqhZk92PPNRj9ZEXEuqg8bUobSKRw+q0YQ3TKI5xkce7bUJobL4Z/OtiEbAAv70yEpYIXp4iQ9L8oPVog==", + "dev": true, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } @@ -27282,6 +29383,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-5.0.1.tgz", "integrity": "sha512-MALHuNgYWdGW3gKzuNMuYtcSSZbGQm94fAp16xt8VsYTLBjUSc55bLMKe6gzpWue0Tfi6CBgwCSdDAqutGDhMg==", + "dev": true, "dependencies": { "glob": "^8.0.1", "json-parse-even-better-errors": "^2.3.1", @@ -27296,6 +29398,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz", "integrity": "sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==", + "dev": true, "dependencies": { "json-parse-even-better-errors": "^2.3.0", "npm-normalize-package-bin": "^1.0.1" @@ -27308,6 +29411,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -27316,6 +29420,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -27334,6 +29439,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", + "dev": true, "dependencies": { "lru-cache": "^7.5.1" }, @@ -27345,6 +29451,7 @@ "version": "7.16.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.16.1.tgz", "integrity": "sha512-9kkuMZHnLH/8qXARvYSjNvq8S1GYFFzynQTAfKeaJ0sIrR3PUPuu37Z+EiIANiZBvpfTf2B5y8ecDLSMWlLv+w==", + "dev": true, "engines": { "node": ">=12" } @@ -27353,6 +29460,7 @@ "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -27364,6 +29472,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-4.0.1.tgz", "integrity": "sha512-EBk5QKKuocMJhB3BILuKhmaPjI8vNRSpIfO9woLC6NyHVkKKdVEdAO1mrT0ZfxNR1lKwCcTkuZfmGIFdizZ8Pg==", + "dev": true, "dependencies": { "hosted-git-info": "^5.0.0", "is-core-module": "^2.8.1", @@ -27587,6 +29696,7 @@ "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz", "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==", "deprecated": "This functionality has been moved to @npmcli/fs", + "dev": true, "dependencies": { "debuglog": "^1.0.1", "dezalgo": "^1.0.0", @@ -27637,11 +29747,47 @@ "@babel/runtime": "^7.9.2" } }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "peer": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", + "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", + "peer": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, + "node_modules/regenerator-transform": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz", + "integrity": "sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexp-tree": { + "version": "0.1.24", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.24.tgz", + "integrity": "sha512-s2aEVuLhvnVJW6s/iPgEGK6R+/xngd2jNQ+xy4bXNDKxZKJH6jpPHY6kVeVv1IeLCHgswRj+Kl3ELaDjG6V1iw==", + "peer": true, + "bin": { + "regexp-tree": "bin/regexp-tree" + } + }, "node_modules/regexp.prototype.flags": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", @@ -27662,7 +29808,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, "engines": { "node": ">=8" }, @@ -27670,6 +29815,44 @@ "url": "https://github.com/sponsors/mysticatea" } }, + "node_modules/regexpu-core": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.1.tgz", + "integrity": "sha512-nCOzW2V/X15XpLsK2rlgdwrysrBq+AauCn+omItIz4R1pIcmeot5zvjdmOBRLzEH/CkC6IxMJVmxDe3QcMuNVQ==", + "peer": true, + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "peer": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "peer": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, "node_modules/relateurl": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", @@ -27822,6 +30005,15 @@ "node": ">=0.10.0" } }, + "node_modules/requireindex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.1.0.tgz", + "integrity": "sha512-LBnkqsDE7BZKvqylbmn7lTIVdpx4K/QCduRATpO5R+wtPmky/a8pN1bO2D6wXppn1497AJF9mNjqAXr6bdl9jg==", + "peer": true, + "engines": { + "node": ">=0.10.5" + } + }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -27946,6 +30138,7 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.3.1.tgz", "integrity": "sha512-GfHJHBzFQra23IxDzIdBqhOWfbtdgS1/dCHrDy+yvhpoJY5TdwdT28oWaHWfRpKFDLd3GZnGTx6Mlt4+anbsxQ==", + "dev": true, "dependencies": { "glob": "^9.2.0" }, @@ -27963,6 +30156,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -27971,6 +30165,7 @@ "version": "9.2.1", "resolved": "https://registry.npmjs.org/glob/-/glob-9.2.1.tgz", "integrity": "sha512-Pxxgq3W0HyA3XUvSXcFhRSs+43Jsx0ddxcFrbjxNGkL2Ak5BAUBxLqI5G6ADDeCHLfzzXFhe0b1yYcctGmytMA==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "minimatch": "^7.4.1", @@ -27988,6 +30183,7 @@ "version": "7.4.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.2.tgz", "integrity": "sha512-xy4q7wou3vUoC9k1xGTXc+awNdGaGVHtFUaey8tiX4H1QRc04DZ/rmDFwNm2EBsuYEhAZ6SgMmYf3InGY6OauA==", + "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -28069,11 +30265,19 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/safe-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz", + "integrity": "sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==", + "peer": true, + "dependencies": { + "regexp-tree": "~0.1.1" + } + }, "node_modules/safe-regex-test": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.1.3", @@ -28478,7 +30682,8 @@ "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true }, "node_modules/set-getter": { "version": "0.1.1", @@ -28723,6 +30928,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" @@ -28743,6 +30949,7 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "dev": true, "dependencies": { "ip": "^2.0.0", "smart-buffer": "^4.2.0" @@ -28756,6 +30963,7 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "dev": true, "dependencies": { "agent-base": "^6.0.2", "debug": "^4.3.3", @@ -28857,6 +31065,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -28865,12 +31074,14 @@ "node_modules/spdx-exceptions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true }, "node_modules/spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -28879,7 +31090,8 @@ "node_modules/spdx-license-ids": { "version": "3.0.12", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", - "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==" + "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", + "dev": true }, "node_modules/spdy": { "version": "4.0.2", @@ -28975,6 +31187,7 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", + "dev": true, "dependencies": { "minipass": "^3.1.1" }, @@ -28986,6 +31199,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -28996,7 +31210,8 @@ "node_modules/ssri/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/stack-trace": { "version": "0.0.10", @@ -29235,6 +31450,12 @@ "node": ">=10" } }, + "node_modules/string-natural-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-3.0.1.tgz", + "integrity": "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==", + "peer": true + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -29252,7 +31473,6 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -29271,7 +31491,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -29285,7 +31504,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -30361,6 +32579,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/treeverse/-/treeverse-2.0.0.tgz", "integrity": "sha512-N5gJCkLu1aXccpOTtqV6ddSEi6ZmGkh3hjmbu1IjcavJK4qyOVQmi0myQKM7z5jVGmD68SJoliaVrMmVObhj6A==", + "dev": true, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } @@ -30527,7 +32746,6 @@ "version": "3.21.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, "dependencies": { "tslib": "^1.8.1" }, @@ -30541,8 +32759,7 @@ "node_modules/tsutils/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/tunnel": { "version": "0.0.6", @@ -30574,7 +32791,6 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, "dependencies": { "prelude-ls": "^1.2.1" }, @@ -30594,7 +32810,6 @@ "version": "2.19.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true, "engines": { "node": ">=12.20" }, @@ -30619,7 +32834,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "for-each": "^0.3.3", @@ -30761,7 +32975,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, "dependencies": { "call-bind": "^1.0.2", "has-bigints": "^1.0.2", @@ -30783,10 +32996,51 @@ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", "integrity": "sha512-cp0oQQyZhUM1kpJDLdGO1jPZHgS/MpzoWYfe9+CM2h/QGDZlqwT2T3YGukuBdaNJ/CAPoeyAZRRHz8JFo176vA==" }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "peer": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "peer": true, + "engines": { + "node": ">=4" + } + }, "node_modules/unique-filename": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "dev": true, "dependencies": { "unique-slug": "^3.0.0" }, @@ -30798,6 +33052,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "dev": true, "dependencies": { "imurmurhash": "^0.1.4" }, @@ -31028,6 +33283,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" @@ -31037,6 +33293,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz", "integrity": "sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==", + "dev": true, "dependencies": { "builtins": "^5.0.0" }, @@ -31139,7 +33396,8 @@ "node_modules/walk-up-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-1.0.0.tgz", - "integrity": "sha512-hwj/qMDUEjCU5h0xr90KGCf0tg0/LgJbmOWgrWKYlcJZM7XvquvUJZ0G/HMGr7F7OQMOUuPHWP9JpriinkAlkg==" + "integrity": "sha512-hwj/qMDUEjCU5h0xr90KGCf0tg0/LgJbmOWgrWKYlcJZM7XvquvUJZ0G/HMGr7F7OQMOUuPHWP9JpriinkAlkg==", + "dev": true }, "node_modules/walker": { "version": "1.0.8", @@ -31665,6 +33923,7 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" } @@ -32086,9 +34345,9 @@ } }, "node_modules/zod": { - "version": "3.21.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz", - "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==", + "version": "3.20.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.20.6.tgz", + "integrity": "sha512-oyu0m54SGCtzh6EClBVqDDlAYRz4jrVtKwQ7ZnsEmMI9HnzuZFj8QFwAY1M5uniIYACdGvv0PBWPF2kO0aNofA==", "funding": { "url": "https://github.com/sponsors/colinhacks" } @@ -32113,9 +34372,9 @@ } }, "packages/bump-version-for-cron/node_modules/@types/node": { - "version": "16.18.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.14.tgz", - "integrity": "sha512-wvzClDGQXOCVNU4APPopC2KtMYukaF1MN/W3xAmslx22Z4/IF1/izDMekuyoUlwfnDHYCIZGaj7jMwnJKBTxKw==", + "version": "16.18.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.12.tgz", + "integrity": "sha512-vzLe5NaNMjIE3mcddFVGlAXN1LEWueUsMsOJWaT6wWMJGyljHAWHznqfnKUQWGzu7TLPrGvWdNAsvQYW+C0xtw==", "dev": true }, "packages/core": { @@ -32134,7 +34393,6 @@ "@ogre-tools/injectable-extension-for-auto-registration": "^15.1.2", "@ogre-tools/injectable-extension-for-mobx": "^15.1.2", "@ogre-tools/injectable-react": "^15.1.2", - "@ogre-tools/injectable-utils": "^15.1.2", "@sentry/electron": "^3.0.8", "@sentry/integrations": "^6.19.3", "@side/jest-runtime": "^1.1.0", @@ -32334,6 +34592,9 @@ "peerDependencies": { "@k8slens/application": "^6.5.0-alpha.0", "@k8slens/application-for-electron-main": "^6.5.0-alpha.0", + "@k8slens/run-many": "^1.0.0", + "@k8slens/test-utils": "^1.0.0", + "@k8slens/utilities": "^1.0.0", "@types/byline": "^4.2.33", "@types/chart.js": "^2.9.36", "@types/color": "^3.0.3", @@ -32355,9 +34616,9 @@ } }, "packages/core/node_modules/@types/node": { - "version": "16.18.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.14.tgz", - "integrity": "sha512-wvzClDGQXOCVNU4APPopC2KtMYukaF1MN/W3xAmslx22Z4/IF1/izDMekuyoUlwfnDHYCIZGaj7jMwnJKBTxKw==", + "version": "16.18.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.12.tgz", + "integrity": "sha512-vzLe5NaNMjIE3mcddFVGlAXN1LEWueUsMsOJWaT6wWMJGyljHAWHznqfnKUQWGzu7TLPrGvWdNAsvQYW+C0xtw==", "dev": true }, "packages/ensure-binaries": { @@ -32387,9 +34648,9 @@ } }, "packages/ensure-binaries/node_modules/@types/node": { - "version": "16.18.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.14.tgz", - "integrity": "sha512-wvzClDGQXOCVNU4APPopC2KtMYukaF1MN/W3xAmslx22Z4/IF1/izDMekuyoUlwfnDHYCIZGaj7jMwnJKBTxKw==", + "version": "16.18.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.12.tgz", + "integrity": "sha512-vzLe5NaNMjIE3mcddFVGlAXN1LEWueUsMsOJWaT6wWMJGyljHAWHznqfnKUQWGzu7TLPrGvWdNAsvQYW+C0xtw==", "dev": true }, "packages/extension-api": { @@ -32420,9 +34681,9 @@ } }, "packages/extension-api/node_modules/@types/node": { - "version": "16.18.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.14.tgz", - "integrity": "sha512-wvzClDGQXOCVNU4APPopC2KtMYukaF1MN/W3xAmslx22Z4/IF1/izDMekuyoUlwfnDHYCIZGaj7jMwnJKBTxKw==", + "version": "16.18.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.12.tgz", + "integrity": "sha512-vzLe5NaNMjIE3mcddFVGlAXN1LEWueUsMsOJWaT6wWMJGyljHAWHznqfnKUQWGzu7TLPrGvWdNAsvQYW+C0xtw==", "dev": true }, "packages/extension-api/node_modules/@webpack-cli/configtest": { @@ -32563,9 +34824,9 @@ } }, "packages/extension-api/node_modules/typescript-plugin-css-modules": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/typescript-plugin-css-modules/-/typescript-plugin-css-modules-4.2.2.tgz", - "integrity": "sha512-X5OYGkX96ENq2c7xFJO4tgtiMTlBkOMoRmVHQXH2H4CGFcVODKGieDqPU2B0IV0I+AyvKYDFdKh4ZKtKxAcAww==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/typescript-plugin-css-modules/-/typescript-plugin-css-modules-4.2.1.tgz", + "integrity": "sha512-WtvRJY9TVFMyOD22KQ+U6Cm9owLMFD4H5YGZFUM1UMgZQv0fQfl7aUeHeXgqG2aaPq0aZc9chUnK7WYd9BTpEw==", "dev": true, "dependencies": { "@types/postcss-modules-local-by-default": "^4.0.0", @@ -32694,6 +34955,58 @@ "url": "https://opencollective.com/libvips" } }, + "packages/infrastructure/code-style": { + "name": "@k8slens/code-style", + "version": "^6.5.0-alpha.0", + "extraneous": true, + "license": "UNLICENSED", + "peerDependencies": { + "@typescript-eslint/eslint-plugin": ">= 5", + "@typescript-eslint/parser": ">= 5", + "eslint": ">= 7", + "eslint-config-airbnb-typescript": ">= 17", + "eslint-config-prettier": ">= 8", + "eslint-config-react-app": "^7.0.1", + "eslint-plugin-import": ">= 2", + "eslint-plugin-jest": ">= 27", + "eslint-plugin-jsx-a11y": ">= 6", + "eslint-plugin-no-unsanitized": ">= 4.0.2", + "eslint-plugin-prettier": ">= 4", + "eslint-plugin-react-hooks": ">= 4", + "eslint-plugin-security": ">= 1.6.0", + "eslint-plugin-simple-import-sort": ">= 7", + "eslint-plugin-unused-imports": ">= 2", + "eslint-plugin-xss": ">= 0.1.12", + "prettier": ">= 2" + } + }, + "packages/infrastructure/eslint-config": { + "name": "@k8slens/eslint-config", + "version": "^6.5.0-alpha.0", + "license": "MIT", + "bin": { + "lens-lint": "bin/lint" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": ">= 5", + "@typescript-eslint/parser": ">= 5", + "eslint": ">= 7", + "eslint-config-airbnb-typescript": ">= 17", + "eslint-config-prettier": ">= 8", + "eslint-config-react-app": "^7.0.1", + "eslint-plugin-import": ">= 2", + "eslint-plugin-jest": ">= 27", + "eslint-plugin-jsx-a11y": ">= 6", + "eslint-plugin-no-unsanitized": ">= 4.0.2", + "eslint-plugin-prettier": ">= 4", + "eslint-plugin-react-hooks": ">= 4", + "eslint-plugin-security": ">= 1.6.0", + "eslint-plugin-simple-import-sort": ">= 7", + "eslint-plugin-unused-imports": ">= 2", + "eslint-plugin-xss": ">= 0.1.12", + "prettier": ">= 2" + } + }, "packages/infrastructure/jest": { "name": "@k8slens/jest", "version": "6.5.0-alpha.0", @@ -34175,12 +36488,14 @@ "@k8slens/ensure-binaries": "^6.5.0-alpha.0", "@k8slens/feature-core": "^6.5.0-alpha.0", "@k8slens/generate-tray-icons": "^6.5.0-alpha.0", + "@k8slens/run-many": "^1.0.0", + "@k8slens/test-utils": "^1.0.0", + "@k8slens/utilities": "^1.0.0", "@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", "@ogre-tools/injectable-react": "^15.1.2", - "@ogre-tools/injectable-utils": "^15.1.2", "mobx": "^6.8.0", "rimraf": "^4.1.2" }, @@ -34257,9 +36572,9 @@ } }, "packages/open-lens/node_modules/@types/node": { - "version": "16.18.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.14.tgz", - "integrity": "sha512-wvzClDGQXOCVNU4APPopC2KtMYukaF1MN/W3xAmslx22Z4/IF1/izDMekuyoUlwfnDHYCIZGaj7jMwnJKBTxKw==", + "version": "16.18.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.12.tgz", + "integrity": "sha512-vzLe5NaNMjIE3mcddFVGlAXN1LEWueUsMsOJWaT6wWMJGyljHAWHznqfnKUQWGzu7TLPrGvWdNAsvQYW+C0xtw==", "dev": true }, "packages/open-lens/node_modules/dotenv": { @@ -34317,9 +36632,9 @@ } }, "packages/open-lens/node_modules/typescript-plugin-css-modules": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/typescript-plugin-css-modules/-/typescript-plugin-css-modules-4.2.2.tgz", - "integrity": "sha512-X5OYGkX96ENq2c7xFJO4tgtiMTlBkOMoRmVHQXH2H4CGFcVODKGieDqPU2B0IV0I+AyvKYDFdKh4ZKtKxAcAww==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/typescript-plugin-css-modules/-/typescript-plugin-css-modules-4.2.1.tgz", + "integrity": "sha512-WtvRJY9TVFMyOD22KQ+U6Cm9owLMFD4H5YGZFUM1UMgZQv0fQfl7aUeHeXgqG2aaPq0aZc9chUnK7WYd9BTpEw==", "dev": true, "dependencies": { "@types/postcss-modules-local-by-default": "^4.0.0", @@ -34364,9 +36679,9 @@ } }, "packages/release-tool/node_modules/@types/node": { - "version": "16.18.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.14.tgz", - "integrity": "sha512-wvzClDGQXOCVNU4APPopC2KtMYukaF1MN/W3xAmslx22Z4/IF1/izDMekuyoUlwfnDHYCIZGaj7jMwnJKBTxKw==", + "version": "16.18.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.12.tgz", + "integrity": "sha512-vzLe5NaNMjIE3mcddFVGlAXN1LEWueUsMsOJWaT6wWMJGyljHAWHznqfnKUQWGzu7TLPrGvWdNAsvQYW+C0xtw==", "dev": true }, "packages/release-tool/node_modules/ansi-escapes": { @@ -34632,9 +36947,9 @@ } }, "packages/release-tool/node_modules/type-fest": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.6.1.tgz", - "integrity": "sha512-htXWckxlT6U4+ilVgweNliPqlsVSSucbxVexRYllyMVJDtf5rTjv6kF/s+qAd4QSL1BZcnJPEJavYBPQiWuZDA==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.6.0.tgz", + "integrity": "sha512-RqTRtKTzvPpNdDUp1dVkKQRunlPITk4mXeqFlAZoJsS+fLRn8AdPK0TcQDumGayhU7fjlBfiBjsq3pe3rIfXZQ==", "engines": { "node": ">=14.16" }, @@ -34676,9 +36991,9 @@ } }, "packages/semver/node_modules/@types/node": { - "version": "16.18.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.14.tgz", - "integrity": "sha512-wvzClDGQXOCVNU4APPopC2KtMYukaF1MN/W3xAmslx22Z4/IF1/izDMekuyoUlwfnDHYCIZGaj7jMwnJKBTxKw==", + "version": "16.18.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.12.tgz", + "integrity": "sha512-vzLe5NaNMjIE3mcddFVGlAXN1LEWueUsMsOJWaT6wWMJGyljHAWHznqfnKUQWGzu7TLPrGvWdNAsvQYW+C0xtw==", "dev": true }, "packages/technical-features/application": { @@ -34693,7 +37008,6 @@ "@ogre-tools/fp": "^15.1.1", "@ogre-tools/injectable": "^15.1.1", "@ogre-tools/injectable-extension-for-auto-registration": "^15.1.1", - "@ogre-tools/injectable-utils": "^15.1.1", "lodash": "^4.17.15" } }, @@ -34702,14 +37016,14 @@ "version": "6.5.0-alpha.0", "license": "MIT", "devDependencies": { - "@async-fn/jest": "^1.6.4" + "@async-fn/jest": "^1.6.4", + "@k8slens/eslint-config": "*" }, "peerDependencies": { "@k8slens/feature-core": "^6.5.0-alpha.0", "@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-utils": "^15.1.2", "lodash": "^4.17.15" } }, @@ -34719,6 +37033,7 @@ "license": "MIT", "devDependencies": { "@async-fn/jest": "^1.6.4", + "@k8slens/eslint-config": "*", "@ogre-tools/test-utils": "^15.1.2" }, "peerDependencies": { @@ -34726,7 +37041,6 @@ "@k8slens/feature-core": "^6.5.0-alpha.0", "@ogre-tools/injectable": "^15.1.2", "@ogre-tools/injectable-extension-for-auto-registration": "^15.1.2", - "@ogre-tools/injectable-utils": "^15.1.2", "electron": "^19.1.9" } }, @@ -34734,9 +37048,52 @@ "name": "@k8slens/feature-core", "version": "6.5.0-alpha.0", "license": "MIT", + "devDependencies": { + "@k8slens/eslint-config": "*" + }, "peerDependencies": { "@ogre-tools/injectable": "^15.1.2" } + }, + "packages/utility-features/run-many": { + "name": "@k8slens/run-many", + "version": "1.0.0", + "license": "MIT", + "peerDependencies": { + "@k8slens/test-utils": "^1.0.0", + "@k8slens/utilities": "^1.0.0", + "@ogre-tools/fp": "^15.1.1", + "@ogre-tools/injectable": "^15.1.1" + } + }, + "packages/utility-features/test-utils": { + "name": "@k8slens/test-utils", + "version": "1.0.0", + "license": "MIT" + }, + "packages/utility-features/types": { + "version": "1.0.0", + "extraneous": true, + "license": "MIT" + }, + "packages/utility-features/utilities": { + "name": "@k8slens/utilities", + "version": "1.0.0", + "license": "MIT", + "peerDependencies": { + "mobx": "^6.8.0", + "type-fest": "^2.19.0" + } + }, + "packages/utility-features/utility-types": { + "name": "@k8slens/utilities", + "version": "1.0.0", + "extraneous": true, + "license": "MIT", + "peerDependencies": { + "mobx": "^6.8.0", + "type-fest": "^2.19.0" + } } } } diff --git a/packages/core/package.json b/packages/core/package.json index 9d216e60d9..04ca0224c3 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -135,7 +135,6 @@ "@ogre-tools/injectable-extension-for-auto-registration": "^15.1.2", "@ogre-tools/injectable-extension-for-mobx": "^15.1.2", "@ogre-tools/injectable-react": "^15.1.2", - "@ogre-tools/injectable-utils": "^15.1.2", "@sentry/electron": "^3.0.8", "@sentry/integrations": "^6.19.3", "@side/jest-runtime": "^1.1.0", @@ -332,6 +331,9 @@ "peerDependencies": { "@k8slens/application": "^6.5.0-alpha.0", "@k8slens/application-for-electron-main": "^6.5.0-alpha.0", + "@k8slens/run-many": "^1.0.0", + "@k8slens/test-utils": "^1.0.0", + "@k8slens/utilities": "^1.0.0", "@types/byline": "^4.2.33", "@types/chart.js": "^2.9.36", "@types/color": "^3.0.3", diff --git a/packages/core/src/common/__tests__/cluster-store.test.ts b/packages/core/src/common/__tests__/cluster-store.test.ts index b30bc8178d..5b052548a5 100644 --- a/packages/core/src/common/__tests__/cluster-store.test.ts +++ b/packages/core/src/common/__tests__/cluster-store.test.ts @@ -8,8 +8,6 @@ import type { GetCustomKubeConfigFilePath } from "../app-paths/get-custom-kube-c import getCustomKubeConfigFilePathInjectable from "../app-paths/get-custom-kube-config-directory/get-custom-kube-config-directory.injectable"; import clusterStoreInjectable from "../cluster-store/cluster-store.injectable"; import type { DiContainer } from "@ogre-tools/injectable"; -import type { CreateCluster } from "../cluster/create-cluster-injection-token"; -import { createClusterInjectionToken } from "../cluster/create-cluster-injection-token"; import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable"; import { getDiForUnitTesting } from "../../main/getDiForUnitTesting"; import assert from "assert"; @@ -27,6 +25,7 @@ import type { WriteFileSync } from "../fs/write-file-sync.injectable"; import writeFileSyncInjectable from "../fs/write-file-sync.injectable"; import type { WriteBufferSync } from "../fs/write-buffer-sync.injectable"; import writeBufferSyncInjectable from "../fs/write-buffer-sync.injectable"; +import { Cluster } from "../cluster/cluster"; // NOTE: this is intended to read the actual file system const testDataIcon = readFileSync("test-data/cluster-store-migration-icon.png"); @@ -58,7 +57,6 @@ users: describe("cluster-store", () => { let di: DiContainer; let clusterStore: ClusterStore; - let createCluster: CreateCluster; let writeJsonSync: WriteJsonSync; let writeFileSync: WriteFileSync; let writeBufferSync: WriteBufferSync; @@ -74,7 +72,6 @@ describe("cluster-store", () => { di.override(kubectlBinaryNameInjectable, () => "kubectl"); di.override(kubectlDownloadingNormalizedArchInjectable, () => "amd64"); di.override(normalizedPlatformInjectable, () => "darwin"); - writeJsonSync = di.inject(writeJsonSyncInjectable); writeFileSync = di.inject(writeFileSyncInjectable); writeBufferSync = di.inject(writeBufferSyncInjectable); @@ -84,7 +81,6 @@ describe("cluster-store", () => { describe("empty config", () => { beforeEach(async () => { - createCluster = di.inject(createClusterInjectionToken); getCustomKubeConfigFilePath = di.inject(getCustomKubeConfigFilePathInjectable); writeJsonSync("/some-directory-for-user-data/lens-cluster-store.json", {}); @@ -94,7 +90,7 @@ describe("cluster-store", () => { describe("with foo cluster added", () => { beforeEach(() => { - const cluster = createCluster({ + const cluster = new Cluster({ id: "foo", contextName: "foo", preferences: { @@ -201,7 +197,6 @@ describe("cluster-store", () => { ], }); - createCluster = di.inject(createClusterInjectionToken); getCustomKubeConfigFilePath = di.inject(getCustomKubeConfigFilePathInjectable); clusterStore = di.inject(clusterStoreInjectable); @@ -256,7 +251,6 @@ describe("cluster-store", () => { ], }); - createCluster = di.inject(createClusterInjectionToken); getCustomKubeConfigFilePath = di.inject(getCustomKubeConfigFilePathInjectable); clusterStore = di.inject(clusterStoreInjectable); @@ -274,7 +268,6 @@ describe("cluster-store", () => { beforeEach(() => { di.override(storeMigrationVersionInjectable, () => "3.6.0"); - createCluster = di.inject(createClusterInjectionToken); getCustomKubeConfigFilePath = di.inject(getCustomKubeConfigFilePathInjectable); writeJsonSync("/some-directory-for-user-data/lens-cluster-store.json", { @@ -302,9 +295,9 @@ describe("cluster-store", () => { }); it("migrates to modern format with kubeconfig in a file", async () => { - const config = clusterStore.clustersList[0].kubeConfigPath; + const configPath = clusterStore.clustersList[0].kubeConfigPath.get(); - expect(readFileSync(config)).toBe(minimalValidKubeConfig); + expect(readFileSync(configPath)).toBe(minimalValidKubeConfig); }); it("migrates to modern format with icon not in file", async () => { diff --git a/packages/core/src/common/app-paths/path-to-npm-cli.global-override-for-injectable.ts b/packages/core/src/common/app-paths/path-to-npm-cli.global-override-for-injectable.ts index db4734994d..76a7a9b539 100644 --- a/packages/core/src/common/app-paths/path-to-npm-cli.global-override-for-injectable.ts +++ b/packages/core/src/common/app-paths/path-to-npm-cli.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import pathToNpmCliInjectable from "./path-to-npm-cli.injectable"; export default getGlobalOverride(pathToNpmCliInjectable, () => "/some/npm/cli/path"); diff --git a/packages/core/src/common/base-store/base-store.ts b/packages/core/src/common/base-store/base-store.ts index ecdad5bd4d..be7abf1293 100644 --- a/packages/core/src/common/base-store/base-store.ts +++ b/packages/core/src/common/base-store/base-store.ts @@ -7,7 +7,7 @@ import type Config from "conf"; import type { Migrations, Options as ConfOptions } from "conf/dist/source/types"; import type { IEqualsComparer } from "mobx"; import { makeObservable, reaction } from "mobx"; -import { disposer, isPromiseLike, toJS } from "../utils"; +import { disposer, isPromiseLike } from "@k8slens/utilities"; import { broadcastMessage } from "../ipc"; import isEqual from "lodash/isEqual"; import { kebabCase } from "lodash"; @@ -16,6 +16,7 @@ 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 { toJS } from "../utils"; export interface BaseStoreParams extends Omit, "migrations"> { syncOptions?: { diff --git a/packages/core/src/common/base-store/migrations.injectable.ts b/packages/core/src/common/base-store/migrations.injectable.ts index 27f7489dfa..d97abee1ec 100644 --- a/packages/core/src/common/base-store/migrations.injectable.ts +++ b/packages/core/src/common/base-store/migrations.injectable.ts @@ -7,7 +7,7 @@ import { lifecycleEnum, getInjectable } from "@ogre-tools/injectable"; import type Conf from "conf/dist/source"; import type { Migrations } from "conf/dist/source/types"; import loggerInjectable from "../logger.injectable"; -import { getOrInsert, iter } from "../utils"; +import { getOrInsert, iter } from "@k8slens/utilities"; export interface MigrationDeclaration { version: string; diff --git a/packages/core/src/common/catalog-entities/general-catalog-entities/implementations/catalog-catalog-entity.injectable.ts b/packages/core/src/common/catalog-entities/general-catalog-entities/implementations/catalog-catalog-entity.injectable.ts index 15195a4b74..b36be73de6 100644 --- a/packages/core/src/common/catalog-entities/general-catalog-entities/implementations/catalog-catalog-entity.injectable.ts +++ b/packages/core/src/common/catalog-entities/general-catalog-entities/implementations/catalog-catalog-entity.injectable.ts @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import { generalCatalogEntityInjectionToken } from "../general-catalog-entity-injection-token"; import { GeneralEntity } from "../../index"; -import { buildURL } from "../../../utils/buildUrl"; +import { buildURL } from "@k8slens/utilities"; import catalogRouteInjectable from "../../../front-end-routing/routes/catalog/catalog-route.injectable"; const catalogCatalogEntityInjectable = getInjectable({ diff --git a/packages/core/src/common/catalog-entities/general-catalog-entities/implementations/welcome-catalog-entity.injectable.ts b/packages/core/src/common/catalog-entities/general-catalog-entities/implementations/welcome-catalog-entity.injectable.ts index 363dd73c5f..a00dcec323 100644 --- a/packages/core/src/common/catalog-entities/general-catalog-entities/implementations/welcome-catalog-entity.injectable.ts +++ b/packages/core/src/common/catalog-entities/general-catalog-entities/implementations/welcome-catalog-entity.injectable.ts @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import { generalCatalogEntityInjectionToken } from "../general-catalog-entity-injection-token"; import { GeneralEntity } from "../../index"; -import { buildURL } from "../../../utils/buildUrl"; +import { buildURL } from "@k8slens/utilities"; import welcomeRouteInjectable from "../../../front-end-routing/routes/welcome/welcome-route.injectable"; const welcomeCatalogEntityInjectable = getInjectable({ diff --git a/packages/core/src/common/catalog-entities/kubernetes-cluster.ts b/packages/core/src/common/catalog-entities/kubernetes-cluster.ts index a9dac5873a..7615c19f3e 100644 --- a/packages/core/src/common/catalog-entities/kubernetes-cluster.ts +++ b/packages/core/src/common/catalog-entities/kubernetes-cluster.ts @@ -13,6 +13,7 @@ import { requestClusterActivation, requestClusterDisconnection } from "../../ren import KubeClusterCategoryIcon from "./icons/kubernetes.svg"; import getClusterByIdInjectable from "../cluster-store/get-by-id.injectable"; import { getLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; +import clusterConnectionInjectable from "../../main/cluster/cluster-connection.injectable"; export interface KubernetesClusterPrometheusMetrics { address?: { @@ -79,8 +80,15 @@ export class KubernetesCluster< if (app) { const di = getLegacyGlobalDiForExtensionApi(); const getClusterById = di.inject(getClusterByIdInjectable); + const cluster = getClusterById(this.getId()); - await getClusterById(this.getId())?.activate(); + if (!cluster) { + return; + } + + const connectionCluster = di.inject(clusterConnectionInjectable, cluster); + + await connectionCluster.activate(); } else { await requestClusterActivation(this.getId(), false); } @@ -90,8 +98,15 @@ export class KubernetesCluster< if (app) { const di = getLegacyGlobalDiForExtensionApi(); const getClusterById = di.inject(getClusterByIdInjectable); + const cluster = getClusterById(this.getId()); - getClusterById(this.getId())?.disconnect(); + if (!cluster) { + return; + } + + const connectionCluster = di.inject(clusterConnectionInjectable, cluster); + + connectionCluster.disconnect(); } else { await requestClusterDisconnection(this.getId(), false); } diff --git a/packages/core/src/common/catalog/catalog-entity.ts b/packages/core/src/common/catalog/catalog-entity.ts index 3a86da757f..bb45f4cb27 100644 --- a/packages/core/src/common/catalog/catalog-entity.ts +++ b/packages/core/src/common/catalog/catalog-entity.ts @@ -7,8 +7,8 @@ import EventEmitter from "events"; import type TypedEmitter from "typed-emitter"; import { observable, makeObservable } from "mobx"; import { once } from "lodash"; -import type { Disposer } from "../utils"; -import { iter } from "../utils"; +import type { Disposer } from "@k8slens/utilities"; +import { iter } from "@k8slens/utilities"; import type { CategoryColumnRegistration, TitleCellProps } from "../../renderer/components/+catalog/custom-category-columns"; export type { CategoryColumnRegistration, TitleCellProps }; @@ -241,7 +241,7 @@ export interface CatalogEntityMetadata extends EntityMetadataObject { shortName?: string; description?: string; source?: string; - labels: Record; + labels: Partial>; } export interface CatalogEntityStatus { diff --git a/packages/core/src/common/catalog/category-registry.ts b/packages/core/src/common/catalog/category-registry.ts index e4de26b322..f541645df0 100644 --- a/packages/core/src/common/catalog/category-registry.ts +++ b/packages/core/src/common/catalog/category-registry.ts @@ -5,8 +5,8 @@ import { action, computed, observable, makeObservable } from "mobx"; import { once } from "lodash"; -import { iter, getOrInsertMap, strictSet } from "../utils"; -import type { Disposer } from "../utils"; +import { iter, getOrInsertMap, strictSet } from "@k8slens/utilities"; +import type { Disposer } from "@k8slens/utilities"; import type { CatalogCategory, CatalogEntityData, CatalogEntityKindData } from "./catalog-entity"; export type CategoryFilter = (category: CatalogCategory) => any; diff --git a/packages/core/src/common/certificate/lens-proxy-certificate.global-override-for-injectable.ts b/packages/core/src/common/certificate/lens-proxy-certificate.global-override-for-injectable.ts index d547516062..4d0aeec1d8 100644 --- a/packages/core/src/common/certificate/lens-proxy-certificate.global-override-for-injectable.ts +++ b/packages/core/src/common/certificate/lens-proxy-certificate.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import lensProxyCertificateInjectable from "./lens-proxy-certificate.injectable"; export default getGlobalOverride(lensProxyCertificateInjectable, () => { 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 9712e3fdb0..ddd811c760 100644 --- a/packages/core/src/common/cluster-store/cluster-store.injectable.ts +++ b/packages/core/src/common/cluster-store/cluster-store.injectable.ts @@ -4,7 +4,6 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { ClusterStore } from "./cluster-store"; -import { createClusterInjectionToken } from "../cluster/create-cluster-injection-token"; import readClusterConfigSyncInjectable from "./read-cluster-config.injectable"; import emitAppEventInjectable from "../app-event-bus/emit-event.injectable"; import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable"; @@ -23,7 +22,6 @@ const clusterStoreInjectable = getInjectable({ id: "cluster-store", instantiate: (di) => new ClusterStore({ - createCluster: di.inject(createClusterInjectionToken), readClusterConfigSync: di.inject(readClusterConfigSyncInjectable), emitAppEvent: di.inject(emitAppEventInjectable), directoryForUserData: di.inject(directoryForUserDataInjectable), diff --git a/packages/core/src/common/cluster-store/cluster-store.ts b/packages/core/src/common/cluster-store/cluster-store.ts index 20929cf77e..8d283411c9 100644 --- a/packages/core/src/common/cluster-store/cluster-store.ts +++ b/packages/core/src/common/cluster-store/cluster-store.ts @@ -10,7 +10,6 @@ import { BaseStore } from "../base-store/base-store"; import { Cluster } from "../cluster/cluster"; import { toJS } from "../utils"; import type { ClusterModel, ClusterId } from "../cluster-types"; -import type { CreateCluster } from "../cluster/create-cluster-injection-token"; import type { ReadClusterConfigSync } from "./read-cluster-config.injectable"; import type { EmitAppEvent } from "../app-event-bus/emit-event.injectable"; @@ -19,7 +18,6 @@ export interface ClusterStoreModel { } interface Dependencies extends BaseStoreDependencies { - createCluster: CreateCluster; readClusterConfigSync: ReadClusterConfigSync; emitAppEvent: EmitAppEvent; } @@ -64,7 +62,7 @@ export class ClusterStore extends BaseStore { const cluster = clusterOrModel instanceof Cluster ? clusterOrModel - : this.dependencies.createCluster( + : new Cluster( clusterOrModel, this.dependencies.readClusterConfigSync(clusterOrModel), ); @@ -87,7 +85,7 @@ export class ClusterStore extends BaseStore { if (cluster) { cluster.updateModel(clusterModel); } else { - cluster = this.dependencies.createCluster( + cluster = new Cluster( clusterModel, this.dependencies.readClusterConfigSync(clusterModel), ); diff --git a/packages/core/src/common/cluster-types.ts b/packages/core/src/common/cluster-types.ts index 3e904a385e..ba01489152 100644 --- a/packages/core/src/common/cluster-types.ts +++ b/packages/core/src/common/cluster-types.ts @@ -39,10 +39,6 @@ export const updateClusterModelChecker = Joi.object({ contextName: Joi.string() .required() .min(1), - workspace: Joi.string() - .optional(), - workspaces: Joi.array() - .items(Joi.string()), preferences: Joi.object(), metadata: Joi.object(), accessibleNamespaces: Joi.array() @@ -70,18 +66,6 @@ export interface ClusterModel { /** Path to cluster kubeconfig */ kubeConfigPath: string; - /** - * Workspace id - * - * @deprecated - */ - workspace?: string; - - /** - * @deprecated this is used only for hotbar migrations from 4.2.X - */ - workspaces?: string[]; - /** User context in kubeconfig */ contextName: string; @@ -97,7 +81,7 @@ export interface ClusterModel { /** * Labels for the catalog entity */ - labels?: Record; + labels?: Partial>; } /** @@ -206,6 +190,6 @@ export interface ClusterState { ready: boolean; isAdmin: boolean; allowedNamespaces: string[]; - allowedResources: string[]; + resourcesToShow: string[]; isGlobalWatchEnabled: boolean; } diff --git a/packages/core/src/common/cluster/authorization-review.injectable.ts b/packages/core/src/common/cluster/authorization-review.injectable.ts index 4c9b83330d..3352423377 100644 --- a/packages/core/src/common/cluster/authorization-review.injectable.ts +++ b/packages/core/src/common/cluster/authorization-review.injectable.ts @@ -6,7 +6,6 @@ import type { KubeConfig, V1ResourceAttributes } from "@kubernetes/client-node"; import { AuthorizationV1Api } from "@kubernetes/client-node"; import { getInjectable } from "@ogre-tools/injectable"; -import type { Logger } from "../logger"; import loggerInjectable from "../logger.injectable"; /** @@ -19,41 +18,33 @@ export type CanI = (resourceAttributes: V1ResourceAttributes) => Promise CanI; +export type CreateAuthorizationReview = (proxyConfig: KubeConfig) => CanI; -interface Dependencies { - logger: Logger; -} - -const authorizationReview = ({ logger }: Dependencies): AuthorizationReview => { - 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; - } - }; - }; -}; - -const authorizationReviewInjectable = getInjectable({ +const createAuthorizationReviewInjectable = getInjectable({ id: "authorization-review", - instantiate: (di) => { + instantiate: (di): CreateAuthorizationReview => { const logger = di.inject(loggerInjectable); - return authorizationReview({ logger }); + 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 authorizationReviewInjectable; +export default createAuthorizationReviewInjectable; diff --git a/packages/core/src/common/cluster/cluster.ts b/packages/core/src/common/cluster/cluster.ts index 329d6e2df7..fc66d9aa29 100644 --- a/packages/core/src/common/cluster/cluster.ts +++ b/packages/core/src/common/cluster/cluster.ts @@ -3,164 +3,74 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { action, comparer, computed, makeObservable, observable, reaction, runInAction, when } from "mobx"; -import type { ClusterContextHandler } from "../../main/context-handler/context-handler"; -import type { KubeConfig } from "@kubernetes/client-node"; -import { HttpError } from "@kubernetes/client-node"; -import type { Kubectl } from "../../main/kubectl/kubectl"; -import type { KubeconfigManager } from "../../main/kubeconfig-manager/kubeconfig-manager"; -import type { KubeApiResource, KubeApiResourceDescriptor } from "../rbac"; -import { formatKubeApiResource } from "../rbac"; -import plimit from "p-limit"; -import type { ClusterState, ClusterMetricsResourceType, ClusterId, ClusterMetadata, ClusterModel, ClusterPreferences, ClusterPrometheusPreferences, UpdateClusterModel, KubeAuthUpdate, ClusterConfigData } from "../cluster-types"; -import { ClusterMetadataKey, initialNodeShellImage, ClusterStatus, clusterModelIdChecker, updateClusterModelChecker } from "../cluster-types"; -import { disposer, isDefined, isRequestError, toJS } from "../utils"; -import { clusterListNamespaceForbiddenChannel } from "../ipc/cluster"; -import type { CanI } from "./authorization-review.injectable"; -import type { ListNamespaces } from "./list-namespaces.injectable"; -import assert from "assert"; -import type { Logger } from "../logger"; -import type { BroadcastMessage } from "../ipc/broadcast-message.injectable"; -import type { LoadConfigfromFile } from "../kube-helpers/load-config-from-file.injectable"; -import type { CanListResource, RequestNamespaceListPermissions, RequestNamespaceListPermissionsFor } from "./request-namespace-list-permissions.injectable"; -import type { RequestApiResources } from "../../main/cluster/request-api-resources.injectable"; -import type { DetectClusterMetadata } from "../../main/cluster-detectors/detect-cluster-metadata.injectable"; -import type { FalibleOnlyClusterMetadataDetector } from "../../main/cluster-detectors/token"; +import { computed, observable, toJS, runInAction } from "mobx"; +import type { KubeApiResource } from "../rbac"; +import type { ClusterState, ClusterId, ClusterMetadata, ClusterModel, ClusterPreferences, ClusterPrometheusPreferences, UpdateClusterModel, ClusterConfigData } from "../cluster-types"; +import { ClusterMetadataKey, clusterModelIdChecker, updateClusterModelChecker } from "../cluster-types"; +import type { IObservableValue } from "mobx"; +import { replaceObservableObject } from "../utils/replace-observable-object"; +import { pick } from "lodash"; -export interface ClusterDependencies { - readonly directoryForKubeConfigs: string; - readonly logger: Logger; - readonly clusterVersionDetector: FalibleOnlyClusterMetadataDetector; - detectClusterMetadata: DetectClusterMetadata; - createKubeconfigManager: (cluster: Cluster) => KubeconfigManager; - createContextHandler: (cluster: Cluster) => ClusterContextHandler; - createKubectl: (clusterVersion: string) => Kubectl; - createAuthorizationReview: (config: KubeConfig) => CanI; - requestApiResources: RequestApiResources; - requestNamespaceListPermissionsFor: RequestNamespaceListPermissionsFor; - createListNamespaces: (config: KubeConfig) => ListNamespaces; - broadcastMessage: BroadcastMessage; - loadConfigfromFile: LoadConfigfromFile; -} - -/** - * Cluster - * - * @beta - */ -export class Cluster implements ClusterModel { - /** Unique id for a cluster */ - public readonly id: ClusterId; - private kubeCtl: Kubectl | undefined; +export class Cluster { /** - * Context handler - * - * @internal + * Unique id for a cluster */ - protected readonly _contextHandler: ClusterContextHandler | undefined; - protected readonly _proxyKubeconfigManager: KubeconfigManager | undefined; - protected readonly eventsDisposer = disposer(); - protected activated = false; - - public get contextHandler() { - // TODO: remove these once main/renderer are seperate classes - assert(this._contextHandler, "contextHandler is only defined in the main environment"); - - return this._contextHandler; - } - - protected get proxyKubeconfigManager() { - // TODO: remove these once main/renderer are seperate classes - assert(this._proxyKubeconfigManager, "proxyKubeconfigManager is only defined in the main environment"); - - return this._proxyKubeconfigManager; - } - - get whenReady() { - return when(() => this.ready); - } + readonly id: ClusterId; /** * Kubeconfig context name - * - * @observable */ - @observable contextName!: string; + readonly contextName = observable.box() as IObservableValue; + /** * Path to kubeconfig - * - * @observable */ - @observable kubeConfigPath!: string; - /** - * @deprecated - */ - @observable workspace?: string; - /** - * @deprecated - */ - @observable workspaces?: string[]; + readonly kubeConfigPath = observable.box() as IObservableValue; + /** * Kubernetes API server URL - * - * @observable */ - @observable apiUrl: string; // cluster server url + readonly apiUrl: IObservableValue; + /** - * Is cluster online - * - * @observable + * Describes if we can detect that cluster is online */ - @observable online = false; // describes if we can detect that cluster is online + readonly online = observable.box(false); + /** - * Can user access cluster resources - * - * @observable + * Describes if user is able to access cluster resources */ - @observable accessible = false; // if user is able to access cluster resources + readonly accessible = observable.box(false); + /** * Is cluster instance in usable state - * - * @observable */ - @observable ready = false; // cluster is in usable state - /** - * Is cluster currently reconnecting - * - * @observable - */ - @observable reconnecting = false; + readonly ready = observable.box(false); + /** * Is cluster disconnected. False if user has selected to connect. - * - * @observable */ - @observable disconnected = true; + readonly disconnected = observable.box(true); + /** * Does user have admin like access - * - * @observable */ - @observable isAdmin = false; + readonly isAdmin = observable.box(false); /** * Global watch-api accessibility , e.g. "/api/v1/services?watch=1" - * - * @observable */ - @observable isGlobalWatchEnabled = false; + readonly isGlobalWatchEnabled = observable.box(false); + /** * Preferences - * - * @observable */ - @observable preferences: ClusterPreferences = {}; + readonly preferences = observable.object({}); + /** * Metadata - * - * @observable */ - @observable metadata: ClusterMetadata = {}; + readonly metadata = observable.object({}); /** * List of allowed namespaces verified via K8S::SelfSubjectAccessReview api @@ -172,73 +82,47 @@ export class Cluster implements ClusterModel { */ readonly accessibleNamespaces = observable.array(); - private readonly knownResources = observable.array(); + /** + * The list of all known resources associated with this cluster + */ + readonly knownResources = observable.array(); - // The formatting of this is `group.name` or `name` (if in core) - private readonly allowedResources = observable.set(); + /** + * The formatting of this is `group.name` or `name` (if in core) + */ + readonly resourcesToShow = observable.set(); /** * Labels for the catalog entity */ - @observable labels: Record = {}; + readonly labels = observable.object>>({}); /** * Is cluster available - * - * @computed */ - @computed get available() { - return this.accessible && !this.disconnected; - } + readonly available = computed(() => this.accessible.get() && !this.disconnected.get()); /** * Cluster name - * - * @computed */ - @computed get name() { - return this.preferences.clusterName || this.contextName; - } + readonly name = computed(() => this.preferences.clusterName || this.contextName.get()); /** * The detected kubernetes distribution */ - @computed get distribution(): string { - return this.metadata[ClusterMetadataKey.DISTRIBUTION]?.toString() || "unknown"; - } + readonly distribution = computed(() => this.metadata[ClusterMetadataKey.DISTRIBUTION]?.toString() || "unknown"); /** * The detected kubernetes version */ - @computed get version(): string { - return this.metadata[ClusterMetadataKey.VERSION]?.toString() || "unknown"; - } + readonly version = computed(() => this.metadata[ClusterMetadataKey.VERSION]?.toString() || "unknown"); /** * Prometheus preferences - * - * @computed - * @internal */ - @computed get prometheusPreferences(): ClusterPrometheusPreferences { - const { prometheus, prometheusProvider } = this.preferences; - - return toJS({ prometheus, prometheusProvider }); - } - - /** - * defaultNamespace preference - * - * @computed - * @internal - */ - @computed get defaultNamespace(): string | undefined { - return this.preferences.defaultNamespace; - } - - constructor(private readonly dependencies: ClusterDependencies, { id, ...model }: ClusterModel, configData: ClusterConfigData) { - makeObservable(this); + readonly prometheusPreferences = computed(() => pick(toJS(this.preferences), "prometheus", "prometheusProvider") as ClusterPrometheusPreferences); + constructor({ id, ...model }: ClusterModel, configData: ClusterConfigData) { const { error } = clusterModelIdChecker.validate({ id }); if (error) { @@ -247,16 +131,7 @@ export class Cluster implements ClusterModel { this.id = id; this.updateModel(model); - this.apiUrl = configData.clusterServerUrl; - - // for the time being, until renderer gets its own cluster type - this._contextHandler = this.dependencies.createContextHandler(this); - this._proxyKubeconfigManager = this.dependencies.createKubeconfigManager(this); - this.dependencies.logger.debug(`[CLUSTER]: Cluster init success`, { - id: this.id, - context: this.contextName, - apiUrl: this.apiUrl, - }); + this.apiUrl = observable.box(configData.clusterServerUrl); } /** @@ -264,7 +139,7 @@ export class Cluster implements ClusterModel { * * @param model */ - @action updateModel(model: UpdateClusterModel) { + updateModel(model: UpdateClusterModel) { // Note: do not assign ID as that should never be updated const { error } = updateClusterModelChecker.validate(model, { allowUnknown: true }); @@ -273,454 +148,83 @@ export class Cluster implements ClusterModel { throw error; } - this.kubeConfigPath = model.kubeConfigPath; - this.contextName = model.contextName; - - if (model.workspace) { - this.workspace = model.workspace; - } - - if (model.workspaces) { - this.workspaces = model.workspaces; - } - - if (model.preferences) { - this.preferences = model.preferences; - } - - if (model.metadata) { - this.metadata = model.metadata; - } - - if (model.accessibleNamespaces) { - this.accessibleNamespaces.replace(model.accessibleNamespaces); - } - - if (model.labels) { - this.labels = model.labels; - } - } - - /** - * @internal - */ - protected bindEvents() { - this.dependencies.logger.info(`[CLUSTER]: bind events`, this.getMeta()); - const refreshTimer = setInterval(() => !this.disconnected && this.refresh(), 30000); // every 30s - const refreshMetadataTimer = setInterval(() => this.available && this.refreshAccessibilityAndMetadata(), 900000); // every 15 minutes - - this.eventsDisposer.push( - reaction( - () => this.prometheusPreferences, - prefs => this.contextHandler.setupPrometheus(prefs), - { equals: comparer.structural }, - ), - () => clearInterval(refreshTimer), - () => clearInterval(refreshMetadataTimer), - reaction(() => this.defaultNamespace, () => this.recreateProxyKubeconfig()), - ); - } - - /** - * @internal - */ - protected async recreateProxyKubeconfig() { - this.dependencies.logger.info("[CLUSTER]: Recreating proxy kubeconfig"); - - try { - await this.proxyKubeconfigManager.clear(); - await this.getProxyKubeconfig(); - } catch (error) { - this.dependencies.logger.error(`[CLUSTER]: failed to recreate proxy kubeconfig`, error); - } - } - - /** - * @param force force activation - * @internal - */ - @action - async activate(force = false) { - if (this.activated && !force) { - return; - } - - this.dependencies.logger.info(`[CLUSTER]: activate`, this.getMeta()); - - if (!this.eventsDisposer.length) { - this.bindEvents(); - } - - if (this.disconnected || !this.accessible) { - try { - this.broadcastConnectUpdate("Starting connection ..."); - await this.reconnect(); - } catch (error) { - this.broadcastConnectUpdate(`Failed to start connection: ${error}`, "error"); - - return; - } - } - - try { - this.broadcastConnectUpdate("Refreshing connection status ..."); - await this.refreshConnectionStatus(); - } catch (error) { - this.broadcastConnectUpdate(`Failed to connection status: ${error}`, "error"); - - return; - } - - if (this.accessible) { - try { - this.broadcastConnectUpdate("Refreshing cluster accessibility ..."); - await this.refreshAccessibility(); - } catch (error) { - this.broadcastConnectUpdate(`Failed to refresh accessibility: ${error}`, "error"); - - return; - } - - // download kubectl in background, so it's not blocking dashboard - this.ensureKubectl() - .catch(error => this.dependencies.logger.warn(`[CLUSTER]: failed to download kubectl for clusterId=${this.id}`, error)); - this.broadcastConnectUpdate("Connected, waiting for view to load ..."); - } - - this.activated = true; - } - - /** - * @internal - */ - async ensureKubectl() { - this.kubeCtl ??= this.dependencies.createKubectl(this.version); - - await this.kubeCtl.ensureKubectl(); - - return this.kubeCtl; - } - - /** - * @internal - */ - @action - async reconnect() { - this.dependencies.logger.info(`[CLUSTER]: reconnect`, this.getMeta()); - await this.contextHandler?.restartServer(); - this.disconnected = false; - } - - /** - * @internal - */ - @action disconnect(): void { - if (this.disconnected) { - return void this.dependencies.logger.debug("[CLUSTER]: already disconnected", { id: this.id }); - } - - this.dependencies.logger.info(`[CLUSTER]: disconnecting`, { id: this.id }); - this.eventsDisposer(); - this.contextHandler?.stopServer(); - this.disconnected = true; - this.online = false; - this.accessible = false; - this.ready = false; - this.activated = false; - this.allowedNamespaces.clear(); - this.dependencies.logger.info(`[CLUSTER]: disconnected`, { id: this.id }); - } - - /** - * @internal - */ - @action - async refresh() { - this.dependencies.logger.info(`[CLUSTER]: refresh`, this.getMeta()); - await this.refreshConnectionStatus(); - } - - /** - * @internal - */ - @action - async refreshAccessibilityAndMetadata() { - await this.refreshAccessibility(); - await this.refreshMetadata(); - } - - /** - * @internal - */ - async refreshMetadata() { - this.dependencies.logger.info(`[CLUSTER]: refreshMetadata`, this.getMeta()); - - const newMetadata = await this.dependencies.detectClusterMetadata(this); - runInAction(() => { - this.metadata = { - ...this.metadata, - ...newMetadata, - }; - }); - } + this.kubeConfigPath.set(model.kubeConfigPath); + this.contextName.set(model.contextName); - /** - * @internal - */ - private async refreshAccessibility(): Promise { - this.dependencies.logger.info(`[CLUSTER]: refreshAccessibility`, this.getMeta()); - const proxyConfig = await this.getProxyKubeconfig(); - const canI = this.dependencies.createAuthorizationReview(proxyConfig); - const requestNamespaceListPermissions = this.dependencies.requestNamespaceListPermissionsFor(proxyConfig); - - this.isAdmin = await canI({ - namespace: "kube-system", - resource: "*", - verb: "create", - }); - this.isGlobalWatchEnabled = await canI({ - verb: "watch", - resource: "*", - }); - this.allowedNamespaces.replace(await this.requestAllowedNamespaces(proxyConfig)); - - const knownResources = await this.dependencies.requestApiResources(this); - - if (knownResources.callWasSuccessful) { - this.knownResources.replace(knownResources.response); - } else if (this.knownResources.length > 0) { - this.dependencies.logger.warn(`[CLUSTER]: failed to list KUBE resources, sticking with previous list`); - } else { - this.dependencies.logger.warn(`[CLUSTER]: failed to list KUBE resources for the first time, blocking connection to cluster...`); - this.broadcastConnectUpdate("Failed to list kube API resources, please reconnect...", "error"); - } - - this.allowedResources.replace(await this.getAllowedResources(requestNamespaceListPermissions)); - this.ready = this.knownResources.length > 0; - this.dependencies.logger.debug(`[CLUSTER]: refreshed accessibility data`, this.getState()); - } - - /** - * @internal - */ - @action - async refreshConnectionStatus() { - const connectionStatus = await this.getConnectionStatus(); - - this.online = connectionStatus > ClusterStatus.Offline; - this.accessible = connectionStatus == ClusterStatus.AccessGranted; - } - - async getKubeconfig(): Promise { - const { config } = await this.dependencies.loadConfigfromFile(this.kubeConfigPath); - - return config; - } - - /** - * @internal - */ - async getProxyKubeconfig(): Promise { - const proxyKCPath = await this.getProxyKubeconfigPath(); - const { config } = await this.dependencies.loadConfigfromFile(proxyKCPath); - - return config; - } - - /** - * @internal - */ - async getProxyKubeconfigPath(): Promise { - return this.proxyKubeconfigManager.getPath(); - } - - protected async getConnectionStatus(): Promise { - try { - const versionData = await this.dependencies.clusterVersionDetector.detect(this); - - this.metadata.version = versionData.value; - - return ClusterStatus.AccessGranted; - } catch (error) { - this.dependencies.logger.error(`[CLUSTER]: Failed to connect to "${this.contextName}": ${error}`); - - if (isRequestError(error)) { - if (error.statusCode) { - if (error.statusCode >= 400 && error.statusCode < 500) { - this.broadcastConnectUpdate("Invalid credentials", "error"); - - return ClusterStatus.AccessDenied; - } - - const message = String(error.error || error.message) || String(error); - - this.broadcastConnectUpdate(message, "error"); - - return ClusterStatus.Offline; - } - - if (error.failed === true) { - if (error.timedOut === true) { - this.broadcastConnectUpdate("Connection timed out", "error"); - - return ClusterStatus.Offline; - } - - this.broadcastConnectUpdate("Failed to fetch credentials", "error"); - - return ClusterStatus.AccessDenied; - } - - const message = String(error.error || error.message) || String(error); - - this.broadcastConnectUpdate(message, "error"); - } else if (error instanceof Error || typeof error === "string") { - this.broadcastConnectUpdate(`${error}`, "error"); - } else { - this.broadcastConnectUpdate("Unknown error has occurred", "error"); + if (model.preferences) { + replaceObservableObject(this.preferences, model.preferences); } - return ClusterStatus.Offline; - } + if (model.metadata) { + replaceObservableObject(this.metadata, model.metadata); + } + + if (model.accessibleNamespaces) { + this.accessibleNamespaces.replace(model.accessibleNamespaces); + } + + if (model.labels) { + replaceObservableObject(this.labels, model.labels); + } + }); } toJSON(): ClusterModel { - return toJS({ + return { id: this.id, - contextName: this.contextName, - kubeConfigPath: this.kubeConfigPath, - workspace: this.workspace, - workspaces: this.workspaces, - preferences: this.preferences, - metadata: this.metadata, - accessibleNamespaces: this.accessibleNamespaces, - labels: this.labels, - }); + contextName: this.contextName.get(), + kubeConfigPath: this.kubeConfigPath.get(), + preferences: toJS(this.preferences), + metadata: toJS(this.metadata), + accessibleNamespaces: this.accessibleNamespaces.toJSON(), + labels: toJS(this.labels), + }; } /** * Serializable cluster-state used for sync btw main <-> renderer */ getState(): ClusterState { - return toJS({ - apiUrl: this.apiUrl, - online: this.online, - ready: this.ready, - disconnected: this.disconnected, - accessible: this.accessible, - isAdmin: this.isAdmin, - allowedNamespaces: this.allowedNamespaces, - allowedResources: [...this.allowedResources], - isGlobalWatchEnabled: this.isGlobalWatchEnabled, - }); + return { + apiUrl: this.apiUrl.get(), + online: this.online.get(), + ready: this.ready.get(), + disconnected: this.disconnected.get(), + accessible: this.accessible.get(), + isAdmin: this.isAdmin.get(), + allowedNamespaces: this.allowedNamespaces.toJSON(), + resourcesToShow: this.resourcesToShow.toJSON(), + isGlobalWatchEnabled: this.isGlobalWatchEnabled.get(), + }; } /** - * @internal * @param state cluster state */ - @action setState(state: ClusterState) { - this.accessible = state.accessible; - this.allowedNamespaces.replace(state.allowedNamespaces); - this.allowedResources.replace(state.allowedResources); - this.apiUrl = state.apiUrl; - this.disconnected = state.disconnected; - this.isAdmin = state.isAdmin; - this.isGlobalWatchEnabled = state.isGlobalWatchEnabled; - this.online = state.online; - this.ready = state.ready; + setState(state: ClusterState) { + runInAction(() => { + this.accessible.set(state.accessible); + this.allowedNamespaces.replace(state.allowedNamespaces); + this.resourcesToShow.replace(state.resourcesToShow); + this.apiUrl.set(state.apiUrl); + this.disconnected.set(state.disconnected); + this.isAdmin.set(state.isAdmin); + this.isGlobalWatchEnabled.set(state.isGlobalWatchEnabled); + this.online.set(state.online); + this.ready.set(state.ready); + }); } // get cluster system meta, e.g. use in "logger" getMeta() { return { id: this.id, - name: this.contextName, - ready: this.ready, - online: this.online, - accessible: this.accessible, - disconnected: this.disconnected, + name: this.contextName.get(), + ready: this.ready.get(), + online: this.online.get(), + accessible: this.accessible.get(), + disconnected: this.disconnected.get(), }; } - - /** - * broadcast an authentication update concerning this cluster - * @internal - */ - broadcastConnectUpdate(message: string, level: KubeAuthUpdate["level"] = "info"): void { - const update: KubeAuthUpdate = { message, level }; - - this.dependencies.logger.debug(`[CLUSTER]: broadcasting connection update`, { ...update, meta: this.getMeta() }); - this.dependencies.broadcastMessage(`cluster:${this.id}:connection-update`, update); - } - - protected async requestAllowedNamespaces(proxyConfig: KubeConfig) { - if (this.accessibleNamespaces.length) { - return this.accessibleNamespaces; - } - - try { - const listNamespaces = this.dependencies.createListNamespaces(proxyConfig); - - return await listNamespaces(); - } catch (error) { - const ctx = proxyConfig.getContextObject(this.contextName); - const namespaceList = [ctx?.namespace].filter(isDefined); - - if (namespaceList.length === 0 && error instanceof HttpError && error.statusCode === 403) { - const { response } = error as HttpError & { response: { body: unknown }}; - - this.dependencies.logger.info("[CLUSTER]: listing namespaces is forbidden, broadcasting", { clusterId: this.id, error: response.body }); - this.dependencies.broadcastMessage(clusterListNamespaceForbiddenChannel, this.id); - } - - return namespaceList; - } - } - - protected async getAllowedResources(requestNamespaceListPermissions: RequestNamespaceListPermissions) { - if (!this.allowedNamespaces.length || !this.knownResources.length) { - return []; - } - - try { - const apiLimit = plimit(5); // 5 concurrent api requests - const canListResourceCheckers = await Promise.all(( - this.allowedNamespaces.map(namespace => apiLimit(() => requestNamespaceListPermissions(namespace))) - )); - const canListNamespacedResource: CanListResource = (resource) => canListResourceCheckers.some(fn => fn(resource)); - - return this.knownResources - .filter(canListNamespacedResource) - .map(formatKubeApiResource); - } catch (error) { - return []; - } - } - - shouldShowResource(resource: KubeApiResourceDescriptor): boolean { - if (this.allowedResources.size === 0) { - // better to show than hide everything - return true; - } - - return this.allowedResources.has(formatKubeApiResource(resource)); - } - - isMetricHidden(resource: ClusterMetricsResourceType): boolean { - return Boolean(this.preferences.hiddenMetrics?.includes(resource)); - } - - get nodeShellImage(): string { - return this.preferences?.nodeShellImage || initialNodeShellImage; - } - - get imagePullSecret(): string | undefined { - return this.preferences?.imagePullSecret; - } - - isInLocalKubeconfig() { - return this.kubeConfigPath.startsWith(this.dependencies.directoryForKubeConfigs); - } } diff --git a/packages/core/src/common/cluster/create-cluster-injection-token.ts b/packages/core/src/common/cluster/create-cluster-injection-token.ts deleted file mode 100644 index a07ce4459f..0000000000 --- a/packages/core/src/common/cluster/create-cluster-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 { ClusterConfigData, ClusterModel } from "../cluster-types"; -import type { Cluster } from "./cluster"; - -export type CreateCluster = (model: ClusterModel, configData: ClusterConfigData) => Cluster; - -export const createClusterInjectionToken = getInjectionToken({ - id: "create-cluster-token", -}); diff --git a/packages/core/src/common/cluster/list-namespaces.injectable.ts b/packages/core/src/common/cluster/list-namespaces.injectable.ts index 468ff3ac2e..363a10abb1 100644 --- a/packages/core/src/common/cluster/list-namespaces.injectable.ts +++ b/packages/core/src/common/cluster/list-namespaces.injectable.ts @@ -5,25 +5,25 @@ import type { KubeConfig } from "@kubernetes/client-node"; import { CoreV1Api } from "@kubernetes/client-node"; import { getInjectable } from "@ogre-tools/injectable"; -import { isDefined } from "../utils"; +import { isDefined } from "@k8slens/utilities"; export type ListNamespaces = () => Promise; -export function listNamespaces(config: KubeConfig): ListNamespaces { - const coreApi = config.makeApiClient(CoreV1Api); +export type CreateListNamespaces = (config: KubeConfig) => ListNamespaces; - return async () => { - const { body: { items }} = await coreApi.listNamespace(); +const createListNamespacesInjectable = getInjectable({ + id: "create-list-namespaces", + instantiate: (): CreateListNamespaces => (config) => { + const coreApi = config.makeApiClient(CoreV1Api); - return items - .map(ns => ns.metadata?.name) - .filter(isDefined); - }; -} + return async () => { + const { body: { items }} = await coreApi.listNamespace(); -const listNamespacesInjectable = getInjectable({ - id: "list-namespaces", - instantiate: () => listNamespaces, + return items + .map(ns => ns.metadata?.name) + .filter(isDefined); + }; + }, }); -export default listNamespacesInjectable; +export default createListNamespacesInjectable; diff --git a/packages/core/src/common/cluster/load-kubeconfig.injectable.ts b/packages/core/src/common/cluster/load-kubeconfig.injectable.ts new file mode 100644 index 0000000000..4a420dadd3 --- /dev/null +++ b/packages/core/src/common/cluster/load-kubeconfig.injectable.ts @@ -0,0 +1,36 @@ +/** + * 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 { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import type { Cluster } from "./cluster"; +import loadConfigFromFileInjectable from "../kube-helpers/load-config-from-file.injectable"; +import type { ConfigResult } from "../kube-helpers"; + +export interface LoadKubeconfig { + (fullResult?: false): Promise; + (fullResult: true): Promise; +} + +const loadKubeconfigInjectable = getInjectable({ + id: "load-kubeconfig", + instantiate: (di, cluster) => { + const loadConfigFromFile = di.inject(loadConfigFromFileInjectable); + + return (async (fullResult = false) => { + const result = await loadConfigFromFile(cluster.kubeConfigPath.get()); + + if (fullResult) { + return result; + } + + return result.config; + }) as LoadKubeconfig; + }, + lifecycle: lifecycleEnum.keyedSingleton({ + getInstanceKey: (di, cluster: Cluster) => cluster.id, + }), +}); + +export default loadKubeconfigInjectable; diff --git a/packages/core/src/common/error-reporting/initialize-sentry-reporting.global-override-for-injectable.ts b/packages/core/src/common/error-reporting/initialize-sentry-reporting.global-override-for-injectable.ts index 1aa2934ef9..1a7dce6a61 100644 --- a/packages/core/src/common/error-reporting/initialize-sentry-reporting.global-override-for-injectable.ts +++ b/packages/core/src/common/error-reporting/initialize-sentry-reporting.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import initializeSentryReportingWithInjectable from "./initialize-sentry-reporting.injectable"; export default getGlobalOverride(initializeSentryReportingWithInjectable, () => () => {}); diff --git a/packages/core/src/common/fetch/download-binary.injectable.ts b/packages/core/src/common/fetch/download-binary.injectable.ts index b50c4e5782..9f0ce65093 100644 --- a/packages/core/src/common/fetch/download-binary.injectable.ts +++ b/packages/core/src/common/fetch/download-binary.injectable.ts @@ -4,14 +4,14 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import type { RequestInit, Response } from "@k8slens/node-fetch"; -import type { AsyncResult } from "../utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; import fetchInjectable from "./fetch.injectable"; export interface DownloadBinaryOptions { signal?: AbortSignal | null | undefined; } -export type DownloadBinary = (url: string, opts?: DownloadBinaryOptions) => Promise>; +export type DownloadBinary = (url: string, opts?: DownloadBinaryOptions) => AsyncResult; const downloadBinaryInjectable = getInjectable({ id: "download-binary", diff --git a/packages/core/src/common/fetch/download-json/impl.ts b/packages/core/src/common/fetch/download-json/impl.ts index bf5cf06a19..f691cc2762 100644 --- a/packages/core/src/common/fetch/download-json/impl.ts +++ b/packages/core/src/common/fetch/download-json/impl.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 { AsyncResult } from "../../utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; import type { Fetch } from "../fetch.injectable"; import type { RequestInit, Response } from "@k8slens/node-fetch"; @@ -10,7 +10,7 @@ export interface DownloadJsonOptions { signal?: AbortSignal | null | undefined; } -export type DownloadJson = (url: string, opts?: DownloadJsonOptions) => Promise>; +export type DownloadJson = (url: string, opts?: DownloadJsonOptions) => AsyncResult; export const downloadJsonWith = (fetch: Fetch): DownloadJson => async (url, opts) => { let result: Response; diff --git a/packages/core/src/common/fetch/fetch.global-override-for-injectable.ts b/packages/core/src/common/fetch/fetch.global-override-for-injectable.ts index 1a5f80735c..7aa6db7a2d 100644 --- a/packages/core/src/common/fetch/fetch.global-override-for-injectable.ts +++ b/packages/core/src/common/fetch/fetch.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverrideForFunction } from "../test-utils/get-global-override-for-function"; +import { getGlobalOverrideForFunction } from "@k8slens/test-utils"; import fetchInjectable from "./fetch.injectable"; export default getGlobalOverrideForFunction(fetchInjectable); diff --git a/packages/core/src/common/fetch/lens-fetch.global-override-for-injectable.ts b/packages/core/src/common/fetch/lens-fetch.global-override-for-injectable.ts index 0bc144b1be..3598b6ce14 100644 --- a/packages/core/src/common/fetch/lens-fetch.global-override-for-injectable.ts +++ b/packages/core/src/common/fetch/lens-fetch.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverrideForFunction } from "../test-utils/get-global-override-for-function"; +import { getGlobalOverrideForFunction } from "@k8slens/test-utils"; import lensFetchInjectable from "./lens-fetch.injectable"; export default getGlobalOverrideForFunction(lensFetchInjectable); diff --git a/packages/core/src/common/front-end-routing/routes/cluster/network/ingresses/ingresses-route.injectable.ts b/packages/core/src/common/front-end-routing/routes/cluster/network/ingresses/ingresses-route.injectable.ts index 8e01646b82..3a6669d99f 100644 --- a/packages/core/src/common/front-end-routing/routes/cluster/network/ingresses/ingresses-route.injectable.ts +++ b/packages/core/src/common/front-end-routing/routes/cluster/network/ingresses/ingresses-route.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token"; -import { computedOr } from "../../../../../utils/computed-or"; +import { computedOr } from "@k8slens/utilities"; import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token"; const ingressesRouteInjectable = getInjectable({ 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 index b6d899d2c4..3799d3b760 100644 --- a/packages/core/src/common/fs/copy.global-override-for-injectable.ts +++ b/packages/core/src/common/fs/copy.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import copyInjectable from "./copy.injectable"; export default getGlobalOverride(copyInjectable, () => async () => { diff --git a/packages/core/src/common/fs/exec-file.global-override-for-injectable.ts b/packages/core/src/common/fs/exec-file.global-override-for-injectable.ts index 162666a130..381a546125 100644 --- a/packages/core/src/common/fs/exec-file.global-override-for-injectable.ts +++ b/packages/core/src/common/fs/exec-file.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverrideForFunction } from "../test-utils/get-global-override-for-function"; +import { getGlobalOverrideForFunction } from "@k8slens/test-utils"; import execFileInjectable from "./exec-file.injectable"; export default getGlobalOverrideForFunction(execFileInjectable); diff --git a/packages/core/src/common/fs/exec-file.injectable.ts b/packages/core/src/common/fs/exec-file.injectable.ts index f026e0db3a..9ee0fae78f 100644 --- a/packages/core/src/common/fs/exec-file.injectable.ts +++ b/packages/core/src/common/fs/exec-file.injectable.ts @@ -5,14 +5,14 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { ExecFileException, ExecFileOptions } from "child_process"; import { execFile } from "child_process"; -import type { AsyncResult } from "../utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; export type ExecFileError = ExecFileException & { stderr: string }; export interface ExecFile { - (filePath: string): Promise>; - (filePath: string, argsOrOptions: string[] | ExecFileOptions): Promise>; - (filePath: string, args: string[], options: ExecFileOptions): Promise>; + (filePath: string): AsyncResult; + (filePath: string, argsOrOptions: string[] | ExecFileOptions): AsyncResult; + (filePath: string, args: string[], options: ExecFileOptions): AsyncResult; } const execFileInjectable = getInjectable({ diff --git a/packages/core/src/common/fs/extract-tar.global-override-for-injectable.ts b/packages/core/src/common/fs/extract-tar.global-override-for-injectable.ts index 02a46c1d6b..68d1fe4259 100644 --- a/packages/core/src/common/fs/extract-tar.global-override-for-injectable.ts +++ b/packages/core/src/common/fs/extract-tar.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import extractTarInjectable from "./extract-tar.injectable"; export default getGlobalOverride(extractTarInjectable, () => async () => { diff --git a/packages/core/src/common/fs/fs.injectable.ts b/packages/core/src/common/fs/fs.injectable.ts index 600e4eaa40..b42a51aad7 100644 --- a/packages/core/src/common/fs/fs.injectable.ts +++ b/packages/core/src/common/fs/fs.injectable.ts @@ -21,6 +21,7 @@ const fsInjectable = getInjectable({ rm, access, stat, + unlink, }, ensureDir, ensureDirSync, @@ -56,6 +57,7 @@ const fsInjectable = getInjectable({ ensureDirSync, createReadStream, stat, + unlink, }; }, causesSideEffects: true, 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 index 9c9f3d4933..155fac7451 100644 --- a/packages/core/src/common/fs/lstat.global-override-for-injectable.ts +++ b/packages/core/src/common/fs/lstat.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import lstatInjectable from "./lstat.injectable"; export default getGlobalOverride(lstatInjectable, () => async () => { 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 index 57c83ceffb..72d9b523f4 100644 --- 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 @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import readDirectoryInjectable from "./read-directory.injectable"; export default getGlobalOverride(readDirectoryInjectable, () => async () => { 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 index 4b92353344..58fb0f9dce 100644 --- a/packages/core/src/common/fs/remove.global-override-for-injectable.ts +++ b/packages/core/src/common/fs/remove.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import removePathInjectable from "./remove.injectable"; export default getGlobalOverride(removePathInjectable, () => async () => { diff --git a/packages/core/src/common/fs/unlink.injectable.ts b/packages/core/src/common/fs/unlink.injectable.ts new file mode 100644 index 0000000000..e13bf35935 --- /dev/null +++ b/packages/core/src/common/fs/unlink.injectable.ts @@ -0,0 +1,15 @@ +/** + * 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 fsInjectable from "./fs.injectable"; + +export type Unlink = (path: string) => Promise; + +const unlinkInjectable = getInjectable({ + id: "unlink", + instantiate: (di): Unlink => di.inject(fsInjectable).unlink, +}); + +export default unlinkInjectable; diff --git a/packages/core/src/common/fs/validate-directory.injectable.ts b/packages/core/src/common/fs/validate-directory.injectable.ts index efce915238..717caf5ec8 100644 --- a/packages/core/src/common/fs/validate-directory.injectable.ts +++ b/packages/core/src/common/fs/validate-directory.injectable.ts @@ -3,13 +3,13 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import type { AsyncResult } from "../utils/async-result"; -import { isErrnoException } from "../utils"; +import type { AsyncResult } from "@k8slens/utilities"; +import { isErrnoException } from "@k8slens/utilities"; import type { Stats } from "fs-extra"; import { lowerFirst } from "lodash/fp"; import statInjectable from "./stat.injectable"; -export type ValidateDirectory = (path: string) => Promise>; +export type ValidateDirectory = (path: string) => AsyncResult; function getUserReadableFileType(stats: Stats): string { if (stats.isFile()) { diff --git a/packages/core/src/common/fs/watch/watch.global-override-for-injectable.ts b/packages/core/src/common/fs/watch/watch.global-override-for-injectable.ts index 689c7150cf..b74c3eec20 100644 --- a/packages/core/src/common/fs/watch/watch.global-override-for-injectable.ts +++ b/packages/core/src/common/fs/watch/watch.global-override-for-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 { getGlobalOverride } from "../../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import watchInjectable from "./watch.injectable"; export default getGlobalOverride(watchInjectable, () => () => { diff --git a/packages/core/src/common/fs/watch/watch.injectable.ts b/packages/core/src/common/fs/watch/watch.injectable.ts index 50f96cdf57..084197769d 100644 --- a/packages/core/src/common/fs/watch/watch.injectable.ts +++ b/packages/core/src/common/fs/watch/watch.injectable.ts @@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import { watch } from "chokidar"; import type { Stats } from "fs"; import type TypedEventEmitter from "typed-emitter"; -import type { SingleOrMany } from "../../utils"; +import type { SingleOrMany } from "@k8slens/utilities"; export interface AlwaysStatWatcherEvents { add: (path: string, stats: Stats) => void; 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 index c8b7ef8e45..e87f648305 100644 --- 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 @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import writeFileInjectable from "./write-file.injectable"; export default getGlobalOverride(writeFileInjectable, () => async () => { diff --git a/packages/core/src/common/get-configuration-file-model/get-configuration-file-model.global-override-for-injectable.ts b/packages/core/src/common/get-configuration-file-model/get-configuration-file-model.global-override-for-injectable.ts index 5f51460a2b..95e2845825 100644 --- a/packages/core/src/common/get-configuration-file-model/get-configuration-file-model.global-override-for-injectable.ts +++ b/packages/core/src/common/get-configuration-file-model/get-configuration-file-model.global-override-for-injectable.ts @@ -5,7 +5,7 @@ import assert from "assert"; import path from "path"; -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import getConfigurationFileModelInjectable from "./get-configuration-file-model.injectable"; import type Config from "conf"; import readJsonSyncInjectable from "../fs/read-json-sync.injectable"; 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 bf5aa19367..258367c7ec 100644 --- a/packages/core/src/common/helm/add-helm-repository-channel.ts +++ b/packages/core/src/common/helm/add-helm-repository-channel.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import type { HelmRepo } from "./helm-repo"; -import type { AsyncResult } from "../utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token"; export type AddHelmRepositoryChannel = RequestChannel>; 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 26720e9a5f..2ea5a80030 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 @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import type { HelmRepo } from "./helm-repo"; -import type { AsyncResult } from "../utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token"; export type GetActiveHelmRepositoriesChannel = RequestChannel>; 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 4d479d088c..f1189cb580 100644 --- a/packages/core/src/common/helm/remove-helm-repository-channel.ts +++ b/packages/core/src/common/helm/remove-helm-repository-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 { AsyncResult } from "../utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token"; import type { HelmRepo } from "./helm-repo"; diff --git a/packages/core/src/common/hotbars/types.ts b/packages/core/src/common/hotbars/types.ts index 6370fe136d..2925c785a0 100644 --- a/packages/core/src/common/hotbars/types.ts +++ b/packages/core/src/common/hotbars/types.ts @@ -4,8 +4,8 @@ */ import * as uuid from "uuid"; -import type { Tuple } from "../utils"; -import { tuple } from "../utils"; +import type { Tuple } from "@k8slens/utilities"; +import { tuple } from "@k8slens/utilities"; export interface HotbarItem { entity: { diff --git a/packages/core/src/common/ipc/broadcast-message.global-override-for-injectable.ts b/packages/core/src/common/ipc/broadcast-message.global-override-for-injectable.ts index e455b30cdc..519d0761ed 100644 --- a/packages/core/src/common/ipc/broadcast-message.global-override-for-injectable.ts +++ b/packages/core/src/common/ipc/broadcast-message.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverrideForFunction } from "../test-utils/get-global-override-for-function"; +import { getGlobalOverrideForFunction } from "@k8slens/test-utils"; import broadcastMessageInjectable from "./broadcast-message.injectable"; export default getGlobalOverrideForFunction(broadcastMessageInjectable); diff --git a/packages/core/src/common/ipc/ipc.ts b/packages/core/src/common/ipc/ipc.ts index e84fcfec56..4815fbfbf1 100644 --- a/packages/core/src/common/ipc/ipc.ts +++ b/packages/core/src/common/ipc/ipc.ts @@ -11,7 +11,7 @@ import { ipcMain, ipcRenderer, webContents } from "electron"; import { toJS } from "../utils/toJS"; import type { ClusterFrameInfo } from "../cluster-frames"; import { clusterFrameMap } from "../cluster-frames"; -import type { Disposer } from "../utils"; +import type { Disposer } from "@k8slens/utilities"; import { getLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; import ipcRendererInjectable from "../../renderer/utils/channel/ipc-renderer.injectable"; import loggerInjectable from "../logger.injectable"; diff --git a/packages/core/src/common/item.store.ts b/packages/core/src/common/item.store.ts index 805137e95c..4d7c3343ef 100644 --- a/packages/core/src/common/item.store.ts +++ b/packages/core/src/common/item.store.ts @@ -3,8 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ +import autoBind from "auto-bind"; import orderBy from "lodash/orderBy"; -import { autoBind } from "./utils"; import { action, computed, observable, when, makeObservable } from "mobx"; export interface ItemObject { 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 e6092fa417..6ea6327038 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 @@ -17,10 +17,10 @@ import { KubeApi } from "../kube-api"; import { KubeObject } from "../kube-object"; import { KubeObjectStore } from "../kube-object.store"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; -import { createClusterInjectionToken } from "../../cluster/create-cluster-injection-token"; // eslint-disable-next-line no-restricted-imports import { KubeApi as ExternalKubeApi } from "../../../extensions/common-api/k8s-api"; +import { Cluster } from "../../cluster/cluster"; class TestApi extends KubeApi { protected async checkPreferredVersion() { @@ -43,9 +43,7 @@ describe("ApiManager", () => { di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs"); di.override(storesAndApisCanBeCreatedInjectable, () => true); - const createCluster = di.inject(createClusterInjectionToken); - - di.override(hostedClusterInjectable, () => createCluster({ + di.override(hostedClusterInjectable, () => new Cluster({ contextName: "some-context-name", id: "some-cluster-id", kubeConfigPath: "/some-path-to-a-kubeconfig", diff --git a/packages/core/src/common/k8s-api/__tests__/kube-api-version-detection.test.ts b/packages/core/src/common/k8s-api/__tests__/kube-api-version-detection.test.ts index da7c46eda3..e3bcd70a81 100644 --- a/packages/core/src/common/k8s-api/__tests__/kube-api-version-detection.test.ts +++ b/packages/core/src/common/k8s-api/__tests__/kube-api-version-detection.test.ts @@ -10,7 +10,7 @@ import type { Fetch } from "../../fetch/fetch.injectable"; import fetchInjectable from "../../fetch/fetch.injectable"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; -import { flushPromises } from "../../test-utils/flush-promises"; +import { flushPromises } from "@k8slens/test-utils"; import setupAutoRegistrationInjectable from "../../../renderer/before-frame-starts/runnables/setup-auto-registration.injectable"; import { createMockResponseFromString } from "../../../test-utils/mock-responses"; import storesAndApisCanBeCreatedInjectable from "../../../renderer/stores-apis-can-be-created.injectable"; @@ -22,7 +22,7 @@ import type { DiContainer } from "@ogre-tools/injectable"; import ingressApiInjectable from "../endpoints/ingress.api.injectable"; import loggerInjectable from "../../logger.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; -import { createClusterInjectionToken } from "../../cluster/create-cluster-injection-token"; +import { Cluster } from "../../cluster/cluster"; describe("KubeApi", () => { let fetchMock: AsyncFnMock; @@ -39,9 +39,7 @@ describe("KubeApi", () => { di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs"); di.override(storesAndApisCanBeCreatedInjectable, () => true); - const createCluster = di.inject(createClusterInjectionToken); - - di.override(hostedClusterInjectable, () => createCluster({ + di.override(hostedClusterInjectable, () => new Cluster({ contextName: "some-context-name", id: "some-cluster-id", kubeConfigPath: "/some-path-to-a-kubeconfig", @@ -121,7 +119,7 @@ describe("KubeApi", () => { ]); }); - describe("when resource request fufills with a resource", () => { + describe("when resource request fulfills with a resource", () => { beforeEach(async () => { await fetchMock.resolveSpecific( ["https://127.0.0.1:12345/api-kube/apis/networking.k8s.io/v1"], @@ -283,7 +281,7 @@ describe("KubeApi", () => { }); }); - describe("when resource request fufills with no resource", () => { + describe("when resource request fulfills with no resource", () => { beforeEach(async () => { await fetchMock.resolveSpecific( ["https://127.0.0.1:12345/api-kube/apis/networking.k8s.io/v1"], @@ -307,7 +305,7 @@ describe("KubeApi", () => { - describe("when resource request fufills with a resource", () => { + describe("when resource request fulfills with a resource", () => { beforeEach(async () => { await fetchMock.resolveSpecific( ["https://127.0.0.1:12345/api-kube/apis/networking.k8s.io/v1beta1"], @@ -509,7 +507,7 @@ describe("KubeApi", () => { ]); }); - describe("when resource request fufills with a resource", () => { + describe("when resource request fulfills with a resource", () => { beforeEach(async () => { await fetchMock.resolveSpecific( ["https://127.0.0.1:12345/api-kube/apis/extensions"], 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 e2b5907d85..2b3978c0eb 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 @@ -15,7 +15,7 @@ import type { CreateKubeApiForRemoteCluster } from "../create-kube-api-for-remot import createKubeApiForRemoteClusterInjectable from "../create-kube-api-for-remote-cluster.injectable"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; -import { flushPromises } from "../../test-utils/flush-promises"; +import { flushPromises } from "@k8slens/test-utils"; import createKubeJsonApiInjectable from "../create-kube-json-api.injectable"; import type { IKubeWatchEvent } from "../kube-watch-event"; import type { KubeJsonApiDataFor } from "../kube-object"; @@ -35,7 +35,7 @@ import namespaceApiInjectable from "../endpoints/namespace.api.injectable"; // NOTE: this is fine because we are testing something that only exported // eslint-disable-next-line no-restricted-imports import { PodsApi } from "../../../extensions/common-api/k8s-api"; -import { createClusterInjectionToken } from "../../cluster/create-cluster-injection-token"; +import { Cluster } from "../../cluster/cluster"; describe("createKubeApiForRemoteCluster", () => { let createKubeApiForRemoteCluster: CreateKubeApiForRemoteCluster; @@ -48,9 +48,7 @@ describe("createKubeApiForRemoteCluster", () => { di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs"); di.override(storesAndApisCanBeCreatedInjectable, () => true); - const createCluster = di.inject(createClusterInjectionToken); - - di.override(hostedClusterInjectable, () => createCluster({ + di.override(hostedClusterInjectable, () => new Cluster({ contextName: "some-context-name", id: "some-cluster-id", kubeConfigPath: "/some-path-to-a-kubeconfig", @@ -154,10 +152,9 @@ describe("KubeApi", () => { fetchMock = asyncFn(); di.override(fetchInjectable, () => fetchMock); - const createCluster = di.inject(createClusterInjectionToken); const createKubeJsonApi = di.inject(createKubeJsonApiInjectable); - di.override(hostedClusterInjectable, () => createCluster({ + di.override(hostedClusterInjectable, () => new Cluster({ contextName: "some-context-name", id: "some-cluster-id", kubeConfigPath: "/some-path-to-a-kubeconfig", diff --git a/packages/core/src/common/k8s-api/__tests__/kube-object.store.test.ts b/packages/core/src/common/k8s-api/__tests__/kube-object.store.test.ts index 424cffba23..24820648af 100644 --- a/packages/core/src/common/k8s-api/__tests__/kube-object.store.test.ts +++ b/packages/core/src/common/k8s-api/__tests__/kube-object.store.test.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { noop } from "../../utils"; +import { noop } from "@k8slens/utilities"; import type { KubeApi } from "../kube-api"; import { KubeObject } from "../kube-object"; import type { KubeObjectStoreLoadingParams } from "../kube-object.store"; 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 0dad9a2a21..f6c2758921 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,7 @@ 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 { chain, find } from "../../utils/iter"; +import { iter } from "@k8slens/utilities"; export type RegisterableStore = Store extends KubeObjectStore ? Store @@ -38,7 +38,7 @@ export class ApiManager { constructor(private readonly dependencies: Dependencies) { // NOTE: this is done to preserve the old behaviour of an API being discoverable using all previous apiBases autorun(() => { - const apis = chain(this.dependencies.apis.get().values()) + const apis = iter.chain(this.dependencies.apis.get().values()) .concat(this.externalApis.values()); const removedApis = new Set(this.apis.values()); const newState = new Map(this.apis); @@ -62,7 +62,7 @@ export class ApiManager { getApi(pathOrCallback: string | FindApiCallback) { if (typeof pathOrCallback === "function") { - return find(this.apis.values(), pathOrCallback); + return iter.find(this.apis.values(), pathOrCallback); } const { apiBase } = parseKubeApi(pathOrCallback); @@ -130,7 +130,7 @@ export class ApiManager { return undefined; } - return chain(this.dependencies.stores.get().values()) + return iter.chain(this.dependencies.stores.get().values()) .concat(this.externalStores.values()) .find(store => store.api.apiBase === api.apiBase); } diff --git a/packages/core/src/common/k8s-api/endpoints/config-map.api.ts b/packages/core/src/common/k8s-api/endpoints/config-map.api.ts index a2860246b1..cf635fb623 100644 --- a/packages/core/src/common/k8s-api/endpoints/config-map.api.ts +++ b/packages/core/src/common/k8s-api/endpoints/config-map.api.ts @@ -8,7 +8,7 @@ import { KubeObject } from "../kube-object"; import type { KubeJsonApiData } from "../kube-json-api"; import type { DerivedKubeApiOptions, KubeApiDependencies } from "../kube-api"; import { KubeApi } from "../kube-api"; -import { autoBind } from "../../utils"; +import autoBind from "auto-bind"; export interface ConfigMapData extends KubeJsonApiData, void, void> { data?: Partial>; diff --git a/packages/core/src/common/k8s-api/endpoints/cron-job.api.ts b/packages/core/src/common/k8s-api/endpoints/cron-job.api.ts index 2ccb8c910c..1ad0c42511 100644 --- a/packages/core/src/common/k8s-api/endpoints/cron-job.api.ts +++ b/packages/core/src/common/k8s-api/endpoints/cron-job.api.ts @@ -6,7 +6,7 @@ import moment from "moment"; import type { NamespaceScopedMetadata, ObjectReference } from "../kube-object"; import { KubeObject } from "../kube-object"; -import { formatDuration } from "../../utils/formatDuration"; +import { formatDuration } from "@k8slens/utilities"; import type { DerivedKubeApiOptions, KubeApiDependencies } from "../kube-api"; import { KubeApi } from "../kube-api"; import type { JobTemplateSpec } from "./types/job-template-spec"; diff --git a/packages/core/src/common/k8s-api/endpoints/custom-resource-definition.api.ts b/packages/core/src/common/k8s-api/endpoints/custom-resource-definition.api.ts index b438f06b3a..a9259e710e 100644 --- a/packages/core/src/common/k8s-api/endpoints/custom-resource-definition.api.ts +++ b/packages/core/src/common/k8s-api/endpoints/custom-resource-definition.api.ts @@ -5,7 +5,7 @@ import { getLegacyGlobalDiForExtensionApi } from "../../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; import customResourcesRouteInjectable from "../../front-end-routing/routes/cluster/custom-resources/custom-resources/custom-resources-route.injectable"; -import { buildURL } from "../../utils/buildUrl"; +import { buildURL } from "@k8slens/utilities"; import type { BaseKubeObjectCondition, ClusterScopedMetadata } from "../kube-object"; import { KubeObject } from "../kube-object"; import type { DerivedKubeApiOptions, KubeApiDependencies } from "../kube-api"; diff --git a/packages/core/src/common/k8s-api/endpoints/deployment.api.ts b/packages/core/src/common/k8s-api/endpoints/deployment.api.ts index 31bc55ae76..70e7200e3c 100644 --- a/packages/core/src/common/k8s-api/endpoints/deployment.api.ts +++ b/packages/core/src/common/k8s-api/endpoints/deployment.api.ts @@ -10,7 +10,7 @@ import { KubeApi } from "../kube-api"; import type { PodSpec } from "./pod.api"; import type { KubeObjectStatus, LabelSelector, NamespaceScopedMetadata } from "../kube-object"; import { KubeObject } from "../kube-object"; -import { hasTypedProperty, isNumber, isObject } from "../../utils"; +import { hasTypedProperty, isNumber, isObject } from "@k8slens/utilities"; export class DeploymentApi extends KubeApi { constructor(deps: KubeApiDependencies, opts?: DerivedKubeApiOptions) { diff --git a/packages/core/src/common/k8s-api/endpoints/endpoint.api.ts b/packages/core/src/common/k8s-api/endpoints/endpoint.api.ts index c60377a887..1e045e902d 100644 --- a/packages/core/src/common/k8s-api/endpoints/endpoint.api.ts +++ b/packages/core/src/common/k8s-api/endpoints/endpoint.api.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { autoBind } from "../../utils"; +import autoBind from "auto-bind"; import type { KubeObjectMetadata, KubeObjectScope, NamespaceScopedMetadata, ObjectReference } from "../kube-object"; import { KubeObject } from "../kube-object"; import type { DerivedKubeApiOptions, KubeApiDependencies } from "../kube-api"; diff --git a/packages/core/src/common/k8s-api/endpoints/events.api.ts b/packages/core/src/common/k8s-api/endpoints/events.api.ts index aca77712c8..1da4b6afe8 100644 --- a/packages/core/src/common/k8s-api/endpoints/events.api.ts +++ b/packages/core/src/common/k8s-api/endpoints/events.api.ts @@ -6,7 +6,7 @@ import moment from "moment"; import type { KubeObjectMetadata, KubeObjectScope, ObjectReference } from "../kube-object"; import { KubeObject } from "../kube-object"; -import { formatDuration } from "../../utils/formatDuration"; +import { formatDuration } from "@k8slens/utilities"; import type { DerivedKubeApiOptions, KubeApiDependencies } from "../kube-api"; import { KubeApi } from "../kube-api"; import type { KubeJsonApiData } from "../kube-json-api"; diff --git a/packages/core/src/common/k8s-api/endpoints/helm-charts.api.ts b/packages/core/src/common/k8s-api/endpoints/helm-charts.api.ts index 26da740830..da2d8ab00c 100644 --- a/packages/core/src/common/k8s-api/endpoints/helm-charts.api.ts +++ b/packages/core/src/common/k8s-api/endpoints/helm-charts.api.ts @@ -3,7 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { autoBind, bifurcateArray } from "../../utils"; +import { array } from "@k8slens/utilities"; +import autoBind from "auto-bind"; import Joi from "joi"; export interface RawHelmChart { @@ -263,7 +264,7 @@ export class HelmChart implements HelmChartData { return new HelmChart(result.value); } - const [actualErrors, unknownDetails] = bifurcateArray(result.error.details, ({ type }) => type === "object.unknown"); + const [actualErrors, unknownDetails] = array.bifurcate(result.error.details, ({ type }) => type === "object.unknown"); if (unknownDetails.length > 0) { console.warn("HelmChart data has unexpected fields", { original: data, unknownFields: unknownDetails.flatMap(d => d.path) }); diff --git a/packages/core/src/common/k8s-api/endpoints/helm-charts.api/request-charts.injectable.ts b/packages/core/src/common/k8s-api/endpoints/helm-charts.api/request-charts.injectable.ts index 4d9bfc55b1..246b628ea0 100644 --- a/packages/core/src/common/k8s-api/endpoints/helm-charts.api/request-charts.injectable.ts +++ b/packages/core/src/common/k8s-api/endpoints/helm-charts.api/request-charts.injectable.ts @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { RawHelmChart } from "../helm-charts.api"; import { HelmChart } from "../helm-charts.api"; -import { isDefined } from "../../../utils"; +import { isDefined } from "@k8slens/utilities"; import apiBaseInjectable from "../../api-base.injectable"; export type RequestHelmCharts = () => Promise; diff --git a/packages/core/src/common/k8s-api/endpoints/helm-charts.api/request-readme.injectable.ts b/packages/core/src/common/k8s-api/endpoints/helm-charts.api/request-readme.injectable.ts index fb8eaafa10..d6977fc5ca 100644 --- a/packages/core/src/common/k8s-api/endpoints/helm-charts.api/request-readme.injectable.ts +++ b/packages/core/src/common/k8s-api/endpoints/helm-charts.api/request-readme.injectable.ts @@ -3,13 +3,13 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import type { AsyncResult } from "../../../utils/async-result"; -import { urlBuilderFor } from "../../../utils/buildUrl"; +import type { AsyncResult } from "@k8slens/utilities"; +import { urlBuilderFor } from "@k8slens/utilities"; import apiBaseInjectable from "../../api-base.injectable"; const requestReadmeEndpoint = urlBuilderFor("/v2/charts/:repo/:name/readme"); -export type RequestHelmChartReadme = (repo: string, name: string, version?: string) => Promise>; +export type RequestHelmChartReadme = (repo: string, name: string, version?: string) => AsyncResult; const requestHelmChartReadmeInjectable = getInjectable({ id: "request-helm-chart-readme", diff --git a/packages/core/src/common/k8s-api/endpoints/helm-charts.api/request-values.injectable.ts b/packages/core/src/common/k8s-api/endpoints/helm-charts.api/request-values.injectable.ts index 71105c9ff9..2d4e77bf33 100644 --- a/packages/core/src/common/k8s-api/endpoints/helm-charts.api/request-values.injectable.ts +++ b/packages/core/src/common/k8s-api/endpoints/helm-charts.api/request-values.injectable.ts @@ -3,13 +3,13 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import type { AsyncResult } from "../../../utils/async-result"; -import { urlBuilderFor } from "../../../utils/buildUrl"; +import type { AsyncResult } from "@k8slens/utilities"; +import { urlBuilderFor } from "@k8slens/utilities"; import apiBaseInjectable from "../../api-base.injectable"; const requestValuesEndpoint = urlBuilderFor("/v2/charts/:repo/:name/values"); -export type RequestHelmChartValues = (repo: string, name: string, version: string) => Promise>; +export type RequestHelmChartValues = (repo: string, name: string, version: string) => AsyncResult; const requestHelmChartValuesInjectable = getInjectable({ id: "request-helm-chart-values", diff --git a/packages/core/src/common/k8s-api/endpoints/helm-charts.api/request-versions.injectable.ts b/packages/core/src/common/k8s-api/endpoints/helm-charts.api/request-versions.injectable.ts index ab85594ec6..f7527c093a 100644 --- a/packages/core/src/common/k8s-api/endpoints/helm-charts.api/request-versions.injectable.ts +++ b/packages/core/src/common/k8s-api/endpoints/helm-charts.api/request-versions.injectable.ts @@ -3,10 +3,9 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { urlBuilderFor } from "../../../utils/buildUrl"; +import { urlBuilderFor, isDefined } from "@k8slens/utilities"; import { HelmChart } from "../helm-charts.api"; import type { RawHelmChart } from "../helm-charts.api"; -import { isDefined } from "../../../utils"; import apiBaseInjectable from "../../api-base.injectable"; const requestVersionsEndpoint = urlBuilderFor("/v2/charts/:repo/:name/versions"); diff --git a/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-configuration.global-override-for-injectable.ts b/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-configuration.global-override-for-injectable.ts index 18b3bd0ec0..631d4c5e17 100644 --- a/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-configuration.global-override-for-injectable.ts +++ b/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-configuration.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../../../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import requestHelmReleaseConfigurationInjectable from "./request-configuration.injectable"; export default getGlobalOverride(requestHelmReleaseConfigurationInjectable, () => () => { diff --git a/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-configuration.injectable.ts b/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-configuration.injectable.ts index e1581c5d76..b9e6de7b0c 100644 --- a/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-configuration.injectable.ts +++ b/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-configuration.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 { urlBuilderFor } from "../../../utils/buildUrl"; +import { urlBuilderFor } from "@k8slens/utilities"; import apiBaseInjectable from "../../api-base.injectable"; export type RequestHelmReleaseConfiguration = ( diff --git a/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-create.injectable.ts b/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-create.injectable.ts index c1cd09d40f..253e97bf72 100644 --- a/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-create.injectable.ts +++ b/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-create.injectable.ts @@ -5,7 +5,7 @@ import yaml from "js-yaml"; import { getInjectable } from "@ogre-tools/injectable"; import type { HelmReleaseUpdateDetails } from "../helm-releases.api"; -import { urlBuilderFor } from "../../../utils/buildUrl"; +import { urlBuilderFor } from "@k8slens/utilities"; import apiBaseInjectable from "../../api-base.injectable"; interface HelmReleaseCreatePayload { diff --git a/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-delete.injectable.ts b/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-delete.injectable.ts index 44af4311a9..3b48f2d9b7 100644 --- a/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-delete.injectable.ts +++ b/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-delete.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 { urlBuilderFor } from "../../../utils/buildUrl"; +import { urlBuilderFor } from "@k8slens/utilities"; import apiBaseInjectable from "../../api-base.injectable"; export type RequestDeleteHelmRelease = (name: string, namespace: string) => Promise; diff --git a/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-details.injectable.ts b/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-details.injectable.ts index 37f2287377..8c7b3dd472 100644 --- a/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-details.injectable.ts +++ b/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-details.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import type { KubeJsonApiData } from "../../kube-json-api"; -import { urlBuilderFor } from "../../../utils/buildUrl"; +import { urlBuilderFor } from "@k8slens/utilities"; import apiBaseInjectable from "../../api-base.injectable"; export interface HelmReleaseDetails { diff --git a/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-history.injectable.ts b/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-history.injectable.ts index 58b6a37dbb..9a9a3159ea 100644 --- a/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-history.injectable.ts +++ b/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-history.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 { urlBuilderFor } from "../../../utils/buildUrl"; +import { urlBuilderFor } from "@k8slens/utilities"; import apiBaseInjectable from "../../api-base.injectable"; export interface HelmReleaseRevision { diff --git a/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-releases.injectable.ts b/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-releases.injectable.ts index ee6503ca99..ffd3a92dee 100644 --- a/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-releases.injectable.ts +++ b/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-releases.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 { urlBuilderFor } from "../../../utils/buildUrl"; +import { urlBuilderFor } from "@k8slens/utilities"; import apiBaseInjectable from "../../api-base.injectable"; import type { HelmReleaseDto } from "../helm-releases.api"; diff --git a/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-rollback.injectable.ts b/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-rollback.injectable.ts index 036b399ef2..9e43e4d8ac 100644 --- a/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-rollback.injectable.ts +++ b/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-rollback.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 { urlBuilderFor } from "../../../utils/buildUrl"; +import { urlBuilderFor } from "@k8slens/utilities"; import apiBaseInjectable from "../../api-base.injectable"; export type RequestHelmReleaseRollback = (name: string, namespace: string, revision: number) => Promise; diff --git a/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-update.injectable.ts b/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-update.injectable.ts index 715a21cea9..3a23536673 100644 --- a/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-update.injectable.ts +++ b/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-update.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 { urlBuilderFor } from "../../../utils/buildUrl"; -import type { AsyncResult } from "../../../utils/async-result"; +import { urlBuilderFor } from "@k8slens/utilities"; +import type { AsyncResult } from "@k8slens/utilities"; import apiBaseInjectable from "../../api-base.injectable"; interface HelmReleaseUpdatePayload { @@ -18,7 +18,7 @@ export type RequestHelmReleaseUpdate = ( name: string, namespace: string, payload: HelmReleaseUpdatePayload -) => Promise>; +) => AsyncResult; const requestUpdateEndpoint = urlBuilderFor("/v2/releases/:namespace/:name"); diff --git a/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-values.injectable.ts b/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-values.injectable.ts index 99f1cc17d0..a1668b993e 100644 --- a/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-values.injectable.ts +++ b/packages/core/src/common/k8s-api/endpoints/helm-releases.api/request-values.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 { urlBuilderFor } from "../../../utils/buildUrl"; +import { urlBuilderFor } from "@k8slens/utilities"; import apiBaseInjectable from "../../api-base.injectable"; export type RequestHelmReleaseValues = (name: string, namespace: string, all?: boolean) => Promise; diff --git a/packages/core/src/common/k8s-api/endpoints/horizontal-pod-autoscaler.api.ts b/packages/core/src/common/k8s-api/endpoints/horizontal-pod-autoscaler.api.ts index f0bc5d14bc..b3bdbbf21d 100644 --- a/packages/core/src/common/k8s-api/endpoints/horizontal-pod-autoscaler.api.ts +++ b/packages/core/src/common/k8s-api/endpoints/horizontal-pod-autoscaler.api.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { OptionVarient } from "../../utils"; +import type { OptionVariant } from "@k8slens/utilities"; import type { DerivedKubeApiOptions, KubeApiDependencies } from "../kube-api"; import { KubeApi } from "../kube-api"; import type { BaseKubeObjectCondition, LabelSelector, NamespaceScopedMetadata } from "../kube-object"; @@ -46,7 +46,7 @@ export interface V2Beta1ContainerResourceMetricSource { targetAverageValue?: string; } -export type ContainerResourceMetricSource = +export type ContainerResourceMetricSource = | V2ContainerResourceMetricSource | V2Beta1ContainerResourceMetricSource; @@ -74,7 +74,7 @@ export interface V2Beta1ExternalMetricSource { }; } -export type ExternalMetricSource = +export type ExternalMetricSource = | V2Beta1ExternalMetricSource | V2ExternalMetricSource; @@ -152,11 +152,11 @@ export interface BaseHorizontalPodAutoscalerMetricSpec { } export type HorizontalPodAutoscalerMetricSpec = - | OptionVarient - | OptionVarient - | OptionVarient - | OptionVarient - | OptionVarient; + | OptionVariant + | OptionVariant + | OptionVariant + | OptionVariant + | OptionVariant; interface HorizontalPodAutoscalerBehavior { scaleUp?: HPAScalingRules; @@ -294,11 +294,11 @@ export interface BaseHorizontalPodAutoscalerMetricStatus { } export type HorizontalPodAutoscalerMetricStatus = - | OptionVarient - | OptionVarient - | OptionVarient - | OptionVarient - | OptionVarient; + | OptionVariant + | OptionVariant + | OptionVariant + | OptionVariant + | OptionVariant; export interface HorizontalPodAutoscalerSpec { scaleTargetRef: CrossVersionObjectReference; diff --git a/packages/core/src/common/k8s-api/endpoints/ingress.api.ts b/packages/core/src/common/k8s-api/endpoints/ingress.api.ts index d35cd77c0b..2a9a49ad8e 100644 --- a/packages/core/src/common/k8s-api/endpoints/ingress.api.ts +++ b/packages/core/src/common/k8s-api/endpoints/ingress.api.ts @@ -5,7 +5,7 @@ import type { NamespaceScopedMetadata, TypedLocalObjectReference } from "../kube-object"; import { KubeObject } from "../kube-object"; -import { hasTypedProperty, isString, iter } from "../../utils"; +import { hasTypedProperty, isString, iter } from "@k8slens/utilities"; import type { DerivedKubeApiOptions, KubeApiDependencies } from "../kube-api"; import { KubeApi } from "../kube-api"; import type { RequireExactlyOne } from "type-fest"; diff --git a/packages/core/src/common/k8s-api/endpoints/metrics.api.ts b/packages/core/src/common/k8s-api/endpoints/metrics.api.ts index 406ab1d0b2..69465bbf6e 100644 --- a/packages/core/src/common/k8s-api/endpoints/metrics.api.ts +++ b/packages/core/src/common/k8s-api/endpoints/metrics.api.ts @@ -6,7 +6,7 @@ // Metrics api import moment from "moment"; -import { isDefined, object } from "../../utils"; +import { isDefined, object } from "@k8slens/utilities"; export interface MetricData { status: string; diff --git a/packages/core/src/common/k8s-api/endpoints/node.api.ts b/packages/core/src/common/k8s-api/endpoints/node.api.ts index 158f359a57..31839b24f8 100644 --- a/packages/core/src/common/k8s-api/endpoints/node.api.ts +++ b/packages/core/src/common/k8s-api/endpoints/node.api.ts @@ -5,7 +5,7 @@ import type { BaseKubeObjectCondition, ClusterScopedMetadata } from "../kube-object"; import { KubeObject } from "../kube-object"; -import { cpuUnitsToNumber, unitsToBytes, isObject } from "../../../renderer/utils"; +import { cpuUnitsToNumber, unitsToBytes, isObject } from "@k8slens/utilities"; import type { DerivedKubeApiOptions, KubeApiDependencies } from "../kube-api"; import { KubeApi } from "../kube-api"; import { TypedRegEx } from "typed-regex"; diff --git a/packages/core/src/common/k8s-api/endpoints/persistent-volume-claim.api.ts b/packages/core/src/common/k8s-api/endpoints/persistent-volume-claim.api.ts index 947d9139a3..25e4d63454 100644 --- a/packages/core/src/common/k8s-api/endpoints/persistent-volume-claim.api.ts +++ b/packages/core/src/common/k8s-api/endpoints/persistent-volume-claim.api.ts @@ -8,7 +8,7 @@ import { KubeObject } from "../kube-object"; import type { Pod } from "./pod.api"; import type { DerivedKubeApiOptions, KubeApiDependencies } from "../kube-api"; import { KubeApi } from "../kube-api"; -import { object } from "../../utils"; +import { object } from "@k8slens/utilities"; import type { ResourceRequirements } from "./types/resource-requirements"; export class PersistentVolumeClaimApi extends KubeApi { diff --git a/packages/core/src/common/k8s-api/endpoints/persistent-volume.api.ts b/packages/core/src/common/k8s-api/endpoints/persistent-volume.api.ts index f4d80a82eb..6d6e249db5 100644 --- a/packages/core/src/common/k8s-api/endpoints/persistent-volume.api.ts +++ b/packages/core/src/common/k8s-api/endpoints/persistent-volume.api.ts @@ -5,7 +5,7 @@ import type { ClusterScopedMetadata, LabelSelector, ObjectReference, TypedLocalObjectReference } from "../kube-object"; import { KubeObject } from "../kube-object"; -import { unitsToBytes } from "../../utils"; +import { unitsToBytes } from "@k8slens/utilities"; import type { DerivedKubeApiOptions, KubeApiDependencies } from "../kube-api"; import { KubeApi } from "../kube-api"; import type { ResourceRequirements } from "./types/resource-requirements"; diff --git a/packages/core/src/common/k8s-api/endpoints/pod.api.ts b/packages/core/src/common/k8s-api/endpoints/pod.api.ts index 3a0bed57cd..1db41957b2 100644 --- a/packages/core/src/common/k8s-api/endpoints/pod.api.ts +++ b/packages/core/src/common/k8s-api/endpoints/pod.api.ts @@ -10,7 +10,7 @@ import type { KubeObjectMetadata, LocalObjectReference, Affinity, Toleration, Na import type { SecretReference } from "./secret.api"; import type { PersistentVolumeClaimSpec } from "./persistent-volume-claim.api"; import { KubeObject } from "../kube-object"; -import { isDefined } from "../../utils"; +import { isDefined } from "@k8slens/utilities"; import type { PodSecurityContext } from "./types/pod-security-context"; import type { Probe } from "./types/probe"; import type { Container } from "./types/container"; @@ -80,6 +80,8 @@ export interface ContainerState { terminated?: ContainerStateTerminated; } +export type ContainerStateValues = Partial; + export interface PodContainerStatus { name: string; state?: ContainerState; @@ -649,7 +651,7 @@ export class Pod extends KubeObject< .filter(({ name }) => runningContainerNames.has(name)); } - getContainerStatuses(includeInitContainers = true) { + getContainerStatuses(includeInitContainers = true): PodContainerStatus[] { const { containerStatuses = [], initContainerStatuses = [] } = this.status ?? {}; if (includeInitContainers) { diff --git a/packages/core/src/common/k8s-api/endpoints/resource-applier.api/request-patch.injectable.ts b/packages/core/src/common/k8s-api/endpoints/resource-applier.api/request-patch.injectable.ts index 49271fb6d2..714340c78a 100644 --- a/packages/core/src/common/k8s-api/endpoints/resource-applier.api/request-patch.injectable.ts +++ b/packages/core/src/common/k8s-api/endpoints/resource-applier.api/request-patch.injectable.ts @@ -5,10 +5,10 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { Patch } from "rfc6902"; import apiBaseInjectable from "../../api-base.injectable"; -import type { AsyncResult } from "../../../utils/async-result"; +import type { AsyncResult, Result } from "@k8slens/utilities"; import type { KubeJsonApiData } from "../../kube-json-api"; -export type RequestKubeObjectPatch = (name: string, kind: string, ns: string | undefined, patch: Patch) => Promise>; +export type RequestKubeObjectPatch = (name: string, kind: string, ns: string | undefined, patch: Patch) => AsyncResult; const requestKubeObjectPatchInjectable = getInjectable({ id: "request-kube-object-patch", @@ -23,7 +23,7 @@ const requestKubeObjectPatchInjectable = getInjectable({ ns, patch, }, - }) as AsyncResult; + }) as Result; if (!result.callWasSuccessful) { return result; diff --git a/packages/core/src/common/k8s-api/endpoints/resource-applier.api/request-update.injectable.ts b/packages/core/src/common/k8s-api/endpoints/resource-applier.api/request-update.injectable.ts index 1891a779cf..211ada1575 100644 --- a/packages/core/src/common/k8s-api/endpoints/resource-applier.api/request-update.injectable.ts +++ b/packages/core/src/common/k8s-api/endpoints/resource-applier.api/request-update.injectable.ts @@ -4,10 +4,10 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import apiBaseInjectable from "../../api-base.injectable"; -import type { AsyncResult } from "../../../utils/async-result"; +import type { AsyncResult, Result } from "@k8slens/utilities"; import type { KubeJsonApiData } from "../../kube-json-api"; -export type RequestKubeObjectCreation = (resourceDescriptor: string) => Promise>; +export type RequestKubeObjectCreation = (resourceDescriptor: string) => AsyncResult; const requestKubeObjectCreationInjectable = getInjectable({ id: "request-kube-object-creation", @@ -15,7 +15,7 @@ const requestKubeObjectCreationInjectable = getInjectable({ const apiBase = di.inject(apiBaseInjectable); return async (data) => { - const result = await apiBase.post("/stack", { data }) as AsyncResult; + const result = await apiBase.post("/stack", { data }) as Result; if (!result.callWasSuccessful) { return result; diff --git a/packages/core/src/common/k8s-api/endpoints/secret.api.ts b/packages/core/src/common/k8s-api/endpoints/secret.api.ts index a5a3b5eb1c..213aa1ef2b 100644 --- a/packages/core/src/common/k8s-api/endpoints/secret.api.ts +++ b/packages/core/src/common/k8s-api/endpoints/secret.api.ts @@ -6,9 +6,9 @@ import type { KubeObjectMetadata, KubeObjectScope, NamespaceScopedMetadata } from "../kube-object"; import { KubeObject } from "../kube-object"; import type { KubeJsonApiData } from "../kube-json-api"; -import { autoBind } from "../../utils"; import type { DerivedKubeApiOptions, KubeApiDependencies } from "../kube-api"; import { KubeApi } from "../kube-api"; +import autoBind from "auto-bind"; export enum SecretType { Opaque = "Opaque", diff --git a/packages/core/src/common/k8s-api/endpoints/storage-class.api.ts b/packages/core/src/common/k8s-api/endpoints/storage-class.api.ts index bf121e47db..d0b7167876 100644 --- a/packages/core/src/common/k8s-api/endpoints/storage-class.api.ts +++ b/packages/core/src/common/k8s-api/endpoints/storage-class.api.ts @@ -3,12 +3,12 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { autoBind } from "../../utils"; import type { ClusterScopedMetadata, KubeObjectMetadata, KubeObjectScope } from "../kube-object"; import { KubeObject } from "../kube-object"; import type { DerivedKubeApiOptions, KubeApiDependencies } from "../kube-api"; import { KubeApi } from "../kube-api"; import type { KubeJsonApiData } from "../kube-json-api"; +import autoBind from "auto-bind"; export interface TopologySelectorLabelRequirement { key: string; diff --git a/packages/core/src/common/k8s-api/json-api.ts b/packages/core/src/common/k8s-api/json-api.ts index c99fddf4f6..00325f3853 100644 --- a/packages/core/src/common/k8s-api/json-api.ts +++ b/packages/core/src/common/k8s-api/json-api.ts @@ -15,8 +15,8 @@ import type { PartialDeep, ValueOf } from "type-fest"; import { EventEmitter } from "../../common/event-emitter"; import type { Logger } from "../../common/logger"; import type { Fetch } from "../fetch/fetch.injectable"; -import type { Defaulted } from "../utils"; -import { json } from "../utils"; +import type { Defaulted } from "@k8slens/utilities"; +import { isObject, isString, json } from "@k8slens/utilities"; export interface JsonApiData {} @@ -184,20 +184,17 @@ export class JsonApi = Js const res = await this.dependencies.fetch(reqUrl, reqInit); - return this.parseResponse(res, infoLog); + return await this.parseResponse(res, infoLog) as OutData; } - protected async parseResponse(res: Response, log: JsonApiLog): Promise { + protected async parseResponse(res: Response, log: JsonApiLog): Promise { const { status } = res; const text = await res.text(); - let data: any; - - try { - data = text ? json.parse(text) : ""; // DELETE-requests might not have response-body - } catch (e) { - data = text; - } + const parseResponse = json.parse(text || "{}"); + const data = parseResponse.callWasSuccessful + ? parseResponse.response as Data + : text as Data; if (status >= 200 && status < 300) { this.onData.emit(data, res); @@ -211,7 +208,7 @@ export class JsonApi = Js throw data; } - const error = new JsonApiErrorParsed(data, this.parseError(data, res)); + const error = new JsonApiErrorParsed(data as JsonApiError, this.parseError(data, res)); this.onError.emit(error, res); this.writeLog({ ...log, error }); @@ -219,16 +216,20 @@ export class JsonApi = Js throw error; } - protected parseError(error: JsonApiError | string, res: Response): string[] { - if (typeof error === "string") { + protected parseError(error: unknown, res: Response): string[] { + if (isString(error)) { return [error]; } + if (!isObject(error)) { + return []; + } + if (Array.isArray(error.errors)) { return error.errors.map(error => error.title); } - if (error.message) { + if (isString(error.message)) { return [error.message]; } diff --git a/packages/core/src/common/k8s-api/kube-api-parse.ts b/packages/core/src/common/k8s-api/kube-api-parse.ts index cb5315b50c..2bb397a8be 100644 --- a/packages/core/src/common/k8s-api/kube-api-parse.ts +++ b/packages/core/src/common/k8s-api/kube-api-parse.ts @@ -5,7 +5,7 @@ // Parse kube-api path and get api-version, group, etc. -import { splitArray } from "../utils"; +import { array } from "@k8slens/utilities"; export interface IKubeApiLinkRef { apiPrefix?: string; @@ -26,7 +26,7 @@ export function parseKubeApi(path: string): IKubeApiParsed { const apiPath = new URL(path, "https://localhost").pathname; const [, prefix, ...parts] = apiPath.split("/"); const apiPrefix = `/${prefix}`; - const [left, right, namespaced] = splitArray(parts, "namespaces"); + const [left, right, namespaced] = array.split(parts, "namespaces"); let apiGroup!: string; let apiVersion!: string; let namespace!: string; diff --git a/packages/core/src/common/k8s-api/kube-api.ts b/packages/core/src/common/k8s-api/kube-api.ts index 9db60b5484..95210478a1 100644 --- a/packages/core/src/common/k8s-api/kube-api.ts +++ b/packages/core/src/common/k8s-api/kube-api.ts @@ -13,8 +13,8 @@ import { KubeObject, KubeStatus, isKubeStatusData } from "./kube-object"; import byline from "byline"; import type { IKubeWatchEvent } from "./kube-watch-event"; import type { KubeJsonApiData, KubeJsonApi } from "./kube-json-api"; -import type { Disposer } from "../utils"; -import { isDefined, noop, WrappedAbortController } from "../utils"; +import type { Disposer } from "@k8slens/utilities"; +import { isDefined, noop, WrappedAbortController } from "@k8slens/utilities"; import type { RequestInit, Response } from "@k8slens/node-fetch"; import type { Patch } from "rfc6902"; import assert from "assert"; 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 571e395a7b..f26b05283e 100644 --- a/packages/core/src/common/k8s-api/kube-object.store.ts +++ b/packages/core/src/common/k8s-api/kube-object.store.ts @@ -4,8 +4,8 @@ */ import { action, computed, makeObservable, observable, reaction } from "mobx"; -import type { Disposer } from "../utils"; -import { waitUntilDefined, autoBind, includes, rejectPromiseBy } from "../utils"; +import type { Disposer } from "@k8slens/utilities"; +import { waitUntilDefined, includes, rejectPromiseBy, object } from "@k8slens/utilities"; import type { KubeJsonApiDataFor, KubeObject } from "./kube-object"; import { KubeStatus } from "./kube-object"; import type { IKubeWatchEvent } from "./kube-watch-event"; @@ -17,9 +17,9 @@ import type { Patch } from "rfc6902"; import type { Logger } from "../logger"; import assert from "assert"; import type { PartialDeep } from "type-fest"; -import { entries } from "../utils/objects"; import AbortController from "abort-controller"; import type { ClusterContext } from "../../renderer/cluster-frame-context/cluster-frame-context"; +import autoBind from "auto-bind"; export type OnLoadFailure = (error: unknown) => void; @@ -179,7 +179,7 @@ export abstract class KubeObjectStore< return this.items.filter((item: K) => { const itemLabels = item.metadata.labels || {}; - return entries(labels) + return object.entries(labels) .every(([key, value]) => itemLabels[key] === value); }); } diff --git a/packages/core/src/common/k8s-api/kube-object.ts b/packages/core/src/common/k8s-api/kube-object.ts index d88c19db89..e700710788 100644 --- a/packages/core/src/common/k8s-api/kube-object.ts +++ b/packages/core/src/common/k8s-api/kube-object.ts @@ -7,7 +7,7 @@ import moment from "moment"; import type { KubeJsonApiData, KubeJsonApiDataList, KubeJsonApiListMetadata } from "./kube-json-api"; -import { autoBind, formatDuration, hasOptionalTypedProperty, hasTypedProperty, isObject, isString, isNumber, bindPredicate, isTypedArray, isRecord, json } from "../utils"; +import { formatDuration, hasOptionalTypedProperty, hasTypedProperty, isObject, isString, isNumber, bindPredicate, isTypedArray, isRecord } from "@k8slens/utilities"; import type { ItemObject } from "../item.store"; import type { Patch } from "rfc6902"; import assert from "assert"; @@ -17,6 +17,7 @@ import { apiKubeInjectionToken } from "./api-kube"; import requestKubeObjectCreationInjectable from "./endpoints/resource-applier.api/request-update.injectable"; import { dump } from "js-yaml"; import { getLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; +import autoBind from "auto-bind"; export type KubeJsonApiDataFor = K extends KubeObject ? KubeJsonApiData @@ -624,7 +625,7 @@ export class KubeObject< } toPlainObject() { - return json.parse(JSON.stringify(this)) as JsonObject; + return JSON.parse(JSON.stringify(this)) as JsonObject; } /** diff --git a/packages/core/src/common/k8s-api/window-location.global-override-for-injectable.ts b/packages/core/src/common/k8s-api/window-location.global-override-for-injectable.ts index 616e110c88..3a75fb6134 100644 --- a/packages/core/src/common/k8s-api/window-location.global-override-for-injectable.ts +++ b/packages/core/src/common/k8s-api/window-location.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import windowLocationInjectable from "./window-location.injectable"; export default getGlobalOverride(windowLocationInjectable, () => ({ diff --git a/packages/core/src/common/k8s/resource-stack.ts b/packages/core/src/common/k8s/resource-stack.ts index 5bdafdc58d..75460423d1 100644 --- a/packages/core/src/common/k8s/resource-stack.ts +++ b/packages/core/src/common/k8s/resource-stack.ts @@ -7,13 +7,13 @@ import type { KubernetesCluster } from "../catalog-entities"; import yaml from "js-yaml"; import { getLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; import productNameInjectable from "../vars/product-name.injectable"; -import type { AsyncResult } from "../utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; import type { Logger } from "../logger"; import type { KubectlApplyAll, KubectlDeleteAll } from "../kube-helpers/channels"; import type { ReadDirectory } from "../fs/read-directory.injectable"; import type { JoinPaths } from "../path/join-paths.injectable"; import type { ReadFile } from "../fs/read-file.injectable"; -import { hasTypedProperty, isObject } from "../utils"; +import { hasTypedProperty, isObject } from "@k8slens/utilities"; export interface ResourceApplyingStack { kubectlApplyFolder(folderPath: string, templateContext?: any, extraArgs?: string[]): Promise; @@ -72,7 +72,7 @@ export class ResourceStack { return ""; } - protected async applyResources(resources: string[], extraArgs: string[] = []): Promise> { + protected async applyResources(resources: string[], extraArgs: string[] = []): AsyncResult { const kubectlArgs = [...extraArgs, ...this.getAdditionalArgs(extraArgs)]; return this.dependencies.kubectlApplyAll({ @@ -82,7 +82,7 @@ export class ResourceStack { }); } - protected async deleteResources(resources: string[], extraArgs: string[] = []): Promise> { + protected async deleteResources(resources: string[], extraArgs: string[] = []): AsyncResult { const kubectlArgs = [...extraArgs, ...this.getAdditionalArgs(extraArgs)]; return this.dependencies.kubectlDeleteAll({ diff --git a/packages/core/src/common/kube-helpers.ts b/packages/core/src/common/kube-helpers.ts index c439c29d16..6deb9ab8a1 100644 --- a/packages/core/src/common/kube-helpers.ts +++ b/packages/core/src/common/kube-helpers.ts @@ -7,7 +7,7 @@ import { KubeConfig } from "@kubernetes/client-node"; import yaml from "js-yaml"; import type { Cluster, Context, User } from "@kubernetes/client-node/dist/config_types"; import { newClusters, newContexts, newUsers } from "@kubernetes/client-node/dist/config_types"; -import { isDefined } from "./utils"; +import { isDefined } from "@k8slens/utilities"; import Joi from "joi"; import type { PartialDeep } from "type-fest"; diff --git a/packages/core/src/common/kube-helpers/channels.ts b/packages/core/src/common/kube-helpers/channels.ts index 4782f64367..b48f9f1f99 100644 --- a/packages/core/src/common/kube-helpers/channels.ts +++ b/packages/core/src/common/kube-helpers/channels.ts @@ -7,7 +7,7 @@ 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 "../utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token"; export interface KubectlApplyAllArgs { diff --git a/packages/core/src/common/kube-helpers/load-config-from-file.injectable.ts b/packages/core/src/common/kube-helpers/load-config-from-file.injectable.ts index afa9d3c070..f78b5961da 100644 --- a/packages/core/src/common/kube-helpers/load-config-from-file.injectable.ts +++ b/packages/core/src/common/kube-helpers/load-config-from-file.injectable.ts @@ -8,11 +8,11 @@ import type { ConfigResult } from "../kube-helpers"; import { loadConfigFromString } from "../kube-helpers"; import resolveTildeInjectable from "../path/resolve-tilde.injectable"; -export type LoadConfigfromFile = (filePath: string) => Promise; +export type LoadConfigFromFile = (filePath: string) => Promise; -const loadConfigfromFileInjectable = getInjectable({ - id: "load-configfrom-file", - instantiate: (di): LoadConfigfromFile => { +const loadConfigFromFileInjectable = getInjectable({ + id: "load-config-from-file", + instantiate: (di): LoadConfigFromFile => { const readFile = di.inject(readFileInjectable); const resolveTilde = di.inject(resolveTildeInjectable); @@ -20,4 +20,4 @@ const loadConfigfromFileInjectable = getInjectable({ }, }); -export default loadConfigfromFileInjectable; +export default loadConfigFromFileInjectable; diff --git a/packages/core/src/common/log-error.global-override-for-injectable.ts b/packages/core/src/common/log-error.global-override-for-injectable.ts index e3a03c2802..95fa0ac16f 100644 --- a/packages/core/src/common/log-error.global-override-for-injectable.ts +++ b/packages/core/src/common/log-error.global-override-for-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 { getGlobalOverrideForFunction } from "./test-utils/get-global-override-for-function"; +import { getGlobalOverrideForFunction } from "@k8slens/test-utils"; import logErrorInjectable from "./log-error.injectable"; // Note: this should remain as it is, and throw if called. Logging error is something diff --git a/packages/core/src/common/logger.global-override-for-injectable.ts b/packages/core/src/common/logger.global-override-for-injectable.ts index cad548cd22..e314316d47 100644 --- a/packages/core/src/common/logger.global-override-for-injectable.ts +++ b/packages/core/src/common/logger.global-override-for-injectable.ts @@ -4,13 +4,12 @@ */ import loggerInjectable from "./logger.injectable"; -import { getGlobalOverride } from "./test-utils/get-global-override"; -import { noop } from "./utils"; +import { getGlobalOverride } from "@k8slens/test-utils"; export default getGlobalOverride(loggerInjectable, () => ({ - warn: noop, - debug: noop, - error: noop, - info: noop, - silly: noop, + warn: () => {}, + debug: () => {}, + error: () => {}, + info: () => {}, + silly: () => {}, })); diff --git a/packages/core/src/common/os/temp-directory-path.global-override-for-injectable.ts b/packages/core/src/common/os/temp-directory-path.global-override-for-injectable.ts index 05615644f9..dde5e3008c 100644 --- a/packages/core/src/common/os/temp-directory-path.global-override-for-injectable.ts +++ b/packages/core/src/common/os/temp-directory-path.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import tempDirectoryPathInjectable from "./temp-directory-path.injectable"; export default getGlobalOverride(tempDirectoryPathInjectable, () => "/some-temp-directory"); diff --git a/packages/core/src/common/path/get-absolute-path.global-override-for-injectable.ts b/packages/core/src/common/path/get-absolute-path.global-override-for-injectable.ts index 15f377cb2c..6ebbd34bd8 100644 --- a/packages/core/src/common/path/get-absolute-path.global-override-for-injectable.ts +++ b/packages/core/src/common/path/get-absolute-path.global-override-for-injectable.ts @@ -4,7 +4,7 @@ */ import path from "path"; -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import getAbsolutePathInjectable from "./get-absolute-path.injectable"; export default getGlobalOverride(getAbsolutePathInjectable, () => path.posix.resolve); diff --git a/packages/core/src/common/path/get-basename.global-override-for-injectable.ts b/packages/core/src/common/path/get-basename.global-override-for-injectable.ts index 913ec9c5c2..76c45ae30f 100644 --- a/packages/core/src/common/path/get-basename.global-override-for-injectable.ts +++ b/packages/core/src/common/path/get-basename.global-override-for-injectable.ts @@ -4,7 +4,7 @@ */ import path from "path"; -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import getBasenameOfPathInjectable from "./get-basename.injectable"; export default getGlobalOverride(getBasenameOfPathInjectable, () => path.posix.basename); diff --git a/packages/core/src/common/path/get-dirname.global-override-for-injectable.ts b/packages/core/src/common/path/get-dirname.global-override-for-injectable.ts index ed694de182..5579636551 100644 --- a/packages/core/src/common/path/get-dirname.global-override-for-injectable.ts +++ b/packages/core/src/common/path/get-dirname.global-override-for-injectable.ts @@ -4,7 +4,7 @@ */ import path from "path"; -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import getDirnameOfPathInjectable from "./get-dirname.injectable"; export default getGlobalOverride(getDirnameOfPathInjectable, () => path.posix.dirname); diff --git a/packages/core/src/common/path/get-relative-path.global-override-for-injectable.ts b/packages/core/src/common/path/get-relative-path.global-override-for-injectable.ts index 9e96b70301..987165af15 100644 --- a/packages/core/src/common/path/get-relative-path.global-override-for-injectable.ts +++ b/packages/core/src/common/path/get-relative-path.global-override-for-injectable.ts @@ -4,7 +4,7 @@ */ import path from "path"; -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import getRelativePathInjectable from "./get-relative-path.injectable"; export default getGlobalOverride(getRelativePathInjectable, () => path.posix.relative); diff --git a/packages/core/src/common/path/join-paths.global-override-for-injectable.ts b/packages/core/src/common/path/join-paths.global-override-for-injectable.ts index d3e9d5e4c2..320490c0f3 100644 --- a/packages/core/src/common/path/join-paths.global-override-for-injectable.ts +++ b/packages/core/src/common/path/join-paths.global-override-for-injectable.ts @@ -4,7 +4,7 @@ */ import path from "path"; -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import joinPathsInjectable from "./join-paths.injectable"; export default getGlobalOverride(joinPathsInjectable, () => path.posix.join); diff --git a/packages/core/src/common/path/parse.global-override-for-injectable.ts b/packages/core/src/common/path/parse.global-override-for-injectable.ts index fad97db696..9dbc434bca 100644 --- a/packages/core/src/common/path/parse.global-override-for-injectable.ts +++ b/packages/core/src/common/path/parse.global-override-for-injectable.ts @@ -4,7 +4,7 @@ */ import path from "path"; -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import parsePathInjectable from "./parse.injectable"; export default getGlobalOverride(parsePathInjectable, () => path.posix.parse); diff --git a/packages/core/src/common/path/separator.global-override-for-injectable.ts b/packages/core/src/common/path/separator.global-override-for-injectable.ts index 655f8908b0..25d0700481 100644 --- a/packages/core/src/common/path/separator.global-override-for-injectable.ts +++ b/packages/core/src/common/path/separator.global-override-for-injectable.ts @@ -4,7 +4,7 @@ */ import path from "path"; -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import fileSystemSeparatorInjectable from "./separator.injectable"; export default getGlobalOverride(fileSystemSeparatorInjectable, () => path.posix.sep); diff --git a/packages/core/src/common/protocol-handler/router.ts b/packages/core/src/common/protocol-handler/router.ts index 8c9915b287..0018c385c2 100644 --- a/packages/core/src/common/protocol-handler/router.ts +++ b/packages/core/src/common/protocol-handler/router.ts @@ -6,7 +6,7 @@ import type { match } from "react-router"; import { matchPath } from "react-router"; import { countBy } from "lodash"; -import { isDefined, iter } from "../utils"; +import { isDefined, iter } from "@k8slens/utilities"; import { pathToRegexp } from "path-to-regexp"; import type Url from "url-parse"; import { RoutingError, RoutingErrorType } from "./error"; diff --git a/packages/core/src/common/runnable/run-many-for.ts b/packages/core/src/common/runnable/run-many-for.ts deleted file mode 100644 index 106cc74da1..0000000000 --- a/packages/core/src/common/runnable/run-many-for.ts +++ /dev/null @@ -1,140 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import type { DiContainerForInjection, InjectionToken } from "@ogre-tools/injectable"; -import type { SingleOrMany } from "../utils"; -import { getOrInsert, getOrInsertSetFor, isDefined } from "../utils"; -import * as uuid from "uuid"; -import assert from "assert"; -import type { Asyncify } from "type-fest"; -import type TypedEventEmitter from "typed-emitter"; -import EventEmitter from "events"; - -export interface Runnable { - id: string; - run: Run; - runAfter?: SingleOrMany>; -} - -type Run = (parameter: Param) => Promise | void; - -export type RunMany = (injectionToken: InjectionToken, void>) => Asyncify>; - -const computedNextEdge = (traversed: string[], graph: Map>, currentId: string, seenIds: Set) => { - seenIds.add(currentId); - const currentNode = graph.get(currentId); - - assert(currentNode, `Runnable graph does not contain node with id="${currentId}"`); - - for (const nextId of currentNode.values()) { - if (traversed.includes(nextId)) { - throw new Error(`Cycle in runnable graph: "${traversed.join(`" -> "`)}" -> "${nextId}"`); - } - - computedNextEdge([...traversed, nextId], graph, nextId, seenIds); - } -}; - -const verifyRunnablesAreDAG = (injectionToken: InjectionToken, void>, runnables: Runnable[]) => { - const rootId = uuid.v4(); - const runnableGraph = new Map>(); - const seenIds = new Set(); - const addRunnableId = getOrInsertSetFor(runnableGraph); - - // Build the Directed graph - for (const runnable of runnables) { - addRunnableId(runnable.id); - - if (!runnable.runAfter || (Array.isArray(runnable.runAfter) && runnable.runAfter.length === 0)) { - addRunnableId(rootId).add(runnable.id); - } else if (Array.isArray(runnable.runAfter)) { - for (const parentRunnable of runnable.runAfter) { - addRunnableId(parentRunnable.id).add(runnable.id); - } - } else { - addRunnableId(runnable.runAfter.id).add(runnable.id); - } - } - - addRunnableId(rootId); - - // Do a DFS to find any cycles - computedNextEdge([], runnableGraph, rootId, seenIds); - - for (const id of runnableGraph.keys()) { - if (!seenIds.has(id)) { - const runnable = runnables.find(runnable => runnable.id === id); - - if (!runnable) { - throw new Error(`Runnable "${id}" is not part of the injection token "${injectionToken.id}"`); - } - - const runAfters = [runnable.runAfter] - .flat() - .filter(isDefined) - .map(runnable => runnable.id) - .join('", "'); - - throw new Error(`Runnable "${id}" is unreachable for injection token "${injectionToken.id}": run afters "${runAfters}" are a part of different injection tokens.`); - } - } -}; - -interface BarrierEvent { - finish: (id: string) => void; -} - -class DynamicBarrier { - private readonly finishedIds = new Map>(); - private readonly events: TypedEventEmitter = new EventEmitter(); - - private initFinishingPromise(id: string): Promise { - return getOrInsert(this.finishedIds, id, new Promise(resolve => { - const handler = (finishedId: string) => { - if (finishedId === id) { - resolve(); - this.events.removeListener("finish", handler); - } - }; - - this.events.addListener("finish", handler); - })); - } - - setFinished(id: string): void { - void this.initFinishingPromise(id); - - this.events.emit("finish", id); - } - - async blockOn(id: string): Promise { - await this.initFinishingPromise(id); - } -} - -const executeRunnableWith = (param: Param) => { - const barrier = new DynamicBarrier(); - - return async (runnable: Runnable): Promise => { - const parentRunnables = [runnable.runAfter].flat().filter(isDefined); - - for (const parentRunnable of parentRunnables) { - await barrier.blockOn(parentRunnable.id); - } - - await runnable.run(param); - barrier.setFinished(runnable.id); - }; -}; - -export function runManyFor(di: DiContainerForInjection): RunMany { - return (injectionToken: InjectionToken, void>) => async (param: Param) => { - const executeRunnable = executeRunnableWith(param); - const allRunnables = di.injectMany(injectionToken); - - verifyRunnablesAreDAG(injectionToken, allRunnables); - - await Promise.all(allRunnables.map(executeRunnable)); - }; -} diff --git a/packages/core/src/common/runnable/run-many-sync-for.ts b/packages/core/src/common/runnable/run-many-sync-for.ts deleted file mode 100644 index 08dba2f72d..0000000000 --- a/packages/core/src/common/runnable/run-many-sync-for.ts +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import type { DiContainerForInjection, InjectionToken } from "@ogre-tools/injectable"; -import type { Composite } from "../utils/composite/get-composite/get-composite"; -import { getCompositeFor } from "../utils/composite/get-composite/get-composite"; -import * as uuid from "uuid"; - -export interface RunnableSync { - id: string; - run: RunSync; - runAfter?: RunnableSync; -} - -/** - * NOTE: this is the worse of two evils. This makes sure that `RunnableSync` always is sync. - * If the return type is `void` instead then async functions (those return `Promise`) can - * coerce to it. - */ -type RunSync = (parameter: Param) => undefined; - -export type RunManySync = (injectionToken: InjectionToken, void>) => RunSync; - -function runCompositeRunnableSyncs(param: Param, composite: Composite>): undefined { - composite.value.run(param); - composite.children.map(composite => runCompositeRunnableSyncs(param, composite)); - - return undefined; -} - -export function runManySyncFor(di: DiContainerForInjection): RunManySync { - return (injectionToken: InjectionToken, void>) => (param: Param): undefined => { - const allRunnables = di.injectMany(injectionToken); - const rootId = uuid.v4(); - const getCompositeRunnables = getCompositeFor>({ - getId: (runnable) => runnable.id, - getParentId: (runnable) => ( - runnable.id === rootId - ? undefined - : runnable.runAfter?.id ?? rootId - ), - }); - const composite = getCompositeRunnables([ - // This is a dummy runnable to conform to the requirements of `getCompositeFor` to only have one root - { - id: rootId, - run: () => undefined, - }, - ...allRunnables, - ]); - - return runCompositeRunnableSyncs(param, composite); - }; -} diff --git a/packages/core/src/common/test-utils/get-global-override.ts b/packages/core/src/common/test-utils/get-global-override.ts deleted file mode 100644 index ac3c86a33e..0000000000 --- a/packages/core/src/common/test-utils/get-global-override.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * 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"; - -export interface GlobalOverride { - injectable: Injectable; - overridingInstantiate: any; -} - -export const getGlobalOverride = >( - injectable: T, - overridingInstantiate: T["instantiate"], -) => ({ - injectable, - overridingInstantiate, - }); diff --git a/packages/core/src/common/user-store/current-timezone.global-override-for-injectable.ts b/packages/core/src/common/user-store/current-timezone.global-override-for-injectable.ts index 6056074d3c..ef831ca3c1 100644 --- a/packages/core/src/common/user-store/current-timezone.global-override-for-injectable.ts +++ b/packages/core/src/common/user-store/current-timezone.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import currentTimezoneInjectable from "./current-timezone.injectable"; export default getGlobalOverride(currentTimezoneInjectable, () => "Etc/GMT"); diff --git a/packages/core/src/common/user-store/file-name-migration.global-override-for-injectable.ts b/packages/core/src/common/user-store/file-name-migration.global-override-for-injectable.ts index bb0ac054f3..0cd1383cc6 100644 --- a/packages/core/src/common/user-store/file-name-migration.global-override-for-injectable.ts +++ b/packages/core/src/common/user-store/file-name-migration.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import userStoreFileNameMigrationInjectable from "./file-name-migration.injectable"; export default getGlobalOverride(userStoreFileNameMigrationInjectable, () => async () => {}); diff --git a/packages/core/src/common/user-store/file-name-migration.injectable.ts b/packages/core/src/common/user-store/file-name-migration.injectable.ts index 106f559ef0..31d5352056 100644 --- a/packages/core/src/common/user-store/file-name-migration.injectable.ts +++ b/packages/core/src/common/user-store/file-name-migration.injectable.ts @@ -5,7 +5,7 @@ import fse from "fs-extra"; import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable"; -import { isErrnoException } from "../utils"; +import { isErrnoException } from "@k8slens/utilities"; import { getInjectable } from "@ogre-tools/injectable"; import joinPathsInjectable from "../path/join-paths.injectable"; diff --git a/packages/core/src/common/user-store/user-info.global-override-for-injectable.ts b/packages/core/src/common/user-store/user-info.global-override-for-injectable.ts index 21fb26f8a9..cc650f6de3 100644 --- a/packages/core/src/common/user-store/user-info.global-override-for-injectable.ts +++ b/packages/core/src/common/user-store/user-info.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import userInfoInjectable from "./user-info.injectable"; export default getGlobalOverride(userInfoInjectable, () => ({ diff --git a/packages/core/src/common/user-store/user-store.ts b/packages/core/src/common/user-store/user-store.ts index 8979ba3351..4ffa31fac1 100644 --- a/packages/core/src/common/user-store/user-store.ts +++ b/packages/core/src/common/user-store/user-store.ts @@ -6,7 +6,7 @@ import { action, observable, makeObservable, isObservableArray, isObservableSet, isObservableMap } from "mobx"; import type { BaseStoreDependencies } from "../base-store/base-store"; import { BaseStore } from "../base-store/base-store"; -import { getOrInsertSet, toggle, toJS, object } from "../../renderer/utils"; +import { getOrInsertSet, toggle, object } from "@k8slens/utilities"; import type { UserPreferencesModel, StoreType } from "./preferences-helpers"; import type { EmitAppEvent } from "../app-event-bus/emit-event.injectable"; @@ -14,6 +14,7 @@ import type { EmitAppEvent } from "../app-event-bus/emit-event.injectable"; import type { SelectedUpdateChannel } from "../../features/application-update/common/selected-update-channel/selected-update-channel.injectable"; import type { ReleaseChannel } from "../../features/application-update/common/update-channels"; import type { PreferenceDescriptors } from "./preference-descriptors.injectable"; +import { toJS } from "../utils"; export interface UserStoreModel { preferences: UserPreferencesModel; diff --git a/packages/core/src/common/utils/__tests__/iter.test.ts b/packages/core/src/common/utils/__tests__/iter.test.ts deleted file mode 100644 index 2489649d90..0000000000 --- a/packages/core/src/common/utils/__tests__/iter.test.ts +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import { join, nth, reduce, concat } from "../iter"; - -describe("iter", () => { - describe("reduce", () => { - it("can reduce a value", () => { - expect(reduce([1, 2, 3], (acc: number[], current: number) => [current, ...acc], [0])).toEqual([3, 2, 1, 0]); - }); - - it("can reduce an empty iterable", () => { - expect(reduce([], (acc: number[], current: number) => [acc[0] + current], [])).toEqual([]); - }); - }); - - describe("join", () => { - it("should not prefix the output by the seperator", () => { - expect(join(["a", "b", "c"].values(), " ")).toBe("a b c"); - }); - - it("should return empty string if iterator is empty", () => { - expect(join([].values(), " ")).toBe(""); - }); - - it("should return just first entry if iterator is of size 1", () => { - expect(join(["d"].values(), " ")).toBe("d"); - }); - }); - - describe("nth", () => { - it("should return undefined past the end of the iterator", () => { - expect(nth(["a"], 123)).toBeUndefined(); - }); - - it("should by 0-indexing the index", () => { - expect(nth(["a", "b"], 0)).toBe("a"); - }); - }); - - describe("concat", () => { - it("should yield undefined for empty args", () => { - const iter = concat(); - - expect(iter.next()).toEqual({ done: true }); - }); - - it("should yield undefined for only empty args", () => { - const iter = concat([].values(), [].values(), [].values(), [].values()); - - expect(iter.next()).toEqual({ done: true }); - }); - - it("should yield all of the first and then all of the second", () => { - const iter = concat([1, 2, 3].values(), [4, 5, 6].values()); - - expect(iter.next()).toEqual({ done: false, value: 1 }); - expect(iter.next()).toEqual({ done: false, value: 2 }); - expect(iter.next()).toEqual({ done: false, value: 3 }); - expect(iter.next()).toEqual({ done: false, value: 4 }); - expect(iter.next()).toEqual({ done: false, value: 5 }); - expect(iter.next()).toEqual({ done: false, value: 6 }); - expect(iter.next()).toEqual({ done: true }); - }); - }); -}); diff --git a/packages/core/src/common/utils/__tests__/n-fircate.test.ts b/packages/core/src/common/utils/__tests__/n-fircate.test.ts deleted file mode 100644 index 7e6f84a095..0000000000 --- a/packages/core/src/common/utils/__tests__/n-fircate.test.ts +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import { nFircate } from "../n-fircate"; - -describe("nFircate", () => { - it("should produce an empty array if no parts are provided", () => { - expect(nFircate([{ a: 1 }, { a: 2 }], "a", []).length).toBe(0); - }); - - it("should ignore non-matching parts", () => { - const res = nFircate([{ a: 1 }, { a: 2 }], "a", [1]); - - expect(res.length).toBe(1); - expect(res[0].length).toBe(1); - }); - - it("should include all matching parts in each type", () => { - const res = nFircate([{ a: 1, b: "a" }, { a: 2, b: "b" }, { a: 1, b: "c" }], "a", [1, 2]); - - expect(res.length).toBe(2); - expect(res[0].length).toBe(2); - expect(res[0][0].b).toBe("a"); - expect(res[0][1].b).toBe("c"); - expect(res[1].length).toBe(1); - expect(res[1][0].b).toBe("b"); - }); - - it("should throw a type error if the same part is provided more than once", () => { - try { - nFircate([{ a: 1, b: "a" }, { a: 2, b: "b" }, { a: 1, b: "c" }], "a", [1, 2, 1]); - fail("Expected error"); - } catch (error) { - expect(error).toBeInstanceOf(TypeError); - } - }); -}); diff --git a/packages/core/src/common/utils/array.ts b/packages/core/src/common/utils/array.ts deleted file mode 100644 index b9071c33ec..0000000000 --- a/packages/core/src/common/utils/array.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. - */ - -/** - * A inference typed version of `Array(length).fill(value)` - * @param length The number of entries - * @param value The value of each of the indices - */ -export function filled(length: number, value: T): T[] { - return Array(length).fill(value); -} diff --git a/packages/core/src/common/utils/autobind.ts b/packages/core/src/common/utils/autobind.ts deleted file mode 100644 index 49feb435e3..0000000000 --- a/packages/core/src/common/utils/autobind.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import type { Options } from "auto-bind"; -import autoBindClass from "auto-bind"; -import autoBindReactClass from "auto-bind/react"; -import React from "react"; - -// Automatically bind methods to their class instance -export function autoBind(obj: T, opts?: Options): T { - if (obj instanceof React.Component) { - return autoBindReactClass(obj, opts); - } - - return autoBindClass(obj, opts); -} diff --git a/packages/core/src/common/utils/channel/channel.test.ts b/packages/core/src/common/utils/channel/channel.test.ts index 72204d4fb6..c27817dd68 100644 --- a/packages/core/src/common/utils/channel/channel.test.ts +++ b/packages/core/src/common/utils/channel/channel.test.ts @@ -16,7 +16,7 @@ import { requestFromChannelInjectionToken } from "./request-from-channel-injecti 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 "../../test-utils/get-promise-status"; +import { getPromiseStatus } from "@k8slens/test-utils"; import { runInAction } from "mobx"; import type { RequestChannelHandler } from "../../../main/utils/channel/channel-listeners/listener-tokens"; import { 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 index 34f62d51d5..d6db37cea2 100644 --- 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 @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectionToken } from "@ogre-tools/injectable"; -import type { Disposer } from "../disposer"; +import type { Disposer } from "@k8slens/utilities"; import type { MessageChannel, MessageChannelListener } from "./message-channel-listener-injection-token"; export type EnlistMessageChannelListener = (listener: MessageChannelListener>) => Disposer; 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 index afe0c08f24..6ebc9ca7c1 100644 --- 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 @@ -4,9 +4,9 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { getStartableStoppable } from "../get-startable-stoppable"; -import { disposer } from "../index"; 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", diff --git a/packages/core/src/common/utils/channel/request-from-channel-injection-token.ts b/packages/core/src/common/utils/channel/request-from-channel-injection-token.ts index 14e925f190..dc3d1fa1a4 100644 --- a/packages/core/src/common/utils/channel/request-from-channel-injection-token.ts +++ b/packages/core/src/common/utils/channel/request-from-channel-injection-token.ts @@ -6,8 +6,8 @@ import { getInjectionToken } from "@ogre-tools/injectable"; import type { RequestChannel } from "./request-channel-listener-injection-token"; export interface RequestFromChannel { - (channel: RequestChannel, request: Request): Promise; - (channel: RequestChannel): Promise; + (channel: RequestChannel, request: Request): Promise>; + (channel: RequestChannel): Promise>; } export const requestFromChannelInjectionToken = getInjectionToken({ diff --git a/packages/core/src/common/utils/composable-responsibilities/showable/showable.ts b/packages/core/src/common/utils/composable-responsibilities/showable/showable.ts index ad8e2ed25b..c31f1cd8ee 100644 --- a/packages/core/src/common/utils/composable-responsibilities/showable/showable.ts +++ b/packages/core/src/common/utils/composable-responsibilities/showable/showable.ts @@ -3,8 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ +import { isBoolean } from "@k8slens/utilities"; import type { IComputedValue } from "mobx"; -import { isBoolean } from "../../type-narrowing"; export interface Showable { readonly isShown: IComputedValue | boolean; diff --git a/packages/core/src/common/utils/escapeRegExp.ts b/packages/core/src/common/utils/escapeRegExp.ts deleted file mode 100644 index 9d5c7e2ff6..0000000000 --- a/packages/core/src/common/utils/escapeRegExp.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. - */ - -// Helper to sanitize / escape special chars for passing to RegExp-constructor - -export function escapeRegExp(str: string) { - return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string -} diff --git a/packages/core/src/common/utils/get-random-id.global-override-for-injectable.ts b/packages/core/src/common/utils/get-random-id.global-override-for-injectable.ts index a0f87b4180..36f598cde1 100644 --- a/packages/core/src/common/utils/get-random-id.global-override-for-injectable.ts +++ b/packages/core/src/common/utils/get-random-id.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import getRandomIdInjectable from "./get-random-id.injectable"; export default getGlobalOverride(getRandomIdInjectable, () => () => "some-irrelevant-random-id"); diff --git a/packages/core/src/common/utils/getRandId.ts b/packages/core/src/common/utils/getRandId.ts deleted file mode 100644 index 489456d56b..0000000000 --- a/packages/core/src/common/utils/getRandId.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -// Create random system name - -export function getRandId({ prefix = "", suffix = "", sep = "_" } = {}) { - const randId = () => Math.random().toString(16).slice(2); - - return [prefix, randId(), suffix].filter(s => s).join(sep); -} diff --git a/packages/core/src/common/utils/index.ts b/packages/core/src/common/utils/index.ts index 4857d04418..d95bd52904 100644 --- a/packages/core/src/common/utils/index.ts +++ b/packages/core/src/common/utils/index.ts @@ -3,50 +3,5 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -export * from "./abort-controller"; -export * from "./autobind"; -export * from "./camelCase"; export * from "./cluster-id-url-parsing"; -export * from "./collection-functions"; -export * from "./convertCpu"; -export * from "./convertMemory"; -export * from "./debouncePromise"; -export * from "./delay"; -export * from "./disposer"; -export * from "./escapeRegExp"; -export * from "./formatDuration"; -export * from "./getRandId"; -export * from "./hash-set"; -export * from "./n-fircate"; -export * from "./noop"; -export * from "./observable-crate/impl"; -export * from "./promise-exec"; -export * from "./readonly"; -export * from "./reject-promise"; -export * from "./singleton"; -export * from "./sort-compare"; -export * from "./splitArray"; -export * from "./tar"; export * from "./toJS"; -export * from "./type-narrowing"; -export * from "./types"; -export * from "./wait-for-path"; -export * from "./wait"; - -export type { Tuple } from "./tuple"; - -import * as iter from "./iter"; -import * as array from "./array"; -import * as tuple from "./tuple"; -import * as base64 from "./base64"; -import * as object from "./objects"; -import * as json from "./json"; - -export { - iter, - array, - tuple, - base64, - object, - json, -}; diff --git a/packages/core/src/common/utils/is-promise/is-promise.test.ts b/packages/core/src/common/utils/is-promise/is-promise.test.ts deleted file mode 100644 index 565f272ed6..0000000000 --- a/packages/core/src/common/utils/is-promise/is-promise.test.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { isPromise } from "./is-promise"; - -describe("isPromise", () => { - it("given promise, returns true", () => { - const actual = isPromise(new Promise(() => {})); - - expect(actual).toBe(true); - }); - - it("given non-promise, returns false", () => { - const actual = isPromise({}); - - expect(actual).toBe(false); - }); - - it("given thenable, returns false", () => { - const actual = isPromise({ then: () => {} }); - - expect(actual).toBe(false); - }); - - it("given nothing, returns false", () => { - const actual = isPromise(undefined); - - expect(actual).toBe(false); - }); -}); diff --git a/packages/core/src/common/utils/is-promise/is-promise.ts b/packages/core/src/common/utils/is-promise/is-promise.ts deleted file mode 100644 index 6261f569cd..0000000000 --- a/packages/core/src/common/utils/is-promise/is-promise.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -export function isPromise(reference: any): reference is Promise { - return reference?.constructor === Promise; -} diff --git a/packages/core/src/common/utils/json.ts b/packages/core/src/common/utils/json.ts deleted file mode 100644 index 53d357f05c..0000000000 --- a/packages/core/src/common/utils/json.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. - */ - -import type { JsonValue } from "type-fest"; - -export function parse(input: string): JsonValue { - return JSON.parse(input); -} diff --git a/packages/core/src/common/utils/n-fircate.ts b/packages/core/src/common/utils/n-fircate.ts deleted file mode 100644 index 0f195adc10..0000000000 --- a/packages/core/src/common/utils/n-fircate.ts +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -/** - * Split an iterable into several arrays with matching fields - * @param from The iterable of items to split up - * @param field The field of each item to split over - * @param parts What each array will be filtered to - * @returns A `parts.length` tuple of `T[]` where each array has matching `field` values - */ -export function nFircate(from: Iterable, field: keyof T, parts: []): []; -export function nFircate(from: Iterable, field: keyof T, parts: [T[typeof field]]): [T[]]; -export function nFircate(from: Iterable, field: keyof T, parts: [T[typeof field], T[typeof field]]): [T[], T[]]; -export function nFircate(from: Iterable, field: keyof T, parts: [T[typeof field], T[typeof field], T[typeof field]]): [T[], T[], T[]]; - -export function nFircate(from: Iterable, field: keyof T, parts: T[typeof field][]): T[][] { - if (new Set(parts).size !== parts.length) { - throw new TypeError("Duplicate parts entries"); - } - - const res = Array.from(parts, () => [] as T[]); - - for (const item of from) { - const index = parts.indexOf(item[field]); - - if (index < 0) { - continue; - } - - res[index].push(item); - } - - return res; -} diff --git a/packages/core/src/common/utils/objects.ts b/packages/core/src/common/utils/objects.ts deleted file mode 100644 index 9b6355d3e7..0000000000 --- a/packages/core/src/common/utils/objects.ts +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -/** - * A better typed version of `Object.fromEntries` where the keys are known to - * be a specific subset - */ -export function fromEntries(entries: Iterable): Record { - return Object.fromEntries(entries) as Record; -} - -export function keys(obj: Partial>): K[]; - -export function keys(obj: Record): K[] { - return Object.keys(obj) as K[]; -} - -export function entries(obj: Partial> | null | undefined): [K, V][]; -export function entries(obj: Partial> | null | undefined): [K, V][]; -export function entries(obj: Record | null | undefined): [K, V][]; - -export function entries(obj: Record | null | undefined): [K, V][] { - if (obj && typeof obj == "object") { - return Object.entries(obj) as never; - } - - return [] as never; -} diff --git a/packages/core/src/common/utils/open-link-in-browser.global-override-for-injectable.ts b/packages/core/src/common/utils/open-link-in-browser.global-override-for-injectable.ts index 62c1539757..d7e005020e 100644 --- a/packages/core/src/common/utils/open-link-in-browser.global-override-for-injectable.ts +++ b/packages/core/src/common/utils/open-link-in-browser.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import openLinkInBrowserInjectable from "./open-link-in-browser.injectable"; export default getGlobalOverride(openLinkInBrowserInjectable, () => async () => {}); diff --git a/packages/core/src/common/utils/promise-exec.ts b/packages/core/src/common/utils/promise-exec.ts deleted file mode 100644 index e2471d2611..0000000000 --- a/packages/core/src/common/utils/promise-exec.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 * as util from "util"; -import { execFile } from "child_process"; - -export const promiseExecFile = util.promisify(execFile); diff --git a/packages/core/src/common/utils/random-bytes.global-override-for-injectable.ts b/packages/core/src/common/utils/random-bytes.global-override-for-injectable.ts index 9fce1baebd..d4cc7519cd 100644 --- a/packages/core/src/common/utils/random-bytes.global-override-for-injectable.ts +++ b/packages/core/src/common/utils/random-bytes.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import randomBytesInjectable from "./random-bytes.injectable"; export default getGlobalOverride(randomBytesInjectable, () => (size) => { diff --git a/packages/core/src/common/utils/reactive-now/reactive-now.test.tsx b/packages/core/src/common/utils/reactive-now/reactive-now.test.tsx index ab9b185438..5776388516 100644 --- a/packages/core/src/common/utils/reactive-now/reactive-now.test.tsx +++ b/packages/core/src/common/utils/reactive-now/reactive-now.test.tsx @@ -8,8 +8,8 @@ import type { IComputedValue } from "mobx"; import { computed, observe } from "mobx"; import React from "react"; import { observer } from "mobx-react"; -import { advanceFakeTime, testUsingFakeTime } from "../../test-utils/use-fake-time"; import { reactiveNow } from "./reactive-now"; +import { advanceFakeTime, testUsingFakeTime } from "../../../test-utils/use-fake-time"; describe("reactiveNow", () => { let someComputed: IComputedValue; diff --git a/packages/core/src/common/utils/replace-observable-object.ts b/packages/core/src/common/utils/replace-observable-object.ts new file mode 100644 index 0000000000..8b88187b6c --- /dev/null +++ b/packages/core/src/common/utils/replace-observable-object.ts @@ -0,0 +1,18 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { runInAction } from "mobx"; + +export function replaceObservableObject(target: Partial>, source: Partial>): void { + runInAction(() => { + for (const key in target) { + if (!(key in source)) { + delete target[key]; + } + } + + Object.assign(target, source); + }); +} diff --git a/packages/core/src/common/utils/toJS.ts b/packages/core/src/common/utils/toJS.ts index 7a949b46fc..2d70f564cb 100644 --- a/packages/core/src/common/utils/toJS.ts +++ b/packages/core/src/common/utils/toJS.ts @@ -13,6 +13,9 @@ import * as mobx from "mobx"; import { isObservable, observable } from "mobx"; +/** + * @deprecated Switch to doing toJS on each field instead + */ export function toJS(data: T): T { // make data observable for recursive toJS()-output if (typeof data === "object" && !isObservable(data)) { diff --git a/packages/core/src/common/utils/with-error-logging/with-error-logging.injectable.ts b/packages/core/src/common/utils/with-error-logging/with-error-logging.injectable.ts index 0aaca9f97d..37bf7220c7 100644 --- a/packages/core/src/common/utils/with-error-logging/with-error-logging.injectable.ts +++ b/packages/core/src/common/utils/with-error-logging/with-error-logging.injectable.ts @@ -4,7 +4,6 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import logErrorInjectable from "../../log-error.injectable"; -import { isPromise } from "../is-promise/is-promise"; export type WithErrorLoggingFor = ( getErrorMessage: (error: unknown) => string @@ -33,7 +32,7 @@ const withErrorLoggingInjectable = getInjectable({ throw e; } - if (isPromise(returnValue)) { + if ((returnValue as any) instanceof Promise) { return returnValue.catch((e: unknown) => { const errorMessage = getErrorMessage(e); diff --git a/packages/core/src/common/utils/with-error-logging/with-error-logging.test.ts b/packages/core/src/common/utils/with-error-logging/with-error-logging.test.ts index 1e7747a952..9cc5899ce6 100644 --- a/packages/core/src/common/utils/with-error-logging/with-error-logging.test.ts +++ b/packages/core/src/common/utils/with-error-logging/with-error-logging.test.ts @@ -8,7 +8,7 @@ import withErrorLoggingInjectable from "./with-error-logging.injectable"; import { pipeline } from "@ogre-tools/fp"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; -import { getPromiseStatus } from "../../test-utils/get-promise-status"; +import { getPromiseStatus } from "@k8slens/test-utils"; import logErrorInjectable from "../../log-error.injectable"; describe("with-error-logging", () => { diff --git a/packages/core/src/common/utils/with-error-suppression/with-error-suppression.test.ts b/packages/core/src/common/utils/with-error-suppression/with-error-suppression.test.ts index 12d6a60441..63232ad06d 100644 --- a/packages/core/src/common/utils/with-error-suppression/with-error-suppression.test.ts +++ b/packages/core/src/common/utils/with-error-suppression/with-error-suppression.test.ts @@ -5,7 +5,7 @@ import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; -import { getPromiseStatus } from "../../test-utils/get-promise-status"; +import { getPromiseStatus } from "@k8slens/test-utils"; import { withErrorSuppression } from "./with-error-suppression"; describe("with-error-suppression", () => { diff --git a/packages/core/src/common/utils/with-error-suppression/with-error-suppression.ts b/packages/core/src/common/utils/with-error-suppression/with-error-suppression.ts index 657ed13c16..22d51b6014 100644 --- a/packages/core/src/common/utils/with-error-suppression/with-error-suppression.ts +++ b/packages/core/src/common/utils/with-error-suppression/with-error-suppression.ts @@ -12,7 +12,7 @@ export function withErrorSuppression(toBeDecorated: any) { try { const returnValue = toBeDecorated(...args); - if (isPromise(returnValue)) { + if ((returnValue as any) instanceof Promise) { return returnValue.catch(noop); } @@ -22,7 +22,3 @@ export function withErrorSuppression(toBeDecorated: any) { } }; } - -function isPromise(reference: any): reference is Promise { - return !!reference?.then; -} diff --git a/packages/core/src/common/vars/extension-api-version.global-override-for-injectable.ts b/packages/core/src/common/vars/extension-api-version.global-override-for-injectable.ts index 6d473eb1de..b1a74f47b6 100644 --- a/packages/core/src/common/vars/extension-api-version.global-override-for-injectable.ts +++ b/packages/core/src/common/vars/extension-api-version.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import extensionApiVersionInjectable from "./extension-api-version.injectable"; export default getGlobalOverride(extensionApiVersionInjectable, () => "6.0.0"); diff --git a/packages/core/src/common/vars/is-debugging.global-override-for-injectable.ts b/packages/core/src/common/vars/is-debugging.global-override-for-injectable.ts index 7aa500ff2e..fab25913ed 100644 --- a/packages/core/src/common/vars/is-debugging.global-override-for-injectable.ts +++ b/packages/core/src/common/vars/is-debugging.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import isDebuggingInjectable from "./is-debugging.injectable"; export default getGlobalOverride(isDebuggingInjectable, () => false); diff --git a/packages/core/src/common/vars/is-snap-package.global-override-for-injectable.ts b/packages/core/src/common/vars/is-snap-package.global-override-for-injectable.ts index cb3ff0a6e9..a18d89f221 100644 --- a/packages/core/src/common/vars/is-snap-package.global-override-for-injectable.ts +++ b/packages/core/src/common/vars/is-snap-package.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import isSnapPackageInjectable from "./is-snap-package.injectable"; export default getGlobalOverride(isSnapPackageInjectable, () => false); diff --git a/packages/core/src/common/vars/lens-resources-dir.global-override-for-injectable.ts b/packages/core/src/common/vars/lens-resources-dir.global-override-for-injectable.ts index 1a72b0ccf7..f40bbe6cd4 100644 --- a/packages/core/src/common/vars/lens-resources-dir.global-override-for-injectable.ts +++ b/packages/core/src/common/vars/lens-resources-dir.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import lensResourcesDirInjectable from "./lens-resources-dir.injectable"; export default getGlobalOverride(lensResourcesDirInjectable, () => "/irrelavent-dir-for-lens-resources"); diff --git a/packages/core/src/common/vars/platform.global-override-for-injectable.ts b/packages/core/src/common/vars/platform.global-override-for-injectable.ts index 4bb06dec5e..2825ebe8cf 100644 --- a/packages/core/src/common/vars/platform.global-override-for-injectable.ts +++ b/packages/core/src/common/vars/platform.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import platformInjectable from "./platform.injectable"; export default getGlobalOverride(platformInjectable, () => "darwin"); diff --git a/packages/core/src/common/vars/process-arch.global-override-for-injectable.ts b/packages/core/src/common/vars/process-arch.global-override-for-injectable.ts index 42d74d4ec8..bdc4c5e823 100644 --- a/packages/core/src/common/vars/process-arch.global-override-for-injectable.ts +++ b/packages/core/src/common/vars/process-arch.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import processArchInjectable from "./process-arch.injectable"; export default getGlobalOverride(processArchInjectable, () => "x64"); diff --git a/packages/core/src/common/vars/static-files-directory.global-override-for-injectable.ts b/packages/core/src/common/vars/static-files-directory.global-override-for-injectable.ts index 3b8ec43046..2ed47dd1a4 100644 --- a/packages/core/src/common/vars/static-files-directory.global-override-for-injectable.ts +++ b/packages/core/src/common/vars/static-files-directory.global-override-for-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 { getGlobalOverride } from "../test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import staticFilesDirectoryInjectable from "./static-files-directory.injectable"; export default getGlobalOverride(staticFilesDirectoryInjectable, () => "/some-static-directory"); diff --git a/packages/core/src/extensions/__tests__/extension-loader.test.ts b/packages/core/src/extensions/__tests__/extension-loader.test.ts index 92de69590e..4ded8cdbb9 100644 --- a/packages/core/src/extensions/__tests__/extension-loader.test.ts +++ b/packages/core/src/extensions/__tests__/extension-loader.test.ts @@ -7,7 +7,7 @@ import type { ExtensionLoader } from "../extension-loader"; import extensionLoaderInjectable from "../extension-loader/extension-loader.injectable"; import { runInAction } from "mobx"; import updateExtensionsStateInjectable from "../extension-loader/update-extensions-state/update-extensions-state.injectable"; -import { delay } from "../../renderer/utils"; +import { delay } from "@k8slens/utilities"; import { getDiForUnitTesting } from "../../renderer/getDiForUnitTesting"; import ipcRendererInjectable from "../../renderer/utils/channel/ipc-renderer.injectable"; import type { IpcRenderer } from "electron"; diff --git a/packages/core/src/extensions/common-api/utils.ts b/packages/core/src/extensions/common-api/utils.ts index a129cfda60..40f8e00175 100644 --- a/packages/core/src/extensions/common-api/utils.ts +++ b/packages/core/src/extensions/common-api/utils.ts @@ -8,11 +8,49 @@ import buildVersionInjectable from "../../main/vars/build-version/build-version. import { asLegacyGlobalFunctionForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-function-for-extension-api"; import { getLegacyGlobalDiForExtensionApi } from "../as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; -export { Singleton } from "../../common/utils"; -export { prevDefault, stopPropagation } from "../../renderer/utils/prevDefault"; +export { Singleton } from "../../common/utils/singleton"; -export type { IClassName, IgnoredClassNames } from "../../renderer/utils"; -export { cssNames } from "../../renderer/utils/cssNames"; +export { + /** + * @deprecated Switch to using the `@k8slens/utilities` package + */ + prevDefault, + /** + * @deprecated Switch to using the `@k8slens/utilities` package + */ + stopPropagation, + /** + * @deprecated Switch to using the `@k8slens/utilities` package + */ + cssNames, + /** + * @deprecated Switch to using the `@k8slens/utilities` package + */ + disposer, +} from "@k8slens/utilities"; + +export type { + /** + * @deprecated Switch to using the `@k8slens/utilities` package + */ + IClassName, + /** + * @deprecated Switch to using the `@k8slens/utilities` package + */ + IgnoredClassNames, + /** + * @deprecated Switch to using the `@k8slens/utilities` package + */ + Disposer, + /** + * @deprecated Switch to using the `@k8slens/utilities` package + */ + Disposable, + /** + * @deprecated Switch to using the `@k8slens/utilities` package + */ + ExtendableDisposer, +} from "@k8slens/utilities"; export type { OpenLinkInBrowser } from "../../common/utils/open-link-in-browser.injectable"; @@ -24,6 +62,3 @@ export const getAppVersion = () => { return di.inject(buildVersionInjectable).get(); }; - -export { disposer } from "../../common/utils"; -export type { Disposer, Disposable, ExtendableDisposer } from "../../common/utils"; diff --git a/packages/core/src/extensions/extension-discovery/extension-discovery.test.ts b/packages/core/src/extensions/extension-discovery/extension-discovery.test.ts index 6a8f50eda3..e27d00a34e 100644 --- a/packages/core/src/extensions/extension-discovery/extension-discovery.test.ts +++ b/packages/core/src/extensions/extension-discovery/extension-discovery.test.ts @@ -9,7 +9,7 @@ import extensionDiscoveryInjectable from "../extension-discovery/extension-disco import type { ExtensionDiscovery } from "../extension-discovery/extension-discovery"; import installExtensionInjectable from "../install-extension/install-extension.injectable"; import directoryForUserDataInjectable from "../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; -import { delay } from "../../renderer/utils"; +import { delay } from "@k8slens/utilities"; import { observable, runInAction, when } from "mobx"; import readJsonFileInjectable from "../../common/fs/read-json-file.injectable"; import pathExistsInjectable from "../../common/fs/path-exists.injectable"; diff --git a/packages/core/src/extensions/extension-discovery/extension-discovery.ts b/packages/core/src/extensions/extension-discovery/extension-discovery.ts index bd9baff2c8..a91bf9e406 100644 --- a/packages/core/src/extensions/extension-discovery/extension-discovery.ts +++ b/packages/core/src/extensions/extension-discovery/extension-discovery.ts @@ -7,7 +7,8 @@ import { ipcRenderer } from "electron"; import { EventEmitter } from "events"; import { makeObservable, observable, reaction, when } from "mobx"; import { broadcastMessage, ipcMainHandle, ipcRendererOn } from "../../common/ipc"; -import { isErrnoException, toJS } from "../../common/utils"; +import { toJS } from "../../common/utils"; +import { isErrnoException } from "@k8slens/utilities"; import type { ExtensionsStore } from "../extensions-store/extensions-store"; import type { ExtensionLoader } from "../extension-loader"; import type { LensExtensionId, LensExtensionManifest } from "../lens-extension"; diff --git a/packages/core/src/extensions/extension-installation-state-store/extension-installation-state-store.ts b/packages/core/src/extensions/extension-installation-state-store/extension-installation-state-store.ts index 093c80934b..8553ce9c40 100644 --- a/packages/core/src/extensions/extension-installation-state-store/extension-installation-state-store.ts +++ b/packages/core/src/extensions/extension-installation-state-store/extension-installation-state-store.ts @@ -4,8 +4,8 @@ */ import { action, computed, observable } from "mobx"; -import { disposer } from "../../renderer/utils"; -import type { ExtendableDisposer } from "../../renderer/utils"; +import { disposer } from "@k8slens/utilities"; +import type { ExtendableDisposer } from "@k8slens/utilities"; import * as uuid from "uuid"; import { broadcastMessage } from "../../common/ipc"; import { ipcRenderer } from "electron"; diff --git a/packages/core/src/extensions/extension-loader/extension-loader.ts b/packages/core/src/extensions/extension-loader/extension-loader.ts index 5dce874e54..b82fe5c159 100644 --- a/packages/core/src/extensions/extension-loader/extension-loader.ts +++ b/packages/core/src/extensions/extension-loader/extension-loader.ts @@ -6,9 +6,9 @@ import { ipcMain, ipcRenderer } from "electron"; import { isEqual } from "lodash"; import type { ObservableMap } from "mobx"; -import { action, computed, makeObservable, observable, observe, reaction, when } from "mobx"; +import { action, computed, makeObservable, toJS, observable, observe, reaction, when } from "mobx"; import { broadcastMessage, ipcMainOn, ipcRendererOn, ipcMainHandle } from "../../common/ipc"; -import { isDefined, toJS } from "../../common/utils"; +import { isDefined } from "@k8slens/utilities"; import type { InstalledExtension } from "../extension-discovery/extension-discovery"; import type { LensExtension, LensExtensionConstructor, LensExtensionId } from "../lens-extension"; import type { LensExtensionState } from "../extensions-store/extensions-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 6b9424cea4..07f054d3fd 100644 --- a/packages/core/src/extensions/extension-loader/extension/extension.injectable.ts +++ b/packages/core/src/extensions/extension-loader/extension/extension.injectable.ts @@ -6,7 +6,7 @@ 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 "../../../common/utils/disposer"; +import { disposer } from "@k8slens/utilities"; import type { LensExtension } from "../../lens-extension"; import { extensionRegistratorInjectionToken } from "../extension-registrator-injection-token"; @@ -43,7 +43,7 @@ const extensionInjectable = getInjectable({ 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 + // we need to update the registered injectables with a reaction every time they change reaction( () => Array.isArray(injectables) ? injectables : injectables.get(), (currentInjectables, previousInjectables = []) => { diff --git a/packages/core/src/extensions/extension-loader/file-system-provisioner-store/ensure-hashed-directory-for-extension.injectable.ts b/packages/core/src/extensions/extension-loader/file-system-provisioner-store/ensure-hashed-directory-for-extension.injectable.ts index 50051bf094..90bad89625 100644 --- a/packages/core/src/extensions/extension-loader/file-system-provisioner-store/ensure-hashed-directory-for-extension.injectable.ts +++ b/packages/core/src/extensions/extension-loader/file-system-provisioner-store/ensure-hashed-directory-for-extension.injectable.ts @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; -import { getOrInsert } from "../../../common/utils"; +import { getOrInsert } from "@k8slens/utilities"; import randomBytesInjectable from "../../../common/utils/random-bytes.injectable"; import joinPathsInjectable from "../../../common/path/join-paths.injectable"; import directoryForExtensionDataInjectable from "./directory-for-extension-data.injectable"; diff --git a/packages/core/src/extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store.ts b/packages/core/src/extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store.ts index 37bff649ad..86d978d47c 100644 --- a/packages/core/src/extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store.ts +++ b/packages/core/src/extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store.ts @@ -8,7 +8,6 @@ import { action, makeObservable } from "mobx"; import type { BaseStoreDependencies } from "../../../common/base-store/base-store"; import { BaseStore } from "../../../common/base-store/base-store"; import type { LensExtensionId } from "../../lens-extension"; -import { toJS } from "../../../common/utils"; import type { EnsureHashedDirectoryForExtension } from "./ensure-hashed-directory-for-extension.injectable"; interface FSProvisionModel { @@ -46,8 +45,8 @@ export class FileSystemProvisionerStore extends BaseStore { } toJSON(): FSProvisionModel { - return toJS({ - extensions: Object.fromEntries(this.dependencies.registeredExtensions), - }); + return { + extensions: Object.fromEntries(this.dependencies.registeredExtensions.toJSON()), + }; } } diff --git a/packages/core/src/extensions/extension-store.ts b/packages/core/src/extensions/extension-store.ts index e72f394005..cf435fb474 100644 --- a/packages/core/src/extensions/extension-store.ts +++ b/packages/core/src/extensions/extension-store.ts @@ -8,8 +8,8 @@ import { BaseStore } from "../common/base-store/base-store"; import * as path from "path"; import type { LensExtension } from "./lens-extension"; import assert from "assert"; -import type { StaticThis } from "../common/utils"; -import { getOrInsertWith } from "../common/utils"; +import type { StaticThis } from "../common/utils/singleton"; +import { getOrInsertWith } from "@k8slens/utilities"; import { getLegacyGlobalDiForExtensionApi } from "./as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; import directoryForUserDataInjectable from "../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; import getConfigurationFileModelInjectable from "../common/get-configuration-file-model/get-configuration-file-model.injectable"; diff --git a/packages/core/src/extensions/extensions-store/extensions-store.ts b/packages/core/src/extensions/extensions-store/extensions-store.ts index 3b2dc80eb1..1a8e5376b6 100644 --- a/packages/core/src/extensions/extensions-store/extensions-store.ts +++ b/packages/core/src/extensions/extensions-store/extensions-store.ts @@ -5,7 +5,6 @@ import type { LensExtensionId } from "../lens-extension"; import { action, computed, makeObservable, observable } from "mobx"; -import { toJS } from "../../common/utils"; import type { BaseStoreDependencies } from "../../common/base-store/base-store"; import { BaseStore } from "../../common/base-store/base-store"; @@ -57,8 +56,8 @@ export class ExtensionsStore extends BaseStore { } toJSON(): LensExtensionsStoreModel { - return toJS({ - extensions: Object.fromEntries(this.state), - }); + return { + extensions: Object.fromEntries(this.state.toJSON()), + }; } } diff --git a/packages/core/src/extensions/install-extension/install-extension.injectable.ts b/packages/core/src/extensions/install-extension/install-extension.injectable.ts index ca46772eb3..6737b7362b 100644 --- a/packages/core/src/extensions/install-extension/install-extension.injectable.ts +++ b/packages/core/src/extensions/install-extension/install-extension.injectable.ts @@ -13,7 +13,7 @@ import joinPathsInjectable from "../../common/path/join-paths.injectable"; import type { PackageJson } from "../common-api"; import writeJsonFileInjectable from "../../common/fs/write-json-file.injectable"; import { once } from "lodash"; -import { isErrnoException } from "../../common/utils"; +import { isErrnoException } from "@k8slens/utilities"; const baseNpmInstallArgs = [ "install", diff --git a/packages/core/src/extensions/ipc/ipc-main.ts b/packages/core/src/extensions/ipc/ipc-main.ts index 8bb0ada63d..a4f4ec14df 100644 --- a/packages/core/src/extensions/ipc/ipc-main.ts +++ b/packages/core/src/extensions/ipc/ipc-main.ts @@ -6,7 +6,7 @@ import { ipcMain } from "electron"; import { IpcPrefix, IpcRegistrar } from "./ipc-registrar"; import { Disposers, lensExtensionDependencies } from "../lens-extension"; import type { LensMainExtension } from "../lens-main-extension"; -import type { Disposer } from "../../common/utils"; +import type { Disposer } from "@k8slens/utilities"; import { once } from "lodash"; import { ipcMainHandle } from "../../common/ipc"; diff --git a/packages/core/src/extensions/ipc/ipc-registrar.ts b/packages/core/src/extensions/ipc/ipc-registrar.ts index 04222bd64b..7fc27ba0fd 100644 --- a/packages/core/src/extensions/ipc/ipc-registrar.ts +++ b/packages/core/src/extensions/ipc/ipc-registrar.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 { Singleton } from "../../common/utils"; +import { Singleton } from "../../common/utils/singleton"; import type { LensExtension } from "../lens-extension"; import { createHash } from "crypto"; import { broadcastMessage } from "../../common/ipc"; diff --git a/packages/core/src/extensions/ipc/ipc-renderer.ts b/packages/core/src/extensions/ipc/ipc-renderer.ts index ff61738113..9060a19154 100644 --- a/packages/core/src/extensions/ipc/ipc-renderer.ts +++ b/packages/core/src/extensions/ipc/ipc-renderer.ts @@ -6,7 +6,7 @@ import { ipcRenderer } from "electron"; import { IpcPrefix, IpcRegistrar } from "./ipc-registrar"; import { Disposers } from "../lens-extension"; import type { LensRendererExtension } from "../lens-renderer-extension"; -import type { Disposer } from "../../common/utils"; +import type { Disposer } from "@k8slens/utilities"; import { once } from "lodash"; export abstract class IpcRenderer extends IpcRegistrar { diff --git a/packages/core/src/extensions/lens-extension.ts b/packages/core/src/extensions/lens-extension.ts index 53c9343607..30cf19e4a4 100644 --- a/packages/core/src/extensions/lens-extension.ts +++ b/packages/core/src/extensions/lens-extension.ts @@ -6,7 +6,7 @@ import type { InstalledExtension } from "./extension-discovery/extension-discovery"; import { action, computed, makeObservable, observable } from "mobx"; import type { PackageJson } from "type-fest"; -import { disposer } from "../common/utils"; +import { disposer } from "@k8slens/utilities"; import type { LensExtensionDependencies } from "./lens-extension-set-dependencies"; import type { ProtocolHandlerRegistration } from "../common/protocol-handler/registration"; diff --git a/packages/core/src/extensions/lens-renderer-extension.ts b/packages/core/src/extensions/lens-renderer-extension.ts index aa00fd8ba3..5a64a6ec6c 100644 --- a/packages/core/src/extensions/lens-renderer-extension.ts +++ b/packages/core/src/extensions/lens-renderer-extension.ts @@ -5,7 +5,7 @@ import { Disposers, LensExtension, lensExtensionDependencies } from "./lens-extension"; import type { CatalogEntity, CategoryFilter } from "../common/catalog"; -import type { Disposer } from "../common/utils"; +import type { Disposer } from "@k8slens/utilities"; import type { EntityFilter } from "../renderer/api/catalog/entity/registry"; import type { TopBarRegistration } from "../renderer/components/layout/top-bar/top-bar-registration"; import type { KubernetesCluster } from "../common/catalog-entities"; diff --git a/packages/core/src/extensions/main-api/power.ts b/packages/core/src/extensions/main-api/power.ts index 671308798a..bf9f61b480 100644 --- a/packages/core/src/extensions/main-api/power.ts +++ b/packages/core/src/extensions/main-api/power.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { powerMonitor } from "electron"; -import type { Disposer } from "../../common/utils/disposer"; +import type { Disposer } from "@k8slens/utilities"; /** * Event listener for system power events diff --git a/packages/core/src/extensions/renderer-api/catalog.ts b/packages/core/src/extensions/renderer-api/catalog.ts index 43b840a39a..9de698c725 100644 --- a/packages/core/src/extensions/renderer-api/catalog.ts +++ b/packages/core/src/extensions/renderer-api/catalog.ts @@ -6,7 +6,7 @@ import type { CatalogCategory, CatalogEntity } from "../../common/catalog"; import type { CatalogEntityOnBeforeRun } from "../../renderer/api/catalog/entity/registry"; -import type { Disposer } from "../../common/utils"; +import type { Disposer } from "@k8slens/utilities"; import catalogCategoryRegistryInjectable from "../../common/catalog/category-registry.injectable"; import { asLegacyGlobalForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api"; import catalogEntityRegistryInjectable from "../../renderer/api/catalog/entity/registry.injectable"; diff --git a/packages/core/src/extensions/renderer-api/components.ts b/packages/core/src/extensions/renderer-api/components.ts index e4102433bf..8d2bb6840a 100644 --- a/packages/core/src/extensions/renderer-api/components.ts +++ b/packages/core/src/extensions/renderer-api/components.ts @@ -106,6 +106,8 @@ export { type MonacoEditorProps, type MonacoEditorId, type MonacoTheme, type MonacoCustomTheme, } from "../../renderer/components/monaco-editor"; +export * from "../../renderer/components/resource-metrics/resource-metrics"; +export * from "../../renderer/components/+workloads-pods/pod-charts"; /** * @deprecated Use `Renderer.Navigation.getDetailsUrl` diff --git a/packages/core/src/extensions/renderer-api/navigation.ts b/packages/core/src/extensions/renderer-api/navigation.ts index 4b7dcd5d39..667fa7135e 100644 --- a/packages/core/src/extensions/renderer-api/navigation.ts +++ b/packages/core/src/extensions/renderer-api/navigation.ts @@ -14,7 +14,7 @@ import navigateInjectable from "../../renderer/navigation/navigate.injectable"; import { asLegacyGlobalFunctionForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-function-for-extension-api"; export type { PageParamInit, PageParam } from "../../renderer/navigation/page-param"; -export type { URLParams } from "../../common/utils/buildUrl"; +export type { URLParams } from "@k8slens/utilities"; export const getDetailsUrl = asLegacyGlobalFunctionForExtensionApi(getDetailsUrlInjectable); export const showDetails = asLegacyGlobalFunctionForExtensionApi(showDetailsInjectable); diff --git a/packages/core/src/features/application-menu/application-menu.test.ts b/packages/core/src/features/application-menu/application-menu.test.ts index 0db35db744..bd9d016548 100644 --- a/packages/core/src/features/application-menu/application-menu.test.ts +++ b/packages/core/src/features/application-menu/application-menu.test.ts @@ -5,7 +5,7 @@ import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import populateApplicationMenuInjectable from "./main/populate-application-menu.injectable"; -import { advanceFakeTime, testUsingFakeTime } from "../../common/test-utils/use-fake-time"; +import { advanceFakeTime, testUsingFakeTime } from "../../test-utils/use-fake-time"; import { getCompositePaths } from "../../common/utils/composite/get-composite-paths/get-composite-paths"; import platformInjectable, { allPlatforms } from "../../common/vars/platform.injectable"; diff --git a/packages/core/src/features/application-menu/handling-of-orphan-application-menu-items.test.ts b/packages/core/src/features/application-menu/handling-of-orphan-application-menu-items.test.ts index 7f35861a45..465fa48f54 100644 --- a/packages/core/src/features/application-menu/handling-of-orphan-application-menu-items.test.ts +++ b/packages/core/src/features/application-menu/handling-of-orphan-application-menu-items.test.ts @@ -5,7 +5,7 @@ import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import populateApplicationMenuInjectable from "./main/populate-application-menu.injectable"; -import { advanceFakeTime, testUsingFakeTime } from "../../common/test-utils/use-fake-time"; +import { advanceFakeTime, testUsingFakeTime } from "../../test-utils/use-fake-time"; import { getCompositePaths } from "../../common/utils/composite/get-composite-paths/get-composite-paths"; import { getInjectable } from "@ogre-tools/injectable"; import applicationMenuItemInjectionToken from "./main/menu-items/application-menu-item-injection-token"; diff --git a/packages/core/src/features/application-menu/main/menu-items/special-menu-for-mac-application/show-about-application/about-bundled-extensions.injectable.ts b/packages/core/src/features/application-menu/main/menu-items/special-menu-for-mac-application/show-about-application/about-bundled-extensions.injectable.ts index e12922c340..59ae1e1491 100644 --- a/packages/core/src/features/application-menu/main/menu-items/special-menu-for-mac-application/show-about-application/about-bundled-extensions.injectable.ts +++ b/packages/core/src/features/application-menu/main/menu-items/special-menu-for-mac-application/show-about-application/about-bundled-extensions.injectable.ts @@ -5,7 +5,7 @@ import { applicationInformationToken } from "@k8slens/application"; import { getInjectable } from "@ogre-tools/injectable"; import { bundledExtensionInjectionToken } from "../../../../../../common/library"; -import { object } from "../../../../../../common/utils"; +import { object } from "@k8slens/utilities"; import buildSemanticVersionInjectable from "../../../../../../common/vars/build-semantic-version.injectable"; const specificVersionsInjectable = getInjectable({ diff --git a/packages/core/src/features/application-menu/main/populate-application-menu.global-override-for-injectable.ts b/packages/core/src/features/application-menu/main/populate-application-menu.global-override-for-injectable.ts index acd4f5f14e..23f877e2bb 100644 --- a/packages/core/src/features/application-menu/main/populate-application-menu.global-override-for-injectable.ts +++ b/packages/core/src/features/application-menu/main/populate-application-menu.global-override-for-injectable.ts @@ -3,6 +3,6 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import populateApplicationMenuInjectable from "./populate-application-menu.injectable"; -import { getGlobalOverride } from "../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; export default getGlobalOverride(populateApplicationMenuInjectable, () => () => {}); diff --git a/packages/core/src/features/application-menu/main/start-application-menu.injectable.ts b/packages/core/src/features/application-menu/main/start-application-menu.injectable.ts index 59d13760b6..b9a48cb0bd 100644 --- a/packages/core/src/features/application-menu/main/start-application-menu.injectable.ts +++ b/packages/core/src/features/application-menu/main/start-application-menu.injectable.ts @@ -9,18 +9,13 @@ import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; const startApplicationMenuInjectable = getInjectable({ id: "start-application-menu", - instantiate: (di) => { - const applicationMenu = di.inject( - applicationMenuReactivityInjectable, - ); + instantiate: (di) => ({ + run: () => { + const applicationMenu = di.inject(applicationMenuReactivityInjectable); - return { - id: "start-application-menu", - run: () => { - applicationMenu.start(); - }, - }; - }, + applicationMenu.start(); + }, + }), injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/features/application-menu/main/stop-application-menu.injectable.ts b/packages/core/src/features/application-menu/main/stop-application-menu.injectable.ts index 62abd439df..816683b2de 100644 --- a/packages/core/src/features/application-menu/main/stop-application-menu.injectable.ts +++ b/packages/core/src/features/application-menu/main/stop-application-menu.injectable.ts @@ -4,19 +4,20 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import applicationMenuReactivityInjectable from "./application-menu-reactivity.injectable"; -import { beforeQuitOfBackEndInjectionToken } from "../../../main/start-main-application/runnable-tokens/before-quit-of-back-end-injection-token"; +import { beforeQuitOfBackEndInjectionToken } from "../../../main/start-main-application/runnable-tokens/phases"; const stopApplicationMenuInjectable = getInjectable({ id: "stop-application-menu", - instantiate: (di) => { - const applicationMenu = di.inject(applicationMenuReactivityInjectable); + instantiate: (di) => ({ + run: () => { + const applicationMenu = di.inject(applicationMenuReactivityInjectable); - return { - id: "stop-application-menu", - run: () => void applicationMenu.stop(), - }; - }, + applicationMenu.stop(); + + return undefined; + }, + }), injectionToken: beforeQuitOfBackEndInjectionToken, }); diff --git a/packages/core/src/features/application-update/__snapshots__/installing-update.test.ts.snap b/packages/core/src/features/application-update/__snapshots__/installing-update.test.ts.snap index 0b32c94831..cd0d55e25f 100644 --- a/packages/core/src/features/application-update/__snapshots__/installing-update.test.ts.snap +++ b/packages/core/src/features/application-update/__snapshots__/installing-update.test.ts.snap @@ -856,6 +856,601 @@ exports[`installing update when started when user checks for updates when new up `; exports[`installing update when started when user checks for updates when new update is discovered when download fails renders 1`] = ` + +
+
+
+
+
+ + + home + + +
+
+
+ + + arrow_back + + +
+
+
+ + + arrow_forward + + +
+
+
+
+
+
+
+
+ +
+
+

+ Welcome to some-product-name! +

+

+ To get you started we have auto-detected your clusters in your + + kubeconfig file and added them to the catalog, your centralized + + view for managing all your cloud-native resources. +
+
+ If you have any questions or feedback, please join our + + Lens Forums + + . +

+ +
+
+
+
+
+
+
+
+
+
+
+ Ca +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + arrow_left + + +
+
+ 1 +
+
+ + + arrow_right + + +
+
+
+
+
+
+
+
+
+ +`; + +exports[`installing update when started when user checks for updates when new update is discovered when download succeeds given checking for updates again when check resolves with different update that was previously downloaded when download resolves successfully renders 1`] = ` + +
+
+
+
+
+ + + home + + +
+
+
+ + + arrow_back + + +
+
+
+ + + arrow_forward + + +
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+

+ Welcome to some-product-name! +

+

+ To get you started we have auto-detected your clusters in your + + kubeconfig file and added them to the catalog, your centralized + + view for managing all your cloud-native resources. +
+
+ If you have any questions or feedback, please join our + + Lens Forums + + . +

+ +
+
+
+
+
+
+
+
+
+
+
+ Ca +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + arrow_left + + +
+
+ 1 +
+
+ + + arrow_right + + +
+
+
+
+
+
+
+
+
+ +`; + +exports[`installing update when started when user checks for updates when new update is discovered when download succeeds given checking for updates again when check resolves with same update that is already downloaded renders 1`] = `
-
-
- -
diff --git a/packages/core/src/features/application-update/child-features/force-update/force-update.test.ts b/packages/core/src/features/application-update/child-features/force-update/force-update.test.ts index 39ac24570a..1f35592dc7 100644 --- a/packages/core/src/features/application-update/child-features/force-update/force-update.test.ts +++ b/packages/core/src/features/application-update/child-features/force-update/force-update.test.ts @@ -14,11 +14,11 @@ import type { DiContainer } from "@ogre-tools/injectable"; import processCheckingForUpdatesInjectable from "../../main/process-checking-for-updates.injectable"; import type { RenderResult } from "@testing-library/react"; import { fireEvent } from "@testing-library/react"; -import { advanceFakeTime, testUsingFakeTime } from "../../../../common/test-utils/use-fake-time"; import quitAndInstallUpdateInjectable from "../../main/quit-and-install-update.injectable"; import timeAfterUpdateMustBeInstalledInjectable from "./renderer/force-update-modal/time-after-update-must-be-installed.injectable"; import secondsAfterInstallStartsInjectable from "./renderer/force-update-modal/seconds-after-install-starts.injectable"; import forceUpdateModalRootFrameComponentInjectable from "./renderer/force-update-modal/force-update-modal-root-frame-component.injectable"; +import { testUsingFakeTime, advanceFakeTime } from "../../../../test-utils/use-fake-time"; const TIME_AFTER_UPDATE_MUST_BE_INSTALLED = 1000; const TIME_AFTER_INSTALL_STARTS = 5 * 1000; diff --git a/packages/core/src/features/application-update/child-features/force-update/renderer/force-update-modal/force-update-modal-root-frame-component.global-override-for-injectable.ts b/packages/core/src/features/application-update/child-features/force-update/renderer/force-update-modal/force-update-modal-root-frame-component.global-override-for-injectable.ts index 49c4be5075..6de3bb5600 100644 --- a/packages/core/src/features/application-update/child-features/force-update/renderer/force-update-modal/force-update-modal-root-frame-component.global-override-for-injectable.ts +++ b/packages/core/src/features/application-update/child-features/force-update/renderer/force-update-modal/force-update-modal-root-frame-component.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { computed } from "mobx"; -import { getGlobalOverride } from "../../../../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import forceUpdateModalRootFrameComponentInjectable from "./force-update-modal-root-frame-component.injectable"; export default getGlobalOverride( diff --git a/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/periodical-check-for-updates.global-override-for-injectable.ts b/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/periodical-check-for-updates.global-override-for-injectable.ts index db86b30e37..53c808ba5f 100644 --- a/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/periodical-check-for-updates.global-override-for-injectable.ts +++ b/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/periodical-check-for-updates.global-override-for-injectable.ts @@ -4,7 +4,7 @@ */ import periodicalCheckForUpdatesInjectable from "./periodical-check-for-updates.injectable"; -import { getGlobalOverride } from "../../../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; export default getGlobalOverride(periodicalCheckForUpdatesInjectable, () => ({ start: () => {}, diff --git a/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/start-checking-for-updates.injectable.ts b/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/start-checking-for-updates.injectable.ts index 9ec17029ed..5e8ab6622c 100644 --- a/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/start-checking-for-updates.injectable.ts +++ b/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/start-checking-for-updates.injectable.ts @@ -10,19 +10,16 @@ import { afterApplicationIsLoadedInjectionToken } from "@k8slens/application"; const startCheckingForUpdatesInjectable = getInjectable({ id: "start-checking-for-updates", - instantiate: (di) => { - const periodicalCheckForUpdates = di.inject(periodicalCheckForUpdatesInjectable); - const updatingIsEnabled = di.inject(updatingIsEnabledInjectable); + instantiate: (di) => ({ + run: () => { + const periodicalCheckForUpdates = di.inject(periodicalCheckForUpdatesInjectable); + const updatingIsEnabled = di.inject(updatingIsEnabledInjectable); - return { - id: "start-checking-for-updates", - run: () => { - if (updatingIsEnabled && !periodicalCheckForUpdates.started) { - periodicalCheckForUpdates.start(); - } - }, - }; - }, + if (updatingIsEnabled && !periodicalCheckForUpdates.started) { + periodicalCheckForUpdates.start(); + } + }, + }), injectionToken: afterApplicationIsLoadedInjectionToken, }); diff --git a/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/stop-checking-for-updates.injectable.ts b/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/stop-checking-for-updates.injectable.ts index 6e58d7dd77..df1557466e 100644 --- a/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/stop-checking-for-updates.injectable.ts +++ b/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/stop-checking-for-updates.injectable.ts @@ -4,25 +4,22 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import periodicalCheckForUpdatesInjectable from "./periodical-check-for-updates.injectable"; -import { beforeQuitOfBackEndInjectionToken } from "../../../../../main/start-main-application/runnable-tokens/before-quit-of-back-end-injection-token"; +import { beforeQuitOfBackEndInjectionToken } from "../../../../../main/start-main-application/runnable-tokens/phases"; const stopCheckingForUpdatesInjectable = getInjectable({ id: "stop-checking-for-updates", - instantiate: (di) => { - const periodicalCheckForUpdates = di.inject(periodicalCheckForUpdatesInjectable); + instantiate: (di) => ({ + run: () => { + const periodicalCheckForUpdates = di.inject(periodicalCheckForUpdatesInjectable); - return { - id: "stop-checking-for-updates", - run: () => { - if (periodicalCheckForUpdates.started) { - periodicalCheckForUpdates.stop(); - } + if (periodicalCheckForUpdates.started) { + periodicalCheckForUpdates.stop(); + } - return undefined; - }, - }; - }, + return undefined; + }, + }), injectionToken: beforeQuitOfBackEndInjectionToken, }); diff --git a/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/periodical-checking-of-updates.test.ts b/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/periodical-checking-of-updates.test.ts index 22765b85de..63dfb4cc14 100644 --- a/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/periodical-checking-of-updates.test.ts +++ b/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/periodical-checking-of-updates.test.ts @@ -9,7 +9,7 @@ import electronUpdaterIsActiveInjectable from "../../../../main/electron-app/fea import publishIsConfiguredInjectable from "../../main/updating-is-enabled/publish-is-configured/publish-is-configured.injectable"; import processCheckingForUpdatesInjectable from "../../main/process-checking-for-updates.injectable"; import periodicalCheckForUpdatesInjectable from "./main/periodical-check-for-updates.injectable"; -import { advanceFakeTime, testUsingFakeTime } from "../../../../common/test-utils/use-fake-time"; +import { testUsingFakeTime, advanceFakeTime } from "../../../../test-utils/use-fake-time"; const ENOUGH_TIME = 1000 * 60 * 60 * 2; diff --git a/packages/core/src/features/application-update/installing-update.test.ts b/packages/core/src/features/application-update/installing-update.test.ts index 81529a851f..88ccb8ce0f 100644 --- a/packages/core/src/features/application-update/installing-update.test.ts +++ b/packages/core/src/features/application-update/installing-update.test.ts @@ -16,12 +16,13 @@ import type { DownloadPlatformUpdate } from "./main/download-update/download-pla import downloadPlatformUpdateInjectable from "./main/download-update/download-platform-update/download-platform-update.injectable"; import setUpdateOnQuitInjectable from "../../main/electron-app/features/set-update-on-quit.injectable"; import processCheckingForUpdatesInjectable from "./main/process-checking-for-updates.injectable"; -import { testUsingFakeTime } from "../../common/test-utils/use-fake-time"; +import { testUsingFakeTime } from "../../test-utils/use-fake-time"; import staticFilesDirectoryInjectable from "../../common/vars/static-files-directory.injectable"; +import electronQuitAndInstallUpdateInjectable from "../../main/electron-app/features/electron-quit-and-install-update.injectable"; describe("installing update", () => { let builder: ApplicationBuilder; - let quitAndInstallUpdateMock: jest.Mock; + let electronQuitAndInstallUpdateMock: jest.Mock; let checkForPlatformUpdatesMock: AsyncFnMock; let downloadPlatformUpdateMock: AsyncFnMock; let setUpdateOnQuitMock: jest.Mock; @@ -32,7 +33,7 @@ describe("installing update", () => { builder = getApplicationBuilder(); builder.beforeApplicationStart((mainDi) => { - quitAndInstallUpdateMock = jest.fn(); + electronQuitAndInstallUpdateMock = jest.fn(); checkForPlatformUpdatesMock = asyncFn(); downloadPlatformUpdateMock = asyncFn(); setUpdateOnQuitMock = jest.fn(); @@ -52,8 +53,8 @@ describe("installing update", () => { ); mainDi.override( - quitAndInstallUpdateInjectable, - () => quitAndInstallUpdateMock, + electronQuitAndInstallUpdateInjectable, + () => electronQuitAndInstallUpdateMock, ); mainDi.override(electronUpdaterIsActiveInjectable, () => true); @@ -64,6 +65,7 @@ describe("installing update", () => { describe("when started", () => { let rendered: RenderResult; let processCheckingForUpdates: (source: string) => Promise<{ updateIsReadyToBeInstalled: boolean }>; + let quitAndInstallUpdate: () => void; beforeEach(async () => { rendered = await builder.render(); @@ -71,6 +73,10 @@ describe("installing update", () => { processCheckingForUpdates = builder.mainDi.inject( processCheckingForUpdatesInjectable, ); + + quitAndInstallUpdate = builder.mainDi.inject( + quitAndInstallUpdateInjectable, + ); }); it("renders", () => { @@ -155,7 +161,7 @@ describe("installing update", () => { }); it("does not quit and install update yet", () => { - expect(quitAndInstallUpdateMock).not.toHaveBeenCalled(); + expect(electronQuitAndInstallUpdateMock).not.toHaveBeenCalled(); }); it("still shows normal tray icon", () => { @@ -167,6 +173,12 @@ describe("installing update", () => { it("renders", () => { expect(rendered.baseElement).toMatchSnapshot(); }); + + it("does not show the update button", () => { + const button = rendered.queryByTestId("update-button"); + + expect(button).not.toBeInTheDocument(); + }); }); describe("when download succeeds", () => { @@ -175,7 +187,7 @@ describe("installing update", () => { }); it("does not quit and install update yet", () => { - expect(quitAndInstallUpdateMock).not.toHaveBeenCalled(); + expect(electronQuitAndInstallUpdateMock).not.toHaveBeenCalled(); }); it("shows tray icon for update being available", () => { @@ -218,6 +230,26 @@ describe("installing update", () => { "/some-static-files-directory/build/tray/trayIconUpdateAvailableTemplate.png", ); }); + + it("does not quit and install update yet", () => { + expect(electronQuitAndInstallUpdateMock).not.toHaveBeenCalled(); + }); + + it("renders", () => { + expect(rendered.baseElement).toMatchSnapshot(); + }); + + it("shows the update button", () => { + const button = rendered.getByTestId("update-button"); + + expect(button).toBeInTheDocument(); + }); + + it("when triggering the update, quits and installs the update", () => { + quitAndInstallUpdate(); + + expect(electronQuitAndInstallUpdateMock).toHaveBeenCalled(); + }); }); describe("when check resolves with different update that was previously downloaded", () => { @@ -237,6 +269,45 @@ describe("installing update", () => { "/some-static-files-directory/build/tray/trayIconCheckingForUpdatesTemplate.png", ); }); + + it("still shows the update button", () => { + const button = rendered.getByTestId("update-button"); + + expect(button).toBeInTheDocument(); + }); + + describe("when download resolves successfully", () => { + beforeEach(async () => { + await downloadPlatformUpdateMock.resolve({ downloadWasSuccessful: true }); + }); + + it("still shows the update button", () => { + const button = + rendered.getByTestId("update-button"); + + expect(button).toBeInTheDocument(); + }); + + it("does not quit and install update yet", () => { + expect(electronQuitAndInstallUpdateMock).not.toHaveBeenCalled(); + }); + + it("shows tray icon for update being available", () => { + expect(builder.tray.getIconPath()).toBe( + "/some-static-files-directory/build/tray/trayIconUpdateAvailableTemplate.png", + ); + }); + + it("renders", () => { + expect(rendered.baseElement).toMatchSnapshot(); + }); + + it("when triggering the update, quits and installs the update", () => { + quitAndInstallUpdate(); + + expect(electronQuitAndInstallUpdateMock).toHaveBeenCalled(); + }); + }); }); }); }); diff --git a/packages/core/src/features/application-update/main/check-for-updates/check-for-platform-updates/check-for-platform-updates.global-override-for-injectable.ts b/packages/core/src/features/application-update/main/check-for-updates/check-for-platform-updates/check-for-platform-updates.global-override-for-injectable.ts index 5e271eaa30..d8d336ef56 100644 --- a/packages/core/src/features/application-update/main/check-for-updates/check-for-platform-updates/check-for-platform-updates.global-override-for-injectable.ts +++ b/packages/core/src/features/application-update/main/check-for-updates/check-for-platform-updates/check-for-platform-updates.global-override-for-injectable.ts @@ -3,6 +3,6 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import checkForPlatformUpdatesInjectable from "./check-for-platform-updates.injectable"; -import { getGlobalOverrideForFunction } from "../../../../../common/test-utils/get-global-override-for-function"; +import { getGlobalOverrideForFunction } from "@k8slens/test-utils"; export default getGlobalOverrideForFunction(checkForPlatformUpdatesInjectable); diff --git a/packages/core/src/features/application-update/main/check-for-updates/check-for-platform-updates/check-for-platform-updates.test.ts b/packages/core/src/features/application-update/main/check-for-updates/check-for-platform-updates/check-for-platform-updates.test.ts index 408da4eb7d..5a4262baf1 100644 --- a/packages/core/src/features/application-update/main/check-for-updates/check-for-platform-updates/check-for-platform-updates.test.ts +++ b/packages/core/src/features/application-update/main/check-for-updates/check-for-platform-updates/check-for-platform-updates.test.ts @@ -10,9 +10,9 @@ import type { AppUpdater, UpdateCheckResult } from "electron-updater"; import type { CheckForPlatformUpdates } from "./check-for-platform-updates.injectable"; import checkForPlatformUpdatesInjectable from "./check-for-platform-updates.injectable"; import type { UpdateChannel, ReleaseChannel } from "../../../common/update-channels"; -import { getPromiseStatus } from "../../../../../common/test-utils/get-promise-status"; +import { getPromiseStatus } from "@k8slens/test-utils"; import loggerInjectable from "../../../../../common/logger.injectable"; -import { noop } from "../../../../../common/utils"; +import { noop } from "@k8slens/utilities"; describe("check-for-platform-updates", () => { let checkForPlatformUpdates: CheckForPlatformUpdates; diff --git a/packages/core/src/features/application-update/main/download-update/download-platform-update/download-platform-update.global-override-for-injectable.ts b/packages/core/src/features/application-update/main/download-update/download-platform-update/download-platform-update.global-override-for-injectable.ts index 15df5d835b..5a339e3ea3 100644 --- a/packages/core/src/features/application-update/main/download-update/download-platform-update/download-platform-update.global-override-for-injectable.ts +++ b/packages/core/src/features/application-update/main/download-update/download-platform-update/download-platform-update.global-override-for-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 { getGlobalOverrideForFunction } from "../../../../../common/test-utils/get-global-override-for-function"; +import { getGlobalOverrideForFunction } from "@k8slens/test-utils"; import downloadPlatformUpdateInjectable from "./download-platform-update.injectable"; export default getGlobalOverrideForFunction(downloadPlatformUpdateInjectable); diff --git a/packages/core/src/features/application-update/main/download-update/download-platform-update/download-platform-update.test.ts b/packages/core/src/features/application-update/main/download-update/download-platform-update/download-platform-update.test.ts index e2716ed962..d39931e6ac 100644 --- a/packages/core/src/features/application-update/main/download-update/download-platform-update/download-platform-update.test.ts +++ b/packages/core/src/features/application-update/main/download-update/download-platform-update/download-platform-update.test.ts @@ -9,10 +9,10 @@ import downloadPlatformUpdateInjectable from "./download-platform-update.injecta import type { AppUpdater } from "electron-updater"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; -import { getPromiseStatus } from "../../../../../common/test-utils/get-promise-status"; +import { getPromiseStatus } from "@k8slens/test-utils"; import type { DiContainer } from "@ogre-tools/injectable"; import loggerInjectable from "../../../../../common/logger.injectable"; -import { noop } from "../../../../../common/utils"; +import { noop } from "@k8slens/utilities"; describe("download-platform-update", () => { let downloadPlatformUpdate: DownloadPlatformUpdate; diff --git a/packages/core/src/features/application-update/main/download-update/download-update.injectable.ts b/packages/core/src/features/application-update/main/download-update/download-update.injectable.ts index e9019dc7b2..662a2b272d 100644 --- a/packages/core/src/features/application-update/main/download-update/download-update.injectable.ts +++ b/packages/core/src/features/application-update/main/download-update/download-update.injectable.ts @@ -40,12 +40,12 @@ const downloadUpdateInjectable = getInjectable({ if (!downloadWasSuccessful) { progressOfUpdateDownload.set({ percentage: 0, failed: "Download of update failed" }); discoveredVersionState.set(null); + } else { + const currentDateTime = getCurrentDateTime(); + + updateDownloadedDate.set(currentDateTime); } - const currentDateTime = getCurrentDateTime(); - - updateDownloadedDate.set(currentDateTime); - downloadingUpdateState.set(false); }); diff --git a/packages/core/src/features/application-update/main/emit-current-version-to-analytics.injectable.ts b/packages/core/src/features/application-update/main/emit-current-version-to-analytics.injectable.ts index 1a7abcd7ce..cef23c9860 100644 --- a/packages/core/src/features/application-update/main/emit-current-version-to-analytics.injectable.ts +++ b/packages/core/src/features/application-update/main/emit-current-version-to-analytics.injectable.ts @@ -11,25 +11,22 @@ import buildVersionInjectable from "../../../main/vars/build-version/build-versi const emitCurrentVersionToAnalyticsInjectable = getInjectable({ id: "emit-current-version-to-analytics", - instantiate: (di) => { - const emitAppEvent = di.inject(emitAppEventInjectable); - const buildVersion = di.inject(buildVersionInjectable); + instantiate: (di) => ({ + run: () => { + const emitAppEvent = di.inject(emitAppEventInjectable); + const buildVersion = di.inject(buildVersionInjectable); - return { - id: "emit-current-version-to-analytics", - run: () => { - emitAppEvent({ - name: "app", - action: "current-version", + emitAppEvent({ + name: "app", + action: "current-version", - params: { - version: buildVersion.get(), - currentDateTime: getCurrentDateTime(), - }, - }); - }, - }; - }, + params: { + version: buildVersion.get(), + currentDateTime: getCurrentDateTime(), + }, + }); + }, + }), injectionToken: afterApplicationIsLoadedInjectionToken, }); diff --git a/packages/core/src/features/application-update/main/updating-is-enabled/publish-is-configured/publish-is-configured.global-override-for-injectable.ts b/packages/core/src/features/application-update/main/updating-is-enabled/publish-is-configured/publish-is-configured.global-override-for-injectable.ts index f8c36953c6..109958838d 100644 --- a/packages/core/src/features/application-update/main/updating-is-enabled/publish-is-configured/publish-is-configured.global-override-for-injectable.ts +++ b/packages/core/src/features/application-update/main/updating-is-enabled/publish-is-configured/publish-is-configured.global-override-for-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 { getGlobalOverride } from "../../../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import publishIsConfiguredInjectable from "./publish-is-configured.injectable"; export default getGlobalOverride(publishIsConfiguredInjectable, () => false); diff --git a/packages/core/src/features/application-update/main/watch-if-update-should-happen-on-quit/start-watching-if-update-should-happen-on-quit.injectable.ts b/packages/core/src/features/application-update/main/watch-if-update-should-happen-on-quit/start-watching-if-update-should-happen-on-quit.injectable.ts index 73742babaa..2739119a13 100644 --- a/packages/core/src/features/application-update/main/watch-if-update-should-happen-on-quit/start-watching-if-update-should-happen-on-quit.injectable.ts +++ b/packages/core/src/features/application-update/main/watch-if-update-should-happen-on-quit/start-watching-if-update-should-happen-on-quit.injectable.ts @@ -9,16 +9,13 @@ import watchIfUpdateShouldHappenOnQuitInjectable from "./watch-if-update-should- const startWatchingIfUpdateShouldHappenOnQuitInjectable = getInjectable({ id: "start-watching-if-update-should-happen-on-quit", - instantiate: (di) => { - const watchIfUpdateShouldHappenOnQuit = di.inject(watchIfUpdateShouldHappenOnQuitInjectable); + instantiate: (di) => ({ + run: () => { + const watchIfUpdateShouldHappenOnQuit = di.inject(watchIfUpdateShouldHappenOnQuitInjectable); - return { - id: "start-watching-if-update-should-happen-on-quit", - run: () => { - watchIfUpdateShouldHappenOnQuit.start(); - }, - }; - }, + watchIfUpdateShouldHappenOnQuit.start(); + }, + }), injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/features/application-update/main/watch-if-update-should-happen-on-quit/stop-watching-if-update-should-happen-on-quit.injectable.ts b/packages/core/src/features/application-update/main/watch-if-update-should-happen-on-quit/stop-watching-if-update-should-happen-on-quit.injectable.ts index faf67b4ffc..36a6d3174d 100644 --- a/packages/core/src/features/application-update/main/watch-if-update-should-happen-on-quit/stop-watching-if-update-should-happen-on-quit.injectable.ts +++ b/packages/core/src/features/application-update/main/watch-if-update-should-happen-on-quit/stop-watching-if-update-should-happen-on-quit.injectable.ts @@ -4,19 +4,20 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import watchIfUpdateShouldHappenOnQuitInjectable from "./watch-if-update-should-happen-on-quit.injectable"; -import { beforeQuitOfBackEndInjectionToken } from "../../../../main/start-main-application/runnable-tokens/before-quit-of-back-end-injection-token"; +import { beforeQuitOfBackEndInjectionToken } from "../../../../main/start-main-application/runnable-tokens/phases"; const stopWatchingIfUpdateShouldHappenOnQuitInjectable = getInjectable({ id: "stop-watching-if-update-should-happen-on-quit", - instantiate: (di) => { - const watchIfUpdateShouldHappenOnQuit = di.inject(watchIfUpdateShouldHappenOnQuitInjectable); + instantiate: (di) => ({ + run: () => { + const watchIfUpdateShouldHappenOnQuit = di.inject(watchIfUpdateShouldHappenOnQuitInjectable); - return { - id: "stop-watching-if-update-should-happen-on-quit", - run: () => void watchIfUpdateShouldHappenOnQuit.stop(), - }; - }, + watchIfUpdateShouldHappenOnQuit.stop(); + + return undefined; + }, + }), injectionToken: beforeQuitOfBackEndInjectionToken, }); diff --git a/packages/core/src/features/catalog/entity-running.test.tsx b/packages/core/src/features/catalog/entity-running.test.tsx index e3a4438da5..cfe3b8bf92 100644 --- a/packages/core/src/features/catalog/entity-running.test.tsx +++ b/packages/core/src/features/catalog/entity-running.test.tsx @@ -12,8 +12,8 @@ import type { CatalogEntityActionContext } from "../../common/catalog"; import { CatalogCategory, categoryVersion, CatalogEntity } from "../../common/catalog"; import catalogCategoryRegistryInjectable from "../../common/catalog/category-registry.injectable"; import navigateToCatalogInjectable from "../../common/front-end-routing/routes/catalog/navigate-to-catalog.injectable"; -import { flushPromises } from "../../common/test-utils/flush-promises"; -import { advanceFakeTime, testUsingFakeTime } from "../../common/test-utils/use-fake-time"; +import { flushPromises } from "@k8slens/test-utils"; +import { advanceFakeTime, testUsingFakeTime } from "../../test-utils/use-fake-time"; import type { CatalogEntityOnBeforeRun, CatalogEntityRegistry } from "../../renderer/api/catalog/entity/registry"; import catalogEntityRegistryInjectable from "../../renderer/api/catalog/entity/registry.injectable"; import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; diff --git a/packages/core/src/features/catalog/opening-entity-details.test.tsx b/packages/core/src/features/catalog/opening-entity-details.test.tsx index 6cb8c69265..a47f139e80 100644 --- a/packages/core/src/features/catalog/opening-entity-details.test.tsx +++ b/packages/core/src/features/catalog/opening-entity-details.test.tsx @@ -7,11 +7,10 @@ import type { DiContainer } from "@ogre-tools/injectable"; import type { RenderResult } from "@testing-library/react"; import { KubernetesCluster, WebLink } from "../../common/catalog-entities"; import getClusterByIdInjectable from "../../common/cluster-store/get-by-id.injectable"; -import type { Cluster } from "../../common/cluster/cluster"; +import { Cluster } from "../../common/cluster/cluster"; import navigateToCatalogInjectable from "../../common/front-end-routing/routes/catalog/navigate-to-catalog.injectable"; -import { advanceFakeTime, testUsingFakeTime } from "../../common/test-utils/use-fake-time"; +import { advanceFakeTime, testUsingFakeTime } from "../../test-utils/use-fake-time"; import catalogEntityRegistryInjectable from "../../renderer/api/catalog/entity/registry.injectable"; -import createClusterInjectable from "../../renderer/cluster/create-cluster.injectable"; import showEntityDetailsInjectable from "../../renderer/components/+catalog/entity-details/show.injectable"; import { type ApplicationBuilder, getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; @@ -41,8 +40,6 @@ describe("opening catalog entity details panel", () => { testUsingFakeTime(); builder.afterWindowStart((windowDi) => { - const createCluster = windowDi.inject(createClusterInjectable); - clusterEntity = new KubernetesCluster({ metadata: { labels: {}, @@ -85,7 +82,7 @@ describe("opening catalog entity details panel", () => { phase: "available", }, }); - cluster = createCluster({ + cluster = new Cluster({ contextName: clusterEntity.spec.kubeconfigContext, id: clusterEntity.getId(), kubeConfigPath: clusterEntity.spec.kubeconfigPath, 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 d8346706bb..62882fb49f 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 @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import { casChannel } from "../common/channel"; import certificateAuthoritiesChannelListenerInjectable from "./channel-handler.injectable"; 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 300b69c383..206a68ba94 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 @@ -5,7 +5,7 @@ import { getRequestChannelListenerInjectable } from "../../../main/utils/channel/channel-listeners/listener-tokens"; import { casChannel } from "../common/channel"; import { globalAgent } from "https"; -import { isString } from "../../../common/utils"; +import { isString } from "@k8slens/utilities"; const certificateAuthoritiesChannelListenerInjectable = getRequestChannelListenerInjectable({ channel: casChannel, diff --git a/packages/core/src/features/certificate-authorities/main/request-system-cas.injectable.darwin.ts b/packages/core/src/features/certificate-authorities/main/request-system-cas.injectable.darwin.ts index 62cf75f6ff..66c24a1235 100644 --- a/packages/core/src/features/certificate-authorities/main/request-system-cas.injectable.darwin.ts +++ b/packages/core/src/features/certificate-authorities/main/request-system-cas.injectable.darwin.ts @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import execFileInjectable from "../../../common/fs/exec-file.injectable"; import loggerInjectable from "../../../common/logger.injectable"; -import type { AsyncResult } from "../../../common/utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; import { requestSystemCAsInjectionToken } from "../common/request-system-cas-token"; // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Cheatsheet#other_assertions @@ -17,7 +17,7 @@ const requestSystemCAsInjectable = getInjectable({ const execFile = di.inject(execFileInjectable); const logger = di.inject(loggerInjectable); - const execSecurity = async (...args: string[]): Promise> => { + const execSecurity = async (...args: string[]): AsyncResult => { const result = await execFile("/usr/bin/security", args); if (!result.callWasSuccessful) { diff --git a/packages/core/src/features/cluster/delete-dialog/delete-cluster-dialog.test.tsx b/packages/core/src/features/cluster/delete-dialog/delete-cluster-dialog.test.tsx index 5cbf8267de..46b84c44e3 100644 --- a/packages/core/src/features/cluster/delete-dialog/delete-cluster-dialog.test.tsx +++ b/packages/core/src/features/cluster/delete-dialog/delete-cluster-dialog.test.tsx @@ -5,20 +5,16 @@ import "@testing-library/jest-dom/extend-expect"; import { KubeConfig } from "@kubernetes/client-node"; import type { RenderResult } from "@testing-library/react"; -import type { CreateCluster } from "../../../common/cluster/create-cluster-injection-token"; -import { createClusterInjectionToken } from "../../../common/cluster/create-cluster-injection-token"; -import createContextHandlerInjectable from "../../../main/context-handler/create-context-handler.injectable"; -import createKubeconfigManagerInjectable from "../../../main/kubeconfig-manager/create-kubeconfig-manager.injectable"; import normalizedPlatformInjectable from "../../../common/vars/normalized-platform.injectable"; import kubectlBinaryNameInjectable from "../../../main/kubectl/binary-name.injectable"; import kubectlDownloadingNormalizedArchInjectable from "../../../main/kubectl/normalized-arch.injectable"; import openDeleteClusterDialogInjectable, { type OpenDeleteClusterDialog } from "../../../renderer/components/delete-cluster-dialog/open.injectable"; import { type ApplicationBuilder, getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; -import type { Cluster } from "../../../common/cluster/cluster"; +import { Cluster } from "../../../common/cluster/cluster"; import navigateToCatalogInjectable from "../../../common/front-end-routing/routes/catalog/navigate-to-catalog.injectable"; import directoryForKubeConfigsInjectable from "../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable"; import joinPathsInjectable from "../../../common/path/join-paths.injectable"; -import { advanceFakeTime } from "../../../common/test-utils/use-fake-time"; +import { advanceFakeTime } from "../../../test-utils/use-fake-time"; const currentClusterServerUrl = "https://localhost"; const nonCurrentClusterServerUrl = "http://localhost"; @@ -73,7 +69,6 @@ users: describe("Deleting a cluster", () => { let builder: ApplicationBuilder; let openDeleteClusterDialog: OpenDeleteClusterDialog; - let createCluster: CreateCluster; let rendered: RenderResult; let config: KubeConfig; @@ -82,8 +77,6 @@ describe("Deleting a cluster", () => { builder = getApplicationBuilder(); builder.beforeApplicationStart((mainDi) => { - mainDi.override(createContextHandlerInjectable, () => () => undefined as never); - mainDi.override(createKubeconfigManagerInjectable, () => () => undefined as never); mainDi.override(kubectlBinaryNameInjectable, () => "kubectl"); mainDi.override(kubectlDownloadingNormalizedArchInjectable, () => "amd64"); mainDi.override(normalizedPlatformInjectable, () => "darwin"); @@ -94,8 +87,6 @@ describe("Deleting a cluster", () => { }); builder.afterWindowStart(windowDi => { - createCluster = windowDi.inject(createClusterInjectionToken); - const navigateToCatalog = windowDi.inject(navigateToCatalogInjectable); navigateToCatalog(); @@ -111,7 +102,7 @@ describe("Deleting a cluster", () => { beforeEach(() => { config.loadFromString(multiClusterConfig); - currentCluster = createCluster({ + currentCluster = new Cluster({ id: "some-current-context-cluster", contextName: "some-current-context", preferences: { @@ -121,7 +112,7 @@ describe("Deleting a cluster", () => { }, { clusterServerUrl: currentClusterServerUrl, }); - nonCurrentCluster = createCluster({ + nonCurrentCluster = new Cluster({ id: "some-non-current-context-cluster", contextName: "some-non-current-context", preferences: { @@ -199,7 +190,7 @@ describe("Deleting a cluster", () => { const directoryForKubeConfigs = builder.applicationWindow.only.di.inject(directoryForKubeConfigsInjectable); const joinPaths = builder.applicationWindow.only.di.inject(joinPathsInjectable); - currentCluster = createCluster({ + currentCluster = new Cluster({ id: "some-cluster", contextName: "some-context", preferences: { @@ -235,7 +226,7 @@ describe("Deleting a cluster", () => { beforeEach(() => { config.loadFromString(singleClusterConfig); - currentCluster = createCluster({ + currentCluster = new Cluster({ id: "some-cluster", contextName: "some-context", preferences: { 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 b2ac54d5e4..94caf169ba 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 @@ -8,7 +8,8 @@ import clusterStoreInjectable from "../../../../common/cluster-store/cluster-sto import directoryForLensLocalStorageInjectable from "../../../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable"; import removePathInjectable from "../../../../common/fs/remove.injectable"; import joinPathsInjectable from "../../../../common/path/join-paths.injectable"; -import { noop } from "../../../../common/utils"; +import clusterConnectionInjectable from "../../../../main/cluster/cluster-connection.injectable"; +import { noop } from "@k8slens/utilities"; import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens"; import { deleteClusterChannel } from "../common/delete-channel"; @@ -31,7 +32,9 @@ const deleteClusterChannelListenerInjectable = getRequestChannelListenerInjectab return; } - cluster.disconnect(); + const clusterConnection = di.inject(clusterConnectionInjectable, cluster); + + clusterConnection.disconnect(); clusterFrames.delete(cluster.id); // Remove from the cluster store as well, this should clear any old settings diff --git a/packages/core/src/features/cluster/kube-object-status-icon/show-status-for-a-kube-object.test.tsx b/packages/core/src/features/cluster/kube-object-status-icon/show-status-for-a-kube-object.test.tsx index 49fe7f9efd..fde6a1b816 100644 --- a/packages/core/src/features/cluster/kube-object-status-icon/show-status-for-a-kube-object.test.tsx +++ b/packages/core/src/features/cluster/kube-object-status-icon/show-status-for-a-kube-object.test.tsx @@ -5,7 +5,6 @@ import { KubeObjectStatusLevel } from "../../../common/k8s-api/kube-object-status"; import { KubeObject } from "../../../common/k8s-api/kube-object"; import React from "react"; -import { testUsingFakeTime } from "../../../common/test-utils/use-fake-time"; import type { DiContainer } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable"; import type { IAtom } from "mobx"; @@ -20,6 +19,7 @@ import { act } from "@testing-library/react"; import { observer } from "mobx-react"; import { kubeObjectStatusTextInjectionToken } from "../../../renderer/components/kube-object-status-icon/kube-object-status-text-injection-token"; import { KubeObjectStatusIcon } from "../../../renderer/components/kube-object-status-icon"; +import { testUsingFakeTime } from "../../../test-utils/use-fake-time"; describe("show status for a kube object", () => { let builder: ApplicationBuilder; diff --git a/packages/core/src/features/cluster/namespaces/edit-namespace-from-new-tab.test.tsx b/packages/core/src/features/cluster/namespaces/edit-namespace-from-new-tab.test.tsx index 52796fc314..1780186509 100644 --- a/packages/core/src/features/cluster/namespaces/edit-namespace-from-new-tab.test.tsx +++ b/packages/core/src/features/cluster/namespaces/edit-namespace-from-new-tab.test.tsx @@ -64,9 +64,11 @@ describe("cluster/namespaces - edit namespace from new tab", () => { windowDi.override(callForPatchResourceInjectable, () => callForPatchResourceMock); }); - builder.allowKubeResource({ - apiName: "namespaces", - group: "", + builder.afterWindowStart(() => { + builder.allowKubeResource({ + apiName: "namespaces", + group: "", + }); }); }); diff --git a/packages/core/src/features/cluster/namespaces/edit-namespace-from-previously-opened-tab.test.tsx b/packages/core/src/features/cluster/namespaces/edit-namespace-from-previously-opened-tab.test.tsx index c5bbd15dfc..6ec5447bd6 100644 --- a/packages/core/src/features/cluster/namespaces/edit-namespace-from-previously-opened-tab.test.tsx +++ b/packages/core/src/features/cluster/namespaces/edit-namespace-from-previously-opened-tab.test.tsx @@ -35,9 +35,11 @@ describe("cluster/namespaces - edit namespaces from previously opened tab", () = windowDi.override(callForResourceInjectable, () => callForNamespaceMock); }); - builder.allowKubeResource({ - apiName: "namespaces", - group: "", + builder.afterWindowStart(() => { + builder.allowKubeResource({ + apiName: "namespaces", + group: "", + }); }); }); diff --git a/packages/core/src/features/cluster/sidebar-and-tab-navigation-for-core.test.tsx b/packages/core/src/features/cluster/sidebar-and-tab-navigation-for-core.test.tsx index a4995c38ae..bdac7d43b4 100644 --- a/packages/core/src/features/cluster/sidebar-and-tab-navigation-for-core.test.tsx +++ b/packages/core/src/features/cluster/sidebar-and-tab-navigation-for-core.test.tsx @@ -20,9 +20,9 @@ import writeJsonFileInjectable from "../../common/fs/write-json-file.injectable" import pathExistsInjectable from "../../common/fs/path-exists.injectable"; import readJsonFileInjectable from "../../common/fs/read-json-file.injectable"; import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token"; -import { advanceFakeTime, testUsingFakeTime } from "../../common/test-utils/use-fake-time"; import storageSaveDelayInjectable from "../../renderer/utils/create-storage/storage-save-delay.injectable"; -import { flushPromises } from "../../common/test-utils/flush-promises"; +import { flushPromises } from "@k8slens/test-utils"; +import { testUsingFakeTime, advanceFakeTime } from "../../test-utils/use-fake-time"; describe("cluster - sidebar and tab navigation for core", () => { let builder: ApplicationBuilder; diff --git a/packages/core/src/features/cluster/sidebar-and-tab-navigation-for-extensions.test.tsx b/packages/core/src/features/cluster/sidebar-and-tab-navigation-for-extensions.test.tsx index 9bde5663c2..2ccbb1ab1a 100644 --- a/packages/core/src/features/cluster/sidebar-and-tab-navigation-for-extensions.test.tsx +++ b/packages/core/src/features/cluster/sidebar-and-tab-navigation-for-extensions.test.tsx @@ -15,13 +15,13 @@ import pathExistsInjectable from "../../common/fs/path-exists.injectable"; import readJsonFileInjectable from "../../common/fs/read-json-file.injectable"; import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token"; import assert from "assert"; -import { advanceFakeTime, testUsingFakeTime } from "../../common/test-utils/use-fake-time"; import type { IObservableValue } from "mobx"; import { runInAction, computed, observable } from "mobx"; import storageSaveDelayInjectable from "../../renderer/utils/create-storage/storage-save-delay.injectable"; import type { DiContainer } from "@ogre-tools/injectable"; -import { flushPromises } from "../../common/test-utils/flush-promises"; import type { ClusterPageMenuRegistration } from "../../extensions/common-api/types"; +import { flushPromises } from "@k8slens/test-utils"; +import { testUsingFakeTime, advanceFakeTime } from "../../test-utils/use-fake-time"; describe("cluster - sidebar and tab navigation for extensions", () => { let applicationBuilder: ApplicationBuilder; diff --git a/packages/core/src/features/cluster/state-sync/main/setup-sync.injectable.ts b/packages/core/src/features/cluster/state-sync/main/setup-sync.injectable.ts index e61a805ee2..348450958d 100644 --- a/packages/core/src/features/cluster/state-sync/main/setup-sync.injectable.ts +++ b/packages/core/src/features/cluster/state-sync/main/setup-sync.injectable.ts @@ -14,7 +14,6 @@ import emitClusterStateUpdateInjectable from "./emit-update.injectable"; const setupClusterStateBroadcastingInjectable = getInjectable({ id: "setup-cluster-state-broadcasting", instantiate: (di) => ({ - id: "setup-cluster-state-broadcasting", run: () => { const emitClusterStateUpdate = di.inject(emitClusterStateUpdateInjectable); const clusterStore = di.inject(clusterStoreInjectable); @@ -36,7 +35,7 @@ const setupClusterStateBroadcastingInjectable = getInjectable({ } }); }, - runAfter: di.inject(initClusterStoreInjectable), + runAfter: initClusterStoreInjectable, }), injectionToken: beforeApplicationIsLoadingInjectionToken, }); diff --git a/packages/core/src/features/cluster/state-sync/renderer/setup-sync.injectable.ts b/packages/core/src/features/cluster/state-sync/renderer/setup-sync.injectable.ts index e4df4c7f8e..da43ace234 100644 --- a/packages/core/src/features/cluster/state-sync/renderer/setup-sync.injectable.ts +++ b/packages/core/src/features/cluster/state-sync/renderer/setup-sync.injectable.ts @@ -11,17 +11,16 @@ import requestInitialClusterStatesInjectable from "./request-initial.injectable" const setupClusterStateSyncInjectable = getInjectable({ id: "setup-cluster-state-sync", instantiate: (di) => ({ - id: "setup-cluster-state-sync", run: async () => { const requestInitialClusterStates = di.inject(requestInitialClusterStatesInjectable); const getClusterById = di.inject(getClusterByIdInjectable); - const initalStates = await requestInitialClusterStates(); + const initialStates = await requestInitialClusterStates(); - for (const { clusterId, state } of initalStates) { + for (const { clusterId, state } of initialStates) { getClusterById(clusterId)?.setState(state); } }, - runAfter: di.inject(initClusterStoreInjectable), + runAfter: initClusterStoreInjectable, }), injectionToken: beforeFrameStartsSecondInjectionToken, }); diff --git a/packages/core/src/features/cluster/store/main/init.injectable.ts b/packages/core/src/features/cluster/store/main/init.injectable.ts index 28fdb1aa9f..c7a6bc1c9a 100644 --- a/packages/core/src/features/cluster/store/main/init.injectable.ts +++ b/packages/core/src/features/cluster/store/main/init.injectable.ts @@ -9,17 +9,14 @@ import initUserStoreInjectable from "../../../../main/stores/init-user-store.inj const initClusterStoreInjectable = getInjectable({ id: "init-cluster-store", - instantiate: (di) => { - const clusterStore = di.inject(clusterStoreInjectable); + instantiate: (di) => ({ + run: () => { + const clusterStore = di.inject(clusterStoreInjectable); - return { - id: "init-cluster-store", - run: () => { - clusterStore.load(); - }, - runAfter: di.inject(initUserStoreInjectable), - }; - }, + clusterStore.load(); + }, + runAfter: initUserStoreInjectable, + }), injectionToken: beforeApplicationIsLoadingInjectionToken, }); diff --git a/packages/core/src/features/cluster/store/renderer/init.injectable.ts b/packages/core/src/features/cluster/store/renderer/init.injectable.ts index 66d2e31e09..f937796bae 100644 --- a/packages/core/src/features/cluster/store/renderer/init.injectable.ts +++ b/packages/core/src/features/cluster/store/renderer/init.injectable.ts @@ -10,13 +10,12 @@ import initUserStoreInjectable from "../../../../renderer/stores/init-user-store const initClusterStoreInjectable = getInjectable({ id: "init-cluster-store", instantiate: (di) => ({ - id: "init-cluster-store", run: () => { const clusterStore = di.inject(clusterStoreInjectable); clusterStore.load(); }, - runAfter: di.inject(initUserStoreInjectable), + runAfter: initUserStoreInjectable, }), injectionToken: beforeFrameStartsSecondInjectionToken, }); diff --git a/packages/core/src/features/cluster/workload-overview.test.tsx b/packages/core/src/features/cluster/workload-overview.test.tsx index 725ec04e90..c08dcba0f7 100644 --- a/packages/core/src/features/cluster/workload-overview.test.tsx +++ b/packages/core/src/features/cluster/workload-overview.test.tsx @@ -9,20 +9,24 @@ import { type ApplicationBuilder, getApplicationBuilder } from "../../renderer/c describe("workload overview", () => { let rendered: RenderResult; - let applicationBuilder: ApplicationBuilder; + let builder: ApplicationBuilder; beforeEach(async () => { - applicationBuilder = getApplicationBuilder().setEnvironmentToClusterFrame(); - applicationBuilder.allowKubeResource({ - apiName: "pods", - group: "", + builder = getApplicationBuilder().setEnvironmentToClusterFrame(); + + builder.afterWindowStart(() => { + builder.allowKubeResource({ + apiName: "pods", + group: "", + }); }); - rendered = await applicationBuilder.render(); + + rendered = await builder.render(); }); describe("when navigating to workload overview", () => { beforeEach(() => { - applicationBuilder.navigateWith(navigateToWorkloadsOverviewInjectable); + builder.navigateWith(navigateToWorkloadsOverviewInjectable); }); it("renders", () => { diff --git a/packages/core/src/features/entity-settings/showing-settings-for-correct-entity.test.tsx b/packages/core/src/features/entity-settings/showing-settings-for-correct-entity.test.tsx index aafb4ca720..3a24395b49 100644 --- a/packages/core/src/features/entity-settings/showing-settings-for-correct-entity.test.tsx +++ b/packages/core/src/features/entity-settings/showing-settings-for-correct-entity.test.tsx @@ -7,11 +7,10 @@ import type { DiContainer } from "@ogre-tools/injectable"; import type { RenderResult } from "@testing-library/react"; import { KubernetesCluster, WebLink } from "../../common/catalog-entities"; import getClusterByIdInjectable from "../../common/cluster-store/get-by-id.injectable"; -import type { Cluster } from "../../common/cluster/cluster"; +import { Cluster } from "../../common/cluster/cluster"; import navigateToEntitySettingsInjectable from "../../common/front-end-routing/routes/entity-settings/navigate-to-entity-settings.injectable"; import catalogEntityRegistryInjectable from "../../renderer/api/catalog/entity/registry.injectable"; import { type ApplicationBuilder, getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; -import createClusterInjectable from "../../renderer/cluster/create-cluster.injectable"; describe("Showing correct entity settings", () => { let builder: ApplicationBuilder; @@ -37,8 +36,6 @@ describe("Showing correct entity settings", () => { }); builder.afterWindowStart((windowDi) => { - const createCluster = windowDi.inject(createClusterInjectable); - clusterEntity = new KubernetesCluster({ metadata: { labels: {}, @@ -81,7 +78,7 @@ describe("Showing correct entity settings", () => { phase: "available", }, }); - cluster = createCluster({ + cluster = new Cluster({ contextName: clusterEntity.spec.kubeconfigContext, id: clusterEntity.getId(), kubeConfigPath: clusterEntity.spec.kubeconfigPath, diff --git a/packages/core/src/features/file-system-provisioner/main/init-store.injectable.ts b/packages/core/src/features/file-system-provisioner/main/init-store.injectable.ts index 1449a7fa4c..9b60f420b5 100644 --- a/packages/core/src/features/file-system-provisioner/main/init-store.injectable.ts +++ b/packages/core/src/features/file-system-provisioner/main/init-store.injectable.ts @@ -9,7 +9,6 @@ import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; const initFileSystemProvisionerStoreInjectable = getInjectable({ id: "init-file-system-provisioner-store", instantiate: (di) => ({ - id: "init-file-system-provisioner-store", run: () => { const store = di.inject(fileSystemProvisionerStoreInjectable); diff --git a/packages/core/src/features/file-system-provisioner/renderer/init-store.injectable.ts b/packages/core/src/features/file-system-provisioner/renderer/init-store.injectable.ts index 0e64e49fd6..a133c54d20 100644 --- a/packages/core/src/features/file-system-provisioner/renderer/init-store.injectable.ts +++ b/packages/core/src/features/file-system-provisioner/renderer/init-store.injectable.ts @@ -9,7 +9,6 @@ import { beforeFrameStartsSecondInjectionToken } from "../../../renderer/before- const initFileSystemProvisionerStoreInjectable = getInjectable({ id: "init-file-system-provisioner-store", instantiate: (di) => ({ - id: "init-file-system-provisioner-store", run: () => { const store = di.inject(fileSystemProvisionerStoreInjectable); diff --git a/packages/core/src/features/helm-charts/add-custom-helm-repository-in-preferences.test.ts b/packages/core/src/features/helm-charts/add-custom-helm-repository-in-preferences.test.ts index 495d2e9fb3..13e73c5c28 100644 --- a/packages/core/src/features/helm-charts/add-custom-helm-repository-in-preferences.test.ts +++ b/packages/core/src/features/helm-charts/add-custom-helm-repository-in-preferences.test.ts @@ -17,8 +17,8 @@ import requestPublicHelmRepositoriesInjectable from "./child-features/preference import isPathInjectable from "../../renderer/components/input/validators/is-path.injectable"; import showSuccessNotificationInjectable from "../../renderer/components/notifications/show-success-notification.injectable"; import showErrorNotificationInjectable from "../../renderer/components/notifications/show-error-notification.injectable"; -import type { AsyncResult } from "../../common/utils/async-result"; -import { testUsingFakeTime } from "../../common/test-utils/use-fake-time"; +import type { AsyncResult } from "@k8slens/utilities"; +import { testUsingFakeTime } from "../../test-utils/use-fake-time"; describe("add custom helm repository in preferences", () => { let builder: ApplicationBuilder; @@ -26,7 +26,7 @@ describe("add custom helm repository in preferences", () => { let showErrorNotificationMock: jest.Mock; let rendered: RenderResult; let execFileMock: AsyncFnMock; - let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise>>; + let getActiveHelmRepositoriesMock: AsyncFnMock<() => AsyncResult>; beforeEach(async () => { jest.useFakeTimers(); diff --git a/packages/core/src/features/helm-charts/add-helm-repository-from-list-in-preferences.test.ts b/packages/core/src/features/helm-charts/add-helm-repository-from-list-in-preferences.test.ts index 8bdfb4e507..e24e3e09f1 100644 --- a/packages/core/src/features/helm-charts/add-helm-repository-from-list-in-preferences.test.ts +++ b/packages/core/src/features/helm-charts/add-helm-repository-from-list-in-preferences.test.ts @@ -15,7 +15,7 @@ import type { HelmRepo } from "../../common/helm/helm-repo"; import requestPublicHelmRepositoriesInjectable from "./child-features/preferences/renderer/adding-of-public-helm-repository/public-helm-repositories/request-public-helm-repositories.injectable"; import showSuccessNotificationInjectable from "../../renderer/components/notifications/show-success-notification.injectable"; import showErrorNotificationInjectable from "../../renderer/components/notifications/show-error-notification.injectable"; -import type { AsyncResult } from "../../common/utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; describe("add helm repository from list in preferences", () => { let builder: ApplicationBuilder; @@ -23,7 +23,7 @@ describe("add helm repository from list in preferences", () => { let showErrorNotificationMock: jest.Mock; let rendered: RenderResult; let execFileMock: AsyncFnMock; - let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise>>; + let getActiveHelmRepositoriesMock: AsyncFnMock<() => AsyncResult>; let callForPublicHelmRepositoriesMock: AsyncFnMock<() => Promise>; beforeEach(async () => { diff --git a/packages/core/src/features/helm-charts/child-features/preferences/renderer/adding-of-public-helm-repository/public-helm-repositories/request-public-helm-repositories.global-override-for-injectable.ts b/packages/core/src/features/helm-charts/child-features/preferences/renderer/adding-of-public-helm-repository/public-helm-repositories/request-public-helm-repositories.global-override-for-injectable.ts index 0a1304ac2d..f4fff46cce 100644 --- a/packages/core/src/features/helm-charts/child-features/preferences/renderer/adding-of-public-helm-repository/public-helm-repositories/request-public-helm-repositories.global-override-for-injectable.ts +++ b/packages/core/src/features/helm-charts/child-features/preferences/renderer/adding-of-public-helm-repository/public-helm-repositories/request-public-helm-repositories.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverrideForFunction } from "../../../../../../../common/test-utils/get-global-override-for-function"; +import { getGlobalOverrideForFunction } from "@k8slens/test-utils"; import requestPublicHelmRepositoriesInjectable from "./request-public-helm-repositories.injectable"; export default getGlobalOverrideForFunction(requestPublicHelmRepositoriesInjectable); diff --git a/packages/core/src/features/helm-charts/installing-chart/installing-helm-chart-from-new-tab.test.ts b/packages/core/src/features/helm-charts/installing-chart/installing-helm-chart-from-new-tab.test.ts index b63d08f904..a21d44cb92 100644 --- a/packages/core/src/features/helm-charts/installing-chart/installing-helm-chart-from-new-tab.test.ts +++ b/packages/core/src/features/helm-charts/installing-chart/installing-helm-chart-from-new-tab.test.ts @@ -30,7 +30,7 @@ import type { RequestDetailedHelmRelease } from "../../../renderer/components/+h import requestDetailedHelmReleaseInjectable from "../../../renderer/components/+helm-releases/release-details/release-details-model/request-detailed-helm-release.injectable"; import type { RequestHelmReleases } from "../../../common/k8s-api/endpoints/helm-releases.api/request-releases.injectable"; import requestHelmReleasesInjectable from "../../../common/k8s-api/endpoints/helm-releases.api/request-releases.injectable"; -import { flushPromises } from "../../../common/test-utils/flush-promises"; +import { flushPromises } from "@k8slens/test-utils"; describe("installing helm chart from new tab", () => { let builder: ApplicationBuilder; diff --git a/packages/core/src/features/helm-charts/installing-chart/opening-dock-tab-for-installing-helm-chart.test.ts b/packages/core/src/features/helm-charts/installing-chart/opening-dock-tab-for-installing-helm-chart.test.ts index 3fd6a7deb7..e2fe7b9313 100644 --- a/packages/core/src/features/helm-charts/installing-chart/opening-dock-tab-for-installing-helm-chart.test.ts +++ b/packages/core/src/features/helm-charts/installing-chart/opening-dock-tab-for-installing-helm-chart.test.ts @@ -11,7 +11,7 @@ import { getApplicationBuilder } from "../../../renderer/components/test-utils/g import { HelmChart } from "../../../common/k8s-api/endpoints/helm-charts.api"; import getRandomInstallChartTabIdInjectable from "../../../renderer/components/dock/install-chart/get-random-install-chart-tab-id.injectable"; import requestCreateHelmReleaseInjectable from "../../../common/k8s-api/endpoints/helm-releases.api/request-create.injectable"; -import { flushPromises } from "../../../common/test-utils/flush-promises"; +import { flushPromises } from "@k8slens/test-utils"; import directoryForLensLocalStorageInjectable from "../../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable"; import hostedClusterIdInjectable from "../../../renderer/cluster-frame-context/hosted-cluster-id.injectable"; import dockStoreInjectable from "../../../renderer/components/dock/dock/store.injectable"; diff --git a/packages/core/src/features/helm-charts/listing-active-helm-repositories-in-preferences.test.ts b/packages/core/src/features/helm-charts/listing-active-helm-repositories-in-preferences.test.ts index 49a8d0c28e..fd2616817e 100644 --- a/packages/core/src/features/helm-charts/listing-active-helm-repositories-in-preferences.test.ts +++ b/packages/core/src/features/helm-charts/listing-active-helm-repositories-in-preferences.test.ts @@ -16,7 +16,7 @@ import loggerInjectable from "../../common/logger.injectable"; import type { Logger } from "../../common/logger"; import requestPublicHelmRepositoriesInjectable from "./child-features/preferences/renderer/adding-of-public-helm-repository/public-helm-repositories/request-public-helm-repositories.injectable"; import showErrorNotificationInjectable from "../../renderer/components/notifications/show-error-notification.injectable"; -import { noop } from "../../common/utils"; +import { noop } from "@k8slens/utilities"; describe("listing active helm repositories in preferences", () => { let builder: ApplicationBuilder; diff --git a/packages/core/src/features/helm-charts/remove-helm-repository-from-list-of-active-repository-in-preferences.test.ts b/packages/core/src/features/helm-charts/remove-helm-repository-from-list-of-active-repository-in-preferences.test.ts index 59743be36d..704dd8366f 100644 --- a/packages/core/src/features/helm-charts/remove-helm-repository-from-list-of-active-repository-in-preferences.test.ts +++ b/packages/core/src/features/helm-charts/remove-helm-repository-from-list-of-active-repository-in-preferences.test.ts @@ -14,12 +14,12 @@ import helmBinaryPathInjectable from "../../main/helm/helm-binary-path.injectabl import getActiveHelmRepositoriesInjectable from "../../main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable"; import type { HelmRepo } from "../../common/helm/helm-repo"; import requestPublicHelmRepositoriesInjectable from "./child-features/preferences/renderer/adding-of-public-helm-repository/public-helm-repositories/request-public-helm-repositories.injectable"; -import type { AsyncResult } from "../../common/utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; describe("remove helm repository from list of active repositories in preferences", () => { let builder: ApplicationBuilder; let rendered: RenderResult; - let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise>>; + let getActiveHelmRepositoriesMock: AsyncFnMock<() => AsyncResult>; let execFileMock: AsyncFnMock; beforeEach(async () => { diff --git a/packages/core/src/features/helm-charts/upgrade-chart/upgrade-chart-new-tab.test.ts b/packages/core/src/features/helm-charts/upgrade-chart/upgrade-chart-new-tab.test.ts index 7d46856fec..27f50d7f94 100644 --- a/packages/core/src/features/helm-charts/upgrade-chart/upgrade-chart-new-tab.test.ts +++ b/packages/core/src/features/helm-charts/upgrade-chart/upgrade-chart-new-tab.test.ts @@ -17,10 +17,10 @@ import type { RequestHelmReleaseConfiguration } from "../../../common/k8s-api/en import requestHelmReleaseConfigurationInjectable from "../../../common/k8s-api/endpoints/helm-releases.api/request-configuration.injectable"; import type { RequestHelmReleases } from "../../../common/k8s-api/endpoints/helm-releases.api/request-releases.injectable"; import requestHelmReleasesInjectable from "../../../common/k8s-api/endpoints/helm-releases.api/request-releases.injectable"; -import { advanceFakeTime, testUsingFakeTime } from "../../../common/test-utils/use-fake-time"; import dockStoreInjectable from "../../../renderer/components/dock/dock/store.injectable"; import type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; +import { testUsingFakeTime, advanceFakeTime } from "../../../test-utils/use-fake-time"; describe("New Upgrade Helm Chart Dock Tab", () => { let builder: ApplicationBuilder; diff --git a/packages/core/src/features/helm-releases/showing-details-for-helm-release.test.ts b/packages/core/src/features/helm-releases/showing-details-for-helm-release.test.ts index 88ec114eb0..3c90e6540b 100644 --- a/packages/core/src/features/helm-releases/showing-details-for-helm-release.test.ts +++ b/packages/core/src/features/helm-releases/showing-details-for-helm-release.test.ts @@ -15,7 +15,6 @@ import type { RequestHelmReleaseConfiguration } from "../../common/k8s-api/endpo import requestHelmReleaseConfigurationInjectable from "../../common/k8s-api/endpoints/helm-releases.api/request-configuration.injectable"; import type { RequestHelmReleaseUpdate } from "../../common/k8s-api/endpoints/helm-releases.api/request-update.injectable"; import requestHelmReleaseUpdateInjectable from "../../common/k8s-api/endpoints/helm-releases.api/request-update.injectable"; -import { testUsingFakeTime } from "../../common/test-utils/use-fake-time"; import type { RequestDetailedHelmRelease } from "../../renderer/components/+helm-releases/release-details/release-details-model/request-detailed-helm-release.injectable"; import requestDetailedHelmReleaseInjectable from "../../renderer/components/+helm-releases/release-details/release-details-model/request-detailed-helm-release.injectable"; import showSuccessNotificationInjectable from "../../renderer/components/notifications/show-success-notification.injectable"; @@ -30,6 +29,7 @@ import requestHelmChartVersionsInjectable from "../../common/k8s-api/endpoints/h import requestHelmChartReadmeInjectable from "../../common/k8s-api/endpoints/helm-charts.api/request-readme.injectable"; import requestHelmChartValuesInjectable from "../../common/k8s-api/endpoints/helm-charts.api/request-values.injectable"; import { HelmChart } from "../../common/k8s-api/endpoints/helm-charts.api"; +import { testUsingFakeTime } from "../../test-utils/use-fake-time"; describe("showing details for helm release", () => { let builder: ApplicationBuilder; diff --git a/packages/core/src/features/hotbar/store/main/init.injectable.ts b/packages/core/src/features/hotbar/store/main/init.injectable.ts index 5d0b5b0cf9..cb45c396ac 100644 --- a/packages/core/src/features/hotbar/store/main/init.injectable.ts +++ b/packages/core/src/features/hotbar/store/main/init.injectable.ts @@ -9,17 +9,14 @@ import setupSyncingOfGeneralCatalogEntitiesInjectable from "../../../../main/sta const initHotbarStoreInjectable = getInjectable({ id: "init-hotbar-store", - instantiate: (di) => { - const hotbarStore = di.inject(hotbarStoreInjectable); + instantiate: (di) => ({ + run: () => { + const hotbarStore = di.inject(hotbarStoreInjectable); - return { - id: "init-hotbar-store", - run: () => { - hotbarStore.load(); - }, - runAfter: di.inject(setupSyncingOfGeneralCatalogEntitiesInjectable), - }; - }, + hotbarStore.load(); + }, + runAfter: setupSyncingOfGeneralCatalogEntitiesInjectable, + }), injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/features/hotbar/store/renderer/init.injectable.ts b/packages/core/src/features/hotbar/store/renderer/init.injectable.ts index c17e3a4858..239807dfda 100644 --- a/packages/core/src/features/hotbar/store/renderer/init.injectable.ts +++ b/packages/core/src/features/hotbar/store/renderer/init.injectable.ts @@ -10,13 +10,12 @@ import initClusterStoreInjectable from "../../../cluster/store/renderer/init.inj const initHotbarStoreInjectable = getInjectable({ id: "init-hotbar-store", instantiate: (di) => ({ - id: "init-hotbar-store", run: () => { const hotbarStore = di.inject(hotbarStoreInjectable); hotbarStore.load(); }, - runAfter: di.inject(initClusterStoreInjectable), + runAfter: initClusterStoreInjectable, }), injectionToken: beforeFrameStartsSecondInjectionToken, }); 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 c0a43713b7..9953ddcbf9 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 @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import { reloadPageChannel } from "../common/channel"; import reloadPageChannelListenerInjectable from "./register-listener.injectable"; diff --git a/packages/core/src/features/preferences/common/preferences-catalog-entity.injectable.ts b/packages/core/src/features/preferences/common/preferences-catalog-entity.injectable.ts index e4f3a65a93..33eef535af 100644 --- a/packages/core/src/features/preferences/common/preferences-catalog-entity.injectable.ts +++ b/packages/core/src/features/preferences/common/preferences-catalog-entity.injectable.ts @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import { generalCatalogEntityInjectionToken } from "../../../common/catalog-entities/general-catalog-entities/general-catalog-entity-injection-token"; import { GeneralEntity } from "../../../common/catalog-entities"; -import { buildURL } from "../../../common/utils/buildUrl"; +import { buildURL } from "@k8slens/utilities"; import preferencesRouteInjectable from "./preferences-route.injectable"; const preferencesCatalogEntityInjectable = getInjectable({ diff --git a/packages/core/src/features/preferences/renderer/preference-items/kubernetes/kubeconfig-sync/kubeconfig-sync.tsx b/packages/core/src/features/preferences/renderer/preference-items/kubernetes/kubeconfig-sync/kubeconfig-sync.tsx index 94c326c9d3..77642f1082 100644 --- a/packages/core/src/features/preferences/renderer/preference-items/kubernetes/kubeconfig-sync/kubeconfig-sync.tsx +++ b/packages/core/src/features/preferences/renderer/preference-items/kubernetes/kubeconfig-sync/kubeconfig-sync.tsx @@ -8,7 +8,7 @@ import { disposeOnUnmount, observer } from "mobx-react"; import React from "react"; import { Notice } from "../../../../../../renderer/components/+extensions/notice"; import type { UserStore } from "../../../../../../common/user-store"; -import { iter, tuple } from "../../../../../../renderer/utils"; +import { iter, tuple } from "@k8slens/utilities"; import { SubTitle } from "../../../../../../renderer/components/layout/sub-title"; import { PathPicker } from "../../../../../../renderer/components/path-picker/path-picker"; import { Spinner } from "../../../../../../renderer/components/spinner"; diff --git a/packages/core/src/features/preferences/renderer/preference-items/terminal/terminal-shell-path/default-shell/default-shell.global-override-for-injectable.ts b/packages/core/src/features/preferences/renderer/preference-items/terminal/terminal-shell-path/default-shell/default-shell.global-override-for-injectable.ts index 55a8d44fc2..3dfa798270 100644 --- a/packages/core/src/features/preferences/renderer/preference-items/terminal/terminal-shell-path/default-shell/default-shell.global-override-for-injectable.ts +++ b/packages/core/src/features/preferences/renderer/preference-items/terminal/terminal-shell-path/default-shell/default-shell.global-override-for-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 { getGlobalOverride } from "../../../../../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import defaultShellInjectable from "./default-shell.injectable"; export default getGlobalOverride( diff --git a/packages/core/src/features/preferences/renderer/removable-item/removable-item.tsx b/packages/core/src/features/preferences/renderer/removable-item/removable-item.tsx index ee04f9d76c..4371c9c758 100644 --- a/packages/core/src/features/preferences/renderer/removable-item/removable-item.tsx +++ b/packages/core/src/features/preferences/renderer/removable-item/removable-item.tsx @@ -7,7 +7,7 @@ import styles from "./removable-item.module.scss"; import type { DOMAttributes } from "react"; import React from "react"; -import { cssNames } from "../../../../renderer/utils"; +import { cssNames } from "@k8slens/utilities"; import { Icon } from "../../../../renderer/components/icon"; export interface RemovableItemProps extends DOMAttributes{ diff --git a/packages/core/src/features/quitting-and-restarting-the-app/quitting-the-app-using-application-menu.test.ts b/packages/core/src/features/quitting-and-restarting-the-app/quitting-the-app-using-application-menu.test.ts index a7a6e4ae60..bf34068f55 100644 --- a/packages/core/src/features/quitting-and-restarting-the-app/quitting-the-app-using-application-menu.test.ts +++ b/packages/core/src/features/quitting-and-restarting-the-app/quitting-the-app-using-application-menu.test.ts @@ -9,7 +9,7 @@ import type { ClusterManager } from "../../main/cluster/manager"; import exitAppInjectable from "../../main/electron-app/features/exit-app.injectable"; import clusterManagerInjectable from "../../main/cluster/manager.injectable"; import stopServicesAndExitAppInjectable from "../../main/stop-services-and-exit-app.injectable"; -import { advanceFakeTime, testUsingFakeTime } from "../../common/test-utils/use-fake-time"; +import { testUsingFakeTime, advanceFakeTime } from "../../test-utils/use-fake-time"; describe("quitting the app using application menu", () => { describe("given application has started", () => { diff --git a/packages/core/src/features/resolve-system-proxy/resolve-system-proxy.test.ts b/packages/core/src/features/resolve-system-proxy/resolve-system-proxy.test.ts index d2e021ef98..80f62fbd03 100644 --- a/packages/core/src/features/resolve-system-proxy/resolve-system-proxy.test.ts +++ b/packages/core/src/features/resolve-system-proxy/resolve-system-proxy.test.ts @@ -9,7 +9,7 @@ import { getApplicationBuilder } from "../../renderer/components/test-utils/get- import type { ResolveSystemProxy } from "../../common/utils/resolve-system-proxy/resolve-system-proxy-injection-token"; import { resolveSystemProxyInjectionToken } from "../../common/utils/resolve-system-proxy/resolve-system-proxy-injection-token"; import resolveSystemProxyFromElectronInjectable from "../../main/utils/resolve-system-proxy/resolve-system-proxy-from-electron.injectable"; -import { getPromiseStatus } from "../../common/test-utils/get-promise-status"; +import { getPromiseStatus } from "@k8slens/test-utils"; describe("resolve-system-proxy", () => { let builder: ApplicationBuilder; diff --git a/packages/core/src/features/shell-sync/main/compute-shell-environment.global-override-for-injectable.ts b/packages/core/src/features/shell-sync/main/compute-shell-environment.global-override-for-injectable.ts index b4c9051729..9e19022f87 100644 --- a/packages/core/src/features/shell-sync/main/compute-shell-environment.global-override-for-injectable.ts +++ b/packages/core/src/features/shell-sync/main/compute-shell-environment.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import computeShellEnvironmentInjectable from "./compute-shell-environment.injectable"; export default getGlobalOverride(computeShellEnvironmentInjectable, () => async () => ({ diff --git a/packages/core/src/features/shell-sync/main/compute-shell-environment.injectable.ts b/packages/core/src/features/shell-sync/main/compute-shell-environment.injectable.ts index 88fcd0de84..36aa385d01 100644 --- a/packages/core/src/features/shell-sync/main/compute-shell-environment.injectable.ts +++ b/packages/core/src/features/shell-sync/main/compute-shell-environment.injectable.ts @@ -3,13 +3,13 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { AsyncResult } from "../../../common/utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; import { getInjectable } from "@ogre-tools/injectable"; import isWindowsInjectable from "../../../common/vars/is-windows.injectable"; import computeUnixShellEnvironmentInjectable from "./compute-unix-shell-environment.injectable"; export type EnvironmentVariables = Partial>; -export type ComputeShellEnvironment = (shell: string) => Promise>; +export type ComputeShellEnvironment = (shell: string) => AsyncResult; const computeShellEnvironmentInjectable = getInjectable({ id: "compute-shell-environment", diff --git a/packages/core/src/features/shell-sync/main/compute-unix-shell-environment.global-override-for-injectable.ts b/packages/core/src/features/shell-sync/main/compute-unix-shell-environment.global-override-for-injectable.ts index aac810aa62..b923d35d5c 100644 --- a/packages/core/src/features/shell-sync/main/compute-unix-shell-environment.global-override-for-injectable.ts +++ b/packages/core/src/features/shell-sync/main/compute-unix-shell-environment.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import computeUnixShellEnvironmentInjectable from "./compute-unix-shell-environment.injectable"; export default getGlobalOverride(computeUnixShellEnvironmentInjectable, () => async () => { diff --git a/packages/core/src/features/shell-sync/main/compute-unix-shell-environment.injectable.ts b/packages/core/src/features/shell-sync/main/compute-unix-shell-environment.injectable.ts index fa6de94b57..7fd78f9f56 100644 --- a/packages/core/src/features/shell-sync/main/compute-unix-shell-environment.injectable.ts +++ b/packages/core/src/features/shell-sync/main/compute-unix-shell-environment.injectable.ts @@ -10,14 +10,14 @@ import randomUUIDInjectable from "../../../main/crypto/random-uuid.injectable"; import loggerInjectable from "../../../common/logger.injectable"; import processExecPathInjectable from "./execPath.injectable"; import processEnvInjectable from "./env.injectable"; -import { object } from "../../../common/utils"; -import type { AsyncResult } from "../../../common/utils/async-result"; +import { object } from "@k8slens/utilities"; +import type { AsyncResult } from "@k8slens/utilities"; export interface UnixShellEnvOptions { signal: AbortSignal; } -export type ComputeUnixShellEnvironment = (shell: string, opts: UnixShellEnvOptions) => Promise>; +export type ComputeUnixShellEnvironment = (shell: string, opts: UnixShellEnvOptions) => AsyncResult; /** * @param src The object containing the current environment variables @@ -36,9 +36,9 @@ const getResetProcessEnv = (src: Partial>, overrides: Par ...overrides, }, resetEnvPairs: (target) => { - for (const [name, orginalValue] of originals) { - if (typeof orginalValue === "string") { - target[name] = orginalValue; + for (const [name, originalValue] of originals) { + if (typeof originalValue === "string") { + target[name] = originalValue; } else { delete target[name]; } @@ -61,7 +61,7 @@ const computeUnixShellEnvironmentInjectable = getInjectable({ const processExecPath = di.inject(processExecPathInjectable); const processEnv = di.inject(processEnvInjectable); - const getShellSpecifices = (shellName: string) => { + const getShellSpecifics = (shellName: string) => { const mark = randomUUID().replace(/-/g, ""); const regex = new RegExp(`${mark}(\\{.*\\})${mark}`); @@ -100,7 +100,7 @@ const computeUnixShellEnvironmentInjectable = getInjectable({ TERM: "screen-256color-bce", // required for fish }); const shellName = getBasenameOfPath(shellPath); - const { command, shellArgs, regex } = getShellSpecifices(shellName); + const { command, shellArgs, regex } = getShellSpecifics(shellName); logger.info(`[UNIX-SHELL-ENV]: running against ${shellPath}`, { command, shellArgs }); @@ -143,7 +143,7 @@ const computeUnixShellEnvironmentInjectable = getInjectable({ if (code || signal) { return resolve({ callWasSuccessful: false, - error: `Shell did not exit sucessfully: ${getErrorContext({ code, signal })}`, + error: `Shell did not exit successfully: ${getErrorContext({ code, signal })}`, }); } @@ -157,7 +157,7 @@ const computeUnixShellEnvironmentInjectable = getInjectable({ if (!matchedOutput) { return resolve({ callWasSuccessful: false, - error: "Something has blocked the shell from producing the environement variables", + error: "Something has blocked the shell from producing the environment variables", }); } diff --git a/packages/core/src/features/shell-sync/main/compute-unix-shell-environment.test.ts b/packages/core/src/features/shell-sync/main/compute-unix-shell-environment.test.ts index a56473b474..731dc01509 100644 --- a/packages/core/src/features/shell-sync/main/compute-unix-shell-environment.test.ts +++ b/packages/core/src/features/shell-sync/main/compute-unix-shell-environment.test.ts @@ -6,7 +6,7 @@ import type { DiContainer } from "@ogre-tools/injectable"; import type { ChildProcessWithoutNullStreams } from "child_process"; import EventEmitter from "events"; -import { flushPromises } from "../../../common/test-utils/flush-promises"; +import { flushPromises } from "@k8slens/test-utils"; import type { Spawn } from "../../../main/child-process/spawn.injectable"; import spawnInjectable from "../../../main/child-process/spawn.injectable"; import randomUUIDInjectable from "../../../main/crypto/random-uuid.injectable"; @@ -142,7 +142,7 @@ describe("computeUnixShellEnvironment technical tests", () => { it("should resolve with a failed call", async () => { await expect(unixShellEnv).resolves.toEqual({ callWasSuccessful: false, - error: 'Shell did not exit sucessfully: {\n "code": 1,\n "signal": null,\n "stdout": "",\n "stderr": ""\n}', + error: 'Shell did not exit successfully: {\n "code": 1,\n "signal": null,\n "stdout": "",\n "stderr": ""\n}', }); }); }); @@ -155,7 +155,7 @@ describe("computeUnixShellEnvironment technical tests", () => { it("should resolve with a failed call", async () => { await expect(unixShellEnv).resolves.toEqual({ callWasSuccessful: false, - error: 'Shell did not exit sucessfully: {\n "code": 0,\n "signal": "SIGKILL",\n "stdout": "",\n "stderr": ""\n}', + error: 'Shell did not exit successfully: {\n "code": 0,\n "signal": "SIGKILL",\n "stdout": "",\n "stderr": ""\n}', }); }); }); @@ -248,7 +248,7 @@ describe("computeUnixShellEnvironment technical tests", () => { it("should resolve with a failed call", async () => { await expect(unixShellEnv).resolves.toEqual({ callWasSuccessful: false, - error: 'Shell did not exit sucessfully: {\n "code": 1,\n "signal": null,\n "stdout": "",\n "stderr": ""\n}', + error: 'Shell did not exit successfully: {\n "code": 1,\n "signal": null,\n "stdout": "",\n "stderr": ""\n}', }); }); }); @@ -261,7 +261,7 @@ describe("computeUnixShellEnvironment technical tests", () => { it("should resolve with a failed call", async () => { await expect(unixShellEnv).resolves.toEqual({ callWasSuccessful: false, - error: 'Shell did not exit sucessfully: {\n "code": 0,\n "signal": "SIGKILL",\n "stdout": "",\n "stderr": ""\n}', + error: 'Shell did not exit successfully: {\n "code": 0,\n "signal": "SIGKILL",\n "stdout": "",\n "stderr": ""\n}', }); }); }); @@ -353,7 +353,7 @@ describe("computeUnixShellEnvironment technical tests", () => { it("should resolve with a failed call", async () => { await expect(unixShellEnv).resolves.toEqual({ callWasSuccessful: false, - error: 'Shell did not exit sucessfully: {\n "code": 1,\n "signal": null,\n "stdout": "",\n "stderr": ""\n}', + error: 'Shell did not exit successfully: {\n "code": 1,\n "signal": null,\n "stdout": "",\n "stderr": ""\n}', }); }); }); @@ -366,7 +366,7 @@ describe("computeUnixShellEnvironment technical tests", () => { it("should resolve with a failed call", async () => { await expect(unixShellEnv).resolves.toEqual({ callWasSuccessful: false, - error: 'Shell did not exit sucessfully: {\n "code": 0,\n "signal": "SIGKILL",\n "stdout": "",\n "stderr": ""\n}', + error: 'Shell did not exit successfully: {\n "code": 0,\n "signal": "SIGKILL",\n "stdout": "",\n "stderr": ""\n}', }); }); }); @@ -457,7 +457,7 @@ describe("computeUnixShellEnvironment technical tests", () => { it("should resolve with a failed call", async () => { await expect(unixShellEnv).resolves.toEqual({ callWasSuccessful: false, - error: 'Shell did not exit sucessfully: {\n "code": 1,\n "signal": null,\n "stdout": "",\n "stderr": ""\n}', + error: 'Shell did not exit successfully: {\n "code": 1,\n "signal": null,\n "stdout": "",\n "stderr": ""\n}', }); }); }); @@ -470,7 +470,7 @@ describe("computeUnixShellEnvironment technical tests", () => { it("should resolve with a failed call", async () => { await expect(unixShellEnv).resolves.toEqual({ callWasSuccessful: false, - error: 'Shell did not exit sucessfully: {\n "code": 0,\n "signal": "SIGKILL",\n "stdout": "",\n "stderr": ""\n}', + error: 'Shell did not exit successfully: {\n "code": 0,\n "signal": "SIGKILL",\n "stdout": "",\n "stderr": ""\n}', }); }); }); diff --git a/packages/core/src/features/shell-sync/main/setup-shell.injectable.ts b/packages/core/src/features/shell-sync/main/setup-shell.injectable.ts index 200356bb3d..3a763b7426 100644 --- a/packages/core/src/features/shell-sync/main/setup-shell.injectable.ts +++ b/packages/core/src/features/shell-sync/main/setup-shell.injectable.ts @@ -5,67 +5,66 @@ import { getInjectable } from "@ogre-tools/injectable"; import loggerInjectable from "../../../common/logger.injectable"; import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; -import { unionPATHs } from "../../../common/utils/union-env-path"; import isSnapPackageInjectable from "../../../common/vars/is-snap-package.injectable"; import electronAppInjectable from "../../../main/electron-app/electron-app.injectable"; import computeShellEnvironmentInjectable from "./compute-shell-environment.injectable"; import userShellSettingInjectable from "../../../common/user-store/shell-setting.injectable"; import emitShellSyncFailedInjectable from "./emit-failure.injectable"; +import { unionPATHs } from "@k8slens/utilities"; const setupShellInjectable = getInjectable({ id: "setup-shell", - instantiate: (di) => { - const logger = di.inject(loggerInjectable); - const isSnapPackage = di.inject(isSnapPackageInjectable); - const electronApp = di.inject(electronAppInjectable); - const resolvedUserShellSetting = di.inject(userShellSettingInjectable); - const computeShellEnvironment = di.inject(computeShellEnvironmentInjectable); - const emitShellSyncFailed = di.inject(emitShellSyncFailedInjectable); + instantiate: (di) => ({ + run: async () => { + const logger = di.inject(loggerInjectable); + const isSnapPackage = di.inject(isSnapPackageInjectable); + const electronApp = di.inject(electronAppInjectable); + const resolvedUserShellSetting = di.inject(userShellSettingInjectable); + const computeShellEnvironment = di.inject(computeShellEnvironmentInjectable); + const emitShellSyncFailed = di.inject(emitShellSyncFailedInjectable); - return { - id: "setup-shell", - run: async (): Promise => { - logger.info("🐚 Syncing shell environment"); + logger.info("🐚 Syncing shell environment"); - const result = await computeShellEnvironment(resolvedUserShellSetting.get()); + const result = await computeShellEnvironment(resolvedUserShellSetting.get()); - if (!result.callWasSuccessful) { - logger.error(`[SHELL-SYNC]: ${result.error}`); - emitShellSyncFailed(result.error); + if (!result.callWasSuccessful) { + logger.error(`[SHELL-SYNC]: ${result.error}`); + emitShellSyncFailed(result.error); - return; - } + return; + } - const env = result.response; + const env = result.response; - if (!env) { - return void logger.debug("[SHELL-SYNC]: nothing to do, env not special in shells"); - } + if (!env) { + logger.debug("[SHELL-SYNC]: nothing to do, env not special in shells"); - if (!env.LANG) { - // the LANG env var expects an underscore instead of electron's dash - env.LANG = `${electronApp.getLocale().replace("-", "_")}.UTF-8`; - } else if (!env.LANG.endsWith(".UTF-8")) { - env.LANG += ".UTF-8"; - } + return; + } - if (!isSnapPackage) { - // Prefer the synced PATH over the initial one - process.env.PATH = unionPATHs(env.PATH ?? "", process.env.PATH ?? ""); - } + if (!env.LANG) { + // the LANG env var expects an underscore instead of electron's dash + env.LANG = `${electronApp.getLocale().replace("-", "_")}.UTF-8`; + } else if (!env.LANG.endsWith(".UTF-8")) { + env.LANG += ".UTF-8"; + } - // The spread operator allows joining of objects. The precedence is last to first. - process.env = { - ...env, - ...process.env, - }; + if (!isSnapPackage) { + // Prefer the synced PATH over the initial one + process.env.PATH = unionPATHs(env.PATH ?? "", process.env.PATH ?? ""); + } - logger.info(`[SHELL-SYNC]: Synced shell env`); - logger.debug(`[SHELL-SYNC]: updated env`, process.env); - }, - }; - }, + // The spread operator allows joining of objects. The precedence is last to first. + process.env = { + ...env, + ...process.env, + }; + + logger.info(`[SHELL-SYNC]: Synced shell env`); + logger.debug(`[SHELL-SYNC]: updated env`, process.env); + }, + }), injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/features/telemetry/renderer/telemetry-decorator.global-override-for-injectable.ts b/packages/core/src/features/telemetry/renderer/telemetry-decorator.global-override-for-injectable.ts index e163a53862..a1d707fb11 100644 --- a/packages/core/src/features/telemetry/renderer/telemetry-decorator.global-override-for-injectable.ts +++ b/packages/core/src/features/telemetry/renderer/telemetry-decorator.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { identity } from "lodash/fp"; -import { getGlobalOverride } from "../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import telemetryDecoratorInjectable from "./telemetry-decorator.injectable"; export default getGlobalOverride(telemetryDecoratorInjectable, () => ({ diff --git a/packages/core/src/features/terminal/renderer/fonts/load-font.global-override-for-injectable.ts b/packages/core/src/features/terminal/renderer/fonts/load-font.global-override-for-injectable.ts index 0d1b23bfde..b32ca32cb3 100644 --- a/packages/core/src/features/terminal/renderer/fonts/load-font.global-override-for-injectable.ts +++ b/packages/core/src/features/terminal/renderer/fonts/load-font.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import loadTerminalFontInjectable from "./load-font.injectable"; export default getGlobalOverride(loadTerminalFontInjectable, () => async () => {}); diff --git a/packages/core/src/features/terminal/renderer/fonts/preload-fonts.injectable.ts b/packages/core/src/features/terminal/renderer/fonts/preload-fonts.injectable.ts index 64c40247b7..afb0c969fd 100644 --- a/packages/core/src/features/terminal/renderer/fonts/preload-fonts.injectable.ts +++ b/packages/core/src/features/terminal/renderer/fonts/preload-fonts.injectable.ts @@ -10,7 +10,6 @@ import loadTerminalFontInjectable from "./load-font.injectable"; const preloadTerminalFontsInjectable = getInjectable({ id: "preload-terminal-fonts", instantiate: (di) => ({ - id: "preload-terminal-fonts", run: async () => { const terminalFonts = di.inject(terminalFontsInjectable); const loadTerminalFont = di.inject(loadTerminalFontInjectable); diff --git a/packages/core/src/features/theme/system-type/main/setup-update-emitter.injectable.ts b/packages/core/src/features/theme/system-type/main/setup-update-emitter.injectable.ts index 5416fda208..6f342f6480 100644 --- a/packages/core/src/features/theme/system-type/main/setup-update-emitter.injectable.ts +++ b/packages/core/src/features/theme/system-type/main/setup-update-emitter.injectable.ts @@ -10,23 +10,20 @@ import emitSystemThemeTypeUpdateInjectable from "./emit-update.injectable"; const setupSystemThemeTypeUpdaterEmitterInjectable = getInjectable({ id: "setup-system-theme-type-updater-emitter", - instantiate: (di) => { - const operatingSystemTheme = di.inject(operatingSystemThemeInjectable); - const emitSystemThemeTypeUpdate = di.inject(emitSystemThemeTypeUpdateInjectable); + instantiate: (di) => ({ + run: () => { + const operatingSystemTheme = di.inject(operatingSystemThemeInjectable); + const emitSystemThemeTypeUpdate = di.inject(emitSystemThemeTypeUpdateInjectable); - return { - id: "setup-system-theme-type-updater-emitter", - run: () => { - reaction( - () => operatingSystemTheme.get(), - emitSystemThemeTypeUpdate, - { - fireImmediately: true, - }, - ); - }, - }; - }, + reaction( + () => operatingSystemTheme.get(), + emitSystemThemeTypeUpdate, + { + fireImmediately: true, + }, + ); + }, + }), injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/features/theme/system-type/renderer/initialize.injectable.ts b/packages/core/src/features/theme/system-type/renderer/initialize.injectable.ts index 849c8328b2..2e09f8e9d1 100644 --- a/packages/core/src/features/theme/system-type/renderer/initialize.injectable.ts +++ b/packages/core/src/features/theme/system-type/renderer/initialize.injectable.ts @@ -11,14 +11,13 @@ import requestInitialSystemThemeTypeInjectable from "./request-initial.injectabl const initializeSystemThemeTypeInjectable = getInjectable({ id: "initialize-system-theme-type", instantiate: (di) => ({ - id: "initialize-system-theme-type", run: async () => { const systemThemeConfiguration = di.inject(systemThemeConfigurationInjectable); const requestInitialSystemThemeType = di.inject(requestInitialSystemThemeTypeInjectable); systemThemeConfiguration.set(await requestInitialSystemThemeType()); }, - runAfter: di.inject(initUserStoreInjectable), + runAfter: initUserStoreInjectable, }), injectionToken: beforeFrameStartsSecondInjectionToken, }); diff --git a/packages/core/src/main/__test__/cluster.test.ts b/packages/core/src/main/__test__/cluster.test.ts index 721188d059..bb495af847 100644 --- a/packages/core/src/main/__test__/cluster.test.ts +++ b/packages/core/src/main/__test__/cluster.test.ts @@ -2,35 +2,29 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import broadcastMessageInjectable from "../../common/ipc/broadcast-message.injectable"; -import type { Cluster } from "../../common/cluster/cluster"; +import { Cluster } from "../../common/cluster/cluster"; import { Kubectl } from "../kubectl/kubectl"; import { getDiForUnitTesting } from "../getDiForUnitTesting"; -import type { CreateCluster } from "../../common/cluster/create-cluster-injection-token"; -import { createClusterInjectionToken } from "../../common/cluster/create-cluster-injection-token"; -import authorizationReviewInjectable from "../../common/cluster/authorization-review.injectable"; +import createAuthorizationReviewInjectable from "../../common/cluster/authorization-review.injectable"; import requestNamespaceListPermissionsForInjectable from "../../common/cluster/request-namespace-list-permissions.injectable"; -import listNamespacesInjectable from "../../common/cluster/list-namespaces.injectable"; -import createContextHandlerInjectable from "../context-handler/create-context-handler.injectable"; -import type { ClusterContextHandler } from "../context-handler/context-handler"; -import { parse } from "url"; +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"; import kubectlBinaryNameInjectable from "../kubectl/binary-name.injectable"; import kubectlDownloadingNormalizedArchInjectable from "../kubectl/normalized-arch.injectable"; -import pathExistsSyncInjectable from "../../common/fs/path-exists-sync.injectable"; -import pathExistsInjectable from "../../common/fs/path-exists.injectable"; -import readJsonSyncInjectable from "../../common/fs/read-json-sync.injectable"; -import writeJsonSyncInjectable from "../../common/fs/write-json-sync.injectable"; +import type { ClusterConnection } from "../cluster/cluster-connection.injectable"; +import clusterConnectionInjectable from "../cluster/cluster-connection.injectable"; +import kubeconfigManagerInjectable from "../kubeconfig-manager/kubeconfig-manager.injectable"; +import type { KubeconfigManager } from "../kubeconfig-manager/kubeconfig-manager"; +import broadcastConnectionUpdateInjectable from "../cluster/broadcast-connection-update.injectable"; describe("create clusters", () => { let cluster: Cluster; - let createCluster: CreateCluster; + let clusterConnection: ClusterConnection; beforeEach(() => { - jest.clearAllMocks(); - const di = getDiForUnitTesting(); const clusterServerUrl = "https://192.168.64.3:8443"; @@ -39,65 +33,51 @@ describe("create clusters", () => { di.override(kubectlBinaryNameInjectable, () => "kubectl"); di.override(kubectlDownloadingNormalizedArchInjectable, () => "amd64"); di.override(normalizedPlatformInjectable, () => "darwin"); - di.override(broadcastMessageInjectable, () => async () => {}); - di.override(authorizationReviewInjectable, () => () => () => Promise.resolve(true)); + di.override(broadcastConnectionUpdateInjectable, () => async () => {}); + di.override(createAuthorizationReviewInjectable, () => () => () => Promise.resolve(true)); di.override(requestNamespaceListPermissionsForInjectable, () => () => async () => () => true); - di.override(listNamespacesInjectable, () => () => () => Promise.resolve([ "default" ])); - di.override(createContextHandlerInjectable, () => (cluster) => ({ - restartServer: jest.fn(), - stopServer: jest.fn(), - clusterUrl: parse(cluster.apiUrl), - getApiTarget: jest.fn(), + di.override(createListNamespacesInjectable, () => () => () => Promise.resolve([ "default" ])); + di.override(prometheusHandlerInjectable, () => ({ getPrometheusDetails: jest.fn(), - resolveAuthProxyCa: jest.fn(), - resolveAuthProxyUrl: jest.fn(), setupPrometheus: jest.fn(), - ensureServer: jest.fn(), - } as ClusterContextHandler)); - di.override(pathExistsInjectable, () => () => { throw new Error("tried call pathExists without override"); }); - di.override(pathExistsSyncInjectable, () => () => { throw new Error("tried call pathExistsSync without override"); }); - di.override(readJsonSyncInjectable, () => () => { throw new Error("tried call readJsonSync without override"); }); - di.override(writeJsonSyncInjectable, () => () => { throw new Error("tried call writeJsonSync without override"); }); + })); - createCluster = di.inject(createClusterInjectionToken); + di.override(kubeconfigManagerInjectable, () => ({ + ensurePath: async () => "/some-proxy-kubeconfig-file", + } as Partial as KubeconfigManager)); jest.spyOn(Kubectl.prototype, "ensureKubectl").mockReturnValue(Promise.resolve(true)); - cluster = createCluster({ + cluster = new Cluster({ id: "foo", contextName: "minikube", kubeConfigPath: "minikube-config.yml", }, { clusterServerUrl, }); - }); - afterEach(() => { - cluster.disconnect(); + clusterConnection = di.inject(clusterConnectionInjectable, cluster); }); it("should be able to create a cluster from a cluster model and apiURL should be decoded", () => { - expect(cluster.apiUrl).toBe("https://192.168.64.3:8443"); + expect(cluster.apiUrl.get()).toBe("https://192.168.64.3:8443"); }); it("reconnect should not throw if contextHandler is missing", () => { - expect(() => cluster.reconnect()).not.toThrowError(); + expect(() => clusterConnection.reconnect()).not.toThrowError(); }); it("disconnect should not throw if contextHandler is missing", () => { - expect(() => cluster.disconnect()).not.toThrowError(); + expect(() => clusterConnection.disconnect()).not.toThrowError(); }); it("activating cluster should try to connect to cluster and do a refresh", async () => { - jest.spyOn(cluster, "reconnect"); - jest.spyOn(cluster, "refreshConnectionStatus"); + jest.spyOn(clusterConnection, "reconnect").mockImplementation(async () => {}); + jest.spyOn(clusterConnection, "refreshConnectionStatus").mockImplementation(async () => {}); - await cluster.activate(); + await clusterConnection.activate(); - expect(cluster.reconnect).toBeCalled(); - expect(cluster.refreshConnectionStatus).toBeCalled(); - - cluster.disconnect(); - jest.resetAllMocks(); + expect(clusterConnection.reconnect).toBeCalled(); + expect(clusterConnection.refreshConnectionStatus).toBeCalled(); }); }); diff --git a/packages/core/src/main/__test__/context-handler.test.ts b/packages/core/src/main/__test__/context-handler.test.ts index e6ac1cce8c..61bd12398d 100644 --- a/packages/core/src/main/__test__/context-handler.test.ts +++ b/packages/core/src/main/__test__/context-handler.test.ts @@ -3,16 +3,20 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { ClusterContextHandler } from "../context-handler/context-handler"; import { getDiForUnitTesting } from "../getDiForUnitTesting"; -import createContextHandlerInjectable from "../context-handler/create-context-handler.injectable"; -import type { Cluster } from "../../common/cluster/cluster"; +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, @@ -41,22 +45,30 @@ const createTestPrometheusProvider = (kind: string, alwaysFail: ServiceResult): }, }); -const clusterStub = { - getProxyKubeconfig: () => ({ - makeApiClient: (): void => undefined, - }), - apiUrl: "http://localhost:81", -} as unknown as Cluster; - describe("ContextHandler", () => { - let createContextHandler: (cluster: Cluster) => ClusterContextHandler; let di: DiContainer; + let cluster: Cluster; beforeEach(() => { di = getDiForUnitTesting(); - di.override(createKubeAuthProxyInjectable, () => ({} as any)); - createContextHandler = di.inject(createContextHandlerInjectable); + 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", () => { @@ -76,7 +88,7 @@ describe("ContextHandler", () => { } }); - expect(() => createContextHandler(clusterStub).getPrometheusDetails()).rejects.toThrowError(); + expect(() => di.inject(prometheusHandlerInjectable, cluster).getPrometheusDetails()).rejects.toThrowError(); }); it.each([ @@ -107,7 +119,7 @@ describe("ContextHandler", () => { } }); - const details = await createContextHandler(clusterStub).getPrometheusDetails(); + const details = await di.inject(prometheusHandlerInjectable, cluster).getPrometheusDetails(); expect(details.provider.kind === `id_failure_${failures}`); }); @@ -140,7 +152,7 @@ describe("ContextHandler", () => { } }); - const details = await createContextHandler(clusterStub).getPrometheusDetails(); + const details = await di.inject(prometheusHandlerInjectable, cluster).getPrometheusDetails(); expect(details.provider.kind === "id_failure_0"); }); @@ -183,7 +195,7 @@ describe("ContextHandler", () => { } }); - const details = await createContextHandler(clusterStub).getPrometheusDetails(); + 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 5864259712..8fa8a175a5 100644 --- a/packages/core/src/main/__test__/kube-auth-proxy.test.ts +++ b/packages/core/src/main/__test__/kube-auth-proxy.test.ts @@ -4,7 +4,7 @@ */ import waitUntilPortIsUsedInjectable from "../kube-auth-proxy/wait-until-port-is-used/wait-until-port-is-used.injectable"; -import type { Cluster } from "../../common/cluster/cluster"; +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"; @@ -14,8 +14,6 @@ import type { Readable } from "stream"; import { EventEmitter } from "stream"; import { getDiForUnitTesting } from "../getDiForUnitTesting"; import createKubeAuthProxyInjectable from "../kube-auth-proxy/create-kube-auth-proxy.injectable"; -import type { CreateCluster } from "../../common/cluster/create-cluster-injection-token"; -import { createClusterInjectionToken } from "../../common/cluster/create-cluster-injection-token"; import spawnInjectable from "../child-process/spawn.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"; @@ -31,7 +29,6 @@ import getBasenameOfPathInjectable from "../../common/path/get-basename.injectab const clusterServerUrl = "https://192.168.64.3:8443"; describe("kube auth proxy tests", () => { - let createCluster: CreateCluster; let createKubeAuthProxy: (cluster: Cluster, environmentVariables: NodeJS.ProcessEnv) => KubeAuthProxy; let spawnMock: jest.Mock; let waitUntilPortIsUsedMock: jest.Mock; @@ -86,12 +83,11 @@ describe("kube auth proxy tests", () => { di.override(kubectlDownloadingNormalizedArchInjectable, () => "amd64"); di.override(normalizedPlatformInjectable, () => "darwin"); - createCluster = di.inject(createClusterInjectionToken); createKubeAuthProxy = di.inject(createKubeAuthProxyInjectable); }); it("calling exit multiple times shouldn't throw", async () => { - const cluster = createCluster({ + const cluster = new Cluster({ id: "foobar", kubeConfigPath: "minikube-config.yml", contextName: "minikube", @@ -114,8 +110,11 @@ describe("kube auth proxy tests", () => { beforeEach(async () => { mockedCP = mockDeep(); listeners = new EventEmitter(); - const stderr = mockedCP.stderr = mock(); - const stdout = mockedCP.stdout = mock(); + const stderr = mock(); + const stdout = mock(); + + mockedCP.stderr = stderr as any; + mockedCP.stdout = stdout as any; jest.spyOn(Kubectl.prototype, "checkBinary").mockReturnValueOnce(Promise.resolve(true)); jest.spyOn(Kubectl.prototype, "ensureKubectl").mockReturnValueOnce(Promise.resolve(false)); @@ -124,32 +123,32 @@ describe("kube auth proxy tests", () => { return mockedCP; }); - mockedCP.stderr.on.mockImplementation((event: string | symbol, listener: (message: any, sendHandle: any) => void): Readable => { + stderr.on.mockImplementation((event: string | symbol, listener: (message: any, sendHandle: any) => void): Readable => { listeners.on(`stderr/${String(event)}`, listener); return stderr; }); - mockedCP.stderr.off.mockImplementation((event: string | symbol, listener: (message: any, sendHandle: any) => void): Readable => { + stderr.off.mockImplementation((event: string | symbol, listener: (message: any, sendHandle: any) => void): Readable => { listeners.off(`stderr/${String(event)}`, listener); return stderr; }); - mockedCP.stderr.removeListener.mockImplementation((event: string | symbol, listener: (message: any, sendHandle: any) => void): Readable => { + stderr.removeListener.mockImplementation((event: string | symbol, listener: (message: any, sendHandle: any) => void): Readable => { listeners.off(`stderr/${String(event)}`, listener); return stderr; }); - mockedCP.stderr.once.mockImplementation((event: string | symbol, listener: (message: any, sendHandle: any) => void): Readable => { + stderr.once.mockImplementation((event: string | symbol, listener: (message: any, sendHandle: any) => void): Readable => { listeners.once(`stderr/${String(event)}`, listener); return stderr; }); - mockedCP.stderr.removeAllListeners.mockImplementation((event?: string | symbol): Readable => { + stderr.removeAllListeners.mockImplementation((event?: string | symbol): Readable => { listeners.removeAllListeners(event ?? `stderr/${String(event)}`); return stderr; }); - mockedCP.stdout.on.mockImplementation((event: string | symbol, listener: (message: any, sendHandle: any) => void): Readable => { + stdout.on.mockImplementation((event: string | symbol, listener: (message: any, sendHandle: any) => void): Readable => { listeners.on(`stdout/${String(event)}`, listener); if (event === "data") { @@ -158,22 +157,22 @@ describe("kube auth proxy tests", () => { return stdout; }); - mockedCP.stdout.once.mockImplementation((event: string | symbol, listener: (message: any, sendHandle: any) => void): Readable => { + stdout.once.mockImplementation((event: string | symbol, listener: (message: any, sendHandle: any) => void): Readable => { listeners.once(`stdout/${String(event)}`, listener); return stdout; }); - mockedCP.stdout.off.mockImplementation((event: string | symbol, listener: (message: any, sendHandle: any) => void): Readable => { + stdout.off.mockImplementation((event: string | symbol, listener: (message: any, sendHandle: any) => void): Readable => { listeners.off(`stdout/${String(event)}`, listener); return stdout; }); - mockedCP.stdout.removeListener.mockImplementation((event: string | symbol, listener: (message: any, sendHandle: any) => void): Readable => { + stdout.removeListener.mockImplementation((event: string | symbol, listener: (message: any, sendHandle: any) => void): Readable => { listeners.off(`stdout/${String(event)}`, listener); return stdout; }); - mockedCP.stdout.removeAllListeners.mockImplementation((event?: string | symbol): Readable => { + stdout.removeAllListeners.mockImplementation((event?: string | symbol): Readable => { listeners.removeAllListeners(event ?? `stdout/${String(event)}`); return stdout; @@ -185,7 +184,7 @@ describe("kube auth proxy tests", () => { }); waitUntilPortIsUsedMock.mockReturnValueOnce(Promise.resolve()); - const cluster = createCluster({ + const cluster = new Cluster({ id: "foobar", kubeConfigPath: "minikube-config.yml", contextName: "minikube", @@ -194,37 +193,38 @@ describe("kube auth proxy tests", () => { }); proxy = createKubeAuthProxy(cluster, {}); + await proxy.run(); }); - it("should call spawn and broadcast errors", async () => { - await proxy.run(); + it("should call spawn and broadcast errors", () => { listeners.emit("error", { message: "foobarbat" }); expect(broadcastMessageMock).toBeCalledWith("cluster:foobar:connection-update", { message: "foobarbat", level: "error" }); }); - it("should call spawn and broadcast exit", async () => { - await proxy.run(); - listeners.emit("exit", 0); + it("should call spawn and broadcast exit as error when exitCode != 0", () => { + listeners.emit("exit", 1); - expect(broadcastMessageMock).toBeCalledWith("cluster:foobar:connection-update", { message: "proxy exited with code: 0", level: "info" }); + expect(broadcastMessageMock).toBeCalledWith("cluster:foobar:connection-update", { message: "proxy exited with code: 1", level: "error" }); }); - it("should call spawn and broadcast errors from stderr", async () => { - await proxy.run(); + it("should call spawn and broadcast exit as info when exitCode == 0", () => { + listeners.emit("exit", 0); + + expect(broadcastMessageMock).toBeCalledWith("cluster:foobar:connection-update", { message: "proxy exited successfully", level: "info" }); + }); + + it("should call spawn and broadcast errors from stderr", () => { listeners.emit("stderr/data", "an error"); expect(broadcastMessageMock).toBeCalledWith("cluster:foobar:connection-update", { message: "an error", level: "error" }); }); - it("should call spawn and broadcast stdout serving info", async () => { - await proxy.run(); - + it("should call spawn and broadcast stdout serving info", () => { expect(broadcastMessageMock).toBeCalledWith("cluster:foobar:connection-update", { message: "Authentication proxy started", level: "info" }); }); - it("should call spawn and broadcast stdout other info", async () => { - await proxy.run(); + it("should call spawn and broadcast stdout other info", () => { listeners.emit("stdout/data", "some info"); expect(broadcastMessageMock).toBeCalledWith("cluster:foobar:connection-update", { message: "some info", level: "info" }); diff --git a/packages/core/src/main/__test__/kubeconfig-manager.test.ts b/packages/core/src/main/__test__/kubeconfig-manager.test.ts index 4ccb88ba45..1205ba4f8f 100644 --- a/packages/core/src/main/__test__/kubeconfig-manager.test.ts +++ b/packages/core/src/main/__test__/kubeconfig-manager.test.ts @@ -3,14 +3,11 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getDiForUnitTesting } from "../getDiForUnitTesting"; -import { KubeconfigManager } from "../kubeconfig-manager/kubeconfig-manager"; -import type { Cluster } from "../../common/cluster/cluster"; -import createKubeconfigManagerInjectable from "../kubeconfig-manager/create-kubeconfig-manager.injectable"; -import { createClusterInjectionToken } from "../../common/cluster/create-cluster-injection-token"; +import type { KubeconfigManager } from "../kubeconfig-manager/kubeconfig-manager"; +import { Cluster } from "../../common/cluster/cluster"; +import kubeconfigManagerInjectable from "../kubeconfig-manager/kubeconfig-manager.injectable"; import directoryForTempInjectable from "../../common/app-paths/directory-for-temp/directory-for-temp.injectable"; -import createContextHandlerInjectable from "../context-handler/create-context-handler.injectable"; import type { DiContainer } from "@ogre-tools/injectable"; -import { parse } from "url"; import loggerInjectable from "../../common/logger.injectable"; import type { Logger } from "../../common/logger"; import directoryForUserDataInjectable from "../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; @@ -30,12 +27,13 @@ import removePathInjectable from "../../common/fs/remove.injectable"; import pathExistsSyncInjectable from "../../common/fs/path-exists-sync.injectable"; import readJsonSyncInjectable from "../../common/fs/read-json-sync.injectable"; import writeJsonSyncInjectable from "../../common/fs/write-json-sync.injectable"; +import kubeAuthProxyServerInjectable from "../cluster/kube-auth-proxy-server.injectable"; +import lensProxyPortInjectable from "../lens-proxy/lens-proxy-port.injectable"; const clusterServerUrl = "https://192.168.64.3:8443"; describe("kubeconfig manager tests", () => { let clusterFake: Cluster; - let createKubeconfigManager: (cluster: Cluster) => KubeconfigManager; let di: DiContainer; let loggerMock: jest.Mocked; let readFileMock: AsyncFnMock; @@ -56,6 +54,7 @@ describe("kubeconfig manager tests", () => { di.override(pathExistsSyncInjectable, () => () => { throw new Error("tried call pathExistsSync without override"); }); di.override(readJsonSyncInjectable, () => () => { throw new Error("tried call readJsonSync without override"); }); di.override(writeJsonSyncInjectable, () => () => { throw new Error("tried call writeJsonSync without override"); }); + di.inject(lensProxyPortInjectable).set(9191); readFileMock = asyncFn(); di.override(readFileInjectable, () => readFileMock); @@ -78,23 +77,15 @@ describe("kubeconfig manager tests", () => { ensureServerMock = asyncFn(); - di.override(createContextHandlerInjectable, () => (cluster) => ({ - restartServer: jest.fn(), - stopServer: jest.fn(), - clusterUrl: parse(cluster.apiUrl), + di.override(kubeAuthProxyServerInjectable, () => ({ + restart: jest.fn(), + stop: jest.fn(), getApiTarget: jest.fn(), - getPrometheusDetails: jest.fn(), - resolveAuthProxyCa: jest.fn(), - resolveAuthProxyUrl: jest.fn(), - setupPrometheus: jest.fn(), - ensureServer: ensureServerMock, + ensureRunning: ensureServerMock, + ensureAuthProxyUrl: jest.fn(), })); - const createCluster = di.inject(createClusterInjectionToken); - - createKubeconfigManager = di.inject(createKubeconfigManagerInjectable); - - clusterFake = createCluster({ + clusterFake = new Cluster({ id: "foo", contextName: "minikube", kubeConfigPath: "/minikube-config.yml", @@ -102,9 +93,7 @@ describe("kubeconfig manager tests", () => { clusterServerUrl, }); - jest.spyOn(KubeconfigManager.prototype, "resolveProxyUrl", "get").mockReturnValue("https://127.0.0.1:9191/foo"); - - kubeConfManager = createKubeconfigManager(clusterFake); + kubeConfManager = di.inject(kubeconfigManagerInjectable, clusterFake); }); describe("when calling clear", () => { @@ -123,7 +112,7 @@ describe("kubeconfig manager tests", () => { let getPathPromise: Promise; beforeEach(async () => { - getPathPromise = kubeConfManager.getPath(); + getPathPromise = kubeConfManager.ensurePath(); }); it("should not call pathExists()", () => { @@ -174,7 +163,7 @@ describe("kubeconfig manager tests", () => { beforeEach(async () => { await writeFileMock.resolveSpecific( [ - "/some-directory-for-temp/kubeconfig-foo", + "/some-directory-for-temp/kubeconfig-foo", "apiVersion: v1\nkind: Config\npreferences: {}\ncurrent-context: minikube\nclusters:\n - name: minikube\n cluster:\n certificate-authority-data: PGNhLWRhdGE+\n server: https://127.0.0.1:9191/foo\n insecure-skip-tls-verify: false\ncontexts:\n - name: minikube\n context:\n cluster: minikube\n user: proxy\nusers:\n - name: proxy\n user:\n username: lens\n password: fake\n", ], ); @@ -234,7 +223,7 @@ describe("kubeconfig manager tests", () => { let getPathPromise: Promise; beforeEach(async () => { - getPathPromise = kubeConfManager.getPath(); + getPathPromise = kubeConfManager.ensurePath(); }); it("should call pathExists", () => { @@ -303,7 +292,7 @@ describe("kubeconfig manager tests", () => { beforeEach(async () => { await writeFileMock.resolveSpecific( [ - "/some-directory-for-temp/kubeconfig-foo", + "/some-directory-for-temp/kubeconfig-foo", "apiVersion: v1\nkind: Config\npreferences: {}\ncurrent-context: minikube\nclusters:\n - name: minikube\n cluster:\n certificate-authority-data: PGNhLWRhdGE+\n server: https://127.0.0.1:9191/foo\n insecure-skip-tls-verify: false\ncontexts:\n - name: minikube\n context:\n cluster: minikube\n user: proxy\nusers:\n - name: proxy\n user:\n username: lens\n password: fake\n", ], ); diff --git a/packages/core/src/main/__test__/prometheus-handler.test.ts b/packages/core/src/main/__test__/prometheus-handler.test.ts new file mode 100644 index 0000000000..59671553bb --- /dev/null +++ b/packages/core/src/main/__test__/prometheus-handler.test.ts @@ -0,0 +1,213 @@ +/** + * 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 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 loadProxyKubeconfigInjectable from "../cluster/load-proxy-kubeconfig.injectable"; +import { 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, (di, cluster) => async () => { + const res = new KubeConfig(); + + res.addCluster({ + name: "some-cluster-name", + server: cluster.apiUrl.get(), + skipTLSVerify: false, + }); + res.addContext({ + cluster: "some-cluster-name", + name: "some-context-name", + user: "some-user-name", + }); + res.addUser({ + name: "some-user-name", + }); + res.setCurrentContext("some-context-name"); + + return res; + }); + di.override(directoryForTempInjectable, () => "/some-temp-dir"); + di.inject(lensProxyPortInjectable).set(12345); + + cluster = new Cluster({ + contextName: "some-context-name", + id: "some-cluster-id", + kubeConfigPath: "/some/path", + }, { + clusterServerUrl: "http://localhost:81", + }); + }); + + 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/app-paths/directory-for-integration-testing/directory-for-integration-testing.global-override-for-injectable.ts b/packages/core/src/main/app-paths/directory-for-integration-testing/directory-for-integration-testing.global-override-for-injectable.ts index f4e7b5674e..92830fa621 100644 --- a/packages/core/src/main/app-paths/directory-for-integration-testing/directory-for-integration-testing.global-override-for-injectable.ts +++ b/packages/core/src/main/app-paths/directory-for-integration-testing/directory-for-integration-testing.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import directoryForIntegrationTestingInjectable from "./directory-for-integration-testing.injectable"; export default getGlobalOverride(directoryForIntegrationTestingInjectable, () => undefined); 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 c6f1c1e01e..34178547c3 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 @@ -18,38 +18,35 @@ import { beforeAnythingInjectionToken } from "@k8slens/application-for-electron- const setupAppPathsInjectable = getInjectable({ id: "setup-app-paths", - instantiate: (di) => { - const setElectronAppPath = di.inject(setElectronAppPathInjectable); - const appName = di.inject(appNameInjectable); - const getElectronAppPath = di.inject(getElectronAppPathInjectable); - const appPathsState = di.inject(appPathsStateInjectable); - const directoryForIntegrationTesting = di.inject(directoryForIntegrationTestingInjectable); - const joinPaths = di.inject(joinPathsInjectable); + instantiate: (di) => ({ + run: () => { + const setElectronAppPath = di.inject(setElectronAppPathInjectable); + const appName = di.inject(appNameInjectable); + const getElectronAppPath = di.inject(getElectronAppPathInjectable); + const appPathsState = di.inject(appPathsStateInjectable); + const directoryForIntegrationTesting = di.inject(directoryForIntegrationTestingInjectable); + const joinPaths = di.inject(joinPathsInjectable); - return { - id: "setup-app-paths", - run: () => { - if (directoryForIntegrationTesting) { - setElectronAppPath("appData", directoryForIntegrationTesting); - } + if (directoryForIntegrationTesting) { + setElectronAppPath("appData", directoryForIntegrationTesting); + } - const appDataPath = getElectronAppPath("appData"); + const appDataPath = getElectronAppPath("appData"); - setElectronAppPath("userData", joinPaths(appDataPath, appName)); + setElectronAppPath("userData", joinPaths(appDataPath, appName)); - const appPaths = pipeline( - pathNames, - map(name => [name, getElectronAppPath(name)]), - fromPairs, - ) as AppPaths; + const appPaths = pipeline( + pathNames, + map(name => [name, getElectronAppPath(name)]), + fromPairs, + ) as AppPaths; - appPathsState.set(appPaths); + appPathsState.set(appPaths); - // NOTE: this is the worse of two evils. This makes sure that `RunnableSync` always is sync - return undefined; - }, - }; - }, + // NOTE: this is the worse of two evils. This makes sure that `RunnableSync` always is sync + return undefined; + }, + }), injectionToken: beforeAnythingInjectionToken, }); diff --git a/packages/core/src/main/catalog-sources/__test__/kubeconfig-sync.test.ts b/packages/core/src/main/catalog-sources/__test__/kubeconfig-sync.test.ts index 8dbdb87d47..42ffbedf30 100644 --- a/packages/core/src/main/catalog-sources/__test__/kubeconfig-sync.test.ts +++ b/packages/core/src/main/catalog-sources/__test__/kubeconfig-sync.test.ts @@ -3,14 +3,14 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { observable, ObservableMap } from "mobx"; +import { observable, ObservableMap, runInAction } from "mobx"; import type { CatalogEntity } from "../../../common/catalog"; import { loadFromOptions } from "../../../common/kube-helpers"; import type { Cluster } from "../../../common/cluster/cluster"; import { getDiForUnitTesting } from "../../getDiForUnitTesting"; 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 { iter, strictGet } from "../../../common/utils"; +import { iter, strictGet } from "@k8slens/utilities"; import type { ComputeKubeconfigDiff } from "../kubeconfig-sync/compute-diff.injectable"; import computeKubeconfigDiffInjectable from "../kubeconfig-sync/compute-diff.injectable"; import type { ConfigToModels } from "../kubeconfig-sync/config-to-models.injectable"; @@ -34,6 +34,8 @@ import pathExistsSyncInjectable from "../../../common/fs/path-exists-sync.inject import pathExistsInjectable from "../../../common/fs/path-exists.injectable"; import readJsonSyncInjectable from "../../../common/fs/read-json-sync.injectable"; import writeJsonSyncInjectable from "../../../common/fs/write-json-sync.injectable"; +import type { KubeconfigManager } from "../../kubeconfig-manager/kubeconfig-manager"; +import kubeconfigManagerInjectable from "../../kubeconfig-manager/kubeconfig-manager.injectable"; describe("kubeconfig-sync.source tests", () => { let computeKubeconfigDiff: ComputeKubeconfigDiff; @@ -52,6 +54,10 @@ describe("kubeconfig-sync.source tests", () => { di.override(readJsonSyncInjectable, () => () => { throw new Error("tried call readJsonSync without override"); }); di.override(writeJsonSyncInjectable, () => () => { throw new Error("tried call writeJsonSync without override"); }); + di.override(kubeconfigManagerInjectable, () => ({ + ensurePath: async () => "/some-proxy-kubeconfig-file", + } as Partial as KubeconfigManager)); + clusters = new Map(); di.override(getClusterByIdInjectable, () => id => clusters.get(id)); @@ -79,7 +85,7 @@ describe("kubeconfig-sync.source tests", () => { const config = loadFromOptions({ clusters: [{ name: "cluster-name", - server: "1.2.3.4", + server: "https://1.2.3.4", skipTLSVerify: false, }], users: [{ @@ -117,7 +123,7 @@ describe("kubeconfig-sync.source tests", () => { clusters: [{ name: "cluster-name", cluster: { - server: "1.2.3.4", + server: "https://1.2.3.4", }, skipTLSVerify: false, }], @@ -149,8 +155,10 @@ describe("kubeconfig-sync.source tests", () => { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const c = (iter.first(rootSource.values())!)[0]; - expect(c.kubeConfigPath).toBe("/bar"); - expect(c.contextName).toBe("context-name"); + runInAction(() => { + expect(c.kubeConfigPath.get()).toBe("/bar"); + expect(c.contextName.get()).toBe("context-name"); + }); }); it("should remove a cluster when it is removed from the contents", () => { @@ -158,7 +166,7 @@ describe("kubeconfig-sync.source tests", () => { clusters: [{ name: "cluster-name", cluster: { - server: "1.2.3.4", + server: "https://1.2.3.4", }, skipTLSVerify: false, }], @@ -190,8 +198,8 @@ describe("kubeconfig-sync.source tests", () => { const c = rootSource.values().next().value[0] as Cluster; - expect(c.kubeConfigPath).toBe("/bar"); - expect(c.contextName).toBe("context-name"); + expect(c.kubeConfigPath.get()).toBe("/bar"); + expect(c.contextName.get()).toBe("context-name"); computeKubeconfigDiff("{}", rootSource, filePath); @@ -203,7 +211,7 @@ describe("kubeconfig-sync.source tests", () => { clusters: [{ name: "cluster-name", cluster: { - server: "1.2.3.4", + server: "https://1.2.3.4", }, skipTLSVerify: false, }], @@ -243,15 +251,17 @@ describe("kubeconfig-sync.source tests", () => { { const c = rootSource.values().next().value[0] as Cluster; - expect(c.kubeConfigPath).toBe("/bar"); - expect(["context-name", "context-name-2"].includes(c.contextName)).toBe(true); + runInAction(() => { + expect(c.kubeConfigPath.get()).toBe("/bar"); + expect(["context-name", "context-name-2"].includes(c.contextName.get())).toBe(true); + }); } const newContents = JSON.stringify({ clusters: [{ name: "cluster-name", cluster: { - server: "1.2.3.4", + server: "https://1.2.3.4", }, skipTLSVerify: false, }], @@ -283,8 +293,8 @@ describe("kubeconfig-sync.source tests", () => { { const c = rootSource.values().next().value[0] as Cluster; - expect(c.kubeConfigPath).toBe("/bar"); - expect(c.contextName).toBe("context-name"); + expect(c.kubeConfigPath.get()).toBe("/bar"); + expect(c.contextName.get()).toBe("context-name"); } }); }); @@ -444,7 +454,7 @@ const foobarConfig = JSON.stringify({ clusters: [{ name: "cluster-name", cluster: { - server: "1.2.3.4", + server: "https://1.2.3.4", }, skipTLSVerify: false, }], diff --git a/packages/core/src/main/catalog-sources/kubeconfig-sync/compute-diff.injectable.ts b/packages/core/src/main/catalog-sources/kubeconfig-sync/compute-diff.injectable.ts index cb1e62e6e8..3b81e82382 100644 --- a/packages/core/src/main/catalog-sources/kubeconfig-sync/compute-diff.injectable.ts +++ b/packages/core/src/main/catalog-sources/kubeconfig-sync/compute-diff.injectable.ts @@ -10,13 +10,13 @@ import { homedir } from "os"; import directoryForKubeConfigsInjectable from "../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable"; import type { CatalogEntity } from "../../../common/catalog"; import getClusterByIdInjectable from "../../../common/cluster-store/get-by-id.injectable"; -import type { Cluster } from "../../../common/cluster/cluster"; +import { Cluster } from "../../../common/cluster/cluster"; import { loadConfigFromString } from "../../../common/kube-helpers"; import clustersThatAreBeingDeletedInjectable from "../../cluster/are-being-deleted.injectable"; import { catalogEntityFromCluster } from "../../cluster/manager"; -import createClusterInjectable from "../../create-cluster/create-cluster.injectable"; import configToModelsInjectable from "./config-to-models.injectable"; import kubeconfigSyncLoggerInjectable from "./logger.injectable"; +import clusterConnectionInjectable from "../../cluster/cluster-connection.injectable"; export type ComputeKubeconfigDiff = (contents: string, source: ObservableMap, filePath: string) => void; @@ -24,7 +24,6 @@ const computeKubeconfigDiffInjectable = getInjectable({ id: "compute-kubeconfig-diff", instantiate: (di): ComputeKubeconfigDiff => { const directoryForKubeConfigs = di.inject(directoryForKubeConfigsInjectable); - const createCluster = di.inject(createClusterInjectable); const clustersThatAreBeingDeleted = di.inject(clustersThatAreBeingDeletedInjectable); const configToModels = di.inject(configToModelsInjectable); const logger = di.inject(kubeconfigSyncLoggerInjectable); @@ -51,7 +50,9 @@ const computeKubeconfigDiffInjectable = getInjectable({ // remove from the deleting set, so that if a new context of the same name is added, it isn't marked as deleting clustersThatAreBeingDeleted.delete(value[0].id); - value[0].disconnect(); + const clusterConnection = di.inject(clusterConnectionInjectable, value[0]); + + clusterConnection.disconnect(); source.delete(contextName); logger.debug(`Removed old cluster from sync`, { filePath, contextName }); continue; @@ -71,9 +72,9 @@ const computeKubeconfigDiffInjectable = getInjectable({ // add new clusters to the source try { const clusterId = createHash("md5").update(`${filePath}:${contextName}`).digest("hex"); - const cluster = getClusterById(clusterId) ?? createCluster({ ...model, id: clusterId }, configData); + const cluster = getClusterById(clusterId) ?? new Cluster({ ...model, id: clusterId }, configData); - if (!cluster.apiUrl) { + if (!cluster.apiUrl.get()) { throw new Error("Cluster constructor failed, see above error"); } diff --git a/packages/core/src/main/catalog-sources/kubeconfig-sync/diff-changed-kubeconfig.injectable.ts b/packages/core/src/main/catalog-sources/kubeconfig-sync/diff-changed-kubeconfig.injectable.ts index f17293fc2d..ad03c2563d 100644 --- a/packages/core/src/main/catalog-sources/kubeconfig-sync/diff-changed-kubeconfig.injectable.ts +++ b/packages/core/src/main/catalog-sources/kubeconfig-sync/diff-changed-kubeconfig.injectable.ts @@ -10,8 +10,8 @@ import type { Readable } from "stream"; import type { CatalogEntity } from "../../../common/catalog"; import type { Cluster } from "../../../common/cluster/cluster"; import createReadFileStreamInjectable from "../../../common/fs/create-read-file-stream.injectable"; -import type { Disposer } from "../../../common/utils"; -import { bytesToUnits, noop } from "../../../common/utils"; +import type { Disposer } from "@k8slens/utilities"; +import { bytesToUnits, noop } from "@k8slens/utilities"; import computeKubeconfigDiffInjectable from "./compute-diff.injectable"; import kubeconfigSyncLoggerInjectable from "./logger.injectable"; diff --git a/packages/core/src/main/catalog-sources/kubeconfig-sync/manager.ts b/packages/core/src/main/catalog-sources/kubeconfig-sync/manager.ts index cf05577ae7..77ef96b765 100644 --- a/packages/core/src/main/catalog-sources/kubeconfig-sync/manager.ts +++ b/packages/core/src/main/catalog-sources/kubeconfig-sync/manager.ts @@ -6,8 +6,8 @@ import type { IComputedValue, ObservableMap } from "mobx"; import { action, observable, computed, makeObservable, observe } from "mobx"; import type { CatalogEntity } from "../../../common/catalog"; -import type { Disposer } from "../../../common/utils"; -import { iter } from "../../../common/utils"; +import type { Disposer } from "@k8slens/utilities"; +import { iter } from "@k8slens/utilities"; import type { KubeconfigSyncValue } from "../../../common/user-store"; import type { Logger } from "../../../common/logger"; import type { WatchKubeconfigFileChanges } from "./watch-file-changes.injectable"; diff --git a/packages/core/src/main/catalog-sources/kubeconfig-sync/watch-file-changes.injectable.ts b/packages/core/src/main/catalog-sources/kubeconfig-sync/watch-file-changes.injectable.ts index 244daeec69..a54db19390 100644 --- a/packages/core/src/main/catalog-sources/kubeconfig-sync/watch-file-changes.injectable.ts +++ b/packages/core/src/main/catalog-sources/kubeconfig-sync/watch-file-changes.injectable.ts @@ -13,8 +13,8 @@ import type { Cluster } from "../../../common/cluster/cluster"; import statInjectable from "../../../common/fs/stat.injectable"; import type { Watcher } from "../../../common/fs/watch/watch.injectable"; import watchInjectable from "../../../common/fs/watch/watch.injectable"; -import type { Disposer } from "../../../common/utils"; -import { getOrInsertWith, iter } from "../../../common/utils"; +import type { Disposer } from "@k8slens/utilities"; +import { getOrInsertWith, iter } from "@k8slens/utilities"; import diffChangedKubeconfigInjectable from "./diff-changed-kubeconfig.injectable"; import kubeconfigSyncLoggerInjectable from "./logger.injectable"; diff --git a/packages/core/src/main/catalog-sources/weblinks.ts b/packages/core/src/main/catalog-sources/weblinks.ts index 084654efc0..2ff2b645a1 100644 --- a/packages/core/src/main/catalog-sources/weblinks.ts +++ b/packages/core/src/main/catalog-sources/weblinks.ts @@ -8,7 +8,7 @@ import type { WeblinkStore } from "../../common/weblinks-store/weblink-store"; import { WebLink } from "../../common/catalog-entities"; import type { CatalogEntityRegistry } from "../catalog"; import got from "got"; -import type { Disposer } from "../../common/utils"; +import type { Disposer } from "@k8slens/utilities"; import { random } from "lodash"; async function validateLink(link: WebLink) { diff --git a/packages/core/src/main/catalog-sync-to-renderer/broadcaster.global-override-for-injectable.ts b/packages/core/src/main/catalog-sync-to-renderer/broadcaster.global-override-for-injectable.ts index fce2e7d2eb..312af90dba 100644 --- a/packages/core/src/main/catalog-sync-to-renderer/broadcaster.global-override-for-injectable.ts +++ b/packages/core/src/main/catalog-sync-to-renderer/broadcaster.global-override-for-injectable.ts @@ -4,7 +4,7 @@ */ import { debounce } from "lodash"; -import { getGlobalOverride } from "../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import catalogSyncBroadcasterInjectable from "./broadcaster.injectable"; export default getGlobalOverride(catalogSyncBroadcasterInjectable, () => debounce(() => {})); 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 bdcd3034d3..cd77332185 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 @@ -6,10 +6,11 @@ import { getInjectable } from "@ogre-tools/injectable"; import { reaction } from "mobx"; import ipcMainInjectionToken from "../../common/ipc/ipc-main-injection-token"; import { catalogInitChannel } from "../../common/ipc/catalog"; -import { disposer, toJS } from "../../common/utils"; +import { disposer } from "@k8slens/utilities"; import { getStartableStoppable } from "../../common/utils/get-startable-stoppable"; import catalogEntityRegistryInjectable from "../catalog/entity-registry.injectable"; import catalogSyncBroadcasterInjectable from "./broadcaster.injectable"; +import { toJS } from "../../common/utils"; const catalogSyncToRendererInjectable = getInjectable({ id: "catalog-sync-to-renderer", diff --git a/packages/core/src/main/catalog-sync-to-renderer/start-catalog-sync.injectable.ts b/packages/core/src/main/catalog-sync-to-renderer/start-catalog-sync.injectable.ts index ebe1f2a1ac..41db32b8f2 100644 --- a/packages/core/src/main/catalog-sync-to-renderer/start-catalog-sync.injectable.ts +++ b/packages/core/src/main/catalog-sync-to-renderer/start-catalog-sync.injectable.ts @@ -3,24 +3,21 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { afterRootFrameIsReadyInjectionToken } from "../start-main-application/runnable-tokens/after-root-frame-is-ready-injection-token"; +import { afterRootFrameIsReadyInjectionToken } from "../start-main-application/runnable-tokens/phases"; import catalogSyncToRendererInjectable from "./catalog-sync-to-renderer.injectable"; const startCatalogSyncInjectable = getInjectable({ id: "start-catalog-sync", - instantiate: (di) => { - const catalogSyncToRenderer = di.inject(catalogSyncToRendererInjectable); + instantiate: (di) => ({ + run: () => { + const catalogSyncToRenderer = di.inject(catalogSyncToRendererInjectable); - return { - id: "start-catalog-sync", - run: () => { - if (!catalogSyncToRenderer.started) { - catalogSyncToRenderer.start(); - } - }, - }; - }, + if (!catalogSyncToRenderer.started) { + catalogSyncToRenderer.start(); + } + }, + }), injectionToken: afterRootFrameIsReadyInjectionToken, }); diff --git a/packages/core/src/main/catalog-sync-to-renderer/stop-catalog-sync.injectable.ts b/packages/core/src/main/catalog-sync-to-renderer/stop-catalog-sync.injectable.ts index 353790d8b2..faf5013a5f 100644 --- a/packages/core/src/main/catalog-sync-to-renderer/stop-catalog-sync.injectable.ts +++ b/packages/core/src/main/catalog-sync-to-renderer/stop-catalog-sync.injectable.ts @@ -4,25 +4,22 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import catalogSyncToRendererInjectable from "./catalog-sync-to-renderer.injectable"; -import { beforeQuitOfFrontEndInjectionToken } from "../start-main-application/runnable-tokens/before-quit-of-front-end-injection-token"; +import { beforeQuitOfFrontEndInjectionToken } from "../start-main-application/runnable-tokens/phases"; const stopCatalogSyncInjectable = getInjectable({ id: "stop-catalog-sync", - instantiate: (di) => { - const catalogSyncToRenderer = di.inject(catalogSyncToRendererInjectable); + instantiate: (di) => ({ + run: () => { + const catalogSyncToRenderer = di.inject(catalogSyncToRendererInjectable); - return { - id: "stop-catalog-sync", - run: () => { - if (catalogSyncToRenderer.started) { - catalogSyncToRenderer.stop(); - } + if (catalogSyncToRenderer.started) { + catalogSyncToRenderer.stop(); + } - return undefined; - }, - }; - }, + return undefined; + }, + }), injectionToken: beforeQuitOfFrontEndInjectionToken, }); diff --git a/packages/core/src/main/catalog/entity-registry.ts b/packages/core/src/main/catalog/entity-registry.ts index 972da73132..99b7a4ccb3 100644 --- a/packages/core/src/main/catalog/entity-registry.ts +++ b/packages/core/src/main/catalog/entity-registry.ts @@ -6,7 +6,7 @@ import { action, computed, type IComputedValue, type IObservableArray, makeObservable, observable } from "mobx"; import type { CatalogEntity } from "../../common/catalog"; import type { HasCategoryForEntity } from "../../common/catalog/has-category-for-entity.injectable"; -import { iter } from "../../common/utils"; +import { iter } from "@k8slens/utilities"; interface Dependencies { readonly hasCategoryForEntity: HasCategoryForEntity; diff --git a/packages/core/src/main/cluster-detectors/cluster-distribution-detector.injectable.ts b/packages/core/src/main/cluster-detectors/cluster-distribution-detector.injectable.ts index 7a13c62515..44f1c88102 100644 --- a/packages/core/src/main/cluster-detectors/cluster-distribution-detector.injectable.ts +++ b/packages/core/src/main/cluster-detectors/cluster-distribution-detector.injectable.ts @@ -13,18 +13,18 @@ import requestClusterVersionInjectable from "./request-cluster-version.injectabl const isGKE = (version: string) => version.includes("gke"); const isEKS = (version: string) => version.includes("eks"); const isIKS = (version: string) => version.includes("IKS"); -const isAKS = (cluster: Cluster) => cluster.apiUrl.includes("azmk8s.io"); +const isAKS = (cluster: Cluster) => cluster.apiUrl.get().includes("azmk8s.io"); const isMirantis = (version: string) => version.includes("-mirantis-") || version.includes("-docker-"); -const isDigitalOcean = (cluster: Cluster) => cluster.apiUrl.endsWith("k8s.ondigitalocean.com"); -const isMinikube = (cluster: Cluster) => cluster.contextName.startsWith("minikube"); -const isMicrok8s = (cluster: Cluster) => cluster.contextName.startsWith("microk8s"); -const isKind = (cluster: Cluster) => cluster.contextName.startsWith("kubernetes-admin@kind-"); -const isDockerDesktop = (cluster: Cluster) => cluster.contextName === "docker-desktop"; +const isDigitalOcean = (cluster: Cluster) => cluster.apiUrl.get().endsWith("k8s.ondigitalocean.com"); +const isMinikube = (cluster: Cluster) => cluster.contextName.get().startsWith("minikube"); +const isMicrok8s = (cluster: Cluster) => cluster.contextName.get().startsWith("microk8s"); +const isKind = (cluster: Cluster) => cluster.contextName.get().startsWith("kubernetes-admin@kind-"); +const isDockerDesktop = (cluster: Cluster) => cluster.contextName.get() === "docker-desktop"; const isTke = (version: string) => version.includes("-tke."); const isCustom = (version: string) => version.includes("+"); const isVMWare = (version: string) => version.includes("+vmware"); const isRke = (version: string) => version.includes("-rancher"); -const isRancherDesktop = (cluster: Cluster) => cluster.contextName === "rancher-desktop"; +const isRancherDesktop = (cluster: Cluster) => cluster.contextName.get() === "rancher-desktop"; const isK3s = (version: string) => version.includes("+k3s"); const isK0s = (version: string) => version.includes("-k0s") || version.includes("+k0s"); const isAlibaba = (version: string) => version.includes("-aliyun"); diff --git a/packages/core/src/main/cluster-detectors/cluster-id-detector.injectable.ts b/packages/core/src/main/cluster-detectors/cluster-id-detector.injectable.ts index 8d7a90fedc..6699986805 100644 --- a/packages/core/src/main/cluster-detectors/cluster-id-detector.injectable.ts +++ b/packages/core/src/main/cluster-detectors/cluster-id-detector.injectable.ts @@ -28,7 +28,7 @@ const clusterIdDetectorFactoryInjectable = getInjectable({ try { id = await getDefaultNamespaceId(cluster); } catch(_) { - id = cluster.apiUrl; + id = cluster.apiUrl.get(); } const value = createHash("sha256").update(id).digest("hex"); diff --git a/packages/core/src/main/cluster-detectors/detect-cluster-metadata.injectable.ts b/packages/core/src/main/cluster-detectors/detect-cluster-metadata.injectable.ts index cfc492942f..8bb362baa9 100644 --- a/packages/core/src/main/cluster-detectors/detect-cluster-metadata.injectable.ts +++ b/packages/core/src/main/cluster-detectors/detect-cluster-metadata.injectable.ts @@ -8,7 +8,7 @@ import { groupBy, reduce } from "lodash"; import { filter, map } from "lodash/fp"; import type { ClusterMetadata } from "../../common/cluster-types"; import type { Cluster } from "../../common/cluster/cluster"; -import { hasDefinedTupleValue, isDefined, object } from "../../common/utils"; +import { hasDefinedTupleValue, isDefined, object } from "@k8slens/utilities"; import type { ClusterDetectionResult, ClusterMetadataDetector } from "./token"; import { clusterMetadataDetectorInjectionToken } from "./token"; diff --git a/packages/core/src/main/cluster-detectors/detect-cluster-metadata.test.ts b/packages/core/src/main/cluster-detectors/detect-cluster-metadata.test.ts index 496e176afb..9582b386c1 100644 --- a/packages/core/src/main/cluster-detectors/detect-cluster-metadata.test.ts +++ b/packages/core/src/main/cluster-detectors/detect-cluster-metadata.test.ts @@ -7,8 +7,7 @@ import appPathsStateInjectable from "../../common/app-paths/app-paths-state.inje 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 { ClusterMetadataKey } from "../../common/cluster-types"; -import type { Cluster } from "../../common/cluster/cluster"; -import { createClusterInjectionToken } from "../../common/cluster/create-cluster-injection-token"; +import { Cluster } from "../../common/cluster/cluster"; import { getDiForUnitTesting } from "../getDiForUnitTesting"; import clusterDistributionDetectorInjectable from "./cluster-distribution-detector.injectable"; import clusterIdDetectorFactoryInjectable from "./cluster-id-detector.injectable"; @@ -64,9 +63,7 @@ describe("detect-cluster-metadata", () => { detectClusterMetadata = di.inject(detectClusterMetadataInjectable); - const createCluster = di.inject(createClusterInjectionToken); - - cluster = createCluster({ + cluster = new Cluster({ id: "some-id", contextName: "some-context", kubeConfigPath: "minikube-config.yml", diff --git a/packages/core/src/main/cluster-detectors/token.ts b/packages/core/src/main/cluster-detectors/token.ts index fc9031c815..cfc70d8e56 100644 --- a/packages/core/src/main/cluster-detectors/token.ts +++ b/packages/core/src/main/cluster-detectors/token.ts @@ -11,7 +11,7 @@ export interface ClusterDetectionResult { accuracy: number; } -export interface FalibleOnlyClusterMetadataDetector { +export interface FallibleOnlyClusterMetadataDetector { readonly key: string; detect(cluster: Cluster): Promise; } diff --git a/packages/core/src/main/cluster/auth-proxy-url.injectable.ts b/packages/core/src/main/cluster/auth-proxy-url.injectable.ts new file mode 100644 index 0000000000..1ae2a3dca2 --- /dev/null +++ b/packages/core/src/main/cluster/auth-proxy-url.injectable.ts @@ -0,0 +1,21 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import type { Cluster } from "../../common/cluster/cluster"; +import lensProxyPortInjectable from "../lens-proxy/lens-proxy-port.injectable"; + +const kubeAuthProxyUrlInjectable = getInjectable({ + id: "kube-auth-proxy-url", + instantiate: (di, cluster) => { + const lensProxyPort = di.inject(lensProxyPortInjectable); + + return `https://127.0.0.1:${lensProxyPort.get()}/${cluster.id}`; + }, + lifecycle: lifecycleEnum.keyedSingleton({ + getInstanceKey: (di, cluster: Cluster) => cluster.id, + }), +}); + +export default kubeAuthProxyUrlInjectable; diff --git a/packages/core/src/main/cluster/broadcast-connection-update.injectable.ts b/packages/core/src/main/cluster/broadcast-connection-update.injectable.ts new file mode 100644 index 0000000000..51e18f0bfd --- /dev/null +++ b/packages/core/src/main/cluster/broadcast-connection-update.injectable.ts @@ -0,0 +1,29 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import type { KubeAuthUpdate } from "../../common/cluster-types"; +import type { Cluster } from "../../common/cluster/cluster"; +import broadcastMessageInjectable from "../../common/ipc/broadcast-message.injectable"; +import loggerInjectable from "../../common/logger.injectable"; + +export type BroadcastConnectionUpdate = (update: KubeAuthUpdate) => void; + +const broadcastConnectionUpdateInjectable = getInjectable({ + id: "broadcast-connection-update", + instantiate: (di, cluster): BroadcastConnectionUpdate => { + const broadcastMessage = di.inject(broadcastMessageInjectable); + const logger = di.inject(loggerInjectable); + + return (update) => { + logger.debug(`[CLUSTER]: broadcasting connection update`, { ...update, meta: cluster.getMeta() }); + broadcastMessage(`cluster:${cluster.id}:connection-update`, update); + }; + }, + lifecycle: lifecycleEnum.keyedSingleton({ + getInstanceKey: (di, cluster: Cluster) => cluster.id, + }), +}); + +export default broadcastConnectionUpdateInjectable; diff --git a/packages/core/src/main/cluster/cluster-connection.injectable.ts b/packages/core/src/main/cluster/cluster-connection.injectable.ts new file mode 100644 index 0000000000..433a9f5f23 --- /dev/null +++ b/packages/core/src/main/cluster/cluster-connection.injectable.ts @@ -0,0 +1,422 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +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"; +import type { KubeApiResource } from "../../common/rbac"; +import { formatKubeApiResource } from "../../common/rbac"; +import { disposer, isDefined, isRequestError, withConcurrencyLimit } from "@k8slens/utilities"; +import type { ClusterPrometheusHandler } from "./prometheus-handler/prometheus-handler"; +import type { BroadcastConnectionUpdate } from "./broadcast-connection-update.injectable"; +import type { KubeAuthProxyServer } from "./kube-auth-proxy-server.injectable"; +import type { LoadProxyKubeconfig } from "./load-proxy-kubeconfig.injectable"; +import type { RemoveProxyKubeconfig } from "./remove-proxy-kubeconfig.injectable"; +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"; +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"; + +interface Dependencies { + readonly logger: Logger; + readonly prometheusHandler: ClusterPrometheusHandler; + readonly kubeAuthProxyServer: KubeAuthProxyServer; + readonly clusterVersionDetector: FallibleOnlyClusterMetadataDetector; + createAuthorizationReview: CreateAuthorizationReview; + requestApiResources: RequestApiResources; + requestNamespaceListPermissionsFor: RequestNamespaceListPermissionsFor; + createListNamespaces: CreateListNamespaces; + detectClusterMetadata: DetectClusterMetadata; + broadcastMessage: BroadcastMessage; + broadcastConnectionUpdate: BroadcastConnectionUpdate; + loadProxyKubeconfig: LoadProxyKubeconfig; + removeProxyKubeconfig: RemoveProxyKubeconfig; +} + +export type { ClusterConnection }; + +class ClusterConnection { + protected readonly eventsDisposer = disposer(); + + protected activated = false; + + constructor( + private readonly dependencies: Dependencies, + private readonly cluster: Cluster, + ) {} + + private bindEvents() { + this.dependencies.logger.info(`[CLUSTER]: bind events`, this.cluster.getMeta()); + const refreshTimer = setInterval(() => { + if (!this.cluster.disconnected.get()) { + this.refresh(); + } + }, 30_000); // every 30s + const refreshMetadataTimer = setInterval(() => { + if (this.cluster.available.get()) { + this.refreshAccessibilityAndMetadata(); + } + }, 900000); // every 15 minutes + + this.eventsDisposer.push( + reaction( + () => this.cluster.prometheusPreferences.get(), + preferences => this.dependencies.prometheusHandler.setupPrometheus(preferences), + { equals: comparer.structural }, + ), + () => clearInterval(refreshTimer), + () => clearInterval(refreshMetadataTimer), + reaction(() => this.cluster.preferences.defaultNamespace, () => this.recreateProxyKubeconfig()), + ); + } + + protected async recreateProxyKubeconfig() { + this.dependencies.logger.info("[CLUSTER]: Recreating proxy kubeconfig"); + + try { + await this.dependencies.removeProxyKubeconfig(); + await this.dependencies.loadProxyKubeconfig(); + } catch (error) { + this.dependencies.logger.error(`[CLUSTER]: failed to recreate proxy kubeconfig`, error); + } + } + + /** + * @param force force activation + */ + async activate(force = false) { + if (this.activated && !force) { + return; + } + + this.dependencies.logger.info(`[CLUSTER]: activate`, this.cluster.getMeta()); + + if (!this.eventsDisposer.length) { + this.bindEvents(); + } + + if (this.cluster.disconnected || !this.cluster.accessible.get()) { + try { + this.dependencies.broadcastConnectionUpdate({ + level: "info", + message: "Starting connection ...", + }); + await this.reconnect(); + } catch (error) { + this.dependencies.broadcastConnectionUpdate({ + level: "error", + message: `Failed to start connection: ${error}`, + }); + + return; + } + } + + try { + this.dependencies.broadcastConnectionUpdate({ + level: "info", + message: "Refreshing connection status ...", + }); + await this.refreshConnectionStatus(); + } catch (error) { + this.dependencies.broadcastConnectionUpdate({ + level: "error", + message: `Failed to connection status: ${error}`, + }); + + return; + } + + if (this.cluster.accessible.get()) { + try { + this.dependencies.broadcastConnectionUpdate({ + level: "info", + message: "Refreshing cluster accessibility ...", + }); + await this.refreshAccessibility(); + } catch (error) { + this.dependencies.broadcastConnectionUpdate({ + level: "error", + message: `Failed to refresh accessibility: ${error}`, + }); + + return; + } + this.dependencies.broadcastConnectionUpdate({ + level: "info", + message: "Connected, waiting for view to load ...", + }); + } + + this.activated = true; + } + + async reconnect() { + this.dependencies.logger.info(`[CLUSTER]: reconnect`, this.cluster.getMeta()); + await this.dependencies.kubeAuthProxyServer?.restart(); + + runInAction(() => { + this.cluster.disconnected.set(false); + }); + } + + disconnect() { + if (this.cluster.disconnected) { + return this.dependencies.logger.debug("[CLUSTER]: already disconnected", { id: this.cluster.id }); + } + + runInAction(() => { + this.dependencies.logger.info(`[CLUSTER]: disconnecting`, { id: this.cluster.id }); + this.eventsDisposer(); + this.dependencies.kubeAuthProxyServer?.stop(); + this.cluster.disconnected.set(true); + this.cluster.online.set(false); + this.cluster.accessible.set(false); + this.cluster.ready.set(false); + this.activated = false; + this.cluster.allowedNamespaces.clear(); + this.dependencies.logger.info(`[CLUSTER]: disconnected`, { id: this.cluster.id }); + }); + } + + async refresh() { + this.dependencies.logger.info(`[CLUSTER]: refresh`, this.cluster.getMeta()); + await this.refreshConnectionStatus(); + } + + async refreshAccessibilityAndMetadata() { + await this.refreshAccessibility(); + await this.refreshMetadata(); + } + + async refreshMetadata() { + this.dependencies.logger.info(`[CLUSTER]: refreshMetadata`, this.cluster.getMeta()); + const metadata = await this.dependencies.detectClusterMetadata(this.cluster); + + runInAction(() => { + replaceObservableObject(this.cluster.metadata, metadata); + }); + } + + 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 isAdmin = await canI({ + namespace: "kube-system", + resource: "*", + verb: "create", + }); + const isGlobalWatchEnabled = await canI({ + verb: "watch", + resource: "*", + }); + const allowedNamespaces = await this.requestAllowedNamespaces(proxyConfig); + const knownResources = await (async () => { + const result = await this.dependencies.requestApiResources(this.cluster); + + if (result.callWasSuccessful) { + return result.response; + } + + if (this.cluster.knownResources.length > 0) { + this.dependencies.logger.warn(`[CLUSTER]: failed to list KUBE resources, sticking with previous list`); + + return this.cluster.knownResources; + } + + this.dependencies.logger.warn(`[CLUSTER]: failed to list KUBE resources for the first time, blocking connection to cluster...`); + this.dependencies.broadcastConnectionUpdate({ + level: "error", + message: "Failed to list kube API resources, please reconnect...", + }); + + return []; + })(); + const resourcesToShow = await this.getResourcesToShow(allowedNamespaces, knownResources, requestNamespaceListPermissions); + + runInAction(() => { + this.cluster.isAdmin.set(isAdmin); + this.cluster.isGlobalWatchEnabled.set(isGlobalWatchEnabled); + this.cluster.allowedNamespaces.replace(allowedNamespaces); + this.cluster.knownResources.replace(knownResources); + this.cluster.resourcesToShow.replace(resourcesToShow); + this.cluster.ready.set(this.cluster.knownResources.length > 0); + }); + + this.dependencies.logger.debug(`[CLUSTER]: refreshed accessibility data`, this.cluster.getState()); + } + + async refreshConnectionStatus() { + const connectionStatus = await this.getConnectionStatus(); + + runInAction(() => { + this.cluster.online.set(connectionStatus > ClusterStatus.Offline); + this.cluster.accessible.set(connectionStatus == ClusterStatus.AccessGranted); + }); + } + + protected async getConnectionStatus(): Promise { + try { + const versionData = await this.dependencies.clusterVersionDetector.detect(this.cluster); + + runInAction(() => { + this.cluster.metadata.version = versionData.value; + }); + + return ClusterStatus.AccessGranted; + } catch (error) { + this.dependencies.logger.error(`[CLUSTER]: Failed to connect to "${this.cluster.contextName.get()}": ${error}`); + + if (isRequestError(error)) { + if (error.statusCode) { + if (error.statusCode >= 400 && error.statusCode < 500) { + this.dependencies.broadcastConnectionUpdate({ + level: "error", + message: "Invalid credentials", + }); + + return ClusterStatus.AccessDenied; + } + + const message = String(error.error || error.message) || String(error); + + this.dependencies.broadcastConnectionUpdate({ + level: "error", + message, + }); + + return ClusterStatus.Offline; + } + + if (error.failed === true) { + if (error.timedOut === true) { + this.dependencies.broadcastConnectionUpdate({ + level: "error", + message: "Connection timed out", + }); + + return ClusterStatus.Offline; + } + + this.dependencies.broadcastConnectionUpdate({ + level: "error", + message: "Failed to fetch credentials", + }); + + return ClusterStatus.AccessDenied; + } + + const message = String(error.error || error.message) || String(error); + + this.dependencies.broadcastConnectionUpdate({ + level: "error", + message, + }); + } else if (error instanceof Error || typeof error === "string") { + this.dependencies.broadcastConnectionUpdate({ + level: "error", + message: `${error}`, + }); + } else { + this.dependencies.broadcastConnectionUpdate({ + level: "error", + message: "Unknown error has occurred", + }); + } + + return ClusterStatus.Offline; + } + } + + protected async requestAllowedNamespaces(proxyConfig: KubeConfig) { + if (this.cluster.accessibleNamespaces.length) { + return this.cluster.accessibleNamespaces; + } + + try { + const listNamespaces = this.dependencies.createListNamespaces(proxyConfig); + + return await listNamespaces(); + } catch (error) { + const ctx = proxyConfig.getContextObject(this.cluster.contextName.get()); + const namespaceList = [ctx?.namespace].filter(isDefined); + + if (namespaceList.length === 0 && error instanceof HttpError && error.statusCode === 403) { + const { response } = error as HttpError & { response: Response }; + + this.dependencies.logger.info("[CLUSTER]: listing namespaces is forbidden, broadcasting", { clusterId: this.cluster.id, error: response.body }); + this.dependencies.broadcastMessage(clusterListNamespaceForbiddenChannel, this.cluster.id); + } + + return namespaceList; + } + } + + protected async getResourcesToShow(allowedNamespaces: string[], knownResources: KubeApiResource[], req: RequestNamespaceListPermissions) { + if (!allowedNamespaces.length) { + return []; + } + + const requestNamespaceListPermissions = withConcurrencyLimit(5)(req); + const namespaceListPermissions = allowedNamespaces.map(requestNamespaceListPermissions); + const canListResources = await Promise.all(namespaceListPermissions); + + return knownResources + .filter((resource) => canListResources.some(fn => fn(resource))) + .map(formatKubeApiResource); + } +} + +const clusterConnectionInjectable = getInjectable({ + id: "cluster-connection", + instantiate: (di, cluster) => new ClusterConnection( + { + clusterVersionDetector: di.inject(clusterVersionDetectorInjectable), + kubeAuthProxyServer: di.inject(kubeAuthProxyServerInjectable, cluster), + logger: di.inject(loggerInjectable), + 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), + }, + cluster, + ), + lifecycle: lifecycleEnum.keyedSingleton({ + getInstanceKey: (di, cluster: Cluster) => cluster.id, + }), +}); + +export default clusterConnectionInjectable; + diff --git a/packages/core/src/main/cluster/initialize-manager.injectable.ts b/packages/core/src/main/cluster/initialize-manager.injectable.ts index 895355e232..28541a0ca1 100644 --- a/packages/core/src/main/cluster/initialize-manager.injectable.ts +++ b/packages/core/src/main/cluster/initialize-manager.injectable.ts @@ -8,16 +8,13 @@ import clusterManagerInjectable from "./manager.injectable"; const initializeClusterManagerInjectable = getInjectable({ id: "initialize-cluster-manager", - instantiate: (di) => { - const clusterManager = di.inject(clusterManagerInjectable); + instantiate: (di) => ({ + run: () => { + const clusterManager = di.inject(clusterManagerInjectable); - return { - id: "initialize-cluster-manager", - run: () => { - clusterManager.init(); - }, - }; - }, + clusterManager.init(); + }, + }), injectionToken: onLoadOfApplicationInjectionToken, causesSideEffects: true, }); 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 new file mode 100644 index 0000000000..9942c40168 --- /dev/null +++ b/packages/core/src/main/cluster/kube-auth-proxy-server.injectable.ts @@ -0,0 +1,114 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type { ServerOptions } from "http-proxy"; +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"; + +export interface KubeAuthProxyServer { + getApiTarget(isLongRunningRequest?: boolean): Promise; + ensureAuthProxyUrl(): Promise; + restart(): Promise; + ensureRunning(): Promise; + stop(): void; +} + +const fourHoursInMs = 4 * 60 * 60 * 1000; +const thirtySecondsInMs = 30 * 1000; + +const kubeAuthProxyServerInjectable = getInjectable({ + id: "kube-auth-proxy-server", + instantiate: (di, cluster): KubeAuthProxyServer => { + const clusterUrl = new URL(cluster.apiUrl.get()); + + const createKubeAuthProxy = di.inject(createKubeAuthProxyInjectable); + const certificate = di.inject(kubeAuthProxyCertificateInjectable, clusterUrl.hostname); + + let kubeAuthProxy: KubeAuthProxy | undefined = undefined; + let apiTarget: ServerOptions | undefined = undefined; + + const ensureServerHelper = async (): Promise => { + if (!kubeAuthProxy) { + const proxyEnv = Object.assign({}, process.env); + + if (cluster.preferences.httpsProxy) { + proxyEnv.HTTPS_PROXY = cluster.preferences.httpsProxy; + } + + kubeAuthProxy = createKubeAuthProxy(cluster, proxyEnv); + } + + await kubeAuthProxy.run(); + + return kubeAuthProxy; + }; + + const newApiTarget = async (timeout: number): Promise => { + const kubeAuthProxy = await ensureServerHelper(); + const headers: Record = {}; + + if (clusterUrl.hostname) { + headers.Host = clusterUrl.hostname; + + // fix current IPv6 inconsistency in url.Parse() and httpProxy. + // with url.Parse the IPv6 Hostname has no Square brackets but httpProxy needs the Square brackets to work. + if (headers.Host.includes(":")) { + headers.Host = `[${headers.Host}]`; + } + } + + return { + target: { + protocol: "https:", + host: "127.0.0.1", + port: kubeAuthProxy.port, + path: kubeAuthProxy.apiPrefix, + ca: certificate.cert, + }, + changeOrigin: true, + timeout, + secure: true, + headers, + }; + }; + + const stopServer = () => { + kubeAuthProxy?.exit(); + kubeAuthProxy = undefined; + apiTarget = undefined; + }; + + return { + getApiTarget: async (isLongRunningRequest = false) => { + if (isLongRunningRequest) { + return newApiTarget(fourHoursInMs); + } + + return apiTarget ??= await newApiTarget(thirtySecondsInMs); + }, + ensureAuthProxyUrl: async () => { + const kubeAuthProxy = await ensureServerHelper(); + + return `https://127.0.0.1:${kubeAuthProxy.port}${kubeAuthProxy.apiPrefix}`; + }, + ensureRunning: async () => { + await ensureServerHelper(); + }, + restart: async () => { + stopServer(); + await ensureServerHelper(); + }, + stop: stopServer, + }; + }, + lifecycle: lifecycleEnum.keyedSingleton({ + getInstanceKey: (di, cluster: Cluster) => cluster.id, + }), +}); + +export default kubeAuthProxyServerInjectable; diff --git a/packages/core/src/main/cluster/load-proxy-kubeconfig.injectable.ts b/packages/core/src/main/cluster/load-proxy-kubeconfig.injectable.ts new file mode 100644 index 0000000000..b5e5856022 --- /dev/null +++ b/packages/core/src/main/cluster/load-proxy-kubeconfig.injectable.ts @@ -0,0 +1,31 @@ +/** + * 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 { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import type { Cluster } from "../../common/cluster/cluster"; +import loadConfigFromFileInjectable from "../../common/kube-helpers/load-config-from-file.injectable"; +import kubeconfigManagerInjectable from "../kubeconfig-manager/kubeconfig-manager.injectable"; + +export type LoadProxyKubeconfig = () => Promise; + +const loadProxyKubeconfigInjectable = getInjectable({ + id: "load-proxy-kubeconfig", + instantiate: (di, cluster) => { + const loadConfigFromFile = di.inject(loadConfigFromFileInjectable); + const proxyKubeconfigManager = di.inject(kubeconfigManagerInjectable, cluster); + + return async () => { + const proxyKubeconfigPath = await proxyKubeconfigManager.ensurePath(); + const { config } = await loadConfigFromFile(proxyKubeconfigPath); + + return config; + }; + }, + lifecycle: lifecycleEnum.keyedSingleton({ + getInstanceKey: (di, cluster: Cluster) => cluster.id, + }), +}); + +export default loadProxyKubeconfigInjectable; diff --git a/packages/core/src/main/cluster/manager.injectable.ts b/packages/core/src/main/cluster/manager.injectable.ts index 28e55a0734..e1567e51b6 100644 --- a/packages/core/src/main/cluster/manager.injectable.ts +++ b/packages/core/src/main/cluster/manager.injectable.ts @@ -7,6 +7,7 @@ import clusterStoreInjectable from "../../common/cluster-store/cluster-store.inj import loggerInjectable from "../../common/logger.injectable"; import catalogEntityRegistryInjectable from "../catalog/entity-registry.injectable"; import clustersThatAreBeingDeletedInjectable from "./are-being-deleted.injectable"; +import clusterConnectionInjectable from "./cluster-connection.injectable"; import { ClusterManager } from "./manager"; import updateEntityMetadataInjectable from "./update-entity-metadata.injectable"; import updateEntitySpecInjectable from "./update-entity-spec.injectable"; @@ -23,6 +24,7 @@ const clusterManagerInjectable = getInjectable({ logger: di.inject(loggerInjectable), updateEntityMetadata: di.inject(updateEntityMetadataInjectable), updateEntitySpec: di.inject(updateEntitySpecInjectable), + getClusterConnection: (cluster) => di.inject(clusterConnectionInjectable, cluster), }), }); diff --git a/packages/core/src/main/cluster/manager.ts b/packages/core/src/main/cluster/manager.ts index 6d84657a79..bc270b79f1 100644 --- a/packages/core/src/main/cluster/manager.ts +++ b/packages/core/src/main/cluster/manager.ts @@ -7,7 +7,7 @@ import "../../common/ipc/cluster"; import type { IObservableValue, ObservableSet } from "mobx"; import { action, makeObservable, observe, reaction, toJS } from "mobx"; import type { Cluster } from "../../common/cluster/cluster"; -import { isErrnoException } from "../../common/utils"; +import { isErrnoException } from "@k8slens/utilities"; import { isKubernetesCluster, KubernetesCluster, LensKubernetesClusterStatus } from "../../common/catalog-entities/kubernetes-cluster"; import { ipcMainOn } from "../../common/ipc"; import { once } from "lodash"; @@ -17,6 +17,7 @@ import type { CatalogEntityRegistry } from "../catalog"; import type { Logger } from "../../common/logger"; import type { UpdateEntityMetadata } from "./update-entity-metadata.injectable"; import type { UpdateEntitySpec } from "./update-entity-spec.injectable"; +import type { ClusterConnection } from "./cluster-connection.injectable"; const logPrefix = "[CLUSTER-MANAGER]:"; @@ -28,8 +29,9 @@ interface Dependencies { readonly clustersThatAreBeingDeleted: ObservableSet; readonly visibleCluster: IObservableValue; readonly logger: Logger; - readonly updateEntityMetadata: UpdateEntityMetadata; - readonly updateEntitySpec: UpdateEntitySpec; + updateEntityMetadata: UpdateEntityMetadata; + updateEntitySpec: UpdateEntitySpec; + getClusterConnection: (cluster: Cluster) => ClusterConnection; } export class ClusterManager { @@ -119,13 +121,13 @@ export class ClusterManager { return LensKubernetesClusterStatus.DISCONNECTED; } - if (cluster.accessible) { + if (cluster.accessible.get()) { this.dependencies.logger.silly(`${logPrefix} setting entity ${entity.getName()} to CONNECTED, reason="cluster is accessible"`); return LensKubernetesClusterStatus.CONNECTED; } - if (!cluster.disconnected) { + if (!cluster.disconnected.get()) { this.dependencies.logger.silly(`${logPrefix} setting entity ${entity.getName()} to CONNECTING, reason="cluster is not disconnected"`); return LensKubernetesClusterStatus.CONNECTING; @@ -174,8 +176,8 @@ export class ClusterManager { } } } else { - cluster.kubeConfigPath = entity.spec.kubeconfigPath; - cluster.contextName = entity.spec.kubeconfigContext; + cluster.kubeConfigPath.set(entity.spec.kubeconfigPath); + cluster.contextName.set(entity.spec.kubeconfigContext); if (entity.spec.accessibleNamespaces) { cluster.accessibleNamespaces.replace(entity.spec.accessibleNamespaces); @@ -202,30 +204,43 @@ export class ClusterManager { } } - protected onNetworkOffline = () => { + protected onNetworkOffline = async () => { this.dependencies.logger.info(`${logPrefix} network is offline`); - this.dependencies.store.clustersList.forEach((cluster) => { - if (!cluster.disconnected) { - cluster.online = false; - cluster.accessible = false; - cluster.refreshConnectionStatus().catch((e) => e); - } - }); + + await Promise.allSettled( + this.dependencies.store.clustersList + .filter(cluster => !cluster.disconnected.get()) + .map(async (cluster) => { + cluster.online.set(false); + cluster.accessible.set(false); + + await this.dependencies + .getClusterConnection(cluster) + .refreshConnectionStatus(); + }), + ); }; - protected onNetworkOnline = () => { + protected onNetworkOnline = async () => { this.dependencies.logger.info(`${logPrefix} network is online`); - this.dependencies.store.clustersList.forEach((cluster) => { - if (!cluster.disconnected) { - cluster.refreshConnectionStatus().catch((e) => e); - } - }); + + await Promise.allSettled( + this.dependencies.store.clustersList + .filter(cluster => !cluster.disconnected.get()) + .map((cluster) => ( + this.dependencies + .getClusterConnection(cluster) + .refreshConnectionStatus() + )), + ); }; stop() { - this.dependencies.store.clusters.forEach((cluster: Cluster) => { - cluster.disconnect(); - }); + for (const cluster of this.dependencies.store.clustersList) { + this.dependencies + .getClusterConnection(cluster) + .disconnect(); + } } } @@ -233,26 +248,26 @@ export function catalogEntityFromCluster(cluster: Cluster) { return new KubernetesCluster({ metadata: { uid: cluster.id, - name: cluster.name, + name: cluster.name.get(), source: "local", labels: { ...cluster.labels, }, - distro: cluster.distribution, - kubeVersion: cluster.version, + distro: cluster.distribution.get(), + kubeVersion: cluster.version.get(), }, spec: { - kubeconfigPath: cluster.kubeConfigPath, - kubeconfigContext: cluster.contextName, + kubeconfigPath: cluster.kubeConfigPath.get(), + kubeconfigContext: cluster.contextName.get(), icon: {}, }, status: { - phase: cluster.disconnected + phase: cluster.disconnected.get() ? LensKubernetesClusterStatus.DISCONNECTED : LensKubernetesClusterStatus.CONNECTED, reason: "", message: "", - active: !cluster.disconnected, + active: !cluster.disconnected.get(), }, }); } diff --git a/packages/core/src/main/cluster/prometheus-handler/prometheus-handler.injectable.ts b/packages/core/src/main/cluster/prometheus-handler/prometheus-handler.injectable.ts new file mode 100644 index 0000000000..bf022b87f9 --- /dev/null +++ b/packages/core/src/main/cluster/prometheus-handler/prometheus-handler.injectable.ts @@ -0,0 +1,30 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import type { Cluster } from "../../../common/cluster/cluster"; +import { createClusterPrometheusHandler } from "./prometheus-handler"; +import getPrometheusProviderByKindInjectable from "../../prometheus/get-by-kind.injectable"; +import prometheusProvidersInjectable from "../../prometheus/providers.injectable"; +import loggerInjectable from "../../../common/logger.injectable"; +import loadProxyKubeconfigInjectable from "../load-proxy-kubeconfig.injectable"; + +const prometheusHandlerInjectable = getInjectable({ + id: "prometheus-handler", + + instantiate: (di, cluster) => createClusterPrometheusHandler( + { + getPrometheusProviderByKind: di.inject(getPrometheusProviderByKindInjectable), + prometheusProviders: di.inject(prometheusProvidersInjectable), + logger: di.inject(loggerInjectable), + loadProxyKubeconfig: di.inject(loadProxyKubeconfigInjectable, cluster), + }, + cluster, + ), + lifecycle: lifecycleEnum.keyedSingleton({ + getInstanceKey: (di, cluster: Cluster) => cluster.id, + }), +}); + +export default prometheusHandlerInjectable; diff --git a/packages/core/src/main/cluster/prometheus-handler/prometheus-handler.ts b/packages/core/src/main/cluster/prometheus-handler/prometheus-handler.ts new file mode 100644 index 0000000000..ddf5cc461a --- /dev/null +++ b/packages/core/src/main/cluster/prometheus-handler/prometheus-handler.ts @@ -0,0 +1,129 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type { PrometheusProvider, PrometheusService } from "../../prometheus/provider"; +import type { ClusterPrometheusPreferences } from "../../../common/cluster-types"; +import type { Cluster } from "../../../common/cluster/cluster"; +import { CoreV1Api } from "@kubernetes/client-node"; +import type { GetPrometheusProviderByKind } from "../../prometheus/get-by-kind.injectable"; +import type { IComputedValue } from "mobx"; +import type { Logger } from "../../../common/logger"; +import type { LoadProxyKubeconfig } from "../load-proxy-kubeconfig.injectable"; + +export interface PrometheusDetails { + prometheusPath: string; + provider: PrometheusProvider; +} + +interface PrometheusServicePreferences { + namespace: string; + service: string; + port: number; + prefix: string; +} + +interface Dependencies { + readonly prometheusProviders: IComputedValue; + readonly logger: Logger; + getPrometheusProviderByKind: GetPrometheusProviderByKind; + loadProxyKubeconfig: LoadProxyKubeconfig; +} + +export interface ClusterPrometheusHandler { + setupPrometheus(preferences?: ClusterPrometheusPreferences): void; + getPrometheusDetails(): Promise; +} + +const ensurePrometheusPath = ({ service, namespace, port }: PrometheusService) => `${namespace}/services/${service}:${port}`; + +export const createClusterPrometheusHandler = (...args: [Dependencies, Cluster]): ClusterPrometheusHandler => { + const [deps, cluster] = args; + const { + getPrometheusProviderByKind, + loadProxyKubeconfig, + logger, + prometheusProviders, + } = deps; + + let prometheusProvider: string | undefined = undefined; + let prometheus: PrometheusServicePreferences | undefined = undefined; + + const setupPrometheus: ClusterPrometheusHandler["setupPrometheus"] = (preferences = {}) => { + prometheusProvider = preferences.prometheusProvider?.type; + prometheus = preferences.prometheus; + }; + + const ensurePrometheusProvider = (service: PrometheusService) => { + if (!prometheusProvider) { + logger.info(`[CONTEXT-HANDLER]: using ${service.kind} as prometheus provider for clusterId=${cluster.id}`); + prometheusProvider = service.kind; + } + + return getPrometheusProviderByKind(prometheusProvider); + }; + + const listPotentialProviders = () => { + if (prometheusProvider) { + const provider = getPrometheusProviderByKind(prometheusProvider); + + if (provider) { + return [provider]; + } + } + + return prometheusProviders.get(); + }; + + const getPrometheusService = async (): Promise => { + setupPrometheus(cluster.preferences); + + if (prometheus && prometheusProvider) { + return { + kind: prometheusProvider, + namespace: prometheus.namespace, + service: prometheus.service, + port: prometheus.port, + }; + } + + const providers = listPotentialProviders(); + const proxyConfig = await loadProxyKubeconfig(); + const apiClient = proxyConfig.makeApiClient(CoreV1Api); + const potentialServices = await Promise.allSettled( + providers.map(provider => provider.getPrometheusService(apiClient)), + ); + const errors = []; + + for (const res of potentialServices) { + switch (res.status) { + case "rejected": + errors.push(res.reason); + break; + + case "fulfilled": + if (res.value) { + return res.value; + } + } + } + + throw new Error("No Prometheus service found", { cause: errors }); + }; + + const getPrometheusDetails: ClusterPrometheusHandler["getPrometheusDetails"] = async () => { + const service = await getPrometheusService(); + const prometheusPath = ensurePrometheusPath(service); + const provider = ensurePrometheusProvider(service); + + return { prometheusPath, provider }; + }; + + setupPrometheus(cluster.preferences); + + return { + setupPrometheus, + getPrometheusDetails, + }; +}; diff --git a/packages/core/src/main/cluster/remove-proxy-kubeconfig.injectable.ts b/packages/core/src/main/cluster/remove-proxy-kubeconfig.injectable.ts new file mode 100644 index 0000000000..053f7ba18d --- /dev/null +++ b/packages/core/src/main/cluster/remove-proxy-kubeconfig.injectable.ts @@ -0,0 +1,23 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import type { Cluster } from "../../common/cluster/cluster"; +import kubeconfigManagerInjectable from "../kubeconfig-manager/kubeconfig-manager.injectable"; + +export type RemoveProxyKubeconfig = () => Promise; + +const removeProxyKubeconfigInjectable = getInjectable({ + id: "remove-proxy-kubeconfig", + instantiate: (di, cluster): RemoveProxyKubeconfig => { + const proxyKubeconfigManager = di.inject(kubeconfigManagerInjectable, cluster); + + return () => proxyKubeconfigManager.clear(); + }, + lifecycle: lifecycleEnum.keyedSingleton({ + getInstanceKey: (di, cluster: Cluster) => cluster.id, + }), +}); + +export default removeProxyKubeconfigInjectable; 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 552bd47800..d6a21e3ce4 100644 --- a/packages/core/src/main/cluster/request-api-resources.injectable.ts +++ b/packages/core/src/main/cluster/request-api-resources.injectable.ts @@ -8,12 +8,12 @@ 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 { withConcurrencyLimit } from "../../common/utils/with-concurrency-limit"; +import { backoffCaller, withConcurrencyLimit } from "@k8slens/utilities"; import requestKubeApiResourcesForInjectable from "./request-kube-api-resources-for.injectable"; -import type { AsyncResult } from "../../common/utils/async-result"; -import { backoffCaller } from "../../common/utils/backoff-caller"; +import type { AsyncResult } from "@k8slens/utilities"; +import broadcastConnectionUpdateInjectable from "./broadcast-connection-update.injectable"; -export type RequestApiResources = (cluster: Cluster) => Promise>; +export type RequestApiResources = (cluster: Cluster) => AsyncResult; export interface KubeResourceListGroup { group: string; @@ -29,6 +29,7 @@ const requestApiResourcesInjectable = getInjectable({ return async (...args) => { const [cluster] = args; + const broadcastConnectionUpdate = di.inject(broadcastConnectionUpdateInjectable, cluster); const requestKubeApiResources = withConcurrencyLimit(5)(requestKubeApiResourcesFor(cluster)); const groupLists: KubeResourceListGroup[] = []; @@ -36,7 +37,10 @@ const requestApiResourcesInjectable = getInjectable({ for (const apiVersionRequester of apiVersionRequesters) { const result = await backoffCaller(() => apiVersionRequester(cluster), { onIntermediateError: (error, attempt) => { - cluster.broadcastConnectUpdate(`Failed to list kube API resource kinds, attempt ${attempt}: ${error}`, "warning"); + broadcastConnectionUpdate({ + message: `Failed to list kube API resource kinds, attempt ${attempt}: ${error}`, + level: "warning", + }); logger.warn(`[LIST-API-RESOURCES]: failed to list kube api resources: ${error}`, { attempt, clusterId: cluster.id }); }, }); @@ -56,7 +60,10 @@ const requestApiResourcesInjectable = getInjectable({ for (const result of results) { if (!result.callWasSuccessful) { - cluster.broadcastConnectUpdate(`Kube APIs under "${result.listGroup.path}" may not be displayed`, "warning"); + broadcastConnectionUpdate({ + message: `Kube APIs under "${result.listGroup.path}" may not be displayed`, + level: "warning", + }); continue; } diff --git a/packages/core/src/main/cluster/request-api-versions.ts b/packages/core/src/main/cluster/request-api-versions.ts index ac5a08e675..a9b5074549 100644 --- a/packages/core/src/main/cluster/request-api-versions.ts +++ b/packages/core/src/main/cluster/request-api-versions.ts @@ -4,7 +4,7 @@ */ import { getInjectionToken } from "@ogre-tools/injectable"; -import type { AsyncResult } from "../../common/utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; export interface KubeResourceListGroup { group: string; @@ -15,7 +15,7 @@ export interface ClusterData { readonly id: string; } -export type RequestApiVersions = (cluster: ClusterData) => Promise>; +export type RequestApiVersions = (cluster: ClusterData) => AsyncResult; export const requestApiVersionsInjectionToken = getInjectionToken({ id: "request-api-versions-token", 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 681f4ac013..65e326eed7 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 @@ -6,11 +6,11 @@ import type { V1APIResourceList } from "@kubernetes/client-node"; import { getInjectable } from "@ogre-tools/injectable"; import type { Cluster } from "../../common/cluster/cluster"; import type { KubeApiResource } from "../../common/rbac"; -import type { AsyncResult } from "../../common/utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; import k8sRequestInjectable from "../k8s-request.injectable"; import type { KubeResourceListGroup } from "./request-api-versions"; -export type RequestKubeApiResources = (grouping: KubeResourceListGroup) => Promise>; +export type RequestKubeApiResources = (grouping: KubeResourceListGroup) => AsyncResult; export type RequestKubeApiResourcesFor = (cluster: Cluster) => RequestKubeApiResources; 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 25f8676c2a..84e62f6b80 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 @@ -4,7 +4,7 @@ */ import type { V1APIGroupList } from "@kubernetes/client-node"; import { getInjectable } from "@ogre-tools/injectable"; -import { chain } from "../../common/utils/iter"; +import { iter } from "@k8slens/utilities"; import k8sRequestInjectable from "../k8s-request.injectable"; import { requestApiVersionsInjectionToken } from "./request-api-versions"; @@ -19,7 +19,7 @@ const requestNonCoreApiVersionsInjectable = getInjectable({ return { callWasSuccessful: true, - response: chain(groups.values()) + response: iter.chain(groups.values()) .flatMap(group => group.versions.map(version => ({ group: group.name, path: `/apis/${version.groupVersion}`, diff --git a/packages/core/src/main/cluster/store-migrations/5.0.0-beta.10.injectable.ts b/packages/core/src/main/cluster/store-migrations/5.0.0-beta.10.injectable.ts index 0199e57c97..026ded3d1b 100644 --- a/packages/core/src/main/cluster/store-migrations/5.0.0-beta.10.injectable.ts +++ b/packages/core/src/main/cluster/store-migrations/5.0.0-beta.10.injectable.ts @@ -8,7 +8,7 @@ import { clusterStoreMigrationInjectionToken } from "../../../common/cluster-sto import type { ClusterModel } from "../../../common/cluster-types"; import readJsonSyncInjectable from "../../../common/fs/read-json-sync.injectable"; import joinPathsInjectable from "../../../common/path/join-paths.injectable"; -import { isErrnoException } from "../../../common/utils"; +import { isErrnoException } from "@k8slens/utilities"; interface Pre500WorkspaceStoreModel { workspaces: { @@ -17,6 +17,10 @@ interface Pre500WorkspaceStoreModel { }[]; } +interface Pre500ClusterModel extends ClusterModel { + workspace?: string; +} + const v500Beta10ClusterStoreMigrationInjectable = getInjectable({ id: "v5.0.0-beta.10-cluster-store-migration", instantiate: (di) => { @@ -35,7 +39,7 @@ const v500Beta10ClusterStoreMigrationInjectable = getInjectable({ workspaces.set(id, name); } - const clusters = (store.get("clusters") ?? []) as ClusterModel[]; + const clusters = (store.get("clusters") ?? []) as Pre500ClusterModel[]; for (const cluster of clusters) { if (cluster.workspace) { diff --git a/packages/core/src/main/cluster/store-migrations/5.0.0-beta.13.injectable.ts b/packages/core/src/main/cluster/store-migrations/5.0.0-beta.13.injectable.ts index d8f0368df4..9137c81fed 100644 --- a/packages/core/src/main/cluster/store-migrations/5.0.0-beta.13.injectable.ts +++ b/packages/core/src/main/cluster/store-migrations/5.0.0-beta.13.injectable.ts @@ -6,8 +6,17 @@ import type { ClusterModel, ClusterPreferences, ClusterPrometheusPreferences } from "../../../common/cluster-types"; import { moveSync, removeSync } from "fs-extra"; import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; -import { isDefined } from "../../../common/utils"; +import { isDefined } from "@k8slens/utilities"; import joinPathsInjectable from "../../../common/path/join-paths.injectable"; +import { getInjectable } from "@ogre-tools/injectable"; +import loggerInjectable from "../../../common/logger.injectable"; +import { clusterStoreMigrationInjectionToken } from "../../../common/cluster-store/migration-token"; +import { generateNewIdFor } from "../../../common/utils/generate-new-id-for"; + +interface Pre500ClusterModel extends ClusterModel { + workspace?: string; + workspaces?: string[]; +} function mergePrometheusPreferences(left: ClusterPrometheusPreferences, right: ClusterPrometheusPreferences): ClusterPrometheusPreferences { if (left.prometheus && left.prometheusProvider) { @@ -27,24 +36,15 @@ function mergePrometheusPreferences(left: ClusterPrometheusPreferences, right: C return {}; } -function mergePreferences(left: ClusterPreferences, right: ClusterPreferences): ClusterPreferences { - return { - terminalCWD: left.terminalCWD || right.terminalCWD || undefined, - clusterName: left.clusterName || right.clusterName || undefined, - iconOrder: left.iconOrder || right.iconOrder || undefined, - icon: left.icon || right.icon || undefined, - httpsProxy: left.httpsProxy || right.httpsProxy || undefined, - hiddenMetrics: mergeSet(left.hiddenMetrics ?? [], right.hiddenMetrics ?? []), - ...mergePrometheusPreferences(left, right), - }; -} - -function mergeLabels(left: Record, right: Record): Record { - return { - ...right, - ...left, - }; -} +const mergePreferences = (left: ClusterPreferences, right: ClusterPreferences): ClusterPreferences => ({ + terminalCWD: left.terminalCWD || right.terminalCWD || undefined, + clusterName: left.clusterName || right.clusterName || undefined, + iconOrder: left.iconOrder || right.iconOrder || undefined, + icon: left.icon || right.icon || undefined, + httpsProxy: left.httpsProxy || right.httpsProxy || undefined, + hiddenMetrics: mergeSet(left.hiddenMetrics ?? [], right.hiddenMetrics ?? []), + ...mergePrometheusPreferences(left, right), +}); function mergeSet(...iterables: Iterable[]): string[] { const res = new Set(); @@ -60,24 +60,17 @@ function mergeSet(...iterables: Iterable[]): string[] { return [...res]; } -function mergeClusterModel(prev: ClusterModel, right: Omit): ClusterModel { - return { - id: prev.id, - kubeConfigPath: prev.kubeConfigPath, - contextName: prev.contextName, - preferences: mergePreferences(prev.preferences ?? {}, right.preferences ?? {}), - metadata: prev.metadata, - labels: mergeLabels(prev.labels ?? {}, right.labels ?? {}), - accessibleNamespaces: mergeSet(prev.accessibleNamespaces ?? [], right.accessibleNamespaces ?? []), - workspace: prev.workspace || right.workspace, - workspaces: mergeSet([prev.workspace, right.workspace], prev.workspaces ?? [], right.workspaces ?? []), - }; -} - -import { getInjectable } from "@ogre-tools/injectable"; -import loggerInjectable from "../../../common/logger.injectable"; -import { clusterStoreMigrationInjectionToken } from "../../../common/cluster-store/migration-token"; -import { generateNewIdFor } from "../../../common/utils/generate-new-id-for"; +const mergeClusterModel = (prev: Pre500ClusterModel, right: Omit): Pre500ClusterModel => ({ + id: prev.id, + kubeConfigPath: prev.kubeConfigPath, + contextName: prev.contextName, + preferences: mergePreferences(prev.preferences ?? {}, right.preferences ?? {}), + metadata: prev.metadata, + labels: { ...(right.labels ?? {}), ...(prev.labels ?? {}) }, + accessibleNamespaces: mergeSet(prev.accessibleNamespaces ?? [], right.accessibleNamespaces ?? []), + workspace: prev.workspace || right.workspace, + workspaces: mergeSet([prev.workspace, right.workspace], prev.workspaces ?? [], right.workspaces ?? []), +}); const v500Beta13ClusterStoreMigrationInjectable = getInjectable({ id: "v5.0.0-beta.13-cluster-store-migration", @@ -104,8 +97,8 @@ const v500Beta13ClusterStoreMigrationInjectable = getInjectable({ version: "5.0.0-beta.13", run(store) { const folder = joinPaths(userDataPath, "lens-local-storage"); - const oldClusters = (store.get("clusters") ?? []) as ClusterModel[]; - const clusters = new Map(); + const oldClusters = (store.get("clusters") ?? []) as Pre500ClusterModel[]; + const clusters = new Map(); for (const { id: oldId, ...cluster } of oldClusters) { const newId = generateNewIdFor(cluster); diff --git a/packages/core/src/main/cluster/update-entity-metadata.injectable.ts b/packages/core/src/main/cluster/update-entity-metadata.injectable.ts index 102cd9ded0..b236ac1dcf 100644 --- a/packages/core/src/main/cluster/update-entity-metadata.injectable.ts +++ b/packages/core/src/main/cluster/update-entity-metadata.injectable.ts @@ -3,6 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; +import { toJS } from "mobx"; import type { KubernetesCluster } from "../../common/catalog-entities"; import { ClusterMetadataKey } from "../../common/cluster-types"; import type { Cluster } from "../../common/cluster/cluster"; @@ -17,10 +18,10 @@ const updateEntityMetadataInjectable = getInjectable({ return (entity, cluster) => { entity.metadata.labels = { ...entity.metadata.labels, - ...cluster.labels, + ...toJS(cluster.labels), }; - entity.metadata.distro = cluster.distribution; - entity.metadata.kubeVersion = cluster.version; + entity.metadata.distro = cluster.distribution.get(); + entity.metadata.kubeVersion = cluster.version.get(); enumKeys(ClusterMetadataKey).forEach((key) => { const metadataKey = ClusterMetadataKey[key]; diff --git a/packages/core/src/main/cluster/update-entity-metadata.test.ts b/packages/core/src/main/cluster/update-entity-metadata.test.ts index 8583dc2702..13683196bb 100644 --- a/packages/core/src/main/cluster/update-entity-metadata.test.ts +++ b/packages/core/src/main/cluster/update-entity-metadata.test.ts @@ -7,8 +7,8 @@ import appPathsStateInjectable from "../../common/app-paths/app-paths-state.inje import directoryForUserDataInjectable from "../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; import { KubernetesCluster } from "../../common/catalog-entities"; import { ClusterMetadataKey } from "../../common/cluster-types"; -import type { Cluster } from "../../common/cluster/cluster"; -import { createClusterInjectionToken } from "../../common/cluster/create-cluster-injection-token"; +import { Cluster } from "../../common/cluster/cluster"; +import { replaceObservableObject } from "../../common/utils/replace-observable-object"; import { getDiForUnitTesting } from "../getDiForUnitTesting"; import type { UpdateEntityMetadata } from "./update-entity-metadata.injectable"; import updateEntityMetadataInjectable from "./update-entity-metadata.injectable"; @@ -27,11 +27,10 @@ describe("update-entity-metadata", () => { get: () => ({} as AppPaths), set: () => {}, })); - const createCluster = di.inject(createClusterInjectionToken); updateEntityMetadata = di.inject(updateEntityMetadataInjectable); - cluster = createCluster({ + cluster = new Cluster({ id: "some-id", contextName: "some-context", kubeConfigPath: "minikube-config.yml", @@ -50,10 +49,6 @@ describe("update-entity-metadata", () => { }, }; - cluster.metadata = { - ...cluster.metadata, - }; - entity = new KubernetesCluster({ metadata: { uid: "some-uid", @@ -125,9 +120,9 @@ describe("update-entity-metadata", () => { }); it("given cluster has labels, updates entity metadata with labels", () => { - cluster.labels = { + replaceObservableObject(cluster.labels, { "some-label": "some-value", - }; + }); entity.metadata.labels = { "some-other-label": "some-other-value", }; @@ -139,9 +134,9 @@ describe("update-entity-metadata", () => { }); it("given cluster has labels, overwrites entity metadata with cluster labels", () => { - cluster.labels = { + replaceObservableObject(cluster.labels, { "some-label": "some-cluster-value", - }; + }); entity.metadata.labels = { "some-label": "some-entity-value", }; diff --git a/packages/core/src/main/cluster/update-entity-spec.test.ts b/packages/core/src/main/cluster/update-entity-spec.test.ts index 60be847ebe..1cd9ed4f96 100644 --- a/packages/core/src/main/cluster/update-entity-spec.test.ts +++ b/packages/core/src/main/cluster/update-entity-spec.test.ts @@ -6,8 +6,7 @@ import type { AppPaths } from "../../common/app-paths/app-path-injection-token"; import appPathsStateInjectable from "../../common/app-paths/app-paths-state.injectable"; import directoryForUserDataInjectable from "../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; import { KubernetesCluster } from "../../common/catalog-entities"; -import type { Cluster } from "../../common/cluster/cluster"; -import { createClusterInjectionToken } from "../../common/cluster/create-cluster-injection-token"; +import { Cluster } from "../../common/cluster/cluster"; import { getDiForUnitTesting } from "../getDiForUnitTesting"; import type { UpdateEntitySpec } from "./update-entity-spec.injectable"; import updateEntitySpecInjectable from "./update-entity-spec.injectable"; @@ -25,11 +24,10 @@ describe("update-entity-spec", () => { get: () => ({} as AppPaths), set: () => {}, })); - const createCluster = di.inject(createClusterInjectionToken); updateEntitySpec = di.inject(updateEntitySpecInjectable); - cluster = createCluster({ + cluster = new Cluster({ id: "some-id", contextName: "some-context", kubeConfigPath: "minikube-config.yml", diff --git a/packages/core/src/main/context-handler/context-handler.ts b/packages/core/src/main/context-handler/context-handler.ts deleted file mode 100644 index 7d40bfcd00..0000000000 --- a/packages/core/src/main/context-handler/context-handler.ts +++ /dev/null @@ -1,219 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import type { PrometheusProvider, PrometheusService } from "../prometheus/provider"; -import type { ClusterPrometheusPreferences } from "../../common/cluster-types"; -import type { Cluster } from "../../common/cluster/cluster"; -import type httpProxy from "http-proxy"; -import type { UrlWithStringQuery } from "url"; -import url from "url"; -import { CoreV1Api } from "@kubernetes/client-node"; -import type { KubeAuthProxy } from "../kube-auth-proxy/kube-auth-proxy"; -import type { CreateKubeAuthProxy } from "../kube-auth-proxy/create-kube-auth-proxy.injectable"; -import type { GetPrometheusProviderByKind } from "../prometheus/get-by-kind.injectable"; -import type { IComputedValue } from "mobx"; -import type { Logger } from "../../common/logger"; - -export interface PrometheusDetails { - prometheusPath: string; - provider: PrometheusProvider; -} - -interface PrometheusServicePreferences { - namespace: string; - service: string; - port: number; - prefix: string; -} - -export interface ContextHandlerDependencies { - createKubeAuthProxy: CreateKubeAuthProxy; - getPrometheusProviderByKind: GetPrometheusProviderByKind; - readonly authProxyCa: string; - readonly prometheusProviders: IComputedValue; - readonly logger: Logger; -} - -export interface ClusterContextHandler { - readonly clusterUrl: UrlWithStringQuery; - setupPrometheus(preferences?: ClusterPrometheusPreferences): void; - getPrometheusDetails(): Promise; - resolveAuthProxyUrl(): Promise; - resolveAuthProxyCa(): string; - getApiTarget(isLongRunningRequest?: boolean): Promise; - restartServer(): Promise; - ensureServer(): Promise; - stopServer(): void; -} - -export class ContextHandler implements ClusterContextHandler { - public readonly clusterUrl: UrlWithStringQuery; - protected kubeAuthProxy?: KubeAuthProxy; - protected apiTarget?: httpProxy.ServerOptions; - protected prometheusProvider?: string; - protected prometheus?: PrometheusServicePreferences; - - constructor(private readonly dependencies: ContextHandlerDependencies, protected readonly cluster: Cluster) { - this.clusterUrl = url.parse(cluster.apiUrl); - this.setupPrometheus(cluster.preferences); - } - - public setupPrometheus(preferences: ClusterPrometheusPreferences = {}) { - this.prometheusProvider = preferences.prometheusProvider?.type; - this.prometheus = preferences.prometheus; - } - - public async getPrometheusDetails(): Promise { - const service = await this.getPrometheusService(); - const prometheusPath = this.ensurePrometheusPath(service); - const provider = this.ensurePrometheusProvider(service); - - return { prometheusPath, provider }; - } - - protected ensurePrometheusPath({ service, namespace, port }: PrometheusService): string { - return `${namespace}/services/${service}:${port}`; - } - - protected ensurePrometheusProvider(service: PrometheusService): PrometheusProvider { - if (!this.prometheusProvider) { - this.dependencies.logger.info(`[CONTEXT-HANDLER]: using ${service.kind} as prometheus provider for clusterId=${this.cluster.id}`); - this.prometheusProvider = service.kind; - } - - return this.dependencies.getPrometheusProviderByKind(this.prometheusProvider); - } - - protected listPotentialProviders(): PrometheusProvider[] { - const provider = this.prometheusProvider && this.dependencies.getPrometheusProviderByKind(this.prometheusProvider); - - if (provider) { - return [provider]; - } - - return this.dependencies.prometheusProviders.get(); - } - - protected async getPrometheusService(): Promise { - this.setupPrometheus(this.cluster.preferences); - - if (this.prometheus && this.prometheusProvider) { - return { - kind: this.prometheusProvider, - namespace: this.prometheus.namespace, - service: this.prometheus.service, - port: this.prometheus.port, - }; - } - - const providers = this.listPotentialProviders(); - const proxyConfig = await this.cluster.getProxyKubeconfig(); - const apiClient = proxyConfig.makeApiClient(CoreV1Api); - const potentialServices = await Promise.allSettled( - providers.map(provider => provider.getPrometheusService(apiClient)), - ); - const errors = []; - - for (const res of potentialServices) { - switch (res.status) { - case "rejected": - errors.push(res.reason); - break; - - case "fulfilled": - if (res.value) { - return res.value; - } - } - } - - throw new Error("No Prometheus service found", { cause: errors }); - } - - async resolveAuthProxyUrl(): Promise { - const kubeAuthProxy = await this.ensureServerHelper(); - - return `https://127.0.0.1:${kubeAuthProxy.port}${kubeAuthProxy.apiPrefix}`; - } - - resolveAuthProxyCa() { - return this.dependencies.authProxyCa; - } - - async getApiTarget(isLongRunningRequest = false): Promise { - const timeout = isLongRunningRequest ? 4 * 60 * 60_000 : 30_000; // 4 hours for long running request, 30 seconds for the rest - - if (isLongRunningRequest) { - return this.newApiTarget(timeout); - } - - return this.apiTarget ??= await this.newApiTarget(timeout); - } - - protected async newApiTarget(timeout: number): Promise { - const kubeAuthProxy = await this.ensureServerHelper(); - const headers: Record = {}; - - if (this.clusterUrl.hostname) { - headers.Host = this.clusterUrl.hostname; - - // fix current IPv6 inconsistency in url.Parse() and httpProxy. - // with url.Parse the IPv6 Hostname has no Square brackets but httpProxy needs the Square brackets to work. - if (headers.Host.includes(":")) { - headers.Host = `[${headers.Host}]`; - } - } - - return { - target: { - protocol: "https:", - host: "127.0.0.1", - port: kubeAuthProxy.port, - path: kubeAuthProxy.apiPrefix, - ca: this.resolveAuthProxyCa(), - }, - changeOrigin: true, - timeout, - secure: true, - headers, - }; - } - - protected async ensureServerHelper(): Promise { - if (!this.kubeAuthProxy) { - const proxyEnv = Object.assign({}, process.env); - - if (this.cluster.preferences.httpsProxy) { - proxyEnv.HTTPS_PROXY = this.cluster.preferences.httpsProxy; - } - this.kubeAuthProxy = this.dependencies.createKubeAuthProxy(this.cluster, proxyEnv); - await this.kubeAuthProxy.run(); - - return this.kubeAuthProxy; - } - - await this.kubeAuthProxy.whenReady; - - return this.kubeAuthProxy; - } - - async ensureServer(): Promise { - await this.ensureServerHelper(); - } - - async restartServer(): Promise { - this.stopServer(); - - await this.ensureServerHelper(); - } - - stopServer() { - this.prometheus = undefined; - this.prometheusProvider = undefined; - this.kubeAuthProxy?.exit(); - this.kubeAuthProxy = undefined; - this.apiTarget = undefined; - } -} diff --git a/packages/core/src/main/context-handler/create-context-handler.injectable.ts b/packages/core/src/main/context-handler/create-context-handler.injectable.ts deleted file mode 100644 index 1567721ac4..0000000000 --- a/packages/core/src/main/context-handler/create-context-handler.injectable.ts +++ /dev/null @@ -1,38 +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 { Cluster } from "../../common/cluster/cluster"; -import type { ClusterContextHandler, ContextHandlerDependencies } from "./context-handler"; -import { ContextHandler } from "./context-handler"; -import createKubeAuthProxyInjectable from "../kube-auth-proxy/create-kube-auth-proxy.injectable"; -import kubeAuthProxyCertificateInjectable from "../kube-auth-proxy/kube-auth-proxy-certificate.injectable"; -import URLParse from "url-parse"; -import getPrometheusProviderByKindInjectable from "../prometheus/get-by-kind.injectable"; -import prometheusProvidersInjectable from "../prometheus/providers.injectable"; -import loggerInjectable from "../../common/logger.injectable"; - -const createContextHandlerInjectable = getInjectable({ - id: "create-context-handler", - - instantiate: (di) => { - const dependencies: Omit = { - createKubeAuthProxy: di.inject(createKubeAuthProxyInjectable), - getPrometheusProviderByKind: di.inject(getPrometheusProviderByKindInjectable), - prometheusProviders: di.inject(prometheusProvidersInjectable), - logger: di.inject(loggerInjectable), - }; - - return (cluster: Cluster): ClusterContextHandler => { - const clusterUrl = new URLParse(cluster.apiUrl); - - return new ContextHandler({ - ...dependencies, - authProxyCa: di.inject(kubeAuthProxyCertificateInjectable, clusterUrl.hostname).cert, - }, cluster); - }; - }, -}); - -export default createContextHandlerInjectable; diff --git a/packages/core/src/main/create-cluster/create-cluster.injectable.ts b/packages/core/src/main/create-cluster/create-cluster.injectable.ts deleted file mode 100644 index 79eee5a151..0000000000 --- a/packages/core/src/main/create-cluster/create-cluster.injectable.ts +++ /dev/null @@ -1,49 +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 { ClusterDependencies } from "../../common/cluster/cluster"; -import { Cluster } from "../../common/cluster/cluster"; -import directoryForKubeConfigsInjectable from "../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable"; -import createKubeconfigManagerInjectable from "../kubeconfig-manager/create-kubeconfig-manager.injectable"; -import createKubectlInjectable from "../kubectl/create-kubectl.injectable"; -import createContextHandlerInjectable from "../context-handler/create-context-handler.injectable"; -import { createClusterInjectionToken } from "../../common/cluster/create-cluster-injection-token"; -import authorizationReviewInjectable from "../../common/cluster/authorization-review.injectable"; -import listNamespacesInjectable from "../../common/cluster/list-namespaces.injectable"; -import createListApiResourcesInjectable from "../cluster/request-api-resources.injectable"; -import loggerInjectable from "../../common/logger.injectable"; -import broadcastMessageInjectable from "../../common/ipc/broadcast-message.injectable"; -import loadConfigfromFileInjectable from "../../common/kube-helpers/load-config-from-file.injectable"; -import requestNamespaceListPermissionsForInjectable from "../../common/cluster/request-namespace-list-permissions.injectable"; -import detectClusterMetadataInjectable from "../cluster-detectors/detect-cluster-metadata.injectable"; -import clusterVersionDetectorInjectable from "../cluster-detectors/cluster-version-detector.injectable"; - -const createClusterInjectable = getInjectable({ - id: "create-cluster", - - instantiate: (di) => { - const dependencies: ClusterDependencies = { - directoryForKubeConfigs: di.inject(directoryForKubeConfigsInjectable), - logger: di.inject(loggerInjectable), - clusterVersionDetector: di.inject(clusterVersionDetectorInjectable), - createKubeconfigManager: di.inject(createKubeconfigManagerInjectable), - createKubectl: di.inject(createKubectlInjectable), - createContextHandler: di.inject(createContextHandlerInjectable), - createAuthorizationReview: di.inject(authorizationReviewInjectable), - requestNamespaceListPermissionsFor: di.inject(requestNamespaceListPermissionsForInjectable), - requestApiResources: di.inject(createListApiResourcesInjectable), - createListNamespaces: di.inject(listNamespacesInjectable), - broadcastMessage: di.inject(broadcastMessageInjectable), - loadConfigfromFile: di.inject(loadConfigfromFileInjectable), - detectClusterMetadata: di.inject(detectClusterMetadataInjectable), - }; - - return (model, configData) => new Cluster(dependencies, model, configData); - }, - - injectionToken: createClusterInjectionToken, -}); - -export default createClusterInjectable; diff --git a/packages/core/src/main/crypto/random-uuid.global-override-for-injectable.ts b/packages/core/src/main/crypto/random-uuid.global-override-for-injectable.ts index 63e5364a8a..936e30c709 100644 --- a/packages/core/src/main/crypto/random-uuid.global-override-for-injectable.ts +++ b/packages/core/src/main/crypto/random-uuid.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import randomUUIDInjectable from "./random-uuid.injectable"; export default getGlobalOverride(randomUUIDInjectable, () => () => { diff --git a/packages/core/src/main/electron-app/electron-app.global-override-for-injectable.ts b/packages/core/src/main/electron-app/electron-app.global-override-for-injectable.ts index e225745ca3..919303dd08 100644 --- a/packages/core/src/main/electron-app/electron-app.global-override-for-injectable.ts +++ b/packages/core/src/main/electron-app/electron-app.global-override-for-injectable.ts @@ -4,7 +4,7 @@ */ import { kebabCase } from "lodash"; -import { getGlobalOverride } from "../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import electronAppInjectable from "./electron-app.injectable"; export default getGlobalOverride(electronAppInjectable, () => { diff --git a/packages/core/src/main/electron-app/features/electron-dialog.global-override-for-injectable.ts b/packages/core/src/main/electron-app/features/electron-dialog.global-override-for-injectable.ts index 8ccafcfe7a..117c8a3fbd 100644 --- a/packages/core/src/main/electron-app/features/electron-dialog.global-override-for-injectable.ts +++ b/packages/core/src/main/electron-app/features/electron-dialog.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import electronDialogInjectable from "./electron-dialog.injectable"; export default getGlobalOverride(electronDialogInjectable, () => ({ diff --git a/packages/core/src/main/electron-app/features/native-theme.global-override-for-injectable.ts b/packages/core/src/main/electron-app/features/native-theme.global-override-for-injectable.ts index 47c957c722..7e18ea6f15 100644 --- a/packages/core/src/main/electron-app/features/native-theme.global-override-for-injectable.ts +++ b/packages/core/src/main/electron-app/features/native-theme.global-override-for-injectable.ts @@ -4,7 +4,7 @@ */ import EventEmitter from "events"; -import { getGlobalOverride } from "../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import nativeThemeInjectable from "./native-theme.injectable"; export default getGlobalOverride(nativeThemeInjectable, () => Object.assign(new EventEmitter(), { diff --git a/packages/core/src/main/electron-app/features/show-open-dialog.global-override-for-injectable.ts b/packages/core/src/main/electron-app/features/show-open-dialog.global-override-for-injectable.ts index 94e9afbeb4..5015b2c07f 100644 --- a/packages/core/src/main/electron-app/features/show-open-dialog.global-override-for-injectable.ts +++ b/packages/core/src/main/electron-app/features/show-open-dialog.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverrideForFunction } from "../../../common/test-utils/get-global-override-for-function"; +import { getGlobalOverrideForFunction } from "@k8slens/test-utils"; import showOpenDialogInjectable from "./show-open-dialog.injectable"; export default getGlobalOverrideForFunction(showOpenDialogInjectable); diff --git a/packages/core/src/main/electron-app/runnables/clean-up-deep-linking.injectable.ts b/packages/core/src/main/electron-app/runnables/clean-up-deep-linking.injectable.ts index b5088a667a..19fb7e1143 100644 --- a/packages/core/src/main/electron-app/runnables/clean-up-deep-linking.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/clean-up-deep-linking.injectable.ts @@ -3,20 +3,21 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { beforeQuitOfBackEndInjectionToken } from "../../start-main-application/runnable-tokens/before-quit-of-back-end-injection-token"; +import { beforeQuitOfBackEndInjectionToken } from "../../start-main-application/runnable-tokens/phases"; import lensProtocolRouterMainInjectable from "../../protocol-handler/lens-protocol-router-main/lens-protocol-router-main.injectable"; const cleanUpDeepLinkingInjectable = getInjectable({ id: "clean-up-deep-linking", - instantiate: (di) => { - const lensProtocolRouterMain = di.inject(lensProtocolRouterMainInjectable); + instantiate: (di) => ({ + run: () => { + const lensProtocolRouterMain = di.inject(lensProtocolRouterMainInjectable); - return { - id: "clean-up-deep-linking", - run: () => void lensProtocolRouterMain.cleanup(), - }; - }, + lensProtocolRouterMain.cleanup(); + + return undefined; + }, + }), injectionToken: beforeQuitOfBackEndInjectionToken, }); diff --git a/packages/core/src/main/electron-app/runnables/dock-visibility/hide-dock-for-last-closed-window.injectable.ts b/packages/core/src/main/electron-app/runnables/dock-visibility/hide-dock-for-last-closed-window.injectable.ts index 5586c93586..e61af65da4 100644 --- a/packages/core/src/main/electron-app/runnables/dock-visibility/hide-dock-for-last-closed-window.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/dock-visibility/hide-dock-for-last-closed-window.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 { beforeQuitOfFrontEndInjectionToken } from "../../../start-main-application/runnable-tokens/before-quit-of-front-end-injection-token"; +import { beforeQuitOfFrontEndInjectionToken } from "../../../start-main-application/runnable-tokens/phases"; import electronAppInjectable from "../../electron-app.injectable"; import { isEmpty } from "lodash/fp"; import getVisibleWindowsInjectable from "../../../start-main-application/lens-window/get-visible-windows.injectable"; @@ -11,23 +11,19 @@ import getVisibleWindowsInjectable from "../../../start-main-application/lens-wi const hideDockForLastClosedWindowInjectable = getInjectable({ id: "hide-dock-when-there-are-no-windows", - instantiate: (di) => { - const app = di.inject(electronAppInjectable); - const getVisibleWindows = di.inject(getVisibleWindowsInjectable); + instantiate: (di) => ({ + run: () => { + const app = di.inject(electronAppInjectable); + const getVisibleWindows = di.inject(getVisibleWindowsInjectable); + const visibleWindows = getVisibleWindows(); - return { - id: "hide-dock-when-there-are-no-windows", - run: () => { - const visibleWindows = getVisibleWindows(); + if (isEmpty(visibleWindows)) { + app.dock?.hide(); + } - if (isEmpty(visibleWindows)) { - app.dock?.hide(); - } - - return undefined; - }, - }; - }, + return undefined; + }, + }), injectionToken: beforeQuitOfFrontEndInjectionToken, }); diff --git a/packages/core/src/main/electron-app/runnables/dock-visibility/show-dock-for-first-opened-window.injectable.ts b/packages/core/src/main/electron-app/runnables/dock-visibility/show-dock-for-first-opened-window.injectable.ts index b47e511c14..9f52dcab42 100644 --- a/packages/core/src/main/electron-app/runnables/dock-visibility/show-dock-for-first-opened-window.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/dock-visibility/show-dock-for-first-opened-window.injectable.ts @@ -4,21 +4,18 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import electronAppInjectable from "../../electron-app.injectable"; -import { afterWindowIsOpenedInjectionToken } from "../../../start-main-application/runnable-tokens/after-window-is-opened-injection-token"; +import { afterWindowIsOpenedInjectionToken } from "../../../start-main-application/runnable-tokens/phases"; const showDockForFirstOpenedWindowInjectable = getInjectable({ id: "show-dock-for-first-opened-window", - instantiate: (di) => { - const app = di.inject(electronAppInjectable); + instantiate: (di) => ({ + run: () => { + const app = di.inject(electronAppInjectable); - return { - id: "show-dock-for-first-opened-window", - run: () => { - app.dock?.show(); - }, - }; - }, + app.dock?.show(); + }, + }), injectionToken: afterWindowIsOpenedInjectionToken, }); diff --git a/packages/core/src/main/electron-app/runnables/enforce-single-application-instance.injectable.ts b/packages/core/src/main/electron-app/runnables/enforce-single-application-instance.injectable.ts index 1868f61a8a..3dfe63430d 100644 --- a/packages/core/src/main/electron-app/runnables/enforce-single-application-instance.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/enforce-single-application-instance.injectable.ts @@ -10,21 +10,18 @@ import exitAppInjectable from "../features/exit-app.injectable"; const enforceSingleApplicationInstanceInjectable = getInjectable({ id: "enforce-single-application-instance", - instantiate: (di) => { - const requestSingleInstanceLock = di.inject(requestSingleInstanceLockInjectable); - const exitApp = di.inject(exitAppInjectable); + instantiate: (di) => ({ + run: () => { + const requestSingleInstanceLock = di.inject(requestSingleInstanceLockInjectable); + const exitApp = di.inject(exitAppInjectable); - return { - id: "enforce-single-application-instance", - run: () => { - if (!requestSingleInstanceLock()) { - exitApp(); - } + if (!requestSingleInstanceLock()) { + exitApp(); + } - return undefined; - }, - }; - }, + return undefined; + }, + }), injectionToken: beforeElectronIsReadyInjectionToken, }); diff --git a/packages/core/src/main/electron-app/runnables/setup-application-name.injectable.ts b/packages/core/src/main/electron-app/runnables/setup-application-name.injectable.ts index fe86f6d0e2..5935aec41c 100644 --- a/packages/core/src/main/electron-app/runnables/setup-application-name.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/setup-application-name.injectable.ts @@ -10,19 +10,16 @@ import electronAppInjectable from "../electron-app.injectable"; const setupApplicationNameInjectable = getInjectable({ id: "setup-application-name", - instantiate: (di) => { - const app = di.inject(electronAppInjectable); - const appName = di.inject(appNameInjectable); + instantiate: (di) => ({ + run: () => { + const app = di.inject(electronAppInjectable); + const appName = di.inject(appNameInjectable); - return { - id: "setup-application-name", - run: () => { - app.setName(appName); + app.setName(appName); - return undefined; - }, - }; - }, + return undefined; + }, + }), injectionToken: beforeElectronIsReadyInjectionToken, }); diff --git a/packages/core/src/main/electron-app/runnables/setup-deep-linking.injectable.ts b/packages/core/src/main/electron-app/runnables/setup-deep-linking.injectable.ts index f4a7f8eccd..a7a4c7b34c 100644 --- a/packages/core/src/main/electron-app/runnables/setup-deep-linking.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/setup-deep-linking.injectable.ts @@ -7,68 +7,63 @@ import electronAppInjectable from "../electron-app.injectable"; import openDeepLinkInjectable from "../../protocol-handler/lens-protocol-router-main/open-deep-link-for-url/open-deep-link.injectable"; import loggerInjectable from "../../../common/logger.injectable"; import commandLineArgumentsInjectable from "../../utils/command-line-arguments.injectable"; -import { pipeline } from "@ogre-tools/fp"; -import { find, startsWith, toLower, map } from "lodash/fp"; +import { startsWith, toLower } from "lodash/fp"; import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; import showApplicationWindowInjectable from "../../start-main-application/lens-window/show-application-window.injectable"; const setupDeepLinkingInjectable = getInjectable({ id: "setup-deep-linking", - instantiate: (di) => { - const app = di.inject(electronAppInjectable); - const logger = di.inject(loggerInjectable); - const openDeepLinkForUrl = di.inject(openDeepLinkInjectable); - const showApplicationWindow = di.inject(showApplicationWindowInjectable); + instantiate: (di) => ({ + run: async () => { + const app = di.inject(electronAppInjectable); + const logger = di.inject(loggerInjectable); + const openDeepLinkForUrl = di.inject(openDeepLinkInjectable); + const showApplicationWindow = di.inject(showApplicationWindowInjectable); + const firstInstanceCommandLineArguments = di.inject(commandLineArgumentsInjectable); - const firstInstanceCommandLineArguments = di.inject( - commandLineArgumentsInjectable, - ); + logger.info(`📟 Setting protocol client for lens://`); - return { - id: "setup-deep-linking", - run: async () => { - logger.info(`📟 Setting protocol client for lens://`); + if (app.setAsDefaultProtocolClient("lens")) { + logger.info("📟 Protocol client register succeeded ✅"); + } else { + logger.info("📟 Protocol client register failed ❗"); + } - if (app.setAsDefaultProtocolClient("lens")) { - logger.info("📟 Protocol client register succeeded ✅"); - } else { - logger.info("📟 Protocol client register failed ❗"); - } + const url = getDeepLinkUrl(firstInstanceCommandLineArguments); - const url = getDeepLinkUrl(firstInstanceCommandLineArguments); + if (url) { + await openDeepLinkForUrl(url); + } - if (url) { - await openDeepLinkForUrl(url); - } + app.on("open-url", async (event, url) => { + event.preventDefault(); - app.on("open-url", async (event, url) => { - event.preventDefault(); + await openDeepLinkForUrl(url); + }); - await openDeepLinkForUrl(url); - }); + app.on( + "second-instance", + async (_, secondInstanceCommandLineArguments) => { + const url = getDeepLinkUrl(secondInstanceCommandLineArguments); - app.on( - "second-instance", + await showApplicationWindow(); - async (_, secondInstanceCommandLineArguments) => { - const url = getDeepLinkUrl(secondInstanceCommandLineArguments); - - await showApplicationWindow(); - - if (url) { - await openDeepLinkForUrl(url); - } - }, - ); - }, - }; - }, + if (url) { + await openDeepLinkForUrl(url); + } + }, + ); + }, + }), injectionToken: onLoadOfApplicationInjectionToken, }); export default setupDeepLinkingInjectable; -const getDeepLinkUrl = (commandLineArguments: string[]) => - pipeline(commandLineArguments, map(toLower), find(startsWith("lens://"))); +const getDeepLinkUrl = (commandLineArguments: string[]) => ( + commandLineArguments + .map(toLower) + .find(startsWith("lens://")) +); diff --git a/packages/core/src/main/electron-app/runnables/setup-developer-tools-in-development-environment.injectable.ts b/packages/core/src/main/electron-app/runnables/setup-developer-tools-in-development-environment.injectable.ts index 5272494a94..06b1f39f33 100644 --- a/packages/core/src/main/electron-app/runnables/setup-developer-tools-in-development-environment.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/setup-developer-tools-in-development-environment.injectable.ts @@ -10,32 +10,33 @@ import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; const setupDeveloperToolsInDevelopmentEnvironmentInjectable = getInjectable({ id: "setup-developer-tools-in-development-environment", - instantiate: (di) => { - const logger = di.inject(loggerInjectable); - const nodeEnv = di.inject(nodeEnvInjectionToken); + instantiate: (di) => ({ + run: () => { + const logger = di.inject(loggerInjectable); + const nodeEnv = di.inject(nodeEnvInjectionToken); - return { - id: "setup-developer-tools-in-development-environment", - run: () => { - if (nodeEnv !== "development") { - return; + if (nodeEnv !== "development") { + return; + } + + logger.info("🤓 Installing developer tools"); + + void (async () => { + try { + const { + default: devToolsInstaller, + REACT_DEVELOPER_TOOLS, + } = await import("electron-devtools-installer"); + + const name = await devToolsInstaller([REACT_DEVELOPER_TOOLS]); + + logger.info(`[DEVTOOLS-INSTALLER]: installed ${name}`); + } catch (error) { + logger.error(`[DEVTOOLS-INSTALLER]: failed`, { error }); } - - logger.info("🤓 Installing developer tools"); - - import("electron-devtools-installer") - .then(({ default: devToolsInstaller, REACT_DEVELOPER_TOOLS }) => - devToolsInstaller([REACT_DEVELOPER_TOOLS]), - ) - .then((name) => - logger.info(`[DEVTOOLS-INSTALLER]: installed ${name}`), - ) - .catch((error) => - logger.error(`[DEVTOOLS-INSTALLER]: failed`, { error }), - ); - }, - }; - }, + })(); + }, + }), injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/main/electron-app/runnables/setup-device-shutdown.injectable.ts b/packages/core/src/main/electron-app/runnables/setup-device-shutdown.injectable.ts index 2c907909af..c1ddeae175 100644 --- a/packages/core/src/main/electron-app/runnables/setup-device-shutdown.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/setup-device-shutdown.injectable.ts @@ -10,19 +10,14 @@ import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; const setupDeviceShutdownInjectable = getInjectable({ id: "setup-device-shutdown", - instantiate: (di) => { - const powerMonitor = di.inject(powerMonitorInjectable); - const exitApp = di.inject(exitAppInjectable); + instantiate: (di) => ({ + run: () => { + const powerMonitor = di.inject(powerMonitorInjectable); + const exitApp = di.inject(exitAppInjectable); - return { - id: "setup-device-shutdown", - run: () => { - powerMonitor.on("shutdown", async () => { - exitApp(); - }); - }, - }; - }, + powerMonitor.on("shutdown", exitApp); + }, + }), injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/main/electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.injectable.ts b/packages/core/src/main/electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.injectable.ts index 69d6f4405b..932e80c61f 100644 --- a/packages/core/src/main/electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.injectable.ts @@ -11,33 +11,32 @@ import applicationMenuItemCompositeInjectable from "../../../../features/applica import emitAppEventInjectable from "../../../../common/app-event-bus/emit-event.injectable"; import getClusterByIdInjectable from "../../../../common/cluster-store/get-by-id.injectable"; import pushCatalogToRendererInjectable from "../../../catalog-sync-to-renderer/push-catalog-to-renderer.injectable"; +import clusterConnectionInjectable from "../../../cluster/cluster-connection.injectable"; const setupIpcMainHandlersInjectable = getInjectable({ id: "setup-ipc-main-handlers", - instantiate: (di) => { - const logger = di.inject(loggerInjectable); - const applicationMenuItemComposite = di.inject(applicationMenuItemCompositeInjectable); - const pushCatalogToRenderer = di.inject(pushCatalogToRendererInjectable); - const clusterStore = di.inject(clusterStoreInjectable); - const emitAppEvent = di.inject(emitAppEventInjectable); - const getClusterById = di.inject(getClusterByIdInjectable); + instantiate: (di) => ({ + run: () => { + const logger = di.inject(loggerInjectable); + const applicationMenuItemComposite = di.inject(applicationMenuItemCompositeInjectable); + const pushCatalogToRenderer = di.inject(pushCatalogToRendererInjectable); + const clusterStore = di.inject(clusterStoreInjectable); + const emitAppEvent = di.inject(emitAppEventInjectable); + const getClusterById = di.inject(getClusterByIdInjectable); - return { - id: "setup-ipc-main-handlers", - run: () => { - logger.debug("[APP-MAIN] initializing ipc main handlers"); + logger.debug("[APP-MAIN] initializing ipc main handlers"); - setupIpcMainHandlers({ - applicationMenuItemComposite, - pushCatalogToRenderer, - clusterStore, - emitAppEvent, - getClusterById, - }); - }, - }; - }, + setupIpcMainHandlers({ + applicationMenuItemComposite, + pushCatalogToRenderer, + clusterStore, + emitAppEvent, + getClusterById, + getClusterConnection: (cluster) => di.inject(clusterConnectionInjectable, cluster), + }); + }, + }), injectionToken: onLoadOfApplicationInjectionToken, causesSideEffects: true, diff --git a/packages/core/src/main/electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.ts b/packages/core/src/main/electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.ts index 4ae020c42d..ddfc3f2003 100644 --- a/packages/core/src/main/electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.ts +++ b/packages/core/src/main/electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.ts @@ -18,12 +18,15 @@ import { getApplicationMenuTemplate } from "../../../../features/application-men import type { MenuItemRoot } from "../../../../features/application-menu/main/application-menu-item-composite.injectable"; import type { EmitAppEvent } from "../../../../common/app-event-bus/emit-event.injectable"; import type { GetClusterById } from "../../../../common/cluster-store/get-by-id.injectable"; +import type { Cluster } from "../../../../common/cluster/cluster"; +import type { ClusterConnection } from "../../../cluster/cluster-connection.injectable"; interface Dependencies { applicationMenuItemComposite: IComputedValue>; clusterStore: ClusterStore; emitAppEvent: EmitAppEvent; getClusterById: GetClusterById; pushCatalogToRenderer: () => void; + getClusterConnection: (cluster: Cluster) => ClusterConnection; } export const setupIpcMainHandlers = ({ @@ -32,10 +35,18 @@ export const setupIpcMainHandlers = ({ emitAppEvent, getClusterById, pushCatalogToRenderer, + getClusterConnection, }: Dependencies) => { - ipcMainHandle(clusterActivateHandler, (event, clusterId: ClusterId, force = false) => { - return getClusterById(clusterId) - ?.activate(force); + ipcMainHandle(clusterActivateHandler, async (event, clusterId: ClusterId, force = false) => { + const cluster = getClusterById(clusterId); + + if (!cluster) { + return; + } + + const clusterConnection = getClusterConnection(cluster); + + await clusterConnection.activate(force); }); ipcMainHandle(clusterSetFrameIdHandler, (event: IpcMainInvokeEvent, clusterId: ClusterId) => { @@ -51,10 +62,14 @@ export const setupIpcMainHandlers = ({ emitAppEvent({ name: "cluster", action: "stop" }); const cluster = getClusterById(clusterId); - if (cluster) { - cluster.disconnect(); - clusterFrameMap.delete(cluster.id); + if (!cluster) { + return; } + + const clusterConnection = getClusterConnection(cluster); + + clusterConnection.disconnect(); + clusterFrameMap.delete(cluster.id); }); ipcMainHandle(windowActionHandleChannel, (event, action) => handleWindowAction(action)); diff --git a/packages/core/src/main/electron-app/runnables/setup-main-window-visibility-after-activation.injectable.ts b/packages/core/src/main/electron-app/runnables/setup-main-window-visibility-after-activation.injectable.ts index 49c2293397..4752599dcc 100644 --- a/packages/core/src/main/electron-app/runnables/setup-main-window-visibility-after-activation.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/setup-main-window-visibility-after-activation.injectable.ts @@ -11,24 +11,21 @@ import showApplicationWindowInjectable from "../../start-main-application/lens-w const setupMainWindowVisibilityAfterActivationInjectable = getInjectable({ id: "setup-main-window-visibility-after-activation", - instantiate: (di) => { - const app = di.inject(electronAppInjectable); - const showApplicationWindow = di.inject(showApplicationWindowInjectable); - const logger = di.inject(loggerInjectable); + instantiate: (di) => ({ + run: () => { + const app = di.inject(electronAppInjectable); + const showApplicationWindow = di.inject(showApplicationWindowInjectable); + const logger = di.inject(loggerInjectable); - return { - id: "setup-main-window-visibility-after-activation", - run: () => { - app.on("activate", async (_, windowIsVisible) => { - logger.info("APP:ACTIVATE", { hasVisibleWindows: windowIsVisible }); + app.on("activate", (_, windowIsVisible) => { + logger.info("APP:ACTIVATE", { hasVisibleWindows: windowIsVisible }); - if (!windowIsVisible) { - await showApplicationWindow(); - } - }); - }, - }; - }, + if (!windowIsVisible) { + void showApplicationWindow(); + } + }); + }, + }), injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/main/electron-app/runnables/setup-runnables-after-window-is-opened.injectable.ts b/packages/core/src/main/electron-app/runnables/setup-runnables-after-window-is-opened.injectable.ts index 1131efad95..5370c0e303 100644 --- a/packages/core/src/main/electron-app/runnables/setup-runnables-after-window-is-opened.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/setup-runnables-after-window-is-opened.injectable.ts @@ -4,28 +4,25 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { beforeElectronIsReadyInjectionToken } from "@k8slens/application-for-electron-main"; +import { afterWindowIsOpenedInjectionToken } from "../../start-main-application/runnable-tokens/phases"; import electronAppInjectable from "../electron-app.injectable"; -import { runManyFor } from "../../../common/runnable/run-many-for"; -import { afterWindowIsOpenedInjectionToken } from "../../start-main-application/runnable-tokens/after-window-is-opened-injection-token"; +import { runManyFor } from "@k8slens/run-many"; const setupRunnablesAfterWindowIsOpenedInjectable = getInjectable({ id: "setup-runnables-after-window-is-opened", - instantiate: (di) => { - const afterWindowIsOpened = runManyFor(di)(afterWindowIsOpenedInjectionToken); - const app = di.inject(electronAppInjectable); + instantiate: (di) => ({ + run: () => { + const afterWindowIsOpened = runManyFor(di)(afterWindowIsOpenedInjectionToken); + const app = di.inject(electronAppInjectable); - return { - id: "setup-runnables-after-window-is-opened", - run: () => { - app.on("browser-window-created", () => { - afterWindowIsOpened(); - }); + app.on("browser-window-created", () => { + afterWindowIsOpened(); + }); - return undefined; - }, - }; - }, + return undefined; + }, + }), injectionToken: beforeElectronIsReadyInjectionToken, }); diff --git a/packages/core/src/main/electron-app/runnables/setup-runnables-before-closing-of-application.injectable.ts b/packages/core/src/main/electron-app/runnables/setup-runnables-before-closing-of-application.injectable.ts index 4090f3f9c6..0ba1b68137 100644 --- a/packages/core/src/main/electron-app/runnables/setup-runnables-before-closing-of-application.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/setup-runnables-before-closing-of-application.injectable.ts @@ -4,50 +4,45 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { beforeElectronIsReadyInjectionToken } from "@k8slens/application-for-electron-main"; -import { beforeQuitOfFrontEndInjectionToken } from "../../start-main-application/runnable-tokens/before-quit-of-front-end-injection-token"; -import { beforeQuitOfBackEndInjectionToken } from "../../start-main-application/runnable-tokens/before-quit-of-back-end-injection-token"; +import { beforeQuitOfFrontEndInjectionToken, beforeQuitOfBackEndInjectionToken } from "../../start-main-application/runnable-tokens/phases"; import electronAppInjectable from "../electron-app.injectable"; import isIntegrationTestingInjectable from "../../../common/vars/is-integration-testing.injectable"; import autoUpdaterInjectable from "../features/auto-updater.injectable"; -import { runManySyncFor } from "../../../common/runnable/run-many-sync-for"; +import { runManySyncFor } from "@k8slens/run-many"; const setupRunnablesBeforeClosingOfApplicationInjectable = getInjectable({ id: "setup-closing-of-application", - instantiate: (di) => { - const runManySync = runManySyncFor(di); - const runRunnablesBeforeQuitOfFrontEnd = runManySync(beforeQuitOfFrontEndInjectionToken); - const runRunnablesBeforeQuitOfBackEnd = runManySync(beforeQuitOfBackEndInjectionToken); - const app = di.inject(electronAppInjectable); - const isIntegrationTesting = di.inject(isIntegrationTestingInjectable); - const autoUpdater = di.inject(autoUpdaterInjectable); + instantiate: (di) => ({ + run: () => { + const runManySync = runManySyncFor(di); + const runRunnablesBeforeQuitOfFrontEnd = runManySync(beforeQuitOfFrontEndInjectionToken); + const runRunnablesBeforeQuitOfBackEnd = runManySync(beforeQuitOfBackEndInjectionToken); + const app = di.inject(electronAppInjectable); + const isIntegrationTesting = di.inject(isIntegrationTestingInjectable); + const autoUpdater = di.inject(autoUpdaterInjectable); + let isAutoUpdating = false; - return { - id: "setup-closing-of-application", - run: () => { - let isAutoUpdating = false; + autoUpdater.on("before-quit-for-update", () => { + isAutoUpdating = true; + }); - autoUpdater.on("before-quit-for-update", () => { - isAutoUpdating = true; - }); + app.on("will-quit", (event) => { + runRunnablesBeforeQuitOfFrontEnd(); - app.on("will-quit", (event) => { - runRunnablesBeforeQuitOfFrontEnd(); + const shouldQuitBackEnd = isIntegrationTesting || isAutoUpdating; - const shouldQuitBackEnd = isIntegrationTesting || isAutoUpdating; + if (shouldQuitBackEnd) { + runRunnablesBeforeQuitOfBackEnd(); + } else { + // IMPORTANT: This cannot be destructured as it would break binding of "this" for the Electron event + event.preventDefault(); + } + }); - if (shouldQuitBackEnd) { - runRunnablesBeforeQuitOfBackEnd(); - } else { - // IMPORTANT: This cannot be destructured as it would break binding of "this" for the Electron event - event.preventDefault(); - } - }); - - return undefined; - }, - }; - }, + return undefined; + }, + }), injectionToken: beforeElectronIsReadyInjectionToken, }); diff --git a/packages/core/src/main/get-metrics.injectable.ts b/packages/core/src/main/get-metrics.injectable.ts index 3731435f6b..9a9141cb9b 100644 --- a/packages/core/src/main/get-metrics.injectable.ts +++ b/packages/core/src/main/get-metrics.injectable.ts @@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { Cluster } from "../common/cluster/cluster"; import { FormData } from "@k8slens/node-fetch"; import type { RequestMetricsParams } from "../common/k8s-api/endpoints/metrics.api/request-metrics.injectable"; -import { object } from "../common/utils"; +import { object } from "@k8slens/utilities"; import k8sRequestInjectable from "./k8s-request.injectable"; export type GetMetrics = (cluster: Cluster, prometheusPath: string, queryParams: RequestMetricsParams & { query: string }) => Promise; diff --git a/packages/core/src/main/getDiForUnitTesting.ts b/packages/core/src/main/getDiForUnitTesting.ts index 9720dcfda3..c4dd2a0d52 100644 --- a/packages/core/src/main/getDiForUnitTesting.ts +++ b/packages/core/src/main/getDiForUnitTesting.ts @@ -26,7 +26,7 @@ import setUpdateOnQuitInjectable from "./electron-app/features/set-update-on-qui 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 "../common/test-utils/get-global-override"; +import type { GlobalOverride } from "@k8slens/test-utils"; import { getOverrideFsWithFakes } from "../test-utils/override-fs-with-fakes"; import { setLegacyGlobalDiForExtensionApi, @@ -53,7 +53,7 @@ export function getDiForUnitTesting() { }); for (const globalOverridePath of global.injectablePaths.main.globalOverridePaths) { - const globalOverride = require(globalOverridePath).default as GlobalOverride; + const globalOverride = require(globalOverridePath).default as GlobalOverride; di.override(globalOverride.injectable, globalOverride.overridingInstantiate); } diff --git a/packages/core/src/main/helm/__tests__/helm-service.test.ts b/packages/core/src/main/helm/__tests__/helm-service.test.ts index 7c9a5a9d02..7740533570 100644 --- a/packages/core/src/main/helm/__tests__/helm-service.test.ts +++ b/packages/core/src/main/helm/__tests__/helm-service.test.ts @@ -6,14 +6,14 @@ import { getDiForUnitTesting } from "../../getDiForUnitTesting"; import listHelmChartsInjectable from "../helm-service/list-helm-charts.injectable"; import getActiveHelmRepositoriesInjectable from "../repositories/get-active-helm-repositories/get-active-helm-repositories.injectable"; -import type { AsyncResult } from "../../../common/utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; import type { HelmRepo } from "../../../common/helm/helm-repo"; -import { sortBySemverVersion } from "../../../common/utils"; +import { sortBySemverVersion } from "@k8slens/utilities"; import helmChartManagerInjectable from "../helm-chart-manager.injectable"; describe("Helm Service tests", () => { let listHelmCharts: () => Promise; - let getActiveHelmRepositoriesMock: jest.Mock>>; + let getActiveHelmRepositoriesMock: jest.Mock>; beforeEach(() => { const di = getDiForUnitTesting(); diff --git a/packages/core/src/main/helm/exec-helm/exec-env.global-override-for-injectable.ts b/packages/core/src/main/helm/exec-helm/exec-env.global-override-for-injectable.ts index 59c376cffd..f44e92d394 100644 --- a/packages/core/src/main/helm/exec-helm/exec-env.global-override-for-injectable.ts +++ b/packages/core/src/main/helm/exec-helm/exec-env.global-override-for-injectable.ts @@ -4,7 +4,7 @@ */ import { computed } from "mobx"; -import { getGlobalOverride } from "../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import execHelmEnvInjectable from "./exec-env.injectable"; export default getGlobalOverride(execHelmEnvInjectable, () => computed(() => ({}))); diff --git a/packages/core/src/main/helm/exec-helm/exec-helm.injectable.ts b/packages/core/src/main/helm/exec-helm/exec-helm.injectable.ts index 034ab43248..5fc610f97f 100644 --- a/packages/core/src/main/helm/exec-helm/exec-helm.injectable.ts +++ b/packages/core/src/main/helm/exec-helm/exec-helm.injectable.ts @@ -5,11 +5,11 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { ExecFileException } from "child_process"; import execFileInjectable from "../../../common/fs/exec-file.injectable"; -import type { AsyncResult } from "../../../common/utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; import helmBinaryPathInjectable from "../helm-binary-path.injectable"; import execHelmEnvInjectable from "./exec-env.injectable"; -export type ExecHelm = (args: string[]) => Promise>; +export type ExecHelm = (args: string[]) => AsyncResult; const execHelmInjectable = getInjectable({ id: "exec-helm", diff --git a/packages/core/src/main/helm/get-helm-env/get-helm-env.injectable.ts b/packages/core/src/main/helm/get-helm-env/get-helm-env.injectable.ts index bb74c53f99..e3a9969ffc 100644 --- a/packages/core/src/main/helm/get-helm-env/get-helm-env.injectable.ts +++ b/packages/core/src/main/helm/get-helm-env/get-helm-env.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import execHelmInjectable from "../exec-helm/exec-helm.injectable"; -import type { AsyncResult } from "../../../common/utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; export type HelmEnv = Record & { HELM_REPOSITORY_CACHE?: string; @@ -17,7 +17,7 @@ const getHelmEnvInjectable = getInjectable({ instantiate: (di) => { const execHelm = di.inject(execHelmInjectable); - return async (): Promise> => { + return async (): AsyncResult => { const result = await execHelm(["env"]); if (!result.callWasSuccessful) { diff --git a/packages/core/src/main/helm/helm-chart-manager.ts b/packages/core/src/main/helm/helm-chart-manager.ts index cccf40cbc6..6419e5fc92 100644 --- a/packages/core/src/main/helm/helm-chart-manager.ts +++ b/packages/core/src/main/helm/helm-chart-manager.ts @@ -4,7 +4,7 @@ */ import * as yaml from "js-yaml"; -import { iter, put, sortBySemverVersion } from "../../common/utils"; +import { iter, put, sortBySemverVersion } from "@k8slens/utilities"; import type { HelmRepo } from "../../common/helm/helm-repo"; import type { HelmChartManagerCache } from "./helm-chart-manager-cache.injectable"; import type { Logger } from "../../common/logger"; diff --git a/packages/core/src/main/helm/helm-service/delete-helm-release.injectable.ts b/packages/core/src/main/helm/helm-service/delete-helm-release.injectable.ts index fa27980355..63244b4583 100644 --- a/packages/core/src/main/helm/helm-service/delete-helm-release.injectable.ts +++ b/packages/core/src/main/helm/helm-service/delete-helm-release.injectable.ts @@ -5,6 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { Cluster } from "../../../common/cluster/cluster"; import loggerInjectable from "../../../common/logger.injectable"; +import kubeconfigManagerInjectable from "../../kubeconfig-manager/kubeconfig-manager.injectable"; import type { DeleteHelmReleaseData } from "../delete-helm-release.injectable"; import deleteHelmReleaseInjectable from "../delete-helm-release.injectable"; @@ -16,11 +17,12 @@ const deleteClusterHelmReleaseInjectable = getInjectable({ const deleteHelmRelease = di.inject(deleteHelmReleaseInjectable); return async (cluster: Cluster, data: DeleteHelmReleaseData) => { - const proxyKubeconfig = await cluster.getProxyKubeconfigPath(); + const proxyKubeconfigManager = di.inject(kubeconfigManagerInjectable, cluster); + const proxyKubeconfigPath = await proxyKubeconfigManager.ensurePath(); logger.debug(`[CLUSTER]: Delete helm release`, data); - return deleteHelmRelease(proxyKubeconfig, data); + return deleteHelmRelease(proxyKubeconfigPath, data); }; }, }); diff --git a/packages/core/src/main/helm/helm-service/get-helm-chart-readme.global-override-for-injectable.ts b/packages/core/src/main/helm/helm-service/get-helm-chart-readme.global-override-for-injectable.ts index 6d2c016251..5368a51953 100644 --- a/packages/core/src/main/helm/helm-service/get-helm-chart-readme.global-override-for-injectable.ts +++ b/packages/core/src/main/helm/helm-service/get-helm-chart-readme.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import getHelmChartReadmeInjectable from "./get-helm-chart-readme.injectable"; export default getGlobalOverride(getHelmChartReadmeInjectable, () => () => { diff --git a/packages/core/src/main/helm/helm-service/get-helm-release-history.injectable.ts b/packages/core/src/main/helm/helm-service/get-helm-release-history.injectable.ts index fe4e3448ac..45ca241c89 100644 --- a/packages/core/src/main/helm/helm-service/get-helm-release-history.injectable.ts +++ b/packages/core/src/main/helm/helm-service/get-helm-release-history.injectable.ts @@ -5,6 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { Cluster } from "../../../common/cluster/cluster"; import loggerInjectable from "../../../common/logger.injectable"; +import kubeconfigManagerInjectable from "../../kubeconfig-manager/kubeconfig-manager.injectable"; import type { GetHelmReleaseHistoryData } from "../get-helm-release-history.injectable"; import getHelmReleaseHistoryInjectable from "../get-helm-release-history.injectable"; @@ -16,11 +17,12 @@ const getClusterHelmReleaseHistoryInjectable = getInjectable({ const getHelmReleaseHistory = di.inject(getHelmReleaseHistoryInjectable); return async (cluster: Cluster, data: GetHelmReleaseHistoryData) => { - const proxyKubeconfig = await cluster.getProxyKubeconfigPath(); + const proxyKubeconfigManager = di.inject(kubeconfigManagerInjectable, cluster); + const proxyKubeconfigPath = await proxyKubeconfigManager.ensurePath(); logger.debug(`[CLUSTER]: Fetch release history for clusterId=${cluster.id}`, data); - return getHelmReleaseHistory(proxyKubeconfig, data); + return getHelmReleaseHistory(proxyKubeconfigPath, data); }; }, }); diff --git a/packages/core/src/main/helm/helm-service/get-helm-release-resources/call-for-helm-manifest/call-for-helm-manifest.injectable.ts b/packages/core/src/main/helm/helm-service/get-helm-release-resources/call-for-helm-manifest/call-for-helm-manifest.injectable.ts index b5176b25b9..75115b4c27 100644 --- a/packages/core/src/main/helm/helm-service/get-helm-release-resources/call-for-helm-manifest/call-for-helm-manifest.injectable.ts +++ b/packages/core/src/main/helm/helm-service/get-helm-release-resources/call-for-helm-manifest/call-for-helm-manifest.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 type { AsyncResult } from "../../../../../common/utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; import execHelmInjectable from "../../../exec-helm/exec-helm.injectable"; import yaml from "js-yaml"; import type { KubeJsonApiData, KubeJsonApiDataList } from "../../../../../common/k8s-api/kube-json-api"; @@ -18,7 +18,7 @@ const callForHelmManifestInjectable = getInjectable({ name: string, namespace: string, kubeconfigPath: string, - ): Promise> => { + ): AsyncResult<(KubeJsonApiData | KubeJsonApiDataList)[]> => { const result = await execHelm([ "get", "manifest", diff --git a/packages/core/src/main/helm/helm-service/get-helm-release-resources/call-for-kube-resources-by-manifest/call-for-kube-resources-by-manifest.injectable.ts b/packages/core/src/main/helm/helm-service/get-helm-release-resources/call-for-kube-resources-by-manifest/call-for-kube-resources-by-manifest.injectable.ts index 71a38abf6b..637a4788a8 100644 --- a/packages/core/src/main/helm/helm-service/get-helm-release-resources/call-for-kube-resources-by-manifest/call-for-kube-resources-by-manifest.injectable.ts +++ b/packages/core/src/main/helm/helm-service/get-helm-release-resources/call-for-kube-resources-by-manifest/call-for-kube-resources-by-manifest.injectable.ts @@ -4,7 +4,6 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import type { JsonObject } from "type-fest"; -import { json } from "../../../../../common/utils"; import yaml from "js-yaml"; import execFileWithInputInjectable from "./exec-file-with-input/exec-file-with-input.injectable"; import { getErrorMessage } from "../../../../../common/utils/get-error-message"; @@ -60,7 +59,7 @@ const callForKubeResourcesByManifestInjectable = getInjectable({ throw new Error(errorMessage); } - const output = json.parse(result.response) as { items: JsonObject[] }; + const output = JSON.parse(result.response) as { items: JsonObject[] }; return output.items; }; diff --git a/packages/core/src/main/helm/helm-service/get-helm-release-resources/call-for-kube-resources-by-manifest/exec-file-with-input/exec-file-with-input.global-override-for-injectable.ts b/packages/core/src/main/helm/helm-service/get-helm-release-resources/call-for-kube-resources-by-manifest/exec-file-with-input/exec-file-with-input.global-override-for-injectable.ts index 70b4771468..a359147036 100644 --- a/packages/core/src/main/helm/helm-service/get-helm-release-resources/call-for-kube-resources-by-manifest/exec-file-with-input/exec-file-with-input.global-override-for-injectable.ts +++ b/packages/core/src/main/helm/helm-service/get-helm-release-resources/call-for-kube-resources-by-manifest/exec-file-with-input/exec-file-with-input.global-override-for-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 { getGlobalOverride } from "../../../../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import execFileWithInputInjectable from "./exec-file-with-input.injectable"; export default getGlobalOverride(execFileWithInputInjectable, () => () => { diff --git a/packages/core/src/main/helm/helm-service/get-helm-release-resources/call-for-kube-resources-by-manifest/exec-file-with-input/exec-file-with-input.injectable.ts b/packages/core/src/main/helm/helm-service/get-helm-release-resources/call-for-kube-resources-by-manifest/exec-file-with-input/exec-file-with-input.injectable.ts index 49a1c644f2..031c95cdb6 100644 --- a/packages/core/src/main/helm/helm-service/get-helm-release-resources/call-for-kube-resources-by-manifest/exec-file-with-input/exec-file-with-input.injectable.ts +++ b/packages/core/src/main/helm/helm-service/get-helm-release-resources/call-for-kube-resources-by-manifest/exec-file-with-input/exec-file-with-input.injectable.ts @@ -3,9 +3,9 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import type { AsyncResult } from "../../../../../../common/utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; import nonPromiseExecFileInjectable from "./non-promise-exec-file.injectable"; -import { isNumber } from "../../../../../../common/utils"; +import { isNumber } from "@k8slens/utilities"; import assert from "assert"; import type { ChildProcess } from "child_process"; @@ -13,7 +13,7 @@ export type ExecFileWithInput = (options: { filePath: string; commandArguments: string[]; input: string; -}) => Promise>; +}) => AsyncResult; const execFileWithInputInjectable = getInjectable({ id: "exec-file-with-input", diff --git a/packages/core/src/main/helm/helm-service/get-helm-release-resources/call-for-kube-resources-by-manifest/exec-file-with-input/exec-file-with-input.test.ts b/packages/core/src/main/helm/helm-service/get-helm-release-resources/call-for-kube-resources-by-manifest/exec-file-with-input/exec-file-with-input.test.ts index 68a49c0cf6..d7b08d7a2f 100644 --- a/packages/core/src/main/helm/helm-service/get-helm-release-resources/call-for-kube-resources-by-manifest/exec-file-with-input/exec-file-with-input.test.ts +++ b/packages/core/src/main/helm/helm-service/get-helm-release-resources/call-for-kube-resources-by-manifest/exec-file-with-input/exec-file-with-input.test.ts @@ -5,9 +5,9 @@ import { getDiForUnitTesting } from "../../../../../getDiForUnitTesting"; import type { ExecFileWithInput } from "./exec-file-with-input.injectable"; import execFileWithInputInjectable from "./exec-file-with-input.injectable"; -import type { AsyncResult } from "../../../../../../common/utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; import nonPromiseExecFileInjectable from "./non-promise-exec-file.injectable"; -import { getPromiseStatus } from "../../../../../../common/test-utils/get-promise-status"; +import { getPromiseStatus } from "@k8slens/test-utils"; import EventEmitter from "events"; describe("exec-file-with-input", () => { @@ -56,7 +56,7 @@ describe("exec-file-with-input", () => { }); describe("when called", () => { - let actualPromise: Promise>; + let actualPromise: AsyncResult; beforeEach(() => { actualPromise = execFileWithInput({ diff --git a/packages/core/src/main/helm/helm-service/get-helm-release-resources/get-helm-release-resources.injectable.ts b/packages/core/src/main/helm/helm-service/get-helm-release-resources/get-helm-release-resources.injectable.ts index ce5c60d6b3..cef66508be 100644 --- a/packages/core/src/main/helm/helm-service/get-helm-release-resources/get-helm-release-resources.injectable.ts +++ b/packages/core/src/main/helm/helm-service/get-helm-release-resources/get-helm-release-resources.injectable.ts @@ -5,13 +5,13 @@ import { getInjectable } from "@ogre-tools/injectable"; import callForHelmManifestInjectable from "./call-for-helm-manifest/call-for-helm-manifest.injectable"; import type { KubeJsonApiData, KubeJsonApiDataList } from "../../../../common/k8s-api/kube-json-api"; -import type { AsyncResult } from "../../../../common/utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; export type GetHelmReleaseResources = ( name: string, namespace: string, kubeconfigPath: string, -) => Promise>; +) => AsyncResult; const getHelmReleaseResourcesInjectable = getInjectable({ id: "get-helm-release-resources", diff --git a/packages/core/src/main/helm/helm-service/get-helm-release-resources/get-helm-release-resources.test.ts b/packages/core/src/main/helm/helm-service/get-helm-release-resources/get-helm-release-resources.test.ts index cb1abe7f11..7f2f194a75 100644 --- a/packages/core/src/main/helm/helm-service/get-helm-release-resources/get-helm-release-resources.test.ts +++ b/packages/core/src/main/helm/helm-service/get-helm-release-resources/get-helm-release-resources.test.ts @@ -12,7 +12,7 @@ import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; import type { ExecFileWithInput } from "./call-for-kube-resources-by-manifest/exec-file-with-input/exec-file-with-input.injectable"; import execFileWithInputInjectable from "./call-for-kube-resources-by-manifest/exec-file-with-input/exec-file-with-input.injectable"; -import type { AsyncResult } from "../../../../common/utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; import type { KubeJsonApiData } from "../../../../common/k8s-api/kube-json-api"; describe("get helm release resources", () => { @@ -37,7 +37,7 @@ describe("get helm release resources", () => { }); describe("when called", () => { - let actualPromise: Promise>; + let actualPromise: AsyncResult; beforeEach(() => { actualPromise = getHelmReleaseResources( diff --git a/packages/core/src/main/helm/helm-service/get-helm-release-values.injectable.ts b/packages/core/src/main/helm/helm-service/get-helm-release-values.injectable.ts index 8070ed366e..41c0d44e8f 100644 --- a/packages/core/src/main/helm/helm-service/get-helm-release-values.injectable.ts +++ b/packages/core/src/main/helm/helm-service/get-helm-release-values.injectable.ts @@ -7,6 +7,7 @@ import loggerInjectable from "../../../common/logger.injectable"; import type { Cluster } from "../../../common/cluster/cluster"; import type { GetHelmReleaseValuesData } from "../get-helm-release-values.injectable"; import getHelmReleaseValuesInjectable from "../get-helm-release-values.injectable"; +import kubeconfigManagerInjectable from "../../kubeconfig-manager/kubeconfig-manager.injectable"; const getClusterHelmReleaseValuesInjectable = getInjectable({ id: "get-cluster-helm-release-values", @@ -16,11 +17,12 @@ const getClusterHelmReleaseValuesInjectable = getInjectable({ const getHelmReleaseValues = di.inject(getHelmReleaseValuesInjectable); return async (cluster: Cluster, data: GetHelmReleaseValuesData) => { - const pathToKubeconfig = await cluster.getProxyKubeconfigPath(); + const proxyKubeconfigManager = di.inject(kubeconfigManagerInjectable, cluster); + const proxyKubeconfigPath = await proxyKubeconfigManager.ensurePath(); logger.debug(`[CLUSTER]: getting helm release values`, data); - return getHelmReleaseValues(pathToKubeconfig, data); + return getHelmReleaseValues(proxyKubeconfigPath, data); }; }, }); diff --git a/packages/core/src/main/helm/helm-service/get-helm-release.global-override-for-injectable.ts b/packages/core/src/main/helm/helm-service/get-helm-release.global-override-for-injectable.ts index 0d124468f2..d2ae62843f 100644 --- a/packages/core/src/main/helm/helm-service/get-helm-release.global-override-for-injectable.ts +++ b/packages/core/src/main/helm/helm-service/get-helm-release.global-override-for-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 { getGlobalOverride } from "../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import getHelmReleaseInjectable from "./get-helm-release.injectable"; export default getGlobalOverride(getHelmReleaseInjectable, () => () => { diff --git a/packages/core/src/main/helm/helm-service/get-helm-release.injectable.ts b/packages/core/src/main/helm/helm-service/get-helm-release.injectable.ts index 71d3fe6184..8a9144999f 100644 --- a/packages/core/src/main/helm/helm-service/get-helm-release.injectable.ts +++ b/packages/core/src/main/helm/helm-service/get-helm-release.injectable.ts @@ -5,7 +5,8 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { Cluster } from "../../../common/cluster/cluster"; import loggerInjectable from "../../../common/logger.injectable"; -import { isObject, json } from "../../../common/utils"; +import kubeconfigManagerInjectable from "../../kubeconfig-manager/kubeconfig-manager.injectable"; +import { isObject, json } from "@k8slens/utilities"; import execHelmInjectable from "../exec-helm/exec-helm.injectable"; import getHelmReleaseResourcesInjectable from "./get-helm-release-resources/get-helm-release-resources.injectable"; @@ -18,7 +19,8 @@ const getHelmReleaseInjectable = getInjectable({ const getHelmReleaseResources = di.inject(getHelmReleaseResourcesInjectable); return async (cluster: Cluster, releaseName: string, namespace: string) => { - const kubeconfigPath = await cluster.getProxyKubeconfigPath(); + const proxyKubeconfigManager = di.inject(kubeconfigManagerInjectable, cluster); + const proxyKubeconfigPath = await proxyKubeconfigManager.ensurePath(); logger.debug("Fetch release"); @@ -28,7 +30,7 @@ const getHelmReleaseInjectable = getInjectable({ "--namespace", namespace, "--kubeconfig", - kubeconfigPath, + proxyKubeconfigPath, "--output", "json", ]); @@ -48,7 +50,7 @@ const getHelmReleaseInjectable = getInjectable({ const resourcesResult = await getHelmReleaseResources( releaseName, namespace, - kubeconfigPath, + proxyKubeconfigPath, ); if (!resourcesResult.callWasSuccessful) { diff --git a/packages/core/src/main/helm/helm-service/install-helm-chart.injectable.ts b/packages/core/src/main/helm/helm-service/install-helm-chart.injectable.ts index b81b48cfa6..3500395ad3 100644 --- a/packages/core/src/main/helm/helm-service/install-helm-chart.injectable.ts +++ b/packages/core/src/main/helm/helm-service/install-helm-chart.injectable.ts @@ -5,6 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { JsonObject } from "type-fest"; import type { Cluster } from "../../../common/cluster/cluster"; +import kubeconfigManagerInjectable from "../../kubeconfig-manager/kubeconfig-manager.injectable"; import installHelmChartInjectable from "../install-helm-chart.injectable"; export interface InstallChartArgs { @@ -22,11 +23,12 @@ const installClusterHelmChartInjectable = getInjectable({ const installHelmChart = di.inject(installHelmChartInjectable); return async (cluster: Cluster, data: InstallChartArgs) => { - const proxyKubeconfig = await cluster.getProxyKubeconfigPath(); + const proxyKubeconfigManager = di.inject(kubeconfigManagerInjectable, cluster); + const proxyKubeconfigPath = await proxyKubeconfigManager.ensurePath(); return installHelmChart({ ...data, - kubeconfigPath: proxyKubeconfig, + kubeconfigPath: proxyKubeconfigPath, }); }; }, diff --git a/packages/core/src/main/helm/helm-service/list-helm-charts.injectable.ts b/packages/core/src/main/helm/helm-service/list-helm-charts.injectable.ts index 93a57e7aff..53918baef1 100644 --- a/packages/core/src/main/helm/helm-service/list-helm-charts.injectable.ts +++ b/packages/core/src/main/helm/helm-service/list-helm-charts.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import assert from "assert"; -import { object } from "../../../common/utils"; +import { object } from "@k8slens/utilities"; import getActiveHelmRepositoriesInjectable from "../repositories/get-active-helm-repositories/get-active-helm-repositories.injectable"; import type { HelmRepo } from "../../../common/helm/helm-repo"; import helmChartManagerInjectable from "../helm-chart-manager.injectable"; diff --git a/packages/core/src/main/helm/helm-service/list-helm-releases.injectable.ts b/packages/core/src/main/helm/helm-service/list-helm-releases.injectable.ts index 14a27f6ea6..d594c3f756 100644 --- a/packages/core/src/main/helm/helm-service/list-helm-releases.injectable.ts +++ b/packages/core/src/main/helm/helm-service/list-helm-releases.injectable.ts @@ -5,6 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { Cluster } from "../../../common/cluster/cluster"; import loggerInjectable from "../../../common/logger.injectable"; +import kubeconfigManagerInjectable from "../../kubeconfig-manager/kubeconfig-manager.injectable"; import listHelmReleasesInjectable from "../list-helm-releases.injectable"; const listClusterHelmReleasesInjectable = getInjectable({ @@ -15,11 +16,12 @@ const listClusterHelmReleasesInjectable = getInjectable({ const listHelmReleases = di.inject(listHelmReleasesInjectable); return async (cluster: Cluster, namespace?: string) => { - const proxyKubeconfig = await cluster.getProxyKubeconfigPath(); + const proxyKubeconfigManager = di.inject(kubeconfigManagerInjectable, cluster); + const proxyKubeconfigPath = await proxyKubeconfigManager.ensurePath(); logger.debug(`[CLUSTER]: listing helm releases for clusterId=${cluster.id}`, { namespace }); - return listHelmReleases(proxyKubeconfig, namespace); + return listHelmReleases(proxyKubeconfigPath, namespace); }; }, }); diff --git a/packages/core/src/main/helm/helm-service/rollback-helm-release.injectable.ts b/packages/core/src/main/helm/helm-service/rollback-helm-release.injectable.ts index a426de8f1c..0be6afccbe 100644 --- a/packages/core/src/main/helm/helm-service/rollback-helm-release.injectable.ts +++ b/packages/core/src/main/helm/helm-service/rollback-helm-release.injectable.ts @@ -5,6 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { Cluster } from "../../../common/cluster/cluster"; import loggerInjectable from "../../../common/logger.injectable"; +import kubeconfigManagerInjectable from "../../kubeconfig-manager/kubeconfig-manager.injectable"; import type { RollbackHelmReleaseData } from "../rollback-helm-release.injectable"; import rollbackHelmReleaseInjectable from "../rollback-helm-release.injectable"; @@ -16,11 +17,12 @@ const rollbackClusterHelmReleaseInjectable = getInjectable({ const rollbackHelmRelease = di.inject(rollbackHelmReleaseInjectable); return async (cluster: Cluster, data: RollbackHelmReleaseData) => { - const proxyKubeconfig = await cluster.getProxyKubeconfigPath(); + const proxyKubeconfigManager = di.inject(kubeconfigManagerInjectable, cluster); + const proxyKubeconfigPath = await proxyKubeconfigManager.ensurePath(); logger.debug(`[CLUSTER]: rolling back helm release for clusterId=${cluster.id}`, data); - await rollbackHelmRelease(proxyKubeconfig, data); + await rollbackHelmRelease(proxyKubeconfigPath, data); }; }, }); diff --git a/packages/core/src/main/helm/helm-service/update-helm-release.global-override-for-injectable.ts b/packages/core/src/main/helm/helm-service/update-helm-release.global-override-for-injectable.ts index dc2d8b596f..1d04e393a8 100644 --- a/packages/core/src/main/helm/helm-service/update-helm-release.global-override-for-injectable.ts +++ b/packages/core/src/main/helm/helm-service/update-helm-release.global-override-for-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 { getGlobalOverride } from "../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import updateHelmReleaseInjectable from "./update-helm-release.injectable"; export default getGlobalOverride(updateHelmReleaseInjectable, () => () => { diff --git a/packages/core/src/main/helm/helm-service/update-helm-release.injectable.ts b/packages/core/src/main/helm/helm-service/update-helm-release.injectable.ts index 274dae8cc4..0df63447b3 100644 --- a/packages/core/src/main/helm/helm-service/update-helm-release.injectable.ts +++ b/packages/core/src/main/helm/helm-service/update-helm-release.injectable.ts @@ -10,6 +10,7 @@ import getHelmReleaseInjectable from "./get-helm-release.injectable"; import writeFileInjectable from "../../../common/fs/write-file.injectable"; import removePathInjectable from "../../../common/fs/remove.injectable"; import execHelmInjectable from "../exec-helm/exec-helm.injectable"; +import kubeconfigManagerInjectable from "../../kubeconfig-manager/kubeconfig-manager.injectable"; export interface UpdateChartArgs { chart: string; @@ -28,7 +29,8 @@ const updateHelmReleaseInjectable = getInjectable({ const execHelm = di.inject(execHelmInjectable); return async (cluster: Cluster, releaseName: string, namespace: string, data: UpdateChartArgs) => { - const proxyKubeconfig = await cluster.getProxyKubeconfigPath(); + const proxyKubeconfigManager = di.inject(kubeconfigManagerInjectable, cluster); + const proxyKubeconfigPath = await proxyKubeconfigManager.ensurePath(); const valuesFilePath = tempy.file({ name: "values.yaml" }); logger.debug(`[HELM]: upgrading "${releaseName}" in "${namespace}" to ${data.version}`); @@ -43,7 +45,7 @@ const updateHelmReleaseInjectable = getInjectable({ "--version", data.version, "--values", valuesFilePath, "--namespace", namespace, - "--kubeconfig", proxyKubeconfig, + "--kubeconfig", proxyKubeconfigPath, ]); if (result.callWasSuccessful === false) { diff --git a/packages/core/src/main/helm/list-helm-releases.injectable.ts b/packages/core/src/main/helm/list-helm-releases.injectable.ts index ff362eb3d2..f12cd2ffd2 100644 --- a/packages/core/src/main/helm/list-helm-releases.injectable.ts +++ b/packages/core/src/main/helm/list-helm-releases.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import execHelmInjectable from "./exec-helm/exec-helm.injectable"; -import { isObject, json, toCamelCase } from "../../common/utils"; +import { toCamelCase, isObject } from "@k8slens/utilities"; export type ListHelmReleases = (pathToKubeconfig: string, namespace?: string) => Promise[]>; @@ -34,7 +34,7 @@ const listHelmReleasesInjectable = getInjectable({ throw result.error; } - const output = json.parse(result.response); + const output = JSON.parse(result.response); if (!Array.isArray(output) || output.length == 0) { return []; diff --git a/packages/core/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable.ts b/packages/core/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable.ts index bd05b950d7..fe0690b59d 100644 --- a/packages/core/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable.ts +++ b/packages/core/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable.ts @@ -9,7 +9,7 @@ import readYamlFileInjectable from "../../../../common/fs/read-yaml-file.injecta import getHelmEnvInjectable from "../../get-helm-env/get-helm-env.injectable"; import execHelmInjectable from "../../exec-helm/exec-helm.injectable"; import loggerInjectable from "../../../../common/logger.injectable"; -import type { AsyncResult } from "../../../../common/utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; interface HelmRepositoryFromYaml { name: string; @@ -38,7 +38,7 @@ const getActiveHelmRepositoriesInjectable = getInjectable({ const getRepositories = getRepositoriesFor(readYamlFile); - return async (): Promise> => { + return async (): AsyncResult => { const envResult = await getHelmEnv(); if (!envResult.callWasSuccessful) { diff --git a/packages/core/src/main/helm/repositories/remove-helm-repository/remove-helm-repository.injectable.ts b/packages/core/src/main/helm/repositories/remove-helm-repository/remove-helm-repository.injectable.ts index a662603a96..a7811c006d 100644 --- a/packages/core/src/main/helm/repositories/remove-helm-repository/remove-helm-repository.injectable.ts +++ b/packages/core/src/main/helm/repositories/remove-helm-repository/remove-helm-repository.injectable.ts @@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import execHelmInjectable from "../../exec-helm/exec-helm.injectable"; import type { HelmRepo } from "../../../../common/helm/helm-repo"; import loggerInjectable from "../../../../common/logger.injectable"; -import type { AsyncResult } from "../../../../common/utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; const removeHelmRepositoryInjectable = getInjectable({ id: "remove-helm-repository", @@ -15,7 +15,7 @@ const removeHelmRepositoryInjectable = getInjectable({ const execHelm = di.inject(execHelmInjectable); const logger = di.inject(loggerInjectable); - return async (repo: HelmRepo): Promise> => { + return async (repo: HelmRepo): AsyncResult => { logger.info(`[HELM]: removing repo ${repo.name} (${repo.url})`); const result = await execHelm([ diff --git a/packages/core/src/main/hotbar-store/migrations/5.0.0-beta.10.injectable.ts b/packages/core/src/main/hotbar-store/migrations/5.0.0-beta.10.injectable.ts index ddbda706be..b327085aa6 100644 --- a/packages/core/src/main/hotbar-store/migrations/5.0.0-beta.10.injectable.ts +++ b/packages/core/src/main/hotbar-store/migrations/5.0.0-beta.10.injectable.ts @@ -4,19 +4,19 @@ */ import * as uuid from "uuid"; -import type { ClusterStoreModel } from "../../../common/cluster-store/cluster-store"; import type { Hotbar, HotbarItem } from "../../../common/hotbars/types"; import { defaultHotbarCells, getEmptyHotbar } from "../../../common/hotbars/types"; import { getLegacyGlobalDiForExtensionApi } from "../../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; import catalogCatalogEntityInjectable from "../../../common/catalog-entities/general-catalog-entities/implementations/catalog-catalog-entity.injectable"; -import { isDefined, isErrnoException } from "../../../common/utils"; +import { isDefined, isErrnoException } from "@k8slens/utilities"; import joinPathsInjectable from "../../../common/path/join-paths.injectable"; import { getInjectable } from "@ogre-tools/injectable"; import { hotbarStoreMigrationInjectionToken } from "../../../common/hotbars/migrations-token"; import readJsonSyncInjectable from "../../../common/fs/read-json-sync.injectable"; import loggerInjectable from "../../../common/logger.injectable"; import { generateNewIdFor } from "../../../common/utils/generate-new-id-for"; +import type { ClusterModel } from "../../../common/cluster-types"; interface Pre500WorkspaceStoreModel { workspaces: { @@ -31,6 +31,15 @@ interface PartialHotbar { items: (null | HotbarItem)[]; } +interface Pre500ClusterModel extends ClusterModel { + workspace?: string; + workspaces?: string[]; +} + +interface Pre500ClusterStoreModel { + clusters?: Pre500ClusterModel[]; +} + const v500Beta10HotbarStoreMigrationInjectable = getInjectable({ id: "v5.0.0-beta.10-hotbar-store-migration", instantiate: (di) => { @@ -59,7 +68,7 @@ const v500Beta10HotbarStoreMigrationInjectable = getInjectable({ try { const workspaceStoreData: Pre500WorkspaceStoreModel = readJsonSync(joinPaths(userDataPath, "lens-workspace-store.json")); - const { clusters = [] }: ClusterStoreModel = readJsonSync(joinPaths(userDataPath, "lens-cluster-store.json")); + const { clusters = [] }: Pre500ClusterStoreModel = readJsonSync(joinPaths(userDataPath, "lens-cluster-store.json")); const workspaceHotbars = new Map(); // mapping from WorkspaceId to HotBar for (const { id, name } of workspaceStoreData.workspaces) { 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 e7d66eb8f4..56260347bf 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 @@ -13,14 +13,15 @@ import waitUntilPortIsUsedInjectable from "./wait-until-port-is-used/wait-until- import lensK8sProxyPathInjectable from "./lens-k8s-proxy-path.injectable"; import getPortFromStreamInjectable from "../utils/get-port-from-stream.injectable"; import getDirnameOfPathInjectable from "../../common/path/get-dirname.injectable"; +import broadcastConnectionUpdateInjectable from "../cluster/broadcast-connection-update.injectable"; -export type CreateKubeAuthProxy = (cluster: Cluster, environmentVariables: NodeJS.ProcessEnv) => KubeAuthProxy; +export type CreateKubeAuthProxy = (cluster: Cluster, env: NodeJS.ProcessEnv) => KubeAuthProxy; const createKubeAuthProxyInjectable = getInjectable({ id: "create-kube-auth-proxy", instantiate: (di): CreateKubeAuthProxy => { - const dependencies: Omit = { + const dependencies: Omit = { proxyBinPath: di.inject(lensK8sProxyPathInjectable), spawn: di.inject(spawnInjectable), logger: di.inject(loggerInjectable), @@ -29,13 +30,14 @@ const createKubeAuthProxyInjectable = getInjectable({ dirname: di.inject(getDirnameOfPathInjectable), }; - return (cluster: Cluster, environmentVariables: NodeJS.ProcessEnv) => { - const clusterUrl = new URL(cluster.apiUrl); + return (cluster, env) => { + const clusterUrl = new URL(cluster.apiUrl.get()); return new KubeAuthProxy({ ...dependencies, proxyCert: di.inject(kubeAuthProxyCertificateInjectable, clusterUrl.hostname), - }, cluster, environmentVariables); + broadcastConnectionUpdate: di.inject(broadcastConnectionUpdateInjectable, cluster), + }, cluster, env); }; }, }); 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 669780b5b6..9a9b5a249f 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 @@ -7,7 +7,7 @@ import type { ChildProcess } from "child_process"; import { randomBytes } from "crypto"; import type { Cluster } from "../../common/cluster/cluster"; import type { GetPortFromStream } from "../utils/get-port-from-stream.injectable"; -import { makeObservable, observable, when } from "mobx"; +import { observable, when } from "mobx"; import type { SelfSignedCert } from "selfsigned"; import assert from "assert"; import { TypedRegEx } from "typed-regex"; @@ -15,6 +15,7 @@ import type { Spawn } from "../child-process/spawn.injectable"; 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"; const startingServeMatcher = "starting to serve on (?
.+)"; const startingServeRegex = Object.assign(TypedRegEx(startingServeMatcher, "i"), { @@ -29,6 +30,7 @@ export interface KubeAuthProxyDependencies { waitUntilPortIsUsed: WaitUntilPortIsUsed; getPortFromStream: GetPortFromStream; dirname: GetDirnameOfPath; + broadcastConnectionUpdate: BroadcastConnectionUpdate; } export class KubeAuthProxy { @@ -44,19 +46,17 @@ export class KubeAuthProxy { protected _port?: number; protected proxyProcess?: ChildProcess; - @observable protected ready = false; + protected readonly ready = observable.box(false); - constructor(private readonly dependencies: KubeAuthProxyDependencies, protected readonly cluster: Cluster, protected readonly env: NodeJS.ProcessEnv) { - makeObservable(this); - } - - get whenReady() { - return when(() => this.ready); - } + constructor( + private readonly dependencies: KubeAuthProxyDependencies, + protected readonly cluster: Cluster, + protected readonly env: NodeJS.ProcessEnv, + ) {} public async run(): Promise { if (this.proxyProcess) { - return this.whenReady; + return when(() => this.ready.get()); } const proxyBin = this.dependencies.proxyBinPath; @@ -65,26 +65,42 @@ export class KubeAuthProxy { this.proxyProcess = this.dependencies.spawn(proxyBin, [], { env: { ...this.env, - KUBECONFIG: this.cluster.kubeConfigPath, - KUBECONFIG_CONTEXT: this.cluster.contextName, + KUBECONFIG: this.cluster.kubeConfigPath.get(), + KUBECONFIG_CONTEXT: this.cluster.contextName.get(), API_PREFIX: this.apiPrefix, PROXY_KEY: cert.private, PROXY_CERT: cert.cert, }, - cwd: this.dependencies.dirname(this.cluster.kubeConfigPath), + cwd: this.dependencies.dirname(this.cluster.kubeConfigPath.get()), }); this.proxyProcess.on("error", (error) => { - this.cluster.broadcastConnectUpdate(error.message, "error"); + this.dependencies.broadcastConnectionUpdate({ + level: "error", + message: error.message, + }); this.exit(); }); this.proxyProcess.on("exit", (code) => { - this.cluster.broadcastConnectUpdate(`proxy exited with code: ${code}`, code ? "error" : "info"); + if (code) { + this.dependencies.broadcastConnectionUpdate({ + level: "error", + message: `proxy exited with code: ${code}`, + }); + } else { + this.dependencies.broadcastConnectionUpdate({ + level: "info", + message: "proxy exited successfully", + }); + } this.exit(); }); this.proxyProcess.on("disconnect", () => { - this.cluster.broadcastConnectUpdate("Proxy disconnected communications", "error"); + this.dependencies.broadcastConnectionUpdate({ + level: "error", + message: "Proxy disconnected communications", + }); this.exit(); }); @@ -96,28 +112,40 @@ export class KubeAuthProxy { return; } - this.cluster.broadcastConnectUpdate(data.toString(), "error"); + this.dependencies.broadcastConnectionUpdate({ + level: "error", + message: data.toString(), + }); }); this.proxyProcess.stdout.on("data", (data: Buffer) => { if (typeof this._port === "number") { - this.cluster.broadcastConnectUpdate(data.toString()); + this.dependencies.broadcastConnectionUpdate({ + level: "info", + message: data.toString(), + }); } }); this._port = await this.dependencies.getPortFromStream(this.proxyProcess.stdout, { lineRegex: startingServeRegex, - onFind: () => this.cluster.broadcastConnectUpdate("Authentication proxy started"), + onFind: () => this.dependencies.broadcastConnectionUpdate({ + level: "info", + message: "Authentication proxy started", + }), }); this.dependencies.logger.info(`[KUBE-AUTH-PROXY]: found port=${this._port}`); try { await this.dependencies.waitUntilPortIsUsed(this.port, 500, 10000); - this.ready = true; + this.ready.set(true); } catch (error) { this.dependencies.logger.warn("[KUBE-AUTH-PROXY]: waitUntilUsed failed", error); - this.cluster.broadcastConnectUpdate("Proxy port failed to be used within timelimit, restarting...", "error"); + this.dependencies.broadcastConnectionUpdate({ + level: "error", + message: "Proxy port failed to be used within time limit, restarting...", + }); this.exit(); return this.run(); @@ -125,7 +153,7 @@ export class KubeAuthProxy { } public exit() { - this.ready = false; + this.ready.set(false); if (this.proxyProcess) { this.dependencies.logger.debug("[KUBE-AUTH]: stopping local proxy", this.cluster.getMeta()); diff --git a/packages/core/src/main/kube-auth-proxy/wait-until-port-is-used/wait-until-port-is-used.global-override-for-injectable.ts b/packages/core/src/main/kube-auth-proxy/wait-until-port-is-used/wait-until-port-is-used.global-override-for-injectable.ts index 86f1e374cd..d360d62666 100644 --- a/packages/core/src/main/kube-auth-proxy/wait-until-port-is-used/wait-until-port-is-used.global-override-for-injectable.ts +++ b/packages/core/src/main/kube-auth-proxy/wait-until-port-is-used/wait-until-port-is-used.global-override-for-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 { getGlobalOverride } from "../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import waitUntilPortIsUsedInjectable from "./wait-until-port-is-used.injectable"; export default getGlobalOverride( diff --git a/packages/core/src/main/kubeconfig-manager/create-kubeconfig-manager.injectable.ts b/packages/core/src/main/kubeconfig-manager/kubeconfig-manager.injectable.ts similarity index 61% rename from packages/core/src/main/kubeconfig-manager/create-kubeconfig-manager.injectable.ts rename to packages/core/src/main/kubeconfig-manager/kubeconfig-manager.injectable.ts index 010ec7174e..6e5f54b24c 100644 --- a/packages/core/src/main/kubeconfig-manager/create-kubeconfig-manager.injectable.ts +++ b/packages/core/src/main/kubeconfig-manager/kubeconfig-manager.injectable.ts @@ -2,44 +2,43 @@ * 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 { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; import type { Cluster } from "../../common/cluster/cluster"; import directoryForTempInjectable from "../../common/app-paths/directory-for-temp/directory-for-temp.injectable"; -import type { KubeconfigManagerDependencies } from "./kubeconfig-manager"; import { KubeconfigManager } from "./kubeconfig-manager"; import loggerInjectable from "../../common/logger.injectable"; -import lensProxyPortInjectable from "../lens-proxy/lens-proxy-port.injectable"; import joinPathsInjectable from "../../common/path/join-paths.injectable"; import getDirnameOfPathInjectable from "../../common/path/get-dirname.injectable"; import pathExistsInjectable from "../../common/fs/path-exists.injectable"; import writeFileInjectable from "../../common/fs/write-file.injectable"; import removePathInjectable from "../../common/fs/remove.injectable"; import lensProxyCertificateInjectable from "../../common/certificate/lens-proxy-certificate.injectable"; +import kubeAuthProxyServerInjectable from "../cluster/kube-auth-proxy-server.injectable"; +import kubeAuthProxyUrlInjectable from "../cluster/auth-proxy-url.injectable"; +import loadKubeconfigInjectable from "../../common/cluster/load-kubeconfig.injectable"; -export interface KubeConfigManagerInstantiationParameter { - cluster: Cluster; -} +const kubeconfigManagerInjectable = getInjectable({ + id: "kubeconfig-manager", -export type CreateKubeconfigManager = (cluster: Cluster) => KubeconfigManager; - -const createKubeconfigManagerInjectable = getInjectable({ - id: "create-kubeconfig-manager", - - instantiate: (di): CreateKubeconfigManager => { - const dependencies: KubeconfigManagerDependencies = { + instantiate: (di, cluster) => new KubeconfigManager( + { directoryForTemp: di.inject(directoryForTempInjectable), logger: di.inject(loggerInjectable), - lensProxyPort: di.inject(lensProxyPortInjectable), joinPaths: di.inject(joinPathsInjectable), getDirnameOfPath: di.inject(getDirnameOfPathInjectable), removePath: di.inject(removePathInjectable), pathExists: di.inject(pathExistsInjectable), writeFile: di.inject(writeFileInjectable), certificate: di.inject(lensProxyCertificateInjectable).get(), - }; - - return (cluster) => new KubeconfigManager(dependencies, cluster); - }, + loadKubeconfig: di.inject(loadKubeconfigInjectable, cluster), + kubeAuthProxyServer: di.inject(kubeAuthProxyServerInjectable, cluster), + kubeAuthProxyUrl: di.inject(kubeAuthProxyUrlInjectable, cluster), + }, + cluster, + ), + lifecycle: lifecycleEnum.keyedSingleton({ + getInstanceKey: (di, cluster: Cluster) => cluster.id, + }), }); -export default createKubeconfigManagerInjectable; +export default kubeconfigManagerInjectable; diff --git a/packages/core/src/main/kubeconfig-manager/kubeconfig-manager.ts b/packages/core/src/main/kubeconfig-manager/kubeconfig-manager.ts index 0486521e21..9d28306bbf 100644 --- a/packages/core/src/main/kubeconfig-manager/kubeconfig-manager.ts +++ b/packages/core/src/main/kubeconfig-manager/kubeconfig-manager.ts @@ -4,10 +4,8 @@ */ import type { KubeConfig } from "@kubernetes/client-node"; -import type { Cluster } from "../../common/cluster/cluster"; -import type { ClusterContextHandler } from "../context-handler/context-handler"; import { dumpConfigYaml } from "../../common/kube-helpers"; -import { isErrnoException } from "../../common/utils"; +import { isErrnoException } from "@k8slens/utilities"; import type { PartialDeep } from "type-fest"; import type { Logger } from "../../common/logger"; import type { JoinPaths } from "../../common/path/join-paths.injectable"; @@ -16,17 +14,22 @@ import type { PathExists } from "../../common/fs/path-exists.injectable"; import type { RemovePath } from "../../common/fs/remove.injectable"; import type { WriteFile } from "../../common/fs/write-file.injectable"; import type { SelfSignedCert } from "selfsigned"; +import type { Cluster } from "../../common/cluster/cluster"; +import type { LoadKubeconfig } from "../../common/cluster/load-kubeconfig.injectable"; +import type { KubeAuthProxyServer } from "../cluster/kube-auth-proxy-server.injectable"; -export interface KubeconfigManagerDependencies { +interface KubeconfigManagerDependencies { readonly directoryForTemp: string; readonly logger: Logger; - readonly lensProxyPort: { get: () => number }; + readonly certificate: SelfSignedCert; + readonly kubeAuthProxyServer: KubeAuthProxyServer; + readonly kubeAuthProxyUrl: string; joinPaths: JoinPaths; getDirnameOfPath: GetDirnameOfPath; pathExists: PathExists; removePath: RemovePath; writeFile: WriteFile; - certificate: SelfSignedCert; + loadKubeconfig: LoadKubeconfig; } export class KubeconfigManager { @@ -38,17 +41,16 @@ export class KubeconfigManager { */ protected tempFilePath: string | null = null; - protected readonly contextHandler: ClusterContextHandler; - - constructor(private readonly dependencies: KubeconfigManagerDependencies, protected cluster: Cluster) { - this.contextHandler = cluster.contextHandler; - } + constructor( + private readonly dependencies: KubeconfigManagerDependencies, + private readonly cluster: Cluster, + ) {} /** * * @returns The path to the temporary kubeconfig */ - async getPath(): Promise { + async ensurePath(): Promise { if (this.tempFilePath === null || !(await this.dependencies.pathExists(this.tempFilePath))) { return await this.ensureFile(); } @@ -79,7 +81,7 @@ export class KubeconfigManager { protected async ensureFile() { try { - await this.contextHandler.ensureServer(); + await this.dependencies.kubeAuthProxyServer.ensureRunning(); return this.tempFilePath = await this.createProxyKubeconfig(); } catch (error) { @@ -87,31 +89,26 @@ export class KubeconfigManager { } } - get resolveProxyUrl() { - return `https://127.0.0.1:${this.dependencies.lensProxyPort.get()}/${this.cluster.id}`; - } - /** * Creates new "temporary" kubeconfig that point to the kubectl-proxy. * This way any user of the config does not need to know anything about the auth etc. details. */ protected async createProxyKubeconfig(): Promise { - const { cluster } = this; - const { contextName, id } = cluster; + const { id, preferences: { defaultNamespace }} = this.cluster; + const contextName = this.cluster.contextName.get(); const tempFile = this.dependencies.joinPaths( this.dependencies.directoryForTemp, `kubeconfig-${id}`, ); - const kubeConfig = await cluster.getKubeconfig(); - const { certificate } = this.dependencies; + const kubeConfig = await this.dependencies.loadKubeconfig(); const proxyConfig: PartialDeep = { currentContext: contextName, clusters: [ { name: contextName, - server: this.resolveProxyUrl, + server: this.dependencies.kubeAuthProxyUrl, skipTLSVerify: false, - caData: Buffer.from(certificate.cert).toString("base64"), + caData: Buffer.from(this.dependencies.certificate.cert).toString("base64"), }, ], users: [ @@ -122,7 +119,7 @@ export class KubeconfigManager { user: "proxy", name: contextName, cluster: contextName, - namespace: cluster.defaultNamespace || kubeConfig.getContextObject(contextName)?.namespace, + namespace: defaultNamespace || kubeConfig.getContextObject(contextName)?.namespace, }, ], }; 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 ca9d13577b..7f62ca14fc 100644 --- a/packages/core/src/main/kubectl/apply-all-handler.injectable.ts +++ b/packages/core/src/main/kubectl/apply-all-handler.injectable.ts @@ -5,7 +5,7 @@ import emitAppEventInjectable from "../../common/app-event-bus/emit-event.injectable"; import getClusterByIdInjectable from "../../common/cluster-store/get-by-id.injectable"; import { kubectlApplyAllChannel } from "../../common/kube-helpers/channels"; -import createResourceApplierInjectable from "../resource-applier/create-resource-applier.injectable"; +import resourceApplierInjectable from "../resource-applier/create-resource-applier.injectable"; import { getRequestChannelListenerInjectable } from "../utils/channel/channel-listeners/listener-tokens"; const kubectlApplyAllChannelHandlerInjectable = getRequestChannelListenerInjectable({ @@ -13,7 +13,6 @@ const kubectlApplyAllChannelHandlerInjectable = getRequestChannelListenerInjecta handler: (di) => { const getClusterById = di.inject(getClusterByIdInjectable); const emitAppEvent = di.inject(emitAppEventInjectable); - const createResourceApplier = di.inject(createResourceApplierInjectable); return async ({ clusterId, @@ -30,7 +29,9 @@ const kubectlApplyAllChannelHandlerInjectable = getRequestChannelListenerInjecta }; } - return createResourceApplier(cluster).kubectlApplyAll(resources, extraArgs); + const resourceApplier = di.inject(resourceApplierInjectable, cluster); + + return resourceApplier.kubectlApplyAll(resources, extraArgs); }; }, }); diff --git a/packages/core/src/main/kubectl/create-kubectl.injectable.ts b/packages/core/src/main/kubectl/create-kubectl.injectable.ts index adfce0922f..5d7b19162c 100644 --- a/packages/core/src/main/kubectl/create-kubectl.injectable.ts +++ b/packages/core/src/main/kubectl/create-kubectl.injectable.ts @@ -18,11 +18,15 @@ import getDirnameOfPathInjectable from "../../common/path/get-dirname.injectable import joinPathsInjectable from "../../common/path/join-paths.injectable"; import getBasenameOfPathInjectable from "../../common/path/get-basename.injectable"; import loggerInjectable from "../../common/logger.injectable"; +import execFileInjectable from "../../common/fs/exec-file.injectable"; +import unlinkInjectable from "../../common/fs/unlink.injectable"; + +export type CreateKubectl = (version: string) => Kubectl; const createKubectlInjectable = getInjectable({ id: "create-kubectl", - instantiate: (di) => { + instantiate: (di): CreateKubectl => { const dependencies: KubectlDependencies = { userStore: di.inject(userStoreInjectable), directoryForKubectlBinaries: di.inject(directoryForKubectlBinariesInjectable), @@ -37,9 +41,11 @@ const createKubectlInjectable = getInjectable({ getDirnameOfPath: di.inject(getDirnameOfPathInjectable), joinPaths: di.inject(joinPathsInjectable), getBasenameOfPath: di.inject(getBasenameOfPathInjectable), + execFile: di.inject(execFileInjectable), + unlink: di.inject(unlinkInjectable), }; - return (clusterVersion: string) => new Kubectl(dependencies, clusterVersion); + return (version) => new Kubectl(dependencies, version); }, }); 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 00a8db6707..715eb0caf9 100644 --- a/packages/core/src/main/kubectl/delete-all-handler.injectable.ts +++ b/packages/core/src/main/kubectl/delete-all-handler.injectable.ts @@ -5,7 +5,7 @@ import emitAppEventInjectable from "../../common/app-event-bus/emit-event.injectable"; import getClusterByIdInjectable from "../../common/cluster-store/get-by-id.injectable"; import { kubectlDeleteAllChannel } from "../../common/kube-helpers/channels"; -import createResourceApplierInjectable from "../resource-applier/create-resource-applier.injectable"; +import resourceApplierInjectable from "../resource-applier/create-resource-applier.injectable"; import { getRequestChannelListenerInjectable } from "../utils/channel/channel-listeners/listener-tokens"; const kubectlDeleteAllChannelHandlerInjectable = getRequestChannelListenerInjectable({ @@ -13,7 +13,6 @@ const kubectlDeleteAllChannelHandlerInjectable = getRequestChannelListenerInject handler: (di) => { const emitAppEvent = di.inject(emitAppEventInjectable); const getClusterById = di.inject(getClusterByIdInjectable); - const createResourceApplier = di.inject(createResourceApplierInjectable); return async ({ clusterId, @@ -31,7 +30,9 @@ const kubectlDeleteAllChannelHandlerInjectable = getRequestChannelListenerInject }; } - return createResourceApplier(cluster).kubectlDeleteAll(resources, extraArgs); + const resourceApplier = di.inject(resourceApplierInjectable, cluster); + + return resourceApplier.kubectlDeleteAll(resources, extraArgs); }; }, }); diff --git a/packages/core/src/main/kubectl/kubectl.ts b/packages/core/src/main/kubectl/kubectl.ts index 15773a2ef7..ca0fac16e2 100644 --- a/packages/core/src/main/kubectl/kubectl.ts +++ b/packages/core/src/main/kubectl/kubectl.ts @@ -4,7 +4,6 @@ */ import fs from "fs"; -import { promiseExecFile } from "../../common/utils/promise-exec"; import { ensureDir, pathExists } from "fs-extra"; import * as lockFile from "proper-lockfile"; import { SemVer, coerce } from "semver"; @@ -18,6 +17,9 @@ import type { GetDirnameOfPath } from "../../common/path/get-dirname.injectable" import type { GetBasenameOfPath } from "../../common/path/get-basename.injectable"; import type { NormalizedPlatform } from "../../common/vars/normalized-platform.injectable"; import type { Logger } from "../../common/logger"; +import type { ExecFile } from "../../common/fs/exec-file.injectable"; +import { hasTypedProperty, isObject, isString, json } from "@k8slens/utilities"; +import type { Unlink } from "../../common/fs/unlink.injectable"; const initScriptVersionString = "# lens-initscript v3"; @@ -40,6 +42,8 @@ export interface KubectlDependencies { joinPaths: JoinPaths; getDirnameOfPath: GetDirnameOfPath; getBasenameOfPath: GetBasenameOfPath; + execFile: ExecFile; + unlink: Unlink; } export class Kubectl { @@ -145,38 +149,64 @@ export class Kubectl { public async checkBinary(path: string, checkVersion = true) { const exists = await pathExists(path); - if (exists) { - try { - const args = [ - "version", - "--client", - "--output", "json", - ]; - const { stdout } = await promiseExecFile(path, args); - const output = JSON.parse(stdout); - - if (!checkVersion) { - return true; - } - let version: string = output.clientVersion.gitVersion; - - if (version[0] === "v") { - version = version.slice(1); - } - - if (version === this.kubectlVersion) { - this.dependencies.logger.debug(`Local kubectl is version ${this.kubectlVersion}`); - - return true; - } - this.dependencies.logger.error(`Local kubectl is version ${version}, expected ${this.kubectlVersion}, unlinking`); - } catch (error) { - this.dependencies.logger.error(`Local kubectl failed to run properly (${error}), unlinking`); - } - await fs.promises.unlink(this.path); + if (!exists) { + return false; } - return false; + const args = [ + "version", + "--client", + "--output", "json", + ]; + const execResult = await this.dependencies.execFile(path, args); + + if (!execResult.callWasSuccessful) { + this.dependencies.logger.error(`Local kubectl failed to run properly (${execResult.error}), unlinking`); + await this.dependencies.unlink(this.path); + + return; + } + + const parseResult = json.parse(execResult.response); + + if (!parseResult.callWasSuccessful) { + this.dependencies.logger.error(`Local kubectl failed to run properly (${parseResult.error}), unlinking`); + await this.dependencies.unlink(this.path); + + return; + } + + if (!checkVersion) { + return true; + } + + const { response: output } = parseResult; + + if ( + !isObject(output) + || !hasTypedProperty(output, "clientVersion", isObject) + || !hasTypedProperty(output.clientVersion, "gitVersion", isString) + ) { + this.dependencies.logger.error(`Local kubectl failed to return correct shaped response, unlinking`); + await this.dependencies.unlink(this.path); + + return; + } + + const version = output.clientVersion.gitVersion; + + switch (output.clientVersion.gitVersion) { + case this.kubectlVersion: + case `v${this.kubectlVersion}`: + this.dependencies.logger.debug(`Local kubectl is version ${this.kubectlVersion}`); + + return true; + default: + this.dependencies.logger.error(`Local kubectl is version ${version}, expected ${this.kubectlVersion}, unlinking`); + await this.dependencies.unlink(this.path); + + return false; + } } protected async checkBundled(): Promise { @@ -266,7 +296,7 @@ export class Kubectl { await fs.promises.chmod(this.path, 0o755); this.dependencies.logger.debug("kubectl binary download finished"); } catch (error) { - await fs.promises.unlink(this.path).catch(noop); + await this.dependencies.unlink(this.path).catch(noop); throw error; } } diff --git a/packages/core/src/main/lens-proxy/lens-proxy.injectable.ts b/packages/core/src/main/lens-proxy/lens-proxy.injectable.ts index 541ef18cc3..96079563ca 100644 --- a/packages/core/src/main/lens-proxy/lens-proxy.injectable.ts +++ b/packages/core/src/main/lens-proxy/lens-proxy.injectable.ts @@ -4,7 +4,6 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { LensProxy } from "./lens-proxy"; -import { kubeApiUpgradeRequest } from "./proxy-functions"; import routerInjectable from "../router/router.injectable"; import httpProxy from "http-proxy"; import shellApiRequestInjectable from "./proxy-functions/shell-api-request.injectable"; @@ -14,6 +13,8 @@ import emitAppEventInjectable from "../../common/app-event-bus/emit-event.inject import loggerInjectable from "../../common/logger.injectable"; import lensProxyCertificateInjectable from "../../common/certificate/lens-proxy-certificate.injectable"; import getClusterForRequestInjectable from "./get-cluster-for-request.injectable"; +import kubeAuthProxyServerInjectable from "../cluster/kube-auth-proxy-server.injectable"; +import kubeApiUpgradeRequestInjectable from "./proxy-functions/kube-api-upgrade-request.injectable"; const lensProxyInjectable = getInjectable({ id: "lens-proxy", @@ -21,7 +22,7 @@ const lensProxyInjectable = getInjectable({ instantiate: (di) => new LensProxy({ router: di.inject(routerInjectable), proxy: httpProxy.createProxy(), - kubeApiUpgradeRequest, + kubeApiUpgradeRequest: di.inject(kubeApiUpgradeRequestInjectable), shellApiRequest: di.inject(shellApiRequestInjectable), getClusterForRequest: di.inject(getClusterForRequestInjectable), lensProxyPort: di.inject(lensProxyPortInjectable), @@ -29,6 +30,7 @@ const lensProxyInjectable = getInjectable({ emitAppEvent: di.inject(emitAppEventInjectable), logger: di.inject(loggerInjectable), certificate: di.inject(lensProxyCertificateInjectable).get(), + getKubeAuthProxyServer: (cluster) => di.inject(kubeAuthProxyServerInjectable, cluster), }), }); diff --git a/packages/core/src/main/lens-proxy/lens-proxy.ts b/packages/core/src/main/lens-proxy/lens-proxy.ts index 1a5acdd9f2..629e6a0f12 100644 --- a/packages/core/src/main/lens-proxy/lens-proxy.ts +++ b/packages/core/src/main/lens-proxy/lens-proxy.ts @@ -9,7 +9,6 @@ import type http from "http"; import type httpProxy from "http-proxy"; import { apiPrefix, apiKubePrefix } from "../../common/vars"; import type { Router } from "../router/router"; -import type { ClusterContextHandler } from "../context-handler/context-handler"; import type { Cluster } from "../../common/cluster/cluster"; import type { ProxyApiRequestArgs } from "./proxy-functions"; import { getBoolean } from "../utils/parse-query"; @@ -18,6 +17,7 @@ import type { SetRequired } from "type-fest"; import type { EmitAppEvent } from "../../common/app-event-bus/emit-event.injectable"; import type { Logger } from "../../common/logger"; import type { SelfSignedCert } from "selfsigned"; +import type { KubeAuthProxyServer } from "../cluster/kube-auth-proxy-server.injectable"; export type GetClusterForRequest = (req: http.IncomingMessage) => Cluster | undefined; export type ServerIncomingMessage = SetRequired; @@ -28,6 +28,7 @@ interface Dependencies { shellApiRequest: LensProxyApiRequest; kubeApiUpgradeRequest: LensProxyApiRequest; emitAppEvent: EmitAppEvent; + getKubeAuthProxyServer: (cluster: Cluster) => KubeAuthProxyServer; readonly router: Router; readonly proxy: httpProxy; readonly lensProxyPort: { set: (portNumber: number) => void }; @@ -220,15 +221,6 @@ export class LensProxy { return proxy; } - protected async getProxyTarget(req: http.IncomingMessage, contextHandler: ClusterContextHandler): Promise { - if (req.url?.startsWith(apiKubePrefix)) { - delete req.headers.authorization; - req.url = req.url.replace(apiKubePrefix, ""); - - return contextHandler.getApiTarget(isLongRunningRequest(req.url)); - } - } - protected getRequestId(req: http.IncomingMessage): string { assert(req.headers.host); @@ -238,8 +230,12 @@ export class LensProxy { protected async handleRequest(req: ServerIncomingMessage, res: http.ServerResponse) { const cluster = this.dependencies.getClusterForRequest(req); - if (cluster) { - const proxyTarget = await this.getProxyTarget(req, cluster.contextHandler); + if (cluster && req.url.startsWith(apiKubePrefix)) { + delete req.headers.authorization; + req.url = req.url.replace(apiKubePrefix, ""); + + const kubeAuthProxyServer = this.dependencies.getKubeAuthProxyServer(cluster); + const proxyTarget = await kubeAuthProxyServer.getApiTarget(isLongRunningRequest(req.url)); if (proxyTarget) { return this.dependencies.proxy.web(req, res, proxyTarget); diff --git a/packages/core/src/main/lens-proxy/proxy-functions/index.ts b/packages/core/src/main/lens-proxy/proxy-functions/index.ts index 5d374825ee..72553b2d2e 100644 --- a/packages/core/src/main/lens-proxy/proxy-functions/index.ts +++ b/packages/core/src/main/lens-proxy/proxy-functions/index.ts @@ -2,5 +2,4 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -export * from "./kube-api-upgrade-request"; export * from "./types"; diff --git a/packages/core/src/main/lens-proxy/proxy-functions/kube-api-upgrade-request.injectable.ts b/packages/core/src/main/lens-proxy/proxy-functions/kube-api-upgrade-request.injectable.ts new file mode 100644 index 0000000000..d6ddfca49a --- /dev/null +++ b/packages/core/src/main/lens-proxy/proxy-functions/kube-api-upgrade-request.injectable.ts @@ -0,0 +1,78 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { chunk } from "lodash"; +import type { ConnectionOptions } from "tls"; +import { connect } from "tls"; +import url, { URL } from "url"; +import { apiKubePrefix } from "../../../common/vars"; +import { getInjectable } from "@ogre-tools/injectable"; +import type { LensProxyApiRequest } from "../lens-proxy"; +import kubeAuthProxyServerInjectable from "../../cluster/kube-auth-proxy-server.injectable"; +import kubeAuthProxyCertificateInjectable from "../../kube-auth-proxy/kube-auth-proxy-certificate.injectable"; + +const skipRawHeaders = new Set(["Host", "Authorization"]); + +const kubeApiUpgradeRequestInjectable = getInjectable({ + id: "kube-api-upgrade-request", + instantiate: (di): LensProxyApiRequest => async ({ req, socket, head, cluster }) => { + const clusterUrl = new URL(cluster.apiUrl.get()); + const kubeAuthProxyServer = di.inject(kubeAuthProxyServerInjectable, cluster); + const kubeAuthProxyCertificate = di.inject(kubeAuthProxyCertificateInjectable, clusterUrl.hostname); + + const proxyUrl = await kubeAuthProxyServer.ensureAuthProxyUrl() + req.url.replace(apiKubePrefix, ""); + const apiUrl = url.parse(cluster.apiUrl.get()); + const pUrl = url.parse(proxyUrl); + const connectOpts: ConnectionOptions = { + port: pUrl.port ? parseInt(pUrl.port) : undefined, + host: pUrl.hostname ?? undefined, + ca: kubeAuthProxyCertificate.cert, + }; + + const proxySocket = connect(connectOpts, () => { + proxySocket.write(`${req.method} ${pUrl.path} HTTP/1.1\r\n`); + proxySocket.write(`Host: ${apiUrl.host}\r\n`); + + for (const [key, value] of chunk(req.rawHeaders, 2)) { + if (skipRawHeaders.has(key)) { + continue; + } + + proxySocket.write(`${key}: ${value}\r\n`); + } + + proxySocket.write("\r\n"); + proxySocket.write(head); + }); + + proxySocket.setKeepAlive(true); + socket.setKeepAlive(true); + proxySocket.setTimeout(0); + socket.setTimeout(0); + + proxySocket.on("data", function (chunk) { + socket.write(chunk); + }); + proxySocket.on("end", function () { + socket.end(); + }); + proxySocket.on("error", function () { + socket.write(`HTTP/${req.httpVersion} 500 Connection error\r\n\r\n`); + socket.end(); + }); + socket.on("data", function (chunk) { + proxySocket.write(chunk); + }); + socket.on("end", function () { + proxySocket.end(); + }); + socket.on("error", function () { + proxySocket.end(); + }); + }, +}); + +export default kubeApiUpgradeRequestInjectable; + diff --git a/packages/core/src/main/lens-proxy/proxy-functions/kube-api-upgrade-request.ts b/packages/core/src/main/lens-proxy/proxy-functions/kube-api-upgrade-request.ts deleted file mode 100644 index ddd8e66261..0000000000 --- a/packages/core/src/main/lens-proxy/proxy-functions/kube-api-upgrade-request.ts +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import { chunk } from "lodash"; -import type { ConnectionOptions } from "tls"; -import { connect } from "tls"; -import url from "url"; -import { apiKubePrefix } from "../../../common/vars"; -import type { ProxyApiRequestArgs } from "./types"; - -const skipRawHeaders = new Set(["Host", "Authorization"]); - -export async function kubeApiUpgradeRequest({ req, socket, head, cluster }: ProxyApiRequestArgs) { - const proxyUrl = await cluster.contextHandler.resolveAuthProxyUrl() + req.url.replace(apiKubePrefix, ""); - const proxyCa = cluster.contextHandler.resolveAuthProxyCa(); - const apiUrl = url.parse(cluster.apiUrl); - const pUrl = url.parse(proxyUrl); - const connectOpts: ConnectionOptions = { - port: pUrl.port ? parseInt(pUrl.port) : undefined, - host: pUrl.hostname ?? undefined, - ca: proxyCa, - }; - - const proxySocket = connect(connectOpts, () => { - proxySocket.write(`${req.method} ${pUrl.path} HTTP/1.1\r\n`); - proxySocket.write(`Host: ${apiUrl.host}\r\n`); - - for (const [key, value] of chunk(req.rawHeaders, 2)) { - if (skipRawHeaders.has(key)) { - continue; - } - - proxySocket.write(`${key}: ${value}\r\n`); - } - - proxySocket.write("\r\n"); - proxySocket.write(head); - }); - - proxySocket.setKeepAlive(true); - socket.setKeepAlive(true); - proxySocket.setTimeout(0); - socket.setTimeout(0); - - proxySocket.on("data", function (chunk) { - socket.write(chunk); - }); - proxySocket.on("end", function () { - socket.end(); - }); - proxySocket.on("error", function () { - socket.write(`HTTP/${req.httpVersion} 500 Connection error\r\n\r\n`); - socket.end(); - }); - socket.on("data", function (chunk) { - proxySocket.write(chunk); - }); - socket.on("end", function () { - proxySocket.end(); - }); - socket.on("error", function () { - proxySocket.end(); - }); -} diff --git a/packages/core/src/main/lens-proxy/proxy-functions/shell-request-authenticator/shell-request-authenticator.ts b/packages/core/src/main/lens-proxy/proxy-functions/shell-request-authenticator/shell-request-authenticator.ts index ab5e46eb77..91d4161164 100644 --- a/packages/core/src/main/lens-proxy/proxy-functions/shell-request-authenticator/shell-request-authenticator.ts +++ b/packages/core/src/main/lens-proxy/proxy-functions/shell-request-authenticator/shell-request-authenticator.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 { getOrInsertMap } from "../../../../common/utils"; +import { getOrInsertMap } from "@k8slens/utilities"; import type { ClusterId } from "../../../../common/cluster-types"; import { ipcMainHandle } from "../../../../common/ipc"; import crypto from "crypto"; diff --git a/packages/core/src/main/library.ts b/packages/core/src/main/library.ts index cb396cf448..cf651cb091 100644 --- a/packages/core/src/main/library.ts +++ b/packages/core/src/main/library.ts @@ -4,12 +4,10 @@ */ // @experimental -export type { - Environments, -} from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; - +export type { Environments } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; export { registerLensCore } from "./register-lens-core"; export { nodeEnvInjectionToken } from "../common/vars/node-env-injection-token"; + export * as Mobx from "mobx"; export * as mainExtensionApi from "../extensions/main-api"; export * as commonExtensionApi from "../extensions/common-api"; diff --git a/packages/core/src/main/logger/level.global-override-for-injectable.ts b/packages/core/src/main/logger/level.global-override-for-injectable.ts index ac29c9ee1a..fe280b1d31 100644 --- a/packages/core/src/main/logger/level.global-override-for-injectable.ts +++ b/packages/core/src/main/logger/level.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import logLevelInjectable from "./level.injectable"; export default getGlobalOverride(logLevelInjectable, () => "error"); diff --git a/packages/core/src/main/navigate-to-route/navigate-to-route.injectable.ts b/packages/core/src/main/navigate-to-route/navigate-to-route.injectable.ts index e097bf1569..6615d976f1 100644 --- a/packages/core/src/main/navigate-to-route/navigate-to-route.injectable.ts +++ b/packages/core/src/main/navigate-to-route/navigate-to-route.injectable.ts @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import { navigateToUrlInjectionToken } from "../../common/front-end-routing/navigate-to-url-injection-token"; import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token"; -import { buildURL } from "../../common/utils/buildUrl"; +import { buildURL } from "@k8slens/utilities"; const navigateToRouteInjectable = getInjectable({ id: "navigate-to-route", diff --git a/packages/core/src/main/prometheus/provider.ts b/packages/core/src/main/prometheus/provider.ts index 8944c4c0ed..5bd9588a06 100644 --- a/packages/core/src/main/prometheus/provider.ts +++ b/packages/core/src/main/prometheus/provider.ts @@ -5,7 +5,7 @@ import type { CoreV1Api } from "@kubernetes/client-node"; import { getInjectionToken } from "@ogre-tools/injectable"; -import { isRequestError } from "../../common/utils"; +import { isRequestError } from "@k8slens/utilities"; export interface PrometheusService extends PrometheusServiceInfo { kind: string; diff --git a/packages/core/src/main/protocol-handler/__test__/router.test.ts b/packages/core/src/main/protocol-handler/__test__/router.test.ts index beb40116ed..7919e3f596 100644 --- a/packages/core/src/main/protocol-handler/__test__/router.test.ts +++ b/packages/core/src/main/protocol-handler/__test__/router.test.ts @@ -6,7 +6,7 @@ import * as uuid from "uuid"; import { ProtocolHandlerExtension, ProtocolHandlerInternal, ProtocolHandlerInvalid } from "../../../common/protocol-handler"; -import { delay, noop } from "../../../common/utils"; +import { delay, noop } from "@k8slens/utilities"; import type { ExtensionsStore, IsEnabledExtensionDescriptor } from "../../../extensions/extensions-store/extensions-store"; import type { LensProtocolRouterMain } from "../lens-protocol-router-main/lens-protocol-router-main"; import { getDiForUnitTesting } from "../../getDiForUnitTesting"; diff --git a/packages/core/src/main/protocol-handler/lens-protocol-router-main/lens-protocol-router-main.ts b/packages/core/src/main/protocol-handler/lens-protocol-router-main/lens-protocol-router-main.ts index 3beb596e4e..fb0ad71892 100644 --- a/packages/core/src/main/protocol-handler/lens-protocol-router-main/lens-protocol-router-main.ts +++ b/packages/core/src/main/protocol-handler/lens-protocol-router-main/lens-protocol-router-main.ts @@ -9,7 +9,7 @@ import type { LensExtension } from "../../../extensions/lens-extension"; import { observable, when, makeObservable } from "mobx"; import type { LensProtocolRouterDependencies, RouteAttempt } from "../../../common/protocol-handler"; import { ProtocolHandlerInvalid } from "../../../common/protocol-handler"; -import { disposer, noop } from "../../../common/utils"; +import { disposer, noop } from "@k8slens/utilities"; import type { BroadcastMessage } from "../../../common/ipc/broadcast-message.injectable"; export interface FallbackHandler { diff --git a/packages/core/src/main/resource-applier/create-resource-applier.injectable.ts b/packages/core/src/main/resource-applier/create-resource-applier.injectable.ts index 509dce086c..245a3551bf 100644 --- a/packages/core/src/main/resource-applier/create-resource-applier.injectable.ts +++ b/packages/core/src/main/resource-applier/create-resource-applier.injectable.ts @@ -2,33 +2,36 @@ * 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 { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; import emitAppEventInjectable from "../../common/app-event-bus/emit-event.injectable"; -import type { Cluster } from "../../common/cluster/cluster"; import removePathInjectable from "../../common/fs/remove.injectable"; import execFileInjectable from "../../common/fs/exec-file.injectable"; import writeFileInjectable from "../../common/fs/write-file.injectable"; import loggerInjectable from "../../common/logger.injectable"; import joinPathsInjectable from "../../common/path/join-paths.injectable"; -import type { ResourceApplierDependencies } from "./resource-applier"; import { ResourceApplier } from "./resource-applier"; +import createKubectlInjectable from "../kubectl/create-kubectl.injectable"; +import kubeconfigManagerInjectable from "../kubeconfig-manager/kubeconfig-manager.injectable"; +import type { Cluster } from "../../common/cluster/cluster"; -export type CreateResourceApplier = (cluster: Cluster) => ResourceApplier; - -const createResourceApplierInjectable = getInjectable({ - id: "create-resource-applier", - instantiate: (di): CreateResourceApplier => { - const deps: ResourceApplierDependencies = { +const resourceApplierInjectable = getInjectable({ + id: "resource-applier", + instantiate: (di, cluster) => new ResourceApplier( + { deleteFile: di.inject(removePathInjectable), emitAppEvent: di.inject(emitAppEventInjectable), execFile: di.inject(execFileInjectable), joinPaths: di.inject(joinPathsInjectable), logger: di.inject(loggerInjectable), writeFile: di.inject(writeFileInjectable), - }; - - return (cluster) => new ResourceApplier(deps, cluster); - }, + createKubectl: di.inject(createKubectlInjectable), + proxyKubeconfigManager: di.inject(kubeconfigManagerInjectable, cluster), + }, + cluster, + ), + lifecycle: lifecycleEnum.keyedSingleton({ + getInstanceKey: (di, cluster: Cluster) => cluster.id, + }), }); -export default createResourceApplierInjectable; +export default resourceApplierInjectable; diff --git a/packages/core/src/main/resource-applier/resource-applier.ts b/packages/core/src/main/resource-applier/resource-applier.ts index a604781fce..6df02debc8 100644 --- a/packages/core/src/main/resource-applier/resource-applier.ts +++ b/packages/core/src/main/resource-applier/resource-applier.ts @@ -14,7 +14,9 @@ import type { WriteFile } from "../../common/fs/write-file.injectable"; import type { RemovePath } from "../../common/fs/remove.injectable"; import type { ExecFile } from "../../common/fs/exec-file.injectable"; import type { JoinPaths } from "../../common/path/join-paths.injectable"; -import type { AsyncResult } from "../../common/utils/async-result"; +import type { CreateKubectl } from "../kubectl/create-kubectl.injectable"; +import type { KubeconfigManager } from "../kubeconfig-manager/kubeconfig-manager"; +import type { AsyncResult } from "@k8slens/utilities"; export interface ResourceApplierDependencies { emitAppEvent: EmitAppEvent; @@ -22,11 +24,24 @@ export interface ResourceApplierDependencies { deleteFile: RemovePath; execFile: ExecFile; joinPaths: JoinPaths; + createKubectl: CreateKubectl; + readonly proxyKubeconfigManager: KubeconfigManager; readonly logger: Logger; } export class ResourceApplier { - constructor(protected readonly dependencies: ResourceApplierDependencies, protected readonly cluster: Cluster) {} + constructor( + protected readonly dependencies: ResourceApplierDependencies, + protected readonly cluster: Cluster, + ) {} + + private async getKubectlPath() { + const kubectl = this.dependencies.createKubectl(this.cluster.version.get()); + + await kubectl.ensureKubectl(); + + return kubectl.getPath(); + } /** * Patch a kube resource's manifest, throwing any error that occurs. @@ -38,9 +53,8 @@ export class ResourceApplier { async patch(name: string, kind: string, patch: Patch, ns?: string): Promise { this.dependencies.emitAppEvent({ name: "resource", action: "patch" }); - const kubectl = await this.cluster.ensureKubectl(); - const kubectlPath = await kubectl.getPath(); - const proxyKubeconfigPath = await this.cluster.getProxyKubeconfigPath(); + const kubectlPath = await this.getKubectlPath(); + const proxyKubeconfigPath = await this.dependencies.proxyKubeconfigManager.ensurePath(); const args = [ "--kubeconfig", proxyKubeconfigPath, "patch", @@ -67,16 +81,15 @@ export class ResourceApplier { throw result.error.stderr || result.error.message; } - async create(resource: string): Promise> { + async create(resource: string): AsyncResult { this.dependencies.emitAppEvent({ name: "resource", action: "apply" }); return this.kubectlApply(this.sanitizeObject(resource)); } - protected async kubectlApply(content: string): Promise> { - const kubectl = await this.cluster.ensureKubectl(); - const kubectlPath = await kubectl.getPath(); - const proxyKubeconfigPath = await this.cluster.getProxyKubeconfigPath(); + protected async kubectlApply(content: string): AsyncResult { + const kubectlPath = await this.getKubectlPath(); + const proxyKubeconfigPath = await this.dependencies.proxyKubeconfigManager.ensurePath(); const fileName = tempy.file({ name: "resource.yaml" }); const args = [ "apply", @@ -112,18 +125,17 @@ export class ResourceApplier { } } - public async kubectlApplyAll(resources: string[], extraArgs = ["-o", "json"]): Promise> { + public async kubectlApplyAll(resources: string[], extraArgs = ["-o", "json"]): AsyncResult { return this.kubectlCmdAll("apply", resources, extraArgs); } - public async kubectlDeleteAll(resources: string[], extraArgs?: string[]): Promise> { + public async kubectlDeleteAll(resources: string[], extraArgs?: string[]): AsyncResult { return this.kubectlCmdAll("delete", resources, extraArgs); } - protected async kubectlCmdAll(subCmd: string, resources: string[], parentArgs: string[] = []): Promise> { - const kubectl = await this.cluster.ensureKubectl(); - const kubectlPath = await kubectl.getPath(); - const proxyKubeconfigPath = await this.cluster.getProxyKubeconfigPath(); + protected async kubectlCmdAll(subCmd: string, resources: string[], parentArgs: string[] = []): AsyncResult { + const kubectlPath = await this.getKubectlPath(); + const proxyKubeconfigPath = await this.dependencies.proxyKubeconfigManager.ensurePath(); const tmpDir = tempy.directory(); await Promise.all(resources.map((resource, index) => this.dependencies.writeFile( diff --git a/packages/core/src/main/router/create-handler-for-route.injectable.ts b/packages/core/src/main/router/create-handler-for-route.injectable.ts index 60f62fd282..d007172294 100644 --- a/packages/core/src/main/router/create-handler-for-route.injectable.ts +++ b/packages/core/src/main/router/create-handler-for-route.injectable.ts @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { ServerResponse } from "http"; import loggerInjectable from "../../common/logger.injectable"; -import { object } from "../../common/utils"; +import { object } from "@k8slens/utilities"; import type { LensApiRequest, Route } from "./route"; import { contentTypes } from "./router-content-types"; diff --git a/packages/core/src/main/routes/kubeconfig-route/get-service-account-route.injectable.ts b/packages/core/src/main/routes/kubeconfig-route/get-service-account-route.injectable.ts index 476ee983a3..b6b77d5a40 100644 --- a/packages/core/src/main/routes/kubeconfig-route/get-service-account-route.injectable.ts +++ b/packages/core/src/main/routes/kubeconfig-route/get-service-account-route.injectable.ts @@ -10,15 +10,18 @@ import type { V1Secret } from "@kubernetes/client-node"; import { CoreV1Api } from "@kubernetes/client-node"; import { clusterRoute } from "../../router/route"; import { dump } from "js-yaml"; +import loadProxyKubeconfigInjectable from "../../cluster/load-proxy-kubeconfig.injectable"; const getServiceAccountRouteInjectable = getRouteInjectable({ id: "get-service-account-route", - instantiate: () => clusterRoute({ + instantiate: (di) => clusterRoute({ method: "get", path: `${apiPrefix}/kubeconfig/service-account/{namespace}/{account}`, })(async ({ params, cluster }) => { - const client = (await cluster.getProxyKubeconfig()).makeApiClient(CoreV1Api); + const loadProxyKubeconfig = di.inject(loadProxyKubeconfigInjectable, cluster); + const proxyKubeconfig = await loadProxyKubeconfig(); + const client = proxyKubeconfig.makeApiClient(CoreV1Api); const secretList = await client.listNamespacedSecret(params.namespace); const secret = secretList.body.items.find(secret => { @@ -64,9 +67,9 @@ function generateKubeConfig(username: string, secret: V1Secret, cluster: Cluster "kind": "Config", "clusters": [ { - "name": cluster.contextName, + "name": cluster.contextName.get(), "cluster": { - "server": cluster.apiUrl, + "server": cluster.apiUrl.get(), "certificate-authority-data": caCrt, }, }, @@ -81,14 +84,14 @@ function generateKubeConfig(username: string, secret: V1Secret, cluster: Cluster ], "contexts": [ { - "name": cluster.contextName, + "name": cluster.contextName.get(), "context": { "user": username, - "cluster": cluster.contextName, + "cluster": cluster.contextName.get(), "namespace": secret.metadata.namespace, }, }, ], - "current-context": cluster.contextName, + "current-context": cluster.contextName.get(), }); } diff --git a/packages/core/src/main/routes/metrics/add-metrics-route.injectable.ts b/packages/core/src/main/routes/metrics/add-metrics-route.injectable.ts index eb59f2840b..fe3d2b01fa 100644 --- a/packages/core/src/main/routes/metrics/add-metrics-route.injectable.ts +++ b/packages/core/src/main/routes/metrics/add-metrics-route.injectable.ts @@ -10,10 +10,12 @@ import { ClusterMetadataKey } from "../../../common/cluster-types"; import type { Cluster } from "../../../common/cluster/cluster"; import { clusterRoute } from "../../router/route"; import { isObject } from "lodash"; -import { isRequestError, object } from "../../../common/utils"; +import { isRequestError, object } from "@k8slens/utilities"; import type { GetMetrics } from "../../get-metrics.injectable"; import getMetricsInjectable from "../../get-metrics.injectable"; import loggerInjectable from "../../../common/logger.injectable"; +import prometheusHandlerInjectable from "../../cluster/prometheus-handler/prometheus-handler.injectable"; +import { runInAction } from "mobx"; // This is used for backoff retry tracking. const ATTEMPTS = [false, false, false, false, true]; @@ -66,9 +68,10 @@ const addMetricsRouteInjectable = getRouteInjectable({ })(async ({ cluster, payload, query }) => { const queryParams: Partial> = Object.fromEntries(query.entries()); const prometheusMetadata: ClusterPrometheusMetadata = {}; + const prometheusHandler = di.inject(prometheusHandlerInjectable, cluster); try { - const { prometheusPath, provider } = await cluster.contextHandler.getPrometheusDetails(); + const { prometheusPath, provider } = await prometheusHandler.getPrometheusDetails(); prometheusMetadata.provider = provider?.kind; prometheusMetadata.autoDetected = !cluster.preferences.prometheusProvider?.type; @@ -115,7 +118,9 @@ const addMetricsRouteInjectable = getRouteInjectable({ return { response: {}}; } finally { - cluster.metadata[ClusterMetadataKey.PROMETHEUS] = prometheusMetadata; + runInAction(() => { + cluster.metadata[ClusterMetadataKey.PROMETHEUS] = prometheusMetadata; + }); } }); }, diff --git a/packages/core/src/main/routes/port-forward/start-port-forward-route.injectable.ts b/packages/core/src/main/routes/port-forward/start-port-forward-route.injectable.ts index 0716b81a2f..170f93fef8 100644 --- a/packages/core/src/main/routes/port-forward/start-port-forward-route.injectable.ts +++ b/packages/core/src/main/routes/port-forward/start-port-forward-route.injectable.ts @@ -8,6 +8,7 @@ import { PortForward } from "./functionality/port-forward"; import createPortForwardInjectable from "./functionality/create-port-forward.injectable"; import { clusterRoute } from "../../router/route"; import loggerInjectable from "../../../common/logger.injectable"; +import kubeconfigManagerInjectable from "../../kubeconfig-manager/kubeconfig-manager.injectable"; const startPortForwardRouteInjectable = getRouteInjectable({ id: "start-current-port-forward-route", @@ -24,6 +25,8 @@ const startPortForwardRouteInjectable = getRouteInjectable({ const port = Number(query.get("port")); const forwardPort = Number(query.get("forwardPort")); + const proxyKubeconfigManager = di.inject(kubeconfigManagerInjectable, cluster); + try { let portForward = PortForward.getPortforward({ clusterId: cluster.id, @@ -42,8 +45,9 @@ const startPortForwardRouteInjectable = getRouteInjectable({ const thePort = 0 < forwardPort && forwardPort < 65536 ? forwardPort : 0; + const proxyKubeconfigPath = await proxyKubeconfigManager.ensurePath(); - portForward = createPortForward(await cluster.getProxyKubeconfigPath(), { + portForward = createPortForward(proxyKubeconfigPath, { clusterId: cluster.id, kind: resourceType, namespace, diff --git a/packages/core/src/main/routes/resource-applier/create-resource-route.injectable.ts b/packages/core/src/main/routes/resource-applier/create-resource-route.injectable.ts index 3b68201e9d..a2d8766170 100644 --- a/packages/core/src/main/routes/resource-applier/create-resource-route.injectable.ts +++ b/packages/core/src/main/routes/resource-applier/create-resource-route.injectable.ts @@ -6,22 +6,22 @@ import { getRouteInjectable } from "../../router/router.injectable"; import { apiPrefix } from "../../../common/vars"; import { payloadValidatedClusterRoute } from "../../router/route"; import Joi from "joi"; -import createResourceApplierInjectable from "../../resource-applier/create-resource-applier.injectable"; +import resourceApplierInjectable from "../../resource-applier/create-resource-applier.injectable"; const createResourceRouteInjectable = getRouteInjectable({ id: "create-resource-route", - instantiate: (di) => { - const createResourceApplier = di.inject(createResourceApplierInjectable); + instantiate: (di) => payloadValidatedClusterRoute({ + method: "post", + path: `${apiPrefix}/stack`, + payloadValidator: Joi.string(), + })(async ({ cluster, payload }) => { + const resourceApplier = di.inject(resourceApplierInjectable, cluster); - return payloadValidatedClusterRoute({ - method: "post", - path: `${apiPrefix}/stack`, - payloadValidator: Joi.string(), - })(async ({ cluster, payload }) => ({ - response: await createResourceApplier(cluster).create(payload), - })); - }, + return ({ + response: await resourceApplier.create(payload), + }); + }), }); export default createResourceRouteInjectable; diff --git a/packages/core/src/main/routes/resource-applier/patch-resource-route.injectable.ts b/packages/core/src/main/routes/resource-applier/patch-resource-route.injectable.ts index e962c18607..6cac0436f5 100644 --- a/packages/core/src/main/routes/resource-applier/patch-resource-route.injectable.ts +++ b/packages/core/src/main/routes/resource-applier/patch-resource-route.injectable.ts @@ -7,7 +7,7 @@ import { apiPrefix } from "../../../common/vars"; import { payloadValidatedClusterRoute } from "../../router/route"; import Joi from "joi"; import type { Patch } from "rfc6902"; -import createResourceApplierInjectable from "../../resource-applier/create-resource-applier.injectable"; +import resourceApplierInjectable from "../../resource-applier/create-resource-applier.injectable"; interface PatchResourcePayload { name: string; @@ -40,22 +40,22 @@ const patchResourcePayloadValidator = Joi.object { - const createResourceApplier = di.inject(createResourceApplierInjectable); + instantiate: (di) => payloadValidatedClusterRoute({ + method: "patch", + path: `${apiPrefix}/stack`, + payloadValidator: patchResourcePayloadValidator, + })(async ({ cluster, payload }) => { + const resourceApplier = di.inject(resourceApplierInjectable, cluster); - return payloadValidatedClusterRoute({ - method: "patch", - path: `${apiPrefix}/stack`, - payloadValidator: patchResourcePayloadValidator, - })(async ({ cluster, payload }) => ({ - response: await createResourceApplier(cluster).patch( + return ({ + response: await resourceApplier.patch( payload.name, payload.kind, payload.patch, payload.ns, ), - })); - }, + }); + }), }); export default patchResourceRouteInjectable; diff --git a/packages/core/src/main/shell-session/local-shell-session/local-shell-session.ts b/packages/core/src/main/shell-session/local-shell-session/local-shell-session.ts index 49e6dd059f..567fc1dca7 100644 --- a/packages/core/src/main/shell-session/local-shell-session/local-shell-session.ts +++ b/packages/core/src/main/shell-session/local-shell-session/local-shell-session.ts @@ -52,16 +52,16 @@ export class LocalShellSession extends ShellSession { protected async getShellArgs(shell: string): Promise { const pathFromPreferences = this.dependencies.userStore.kubectlBinariesPath || this.kubectl.getBundledPath(); const kubectlPathDir = this.dependencies.userStore.downloadKubectlBinaries - ? await this.kubectlBinDirP + ? this.dependencies.directoryContainingKubectl : this.dependencies.getDirnameOfPath(pathFromPreferences); switch(this.dependencies.getBasenameOfPath(shell)) { case "powershell.exe": return ["-NoExit", "-command", `& {$Env:PATH="${kubectlPathDir};${this.dependencies.directoryForBinaries};$Env:PATH"}`]; case "bash": - return ["--init-file", this.dependencies.joinPaths(await this.kubectlBinDirP, ".bash_set_path")]; + return ["--init-file", this.dependencies.joinPaths(this.dependencies.directoryContainingKubectl, ".bash_set_path")]; case "fish": - return ["--login", "--init-command", `export PATH="${kubectlPathDir}:${this.dependencies.directoryForBinaries}:$PATH"; export KUBECONFIG="${await this.kubeconfigPathP}"`]; + return ["--login", "--init-command", `export PATH="${kubectlPathDir}:${this.dependencies.directoryForBinaries}:$PATH"; export KUBECONFIG="${await this.dependencies.proxyKubeconfigPath}"`]; case "zsh": return ["--login"]; default: diff --git a/packages/core/src/main/shell-session/local-shell-session/open.injectable.ts b/packages/core/src/main/shell-session/local-shell-session/open.injectable.ts index 084aa2e17c..4d5d54984a 100644 --- a/packages/core/src/main/shell-session/local-shell-session/open.injectable.ts +++ b/packages/core/src/main/shell-session/local-shell-session/open.injectable.ts @@ -24,6 +24,7 @@ import appNameInjectable from "../../../common/vars/app-name.injectable"; import buildVersionInjectable from "../../vars/build-version/build-version.injectable"; import emitAppEventInjectable from "../../../common/app-event-bus/emit-event.injectable"; import statInjectable from "../../../common/fs/stat.injectable"; +import kubeconfigManagerInjectable from "../../kubeconfig-manager/kubeconfig-manager.injectable"; export interface OpenLocalShellSessionArgs { websocket: WebSocket; @@ -38,7 +39,7 @@ const openLocalShellSessionInjectable = getInjectable({ instantiate: (di): OpenLocalShellSession => { const createKubectl = di.inject(createKubectlInjectable); - const dependencies: LocalShellSessionDependencies = { + const dependencies: Omit = { directoryForBinaries: di.inject(directoryForBinariesInjectable), isMac: di.inject(isMacInjectable), isWindows: di.inject(isWindowsInjectable), @@ -57,9 +58,17 @@ const openLocalShellSessionInjectable = getInjectable({ stat: di.inject(statInjectable), }; - return (args) => { - const kubectl = createKubectl(args.cluster.version); - const session = new LocalShellSession(dependencies, { kubectl, ...args }); + return async (args) => { + const kubectl = createKubectl(args.cluster.version.get()); + const kubeconfigManager = di.inject(kubeconfigManagerInjectable, args.cluster); + const proxyKubeconfigPath = await kubeconfigManager.ensurePath(); + const directoryContainingKubectl = await kubectl.binDir(); + + const session = new LocalShellSession({ + ...dependencies, + proxyKubeconfigPath, + directoryContainingKubectl, + }, { kubectl, ...args }); return session.open(); }; diff --git a/packages/core/src/main/shell-session/local-shell-session/techincal.test.ts b/packages/core/src/main/shell-session/local-shell-session/techincal.test.ts index 17d9aa3349..f37e690561 100644 --- a/packages/core/src/main/shell-session/local-shell-session/techincal.test.ts +++ b/packages/core/src/main/shell-session/local-shell-session/techincal.test.ts @@ -5,8 +5,9 @@ import type { DiContainer } from "@ogre-tools/injectable"; import type WebSocket from "ws"; +import directoryForTempInjectable from "../../../common/app-paths/directory-for-temp/directory-for-temp.injectable"; import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; -import type { Cluster } from "../../../common/cluster/cluster"; +import { Cluster } from "../../../common/cluster/cluster"; import pathExistsSyncInjectable from "../../../common/fs/path-exists-sync.injectable"; import pathExistsInjectable from "../../../common/fs/path-exists.injectable"; import readJsonSyncInjectable from "../../../common/fs/read-json-sync.injectable"; @@ -14,8 +15,11 @@ import statInjectable from "../../../common/fs/stat.injectable"; import writeJsonSyncInjectable from "../../../common/fs/write-json-sync.injectable"; import platformInjectable from "../../../common/vars/platform.injectable"; import { getDiForUnitTesting } from "../../getDiForUnitTesting"; +import type { KubeconfigManager } from "../../kubeconfig-manager/kubeconfig-manager"; +import kubeconfigManagerInjectable from "../../kubeconfig-manager/kubeconfig-manager.injectable"; import createKubectlInjectable from "../../kubectl/create-kubectl.injectable"; import type { Kubectl } from "../../kubectl/kubectl"; +import lensProxyPortInjectable from "../../lens-proxy/lens-proxy-port.injectable"; import buildVersionInjectable from "../../vars/build-version/build-version.injectable"; import type { OpenShellSession } from "../create-shell-session.injectable"; import type { SpawnPty } from "../spawn-pty.injectable"; @@ -29,6 +33,7 @@ describe("technical unit tests for local shell sessions", () => { di = getDiForUnitTesting(); di.override(directoryForUserDataInjectable, () => "/some-directory-for-user-data"); + di.override(directoryForTempInjectable, () => "/some-directory-for-tmp"); di.override(buildVersionInjectable, () => ({ get: () => "1.1.1", })); @@ -37,6 +42,7 @@ describe("technical unit tests for local shell sessions", () => { di.override(readJsonSyncInjectable, () => () => { throw new Error("tried call readJsonSync without override"); }); di.override(writeJsonSyncInjectable, () => () => { throw new Error("tried call writeJsonSync without override"); }); di.override(statInjectable, () => () => { throw new Error("tried call stat without override"); }); + di.inject(lensProxyPortInjectable).set(1111); }); describe("when on windows", () => { @@ -54,6 +60,10 @@ describe("technical unit tests for local shell sessions", () => { getBundledPath: () => "/some-bundled-kubectl-path", }) as Partial as Kubectl); + di.override(kubeconfigManagerInjectable, () => ({ + ensurePath: async () => "/some-proxy-kubeconfig-file", + } as Partial as KubeconfigManager)); + openLocalShellSession = di.inject(openLocalShellSessionInjectable); }); @@ -89,11 +99,16 @@ describe("technical unit tests for local shell sessions", () => { once: jest.fn(() => websocket), } as Partial as WebSocket; + const cluster = new Cluster({ + contextName: "some-context-name", + id: "some-cluster-id", + kubeConfigPath: "/some-kube-config-path", + }, { + clusterServerUrl: "https://localhost:9999", + }); + await openLocalShellSession({ - cluster: { - getProxyKubeconfigPath: async () => "/some-proxy-kubeconfig", - preferences: {}, - } as Partial as Cluster, + cluster, tabId: "my-tab-id", websocket, }); diff --git a/packages/core/src/main/shell-session/node-shell-session/node-shell-session.ts b/packages/core/src/main/shell-session/node-shell-session/node-shell-session.ts index 492c70d73d..a9a928adb6 100644 --- a/packages/core/src/main/shell-session/node-shell-session/node-shell-session.ts +++ b/packages/core/src/main/shell-session/node-shell-session/node-shell-session.ts @@ -13,6 +13,8 @@ import { NodeApi } from "../../../common/k8s-api/endpoints"; import { TerminalChannels } from "../../../common/terminal/channels"; import type { CreateKubeJsonApiForCluster } from "../../../common/k8s-api/create-kube-json-api-for-cluster.injectable"; import type { CreateKubeApi } from "../../../common/k8s-api/create-kube-api.injectable"; +import { initialNodeShellImage } from "../../../common/cluster-types"; +import type { LoadProxyKubeconfig } from "../../cluster/load-proxy-kubeconfig.injectable"; export interface NodeShellSessionArgs extends ShellSessionArgs { nodeName: string; @@ -21,6 +23,7 @@ export interface NodeShellSessionArgs extends ShellSessionArgs { export interface NodeShellSessionDependencies extends ShellSessionDependencies { createKubeJsonApiForCluster: CreateKubeJsonApiForCluster; createKubeApi: CreateKubeApi; + loadProxyKubeconfig: LoadProxyKubeconfig; } export class NodeShellSession extends ShellSession { @@ -36,9 +39,8 @@ export class NodeShellSession extends ShellSession { } public async open() { - const kc = await this.cluster.getProxyKubeconfig(); - const coreApi = kc.makeApiClient(CoreV1Api); - const shell = await this.kubectl.getPath(); + const proxyKubeconfig = await this.dependencies.loadProxyKubeconfig(); + const coreApi = proxyKubeconfig.makeApiClient(CoreV1Api); const cleanup = once(() => { coreApi @@ -50,7 +52,7 @@ export class NodeShellSession extends ShellSession { try { await this.createNodeShellPod(coreApi); - await this.waitForRunningPod(kc); + await this.waitForRunningPod(proxyKubeconfig); } catch (error) { cleanup(); @@ -92,13 +94,18 @@ export class NodeShellSession extends ShellSession { break; } - await this.openShellProcess(shell, args, env); + await this.openShellProcess(this.dependencies.directoryContainingKubectl, args, env); } protected createNodeShellPod(coreApi: CoreV1Api) { - const imagePullSecrets = this.cluster.imagePullSecret + const { + imagePullSecret, + nodeShellImage, + } = this.cluster.preferences; + + const imagePullSecrets = imagePullSecret ? [{ - name: this.cluster.imagePullSecret, + name: imagePullSecret, }] : undefined; @@ -121,7 +128,7 @@ export class NodeShellSession extends ShellSession { priorityClassName: "system-node-critical", containers: [{ name: "shell", - image: this.cluster.nodeShellImage, + image: nodeShellImage || initialNodeShellImage, securityContext: { privileged: true, }, diff --git a/packages/core/src/main/shell-session/node-shell-session/open.injectable.ts b/packages/core/src/main/shell-session/node-shell-session/open.injectable.ts index cce3fa5f36..55ec26d362 100644 --- a/packages/core/src/main/shell-session/node-shell-session/open.injectable.ts +++ b/packages/core/src/main/shell-session/node-shell-session/open.injectable.ts @@ -20,6 +20,8 @@ import buildVersionInjectable from "../../vars/build-version/build-version.injec import emitAppEventInjectable from "../../../common/app-event-bus/emit-event.injectable"; import statInjectable from "../../../common/fs/stat.injectable"; import createKubeApiInjectable from "../../../common/k8s-api/create-kube-api.injectable"; +import loadProxyKubeconfigInjectable from "../../cluster/load-proxy-kubeconfig.injectable"; +import kubeconfigManagerInjectable from "../../kubeconfig-manager/kubeconfig-manager.injectable"; export interface NodeShellSessionArgs { websocket: WebSocket; @@ -34,7 +36,7 @@ const openNodeShellSessionInjectable = getInjectable({ id: "open-node-shell-session", instantiate: (di): OpenNodeShellSession => { const createKubectl = di.inject(createKubectlInjectable); - const dependencies: NodeShellSessionDependencies = { + const dependencies: Omit = { isMac: di.inject(isMacInjectable), isWindows: di.inject(isWindowsInjectable), logger: di.inject(loggerInjectable), @@ -50,8 +52,18 @@ const openNodeShellSessionInjectable = getInjectable({ }; return async (args) => { - const kubectl = createKubectl(args.cluster.version); - const session = new NodeShellSession(dependencies, { kubectl, ...args }); + const kubectl = createKubectl(args.cluster.version.get()); + const kubeconfigManager = di.inject(kubeconfigManagerInjectable, args.cluster); + const loadProxyKubeconfig = di.inject(loadProxyKubeconfigInjectable, args.cluster); + const proxyKubeconfigPath = await kubeconfigManager.ensurePath(); + const directoryContainingKubectl = await kubectl.binDir(); + + const session = new NodeShellSession({ + ...dependencies, + loadProxyKubeconfig, + proxyKubeconfigPath, + directoryContainingKubectl, + }, { kubectl, ...args }); return session.open(); }; diff --git a/packages/core/src/main/shell-session/shell-env-modifier/modify-terminal-shell-env.injectable.ts b/packages/core/src/main/shell-session/shell-env-modifier/modify-terminal-shell-env.injectable.ts index 559dbcf645..908ee8bd30 100644 --- a/packages/core/src/main/shell-session/shell-env-modifier/modify-terminal-shell-env.injectable.ts +++ b/packages/core/src/main/shell-session/shell-env-modifier/modify-terminal-shell-env.injectable.ts @@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import { computed } from "mobx"; import type { ClusterId } from "../../../common/cluster-types"; -import { isDefined } from "../../../common/utils"; +import { isDefined } from "@k8slens/utilities"; import mainExtensionsInjectable from "../../../extensions/main-extensions.injectable"; import catalogEntityRegistryInjectable from "../../catalog/entity-registry.injectable"; diff --git a/packages/core/src/main/shell-session/shell-session.ts b/packages/core/src/main/shell-session/shell-session.ts index 196625f42a..ae1434287a 100644 --- a/packages/core/src/main/shell-session/shell-session.ts +++ b/packages/core/src/main/shell-session/shell-session.ts @@ -10,7 +10,7 @@ import { clearKubeconfigEnvVars } from "../utils/clear-kube-env-vars"; import path from "path"; import os from "os"; import type * as pty from "node-pty"; -import { getOrInsertWith } from "../../common/utils"; +import { getOrInsertWith } from "@k8slens/utilities"; import { type TerminalMessage, TerminalChannels } from "../../common/terminal/channels"; import type { Logger } from "../../common/logger"; import type { ComputeShellEnvironment } from "../../features/shell-sync/main/compute-shell-environment.injectable"; @@ -111,6 +111,8 @@ export interface ShellSessionDependencies { readonly userShellSetting: IComputedValue; readonly appName: string; readonly buildVersion: InitializableState; + readonly proxyKubeconfigPath: string; + readonly directoryContainingKubectl: string; computeShellEnvironment: ComputeShellEnvironment; spawnPty: SpawnPty; emitAppEvent: EmitAppEvent; @@ -147,8 +149,6 @@ export abstract class ShellSession { } protected running = false; - protected readonly kubectlBinDirP: Promise; - protected readonly kubeconfigPathP: Promise; protected readonly terminalId: string; protected readonly kubectl: Kubectl; protected readonly websocket: WebSocket; @@ -179,8 +179,6 @@ export abstract class ShellSession { this.kubectl = kubectl; this.websocket = websocket; this.cluster = cluster; - this.kubeconfigPathP = this.cluster.getProxyKubeconfigPath(); - this.kubectlBinDirP = this.kubectl.binDir(); this.terminalId = `${cluster.id}:${terminalId}`; } @@ -297,7 +295,7 @@ export abstract class ShellSession { code !== WebSocketCloseEvent.AbnormalClosure && code !== WebSocketCloseEvent.GoingAway ) - || this.cluster.disconnected + || this.cluster.disconnected.get() ); if (stopShellSession) { @@ -350,7 +348,7 @@ export abstract class ShellSession { })(); const env = clearKubeconfigEnvVars(JSON.parse(JSON.stringify(rawEnv))); - const pathStr = [await this.kubectlBinDirP, ...this.getPathEntries(), env.PATH].join(path.delimiter); + const pathStr = [this.dependencies.directoryContainingKubectl, ...this.getPathEntries(), env.PATH].join(path.delimiter); delete env.DEBUG; // don't pass DEBUG into shells @@ -373,12 +371,12 @@ export abstract class ShellSession { if (path.basename(env.PTYSHELL) === "zsh") { env.OLD_ZDOTDIR = env.ZDOTDIR || env.HOME; - env.ZDOTDIR = await this.kubectlBinDirP; + env.ZDOTDIR = this.dependencies.directoryContainingKubectl; env.DISABLE_AUTO_UPDATE = "true"; } env.PTYPID = process.pid.toString(); - env.KUBECONFIG = await this.kubeconfigPathP; + env.KUBECONFIG = this.dependencies.proxyKubeconfigPath; env.TERM_PROGRAM = this.dependencies.appName; env.TERM_PROGRAM_VERSION = this.dependencies.buildVersion.get(); diff --git a/packages/core/src/main/shell-session/spawn-pty.global-override-for-injectable.ts b/packages/core/src/main/shell-session/spawn-pty.global-override-for-injectable.ts index 239f7c5e47..e382981bc7 100644 --- a/packages/core/src/main/shell-session/spawn-pty.global-override-for-injectable.ts +++ b/packages/core/src/main/shell-session/spawn-pty.global-override-for-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 { getGlobalOverride } from "../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import spawnPtyInjectable from "./spawn-pty.injectable"; export default getGlobalOverride(spawnPtyInjectable, () => () => { diff --git a/packages/core/src/main/start-main-application/lens-window/application-window/create-electron-window.global-override-for-injectable.ts b/packages/core/src/main/start-main-application/lens-window/application-window/create-electron-window.global-override-for-injectable.ts index ef33b43c8e..6a1469bec2 100644 --- a/packages/core/src/main/start-main-application/lens-window/application-window/create-electron-window.global-override-for-injectable.ts +++ b/packages/core/src/main/start-main-application/lens-window/application-window/create-electron-window.global-override-for-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 { getGlobalOverride } from "../../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import createElectronWindowInjectable from "./create-electron-window.injectable"; export default getGlobalOverride(createElectronWindowInjectable, () => () => ({ diff --git a/packages/core/src/main/start-main-application/lens-window/application-window/wait-until-bundled-extensions-are-loaded.injectable.ts b/packages/core/src/main/start-main-application/lens-window/application-window/wait-until-bundled-extensions-are-loaded.injectable.ts index 4046db5d9d..b08ae197d4 100644 --- a/packages/core/src/main/start-main-application/lens-window/application-window/wait-until-bundled-extensions-are-loaded.injectable.ts +++ b/packages/core/src/main/start-main-application/lens-window/application-window/wait-until-bundled-extensions-are-loaded.injectable.ts @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import ipcMainInjectionToken from "../../../../common/ipc/ipc-main-injection-token"; import { bundledExtensionsLoaded } from "../../../../common/ipc/extension-handling"; -import { delay } from "../../../../common/utils"; +import { delay } from "@k8slens/utilities"; const waitUntilBundledExtensionsAreLoadedInjectable = getInjectable({ id: "wait-until-bundled-extensions-are-loaded", diff --git a/packages/core/src/main/start-main-application/lens-window/get-visible-windows.injectable.ts b/packages/core/src/main/start-main-application/lens-window/get-visible-windows.injectable.ts index f8e1ceb562..f22e064ca4 100644 --- a/packages/core/src/main/start-main-application/lens-window/get-visible-windows.injectable.ts +++ b/packages/core/src/main/start-main-application/lens-window/get-visible-windows.injectable.ts @@ -2,23 +2,16 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { pipeline } from "@ogre-tools/fp"; import { getInjectable } from "@ogre-tools/injectable"; -import { filter } from "lodash/fp"; import { applicationWindowInjectionToken } from "./application-window/application-window-injection-token"; const getVisibleWindowsInjectable = getInjectable({ id: "get-visible-windows", - instantiate: (di) => { - const getAllLensWindows = () => di.injectMany(applicationWindowInjectionToken); - - return () => - pipeline( - getAllLensWindows(), - filter((lensWindow) => !!lensWindow.isVisible), - ); - }, + instantiate: (di) => () => ( + di.injectMany(applicationWindowInjectionToken) + .filter(window => window.isVisible) + ), }); export default getVisibleWindowsInjectable; diff --git a/packages/core/src/main/start-main-application/lens-window/navigate-for-extension.injectable.ts b/packages/core/src/main/start-main-application/lens-window/navigate-for-extension.injectable.ts index 0a0661148b..dfec478f7d 100644 --- a/packages/core/src/main/start-main-application/lens-window/navigate-for-extension.injectable.ts +++ b/packages/core/src/main/start-main-application/lens-window/navigate-for-extension.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 { iter } from "../../../common/utils"; +import { iter } from "@k8slens/utilities"; import clusterFramesInjectable from "../../../common/cluster-frames.injectable"; import showApplicationWindowInjectable from "./show-application-window.injectable"; import getCurrentApplicationWindowInjectable from "./application-window/get-current-application-window.injectable"; diff --git a/packages/core/src/main/start-main-application/lens-window/navigate.injectable.ts b/packages/core/src/main/start-main-application/lens-window/navigate.injectable.ts index 7bcd14072b..8ebfa40303 100644 --- a/packages/core/src/main/start-main-application/lens-window/navigate.injectable.ts +++ b/packages/core/src/main/start-main-application/lens-window/navigate.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 { iter } from "../../../common/utils"; +import { iter } from "@k8slens/utilities"; import clusterFramesInjectable from "../../../common/cluster-frames.injectable"; import { IpcRendererNavigationEvents } from "../../../common/ipc/navigation-events"; import showApplicationWindowInjectable from "./show-application-window.injectable"; diff --git a/packages/core/src/main/start-main-application/runnable-tokens/after-application-is-loaded-injection-token.ts b/packages/core/src/main/start-main-application/runnable-tokens/after-application-is-loaded-injection-token.ts deleted file mode 100644 index f89f445ecf..0000000000 --- a/packages/core/src/main/start-main-application/runnable-tokens/after-application-is-loaded-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. - */ -import { getInjectionToken } from "@ogre-tools/injectable"; -import type { Runnable } from "../../../common/runnable/run-many-for"; - -export const afterApplicationIsLoadedInjectionToken = getInjectionToken({ - id: "after-application-is-loaded", -}); diff --git a/packages/core/src/main/start-main-application/runnable-tokens/after-root-frame-is-ready-injection-token.ts b/packages/core/src/main/start-main-application/runnable-tokens/after-root-frame-is-ready-injection-token.ts deleted file mode 100644 index f066c124ba..0000000000 --- a/packages/core/src/main/start-main-application/runnable-tokens/after-root-frame-is-ready-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. - */ -import { getInjectionToken } from "@ogre-tools/injectable"; -import type { Runnable } from "../../../common/runnable/run-many-for"; - -export const afterRootFrameIsReadyInjectionToken = getInjectionToken({ - id: "after-root-frame-is-ready", -}); diff --git a/packages/core/src/main/start-main-application/runnable-tokens/after-window-is-opened-injection-token.ts b/packages/core/src/main/start-main-application/runnable-tokens/after-window-is-opened-injection-token.ts deleted file mode 100644 index d5f33bceff..0000000000 --- a/packages/core/src/main/start-main-application/runnable-tokens/after-window-is-opened-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. - */ -import { getInjectionToken } from "@ogre-tools/injectable"; -import type { Runnable } from "../../../common/runnable/run-many-for"; - -export const afterWindowIsOpenedInjectionToken = getInjectionToken({ - id: "after-window-is-opened", -}); diff --git a/packages/core/src/main/start-main-application/runnable-tokens/before-application-is-loading-injection-token.ts b/packages/core/src/main/start-main-application/runnable-tokens/before-application-is-loading-injection-token.ts deleted file mode 100644 index 7cda9e6aee..0000000000 --- a/packages/core/src/main/start-main-application/runnable-tokens/before-application-is-loading-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. - */ -import { getInjectionToken } from "@ogre-tools/injectable"; -import type { Runnable } from "../../../common/runnable/run-many-for"; - -export const beforeApplicationIsLoadingInjectionToken = getInjectionToken({ - id: "before-application-is-loading", -}); diff --git a/packages/core/src/main/start-main-application/runnable-tokens/before-quit-of-back-end-injection-token.ts b/packages/core/src/main/start-main-application/runnable-tokens/before-quit-of-back-end-injection-token.ts deleted file mode 100644 index d11ecf57d2..0000000000 --- a/packages/core/src/main/start-main-application/runnable-tokens/before-quit-of-back-end-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. - */ -import { getInjectionToken } from "@ogre-tools/injectable"; -import type { RunnableSync } from "../../../common/runnable/run-many-sync-for"; - -export const beforeQuitOfBackEndInjectionToken = getInjectionToken({ - id: "before-quit-of-back-end", -}); diff --git a/packages/core/src/main/start-main-application/runnable-tokens/before-quit-of-front-end-injection-token.ts b/packages/core/src/main/start-main-application/runnable-tokens/before-quit-of-front-end-injection-token.ts deleted file mode 100644 index 0a45a684cd..0000000000 --- a/packages/core/src/main/start-main-application/runnable-tokens/before-quit-of-front-end-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. - */ -import { getInjectionToken } from "@ogre-tools/injectable"; -import type { RunnableSync } from "../../../common/runnable/run-many-sync-for"; - -export const beforeQuitOfFrontEndInjectionToken = getInjectionToken({ - id: "before-quit-of-front-end", -}); diff --git a/packages/core/src/main/start-main-application/runnable-tokens/on-load-of-application-injection-token.ts b/packages/core/src/main/start-main-application/runnable-tokens/on-load-of-application-injection-token.ts deleted file mode 100644 index 35b7a6c0ff..0000000000 --- a/packages/core/src/main/start-main-application/runnable-tokens/on-load-of-application-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. - */ -import { getInjectionToken } from "@ogre-tools/injectable"; -import type { Runnable } from "../../../common/runnable/run-many-for"; - -export const onLoadOfApplicationInjectionToken = getInjectionToken({ - id: "on-load-of-application", -}); diff --git a/packages/core/src/main/start-main-application/runnable-tokens/phases.ts b/packages/core/src/main/start-main-application/runnable-tokens/phases.ts new file mode 100644 index 0000000000..5808062fb2 --- /dev/null +++ b/packages/core/src/main/start-main-application/runnable-tokens/phases.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 { getInjectionToken } from "@ogre-tools/injectable"; +import type { Runnable, RunnableSync } from "@k8slens/run-many"; + +export const beforeQuitOfFrontEndInjectionToken = getInjectionToken({ + id: "before-quit-of-front-end", +}); + +export const beforeQuitOfBackEndInjectionToken = getInjectionToken({ + id: "before-quit-of-back-end", +}); + +export const afterWindowIsOpenedInjectionToken = getInjectionToken({ + id: "after-window-is-opened", +}); + +export const afterRootFrameIsReadyInjectionToken = getInjectionToken({ + id: "after-root-frame-is-ready", +}); + +export const afterApplicationIsLoadedInjectionToken = getInjectionToken({ + id: "after-application-is-loaded", +}); diff --git a/packages/core/src/main/start-main-application/runnables/clean-up-shell-sessions.injectable.ts b/packages/core/src/main/start-main-application/runnables/clean-up-shell-sessions.injectable.ts index 46afa5e692..2388f0fa73 100644 --- a/packages/core/src/main/start-main-application/runnables/clean-up-shell-sessions.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/clean-up-shell-sessions.injectable.ts @@ -3,14 +3,13 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { beforeQuitOfBackEndInjectionToken } from "../runnable-tokens/before-quit-of-back-end-injection-token"; +import { beforeQuitOfBackEndInjectionToken } from "../runnable-tokens/phases"; import { ShellSession } from "../../shell-session/shell-session"; const cleanUpShellSessionsInjectable = getInjectable({ id: "clean-up-shell-sessions", instantiate: () => ({ - id: "clean-up-shell-sessions", run: () => void ShellSession.cleanup(), }), diff --git a/packages/core/src/main/start-main-application/runnables/emit-close-to-event-bus.injectable.ts b/packages/core/src/main/start-main-application/runnables/emit-close-to-event-bus.injectable.ts index e1da8c1d67..cbd7a2d289 100644 --- a/packages/core/src/main/start-main-application/runnables/emit-close-to-event-bus.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/emit-close-to-event-bus.injectable.ts @@ -4,23 +4,20 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import emitAppEventInjectable from "../../../common/app-event-bus/emit-event.injectable"; -import { beforeQuitOfFrontEndInjectionToken } from "../runnable-tokens/before-quit-of-front-end-injection-token"; +import { beforeQuitOfFrontEndInjectionToken } from "../runnable-tokens/phases"; const emitCloseToEventBusInjectable = getInjectable({ id: "emit-close-to-event-bus", - instantiate: (di) => { - const emitAppEvent = di.inject(emitAppEventInjectable); + instantiate: (di) => ({ + run: () => { + const emitAppEvent = di.inject(emitAppEventInjectable); - return { - id: "emit-close-to-event-bus", - run: () => { - emitAppEvent({ name: "app", action: "close" }); + emitAppEvent({ name: "app", action: "close" }); - return undefined; - }, - }; - }, + return undefined; + }, + }), injectionToken: beforeQuitOfFrontEndInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/emit-service-start-to-event-bus.injectable.ts b/packages/core/src/main/start-main-application/runnables/emit-service-start-to-event-bus.injectable.ts index e21256c716..acc4d7a7d5 100644 --- a/packages/core/src/main/start-main-application/runnables/emit-service-start-to-event-bus.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/emit-service-start-to-event-bus.injectable.ts @@ -9,16 +9,13 @@ import { afterApplicationIsLoadedInjectionToken } from "@k8slens/application"; const emitServiceStartToEventBusInjectable = getInjectable({ id: "emit-service-start-to-event-bus", - instantiate: (di) => { - const emitAppEvent = di.inject(emitAppEventInjectable); + instantiate: (di) => ({ + run: () => { + const emitAppEvent = di.inject(emitAppEventInjectable); - return { - id: "emit-service-start-to-event-bus", - run: () => { - emitAppEvent({ name: "service", action: "start" }); - }, - }; - }, + emitAppEvent({ name: "service", action: "start" }); + }, + }), injectionToken: afterApplicationIsLoadedInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/flag-renderer/flag-renderer-as-loaded.injectable.ts b/packages/core/src/main/start-main-application/runnables/flag-renderer/flag-renderer-as-loaded.injectable.ts index 2bb05cfb52..2fe71ed7d5 100644 --- a/packages/core/src/main/start-main-application/runnables/flag-renderer/flag-renderer-as-loaded.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/flag-renderer/flag-renderer-as-loaded.injectable.ts @@ -3,26 +3,23 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { afterRootFrameIsReadyInjectionToken } from "../../runnable-tokens/after-root-frame-is-ready-injection-token"; +import { afterRootFrameIsReadyInjectionToken } from "../../runnable-tokens/phases"; import lensProtocolRouterMainInjectable from "../../../protocol-handler/lens-protocol-router-main/lens-protocol-router-main.injectable"; import { runInAction } from "mobx"; const flagRendererAsLoadedInjectable = getInjectable({ id: "flag-renderer-as-loaded", - instantiate: (di) => { - const lensProtocolRouterMain = di.inject(lensProtocolRouterMainInjectable); + instantiate: (di) => ({ + run: () => { + const lensProtocolRouterMain = di.inject(lensProtocolRouterMainInjectable); - return { - id: "flag-renderer-as-loaded", - run: () => { - runInAction(() => { - // Todo: remove this kludge which enables out-of-place temporal dependency. - lensProtocolRouterMain.rendererLoaded = true; - }); - }, - }; - }, + runInAction(() => { + // Todo: remove this kludge which enables out-of-place temporal dependency. + lensProtocolRouterMain.rendererLoaded = true; + }); + }, + }), injectionToken: afterRootFrameIsReadyInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/flag-renderer/flag-renderer-as-not-loaded.injectable.ts b/packages/core/src/main/start-main-application/runnables/flag-renderer/flag-renderer-as-not-loaded.injectable.ts index d5f7444232..899b234f39 100644 --- a/packages/core/src/main/start-main-application/runnables/flag-renderer/flag-renderer-as-not-loaded.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/flag-renderer/flag-renderer-as-not-loaded.injectable.ts @@ -5,26 +5,23 @@ import { getInjectable } from "@ogre-tools/injectable"; import { runInAction } from "mobx"; import lensProtocolRouterMainInjectable from "../../../protocol-handler/lens-protocol-router-main/lens-protocol-router-main.injectable"; -import { beforeQuitOfFrontEndInjectionToken } from "../../runnable-tokens/before-quit-of-front-end-injection-token"; +import { beforeQuitOfFrontEndInjectionToken } from "../../runnable-tokens/phases"; const flagRendererAsNotLoadedInjectable = getInjectable({ id: "stop-deep-linking", - instantiate: (di) => { - const lensProtocolRouterMain = di.inject(lensProtocolRouterMainInjectable); + instantiate: (di) => ({ + run: () => { + const lensProtocolRouterMain = di.inject(lensProtocolRouterMainInjectable); - return { - id: "stop-deep-linking", - run: () => { - runInAction(() => { - // Todo: remove this kludge which enables out-of-place temporal dependency. - lensProtocolRouterMain.rendererLoaded = false; - }); + runInAction(() => { + // Todo: remove this kludge which enables out-of-place temporal dependency. + lensProtocolRouterMain.rendererLoaded = false; + }); - return undefined; - }, - }; - }, + return undefined; + }, + }), injectionToken: beforeQuitOfFrontEndInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/initialize-extensions.injectable.ts b/packages/core/src/main/start-main-application/runnables/initialize-extensions.injectable.ts index 7815ecc2a7..d9c1aed473 100644 --- a/packages/core/src/main/start-main-application/runnables/initialize-extensions.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/initialize-extensions.injectable.ts @@ -14,51 +14,46 @@ import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; const initializeExtensionsInjectable = getInjectable({ id: "initialize-extensions", - instantiate: (di) => { - const logger = di.inject(loggerInjectable); - const extensionDiscovery = di.inject(extensionDiscoveryInjectable); - const extensionLoader = di.inject(extensionLoaderInjectable); - const showErrorPopup = di.inject(showErrorPopupInjectable); + instantiate: (di) => ({ + run: async () => { + const logger = di.inject(loggerInjectable); + const extensionDiscovery = di.inject(extensionDiscoveryInjectable); + const extensionLoader = di.inject(extensionLoaderInjectable); + const showErrorPopup = di.inject(showErrorPopupInjectable); - return { - id: "initialize-extensions", - run: async () => { - logger.info("🧩 Initializing extensions"); + logger.info("🧩 Initializing extensions"); - await extensionDiscovery.init(); + await extensionDiscovery.init(); - await extensionLoader.init(); + await extensionLoader.init(); - try { - const extensions = await extensionDiscovery.load(); + try { + const extensions = await extensionDiscovery.load(); - // Start watching after bundled extensions are loaded - extensionDiscovery.watchExtensions(); + // Start watching after bundled extensions are loaded + extensionDiscovery.watchExtensions(); - // Subscribe to extensions that are copied or deleted to/from the extensions folder - extensionDiscovery.events - .on("add", (extension: InstalledExtension) => { - extensionLoader.addExtension(extension); - }) - .on("remove", (lensExtensionId: LensExtensionId) => { - extensionLoader.removeExtension(lensExtensionId); - }); + // Subscribe to extensions that are copied or deleted to/from the extensions folder + extensionDiscovery.events + .on("add", (extension: InstalledExtension) => { + extensionLoader.addExtension(extension); + }) + .on("remove", (lensExtensionId: LensExtensionId) => { + extensionLoader.removeExtension(lensExtensionId); + }); - extensionLoader.initExtensions(extensions); - } catch (error: any) { - showErrorPopup( - "Lens Error", - `Could not load extensions${ - error?.message ? `: ${error.message}` : "" - }`, - ); + extensionLoader.initExtensions(extensions); + } catch (error: any) { + showErrorPopup( + "Lens Error", + `Could not load extensions${error?.message ? `: ${error.message}` : ""}`, + ); - console.error(error); - console.trace(); - } - }, - }; - }, + console.error(error); + console.trace(); + } + }, + }), causesSideEffects: true, diff --git a/packages/core/src/main/start-main-application/runnables/kube-config-sync/add-source.injectable.ts b/packages/core/src/main/start-main-application/runnables/kube-config-sync/add-source.injectable.ts index b7ba895c37..5844c7ed96 100644 --- a/packages/core/src/main/start-main-application/runnables/kube-config-sync/add-source.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/kube-config-sync/add-source.injectable.ts @@ -9,17 +9,14 @@ import { afterApplicationIsLoadedInjectionToken } from "@k8slens/application"; const addKubeconfigSyncAsEntitySourceInjectable = getInjectable({ id: "add-kubeconfig-sync-as-entity-source", - instantiate: (di) => { - const kubeConfigSyncManager = di.inject(kubeconfigSyncManagerInjectable); - const entityRegistry = di.inject(catalogEntityRegistryInjectable); + instantiate: (di) => ({ + run: () => { + const kubeConfigSyncManager = di.inject(kubeconfigSyncManagerInjectable); + const entityRegistry = di.inject(catalogEntityRegistryInjectable); - return { - id: "add-kubeconfig-sync-as-entity-source", - run: () => { - entityRegistry.addComputedSource("kubeconfig-sync", kubeConfigSyncManager.source); - }, - }; - }, + entityRegistry.addComputedSource("kubeconfig-sync", kubeConfigSyncManager.source); + }, + }), injectionToken: afterApplicationIsLoadedInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/kube-config-sync/start-kube-config-sync.injectable.ts b/packages/core/src/main/start-main-application/runnables/kube-config-sync/start-kube-config-sync.injectable.ts index 6ae5ccca40..b617791722 100644 --- a/packages/core/src/main/start-main-application/runnables/kube-config-sync/start-kube-config-sync.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/kube-config-sync/start-kube-config-sync.injectable.ts @@ -12,21 +12,18 @@ import addKubeconfigSyncAsEntitySourceInjectable from "./add-source.injectable"; const startKubeConfigSyncInjectable = getInjectable({ id: "start-kubeconfig-sync", - instantiate: (di) => { - const directoryForKubeConfigs = di.inject(directoryForKubeConfigsInjectable); - const kubeConfigSyncManager = di.inject(kubeconfigSyncManagerInjectable); - const ensureDir = di.inject(ensureDirInjectable); + instantiate: (di) => ({ + run: async () => { + const directoryForKubeConfigs = di.inject(directoryForKubeConfigsInjectable); + const kubeConfigSyncManager = di.inject(kubeconfigSyncManagerInjectable); + const ensureDir = di.inject(ensureDirInjectable); - return { - id: "start-kubeconfig-sync", - run: async () => { - await ensureDir(directoryForKubeConfigs); + await ensureDir(directoryForKubeConfigs); - kubeConfigSyncManager.startSync(); - }, - runAfter: di.inject(addKubeconfigSyncAsEntitySourceInjectable), - }; - }, + kubeConfigSyncManager.startSync(); + }, + runAfter: addKubeconfigSyncAsEntitySourceInjectable, + }), injectionToken: afterApplicationIsLoadedInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/kube-config-sync/stop-kube-config-sync.injectable.ts b/packages/core/src/main/start-main-application/runnables/kube-config-sync/stop-kube-config-sync.injectable.ts index 4cb5a98a3f..118dac2ed4 100644 --- a/packages/core/src/main/start-main-application/runnables/kube-config-sync/stop-kube-config-sync.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/kube-config-sync/stop-kube-config-sync.injectable.ts @@ -3,20 +3,21 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { beforeQuitOfBackEndInjectionToken } from "../../runnable-tokens/before-quit-of-back-end-injection-token"; +import { beforeQuitOfBackEndInjectionToken } from "../../runnable-tokens/phases"; import kubeconfigSyncManagerInjectable from "../../../catalog-sources/kubeconfig-sync/manager.injectable"; const stopKubeConfigSyncInjectable = getInjectable({ id: "stop-kube-config-sync", - instantiate: (di) => { - const kubeConfigSyncManager = di.inject(kubeconfigSyncManagerInjectable); + instantiate: (di) => ({ + run: () => { + const kubeConfigSyncManager = di.inject(kubeconfigSyncManagerInjectable); - return { - id: "stop-kube-config-sync", - run: () => void kubeConfigSyncManager.stopSync(), - }; - }, + kubeConfigSyncManager.stopSync(); + + return undefined; + }, + }), injectionToken: beforeQuitOfBackEndInjectionToken, }); 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 40f5ceb788..8b906c79e9 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 @@ -4,8 +4,8 @@ */ import { getMessageChannelListenerInjectable } from "../../../../common/utils/channel/message-channel-listener-injection-token"; import { rootFrameHasRenderedChannel } from "../../../../common/root-frame/root-frame-rendered-channel"; -import { runManyFor } from "../../../../common/runnable/run-many-for"; -import { afterRootFrameIsReadyInjectionToken } from "../../runnable-tokens/after-root-frame-is-ready-injection-token"; +import { runManyFor } from "@k8slens/run-many"; +import { afterRootFrameIsReadyInjectionToken } from "../../runnable-tokens/phases"; const rootFrameRenderedChannelListenerInjectable = getMessageChannelListenerInjectable({ id: "action", diff --git a/packages/core/src/main/start-main-application/runnables/sentry/initialize-on-main.global-override-for-injectable.ts b/packages/core/src/main/start-main-application/runnables/sentry/initialize-on-main.global-override-for-injectable.ts index 3850c736a0..6781ef7023 100644 --- a/packages/core/src/main/start-main-application/runnables/sentry/initialize-on-main.global-override-for-injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/sentry/initialize-on-main.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import initializeSentryOnMainInjectable from "./initialize-on-main.injectable"; export default getGlobalOverride(initializeSentryOnMainInjectable, () => () => {}); diff --git a/packages/core/src/main/start-main-application/runnables/sentry/setup.injectable.ts b/packages/core/src/main/start-main-application/runnables/sentry/setup.injectable.ts index 79141c8d66..841d669fa4 100644 --- a/packages/core/src/main/start-main-application/runnables/sentry/setup.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/sentry/setup.injectable.ts @@ -9,15 +9,16 @@ import initializeSentryOnMainInjectable from "./initialize-on-main.injectable"; const setupSentryInjectable = getInjectable({ id: "setup-sentry", - instantiate: (di) => { - const initializeSentryReportingWith = di.inject(initializeSentryReportingWithInjectable); - const initializeSentryOnMain = di.inject(initializeSentryOnMainInjectable); + instantiate: (di) => ({ + run: () => { + const initializeSentryReportingWith = di.inject(initializeSentryReportingWithInjectable); + const initializeSentryOnMain = di.inject(initializeSentryOnMainInjectable); - return { - id: "setup-sentry", - run: () => void initializeSentryReportingWith(initializeSentryOnMain), - }; - }, + initializeSentryReportingWith(initializeSentryOnMain); + + return undefined; + }, + }), injectionToken: beforeElectronIsReadyInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/setup-hardware-acceleration.injectable.ts b/packages/core/src/main/start-main-application/runnables/setup-hardware-acceleration.injectable.ts index c57e35d822..0acadbb852 100644 --- a/packages/core/src/main/start-main-application/runnables/setup-hardware-acceleration.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/setup-hardware-acceleration.injectable.ts @@ -10,21 +10,18 @@ import { beforeElectronIsReadyInjectionToken } from "@k8slens/application-for-el const setupHardwareAccelerationInjectable = getInjectable({ id: "setup-hardware-acceleration", - instantiate: (di) => { - const hardwareAccelerationShouldBeDisabled = di.inject(hardwareAccelerationShouldBeDisabledInjectable); - const disableHardwareAcceleration = di.inject(disableHardwareAccelerationInjectable); + instantiate: (di) => ({ + run: () => { + const hardwareAccelerationShouldBeDisabled = di.inject(hardwareAccelerationShouldBeDisabledInjectable); + const disableHardwareAcceleration = di.inject(disableHardwareAccelerationInjectable); - return { - id: "setup-hardware-acceleration", - run: () => { - if (hardwareAccelerationShouldBeDisabled) { - disableHardwareAcceleration(); - } + if (hardwareAccelerationShouldBeDisabled) { + disableHardwareAcceleration(); + } - return undefined; - }, - }; - }, + return undefined; + }, + }), injectionToken: beforeElectronIsReadyInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/setup-hostnames.injectable.ts b/packages/core/src/main/start-main-application/runnables/setup-hostnames.injectable.ts index 26d85283d5..44c0a26ddd 100644 --- a/packages/core/src/main/start-main-application/runnables/setup-hostnames.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/setup-hostnames.injectable.ts @@ -9,22 +9,19 @@ import { beforeElectronIsReadyInjectionToken } from "@k8slens/application-for-el const setupHostnamesInjectable = getInjectable({ id: "setup-hostnames", - instantiate: (di) => { - const app = di.inject(electronAppInjectable); + instantiate: (di) => ({ + run: () => { + const app = di.inject(electronAppInjectable); - return { - id: "setup-hostnames", - run: () => { - app.commandLine.appendSwitch("host-rules", [ - "MAP localhost 127.0.0.1", - "MAP lens.app 127.0.0.1", - "MAP *.lens.app 127.0.0.1", - ].join()); + app.commandLine.appendSwitch("host-rules", [ + "MAP localhost 127.0.0.1", + "MAP lens.app 127.0.0.1", + "MAP *.lens.app 127.0.0.1", + ].join()); - return undefined; - }, - }; - }, + return undefined; + }, + }), injectionToken: beforeElectronIsReadyInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/setup-immer.injectable.ts b/packages/core/src/main/start-main-application/runnables/setup-immer.injectable.ts index e847578d01..7dfcbba39d 100644 --- a/packages/core/src/main/start-main-application/runnables/setup-immer.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/setup-immer.injectable.ts @@ -3,19 +3,18 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import * as Immer from "immer"; +import { setAutoFreeze, enableMapSet } from "immer"; import { beforeElectronIsReadyInjectionToken } from "@k8slens/application-for-electron-main"; const setupImmerInjectable = getInjectable({ id: "setup-immer", instantiate: () => ({ - id: "setup-immer", run: () => { // Docs: https://immerjs.github.io/immer/ // Required in `utils/storage-helper.ts` - Immer.setAutoFreeze(false); // allow to merge mobx observables - Immer.enableMapSet(); // allow to merge maps and sets + setAutoFreeze(false); // allow to merge mobx observables + enableMapSet(); // allow to merge maps and sets return undefined; }, diff --git a/packages/core/src/main/start-main-application/runnables/setup-lens-proxy-certificate.injectable.ts b/packages/core/src/main/start-main-application/runnables/setup-lens-proxy-certificate.injectable.ts index 9d473f3182..d75ca643f8 100644 --- a/packages/core/src/main/start-main-application/runnables/setup-lens-proxy-certificate.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/setup-lens-proxy-certificate.injectable.ts @@ -10,42 +10,39 @@ import { beforeElectronIsReadyInjectionToken } from "@k8slens/application-for-el const setupLensProxyCertificateInjectable = getInjectable({ id: "setup-lens-proxy-certificate", - instantiate: (di) => { - const lensProxyCertificate = di.inject(lensProxyCertificateInjectable); + instantiate: (di) => ({ + run: () => { + const lensProxyCertificate = di.inject(lensProxyCertificateInjectable); - return { - id: "setup-lens-proxy-certificate", - run: () => { - const cert = generate([ - { name: "commonName", value: "Lens Certificate Authority" }, - { name: "organizationName", value: "Lens" }, - ], { - keySize: 2048, - algorithm: "sha256", - days: 365, - extensions: [ - { - name: "basicConstraints", - cA: true, - }, - { - name: "subjectAltName", - altNames: [ - { type: 2, value: "*.lens.app" }, - { type: 2, value: "lens.app" }, - { type: 2, value: "localhost" }, - { type: 7, ip: "127.0.0.1" }, - ], - }, - ], - }); + const cert = generate([ + { name: "commonName", value: "Lens Certificate Authority" }, + { name: "organizationName", value: "Lens" }, + ], { + keySize: 2048, + algorithm: "sha256", + days: 365, + extensions: [ + { + name: "basicConstraints", + cA: true, + }, + { + name: "subjectAltName", + altNames: [ + { type: 2, value: "*.lens.app" }, + { type: 2, value: "lens.app" }, + { type: 2, value: "localhost" }, + { type: 7, ip: "127.0.0.1" }, + ], + }, + ], + }); - lensProxyCertificate.set(cert); + lensProxyCertificate.set(cert); - return undefined; - }, - }; - }, + return undefined; + }, + }), injectionToken: beforeElectronIsReadyInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/setup-lens-proxy.injectable.ts b/packages/core/src/main/start-main-application/runnables/setup-lens-proxy.injectable.ts index dc63b8f7a3..c77a0470be 100644 --- a/packages/core/src/main/start-main-application/runnables/setup-lens-proxy.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/setup-lens-proxy.injectable.ts @@ -19,68 +19,65 @@ import { Agent } from "https"; const setupLensProxyInjectable = getInjectable({ id: "setup-lens-proxy", - instantiate: (di) => { - const lensProxy = di.inject(lensProxyInjectable); - const exitApp = di.inject(exitAppInjectable); - const logger = di.inject(loggerInjectable); - const lensProxyPort = di.inject(lensProxyPortInjectable); - const isWindows = di.inject(isWindowsInjectable); - const showErrorPopup = di.inject(showErrorPopupInjectable); - const buildVersion = di.inject(buildVersionInjectable); - const lensProxyCertificate = di.inject(lensProxyCertificateInjectable); - const fetch = di.inject(fetchInjectable); + instantiate: (di) => ({ + run: async () => { + const lensProxy = di.inject(lensProxyInjectable); + const exitApp = di.inject(exitAppInjectable); + const logger = di.inject(loggerInjectable); + const lensProxyPort = di.inject(lensProxyPortInjectable); + const isWindows = di.inject(isWindowsInjectable); + const showErrorPopup = di.inject(showErrorPopupInjectable); + const buildVersion = di.inject(buildVersionInjectable); + const lensProxyCertificate = di.inject(lensProxyCertificateInjectable); + const fetch = di.inject(fetchInjectable); - return { - id: "setup-lens-proxy", - run: async () => { - try { - logger.info("🔌 Starting LensProxy"); - await lensProxy.listen(); // lensProxy.port available - } catch (error: any) { - showErrorPopup("Lens Error", `Could not start proxy: ${error?.message || "unknown error"}`); + try { + logger.info("🔌 Starting LensProxy"); + await lensProxy.listen(); // lensProxy.port available + } catch (error: any) { + showErrorPopup("Lens Error", `Could not start proxy: ${error?.message || "unknown error"}`); + + return exitApp(); + } + + // test proxy connection + try { + logger.info("🔎 Testing LensProxy connection ..."); + const versionResponse = await fetch(`https://127.0.0.1:${lensProxyPort.get()}/version`, { + agent: new Agent({ + ca: lensProxyCertificate.get()?.cert, + }), + }); + + const { version: versionFromProxy } = await versionResponse.json() as { version: string }; + + if (buildVersion.get() !== versionFromProxy) { + logger.error("Proxy server responded with invalid response"); return exitApp(); } - // test proxy connection - try { - logger.info("🔎 Testing LensProxy connection ..."); - const versionResponse = await fetch(`https://127.0.0.1:${lensProxyPort.get()}/version`, { - agent: new Agent({ - ca: lensProxyCertificate.get()?.cert, - }), - }); + logger.info("⚡ LensProxy connection OK"); + } catch (error) { + logger.error(`🛑 LensProxy: failed connection test: ${error}`); - const { version: versionFromProxy } = await versionResponse.json() as { version: string }; + const hostsPath = isWindows + ? "C:\\windows\\system32\\drivers\\etc\\hosts" + : "/etc/hosts"; + const message = [ + `Failed connection test: ${error}`, + "Check to make sure that no other versions of Lens are running", + `Check ${hostsPath} to make sure that it is clean and that the localhost loopback is at the top and set to 127.0.0.1`, + "If you have HTTP_PROXY or http_proxy set in your environment, make sure that the localhost and the ipv4 loopback address 127.0.0.1 are added to the NO_PROXY environment variable.", + ]; - if (buildVersion.get() !== versionFromProxy) { - logger.error("Proxy server responded with invalid response"); + showErrorPopup("Lens Proxy Error", message.join("\n\n")); - return exitApp(); - } - - logger.info("⚡ LensProxy connection OK"); - } catch (error) { - logger.error(`🛑 LensProxy: failed connection test: ${error}`); - - const hostsPath = isWindows - ? "C:\\windows\\system32\\drivers\\etc\\hosts" - : "/etc/hosts"; - const message = [ - `Failed connection test: ${error}`, - "Check to make sure that no other versions of Lens are running", - `Check ${hostsPath} to make sure that it is clean and that the localhost loopback is at the top and set to 127.0.0.1`, - "If you have HTTP_PROXY or http_proxy set in your environment, make sure that the localhost and the ipv4 loopback address 127.0.0.1 are added to the NO_PROXY environment variable.", - ]; - - showErrorPopup("Lens Proxy Error", message.join("\n\n")); - - return exitApp(); - } - }, - runAfter: di.inject(initializeBuildVersionInjectable), - }; - }, + return exitApp(); + } + }, + runAfter: initializeBuildVersionInjectable, + }), causesSideEffects: true, diff --git a/packages/core/src/main/start-main-application/runnables/setup-mobx.injectable.ts b/packages/core/src/main/start-main-application/runnables/setup-mobx.injectable.ts index 8227c9ace6..a566a9da1b 100644 --- a/packages/core/src/main/start-main-application/runnables/setup-mobx.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/setup-mobx.injectable.ts @@ -10,7 +10,6 @@ const setupMobxInjectable = getInjectable({ id: "setup-mobx", instantiate: () => ({ - id: "setup-mobx", run: () => { // Docs: https://mobx.js.org/configuration.html Mobx.configure({ diff --git a/packages/core/src/main/start-main-application/runnables/setup-proxy-env.injectable.ts b/packages/core/src/main/start-main-application/runnables/setup-proxy-env.injectable.ts index 7553eeb7eb..dc74c892c8 100644 --- a/packages/core/src/main/start-main-application/runnables/setup-proxy-env.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/setup-proxy-env.injectable.ts @@ -9,36 +9,31 @@ import getCommandLineSwitchInjectable from "../../electron-app/features/get-comm const setupProxyEnvInjectable = getInjectable({ id: "setup-proxy-env", - instantiate: (di) => { - const getCommandLineSwitch = di.inject(getCommandLineSwitchInjectable); + instantiate: (di) => ({ + run: () => { + const getCommandLineSwitch = di.inject(getCommandLineSwitchInjectable); + const switchValue = getCommandLineSwitch("proxy-server"); - return { - id: "setup-proxy-env", - run: () => { - const switchValue = getCommandLineSwitch("proxy-server"); + let httpsProxy = process.env.HTTPS_PROXY || process.env.HTTP_PROXY || ""; - let httpsProxy = - process.env.HTTPS_PROXY || process.env.HTTP_PROXY || ""; + delete process.env.HTTPS_PROXY; + delete process.env.HTTP_PROXY; - delete process.env.HTTPS_PROXY; - delete process.env.HTTP_PROXY; + if (switchValue !== "") { + httpsProxy = switchValue; + } - if (switchValue !== "") { - httpsProxy = switchValue; - } + if (httpsProxy !== "") { + process.env.APP_HTTPS_PROXY = httpsProxy; + } - if (httpsProxy !== "") { - process.env.APP_HTTPS_PROXY = httpsProxy; - } + if (getCommandLineSwitch("proxy-server") !== "") { + process.env.HTTPS_PROXY = getCommandLineSwitch("proxy-server"); + } - if (getCommandLineSwitch("proxy-server") !== "") { - process.env.HTTPS_PROXY = getCommandLineSwitch("proxy-server"); - } - - return undefined; - }, - }; - }, + return undefined; + }, + }), injectionToken: beforeElectronIsReadyInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/setup-syncing-of-general-catalog-entities.injectable.ts b/packages/core/src/main/start-main-application/runnables/setup-syncing-of-general-catalog-entities.injectable.ts index 07b17dfa46..080a7d72aa 100644 --- a/packages/core/src/main/start-main-application/runnables/setup-syncing-of-general-catalog-entities.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/setup-syncing-of-general-catalog-entities.injectable.ts @@ -9,18 +9,13 @@ import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; const setupSyncingOfGeneralCatalogEntitiesInjectable = getInjectable({ id: "setup-syncing-of-general-catalog-entities", - instantiate: (di) => { - const syncGeneralCatalogEntities = di.inject( - syncGeneralCatalogEntitiesInjectable, - ); + instantiate: (di) => ({ + run: () => { + const syncGeneralCatalogEntities = di.inject(syncGeneralCatalogEntitiesInjectable); - return { - id: "setup-syncing-of-general-catalog-entities", - run: () => { - syncGeneralCatalogEntities(); - }, - }; - }, + syncGeneralCatalogEntities(); + }, + }), injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/setup-syncing-of-weblinks.injectable.ts b/packages/core/src/main/start-main-application/runnables/setup-syncing-of-weblinks.injectable.ts index 9259b44ab1..09a630db37 100644 --- a/packages/core/src/main/start-main-application/runnables/setup-syncing-of-weblinks.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/setup-syncing-of-weblinks.injectable.ts @@ -9,16 +9,13 @@ import syncWeblinksInjectable from "../../catalog-sources/sync-weblinks.injectab const setupSyncingOfWeblinksInjectable = getInjectable({ id: "setup-syncing-of-weblinks", - instantiate: (di) => { - const syncWeblinks = di.inject(syncWeblinksInjectable); + instantiate: (di) => ({ + run: () => { + const syncWeblinks = di.inject(syncWeblinksInjectable); - return { - id: "setup-syncing-of-weblinks", - run: () => { - syncWeblinks(); - }, - }; - }, + syncWeblinks(); + }, + }), injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/setup-system-ca.injectable.ts b/packages/core/src/main/start-main-application/runnables/setup-system-ca.injectable.ts index ecffc60b6c..4d9b043540 100644 --- a/packages/core/src/main/start-main-application/runnables/setup-system-ca.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/setup-system-ca.injectable.ts @@ -9,8 +9,11 @@ import injectSystemCAsInjectable from "../../../features/certificate-authorities const setupSystemCaInjectable = getInjectable({ id: "setup-system-ca", instantiate: (di) => ({ - id: "setup-system-ca", - run: di.inject(injectSystemCAsInjectable), + run: async () => { + const injectSystemCAs = di.inject(injectSystemCAsInjectable); + + await injectSystemCAs(); + }, }), injectionToken: beforeApplicationIsLoadingInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/show-initial-window.injectable.ts b/packages/core/src/main/start-main-application/runnables/show-initial-window.injectable.ts index db1ea42610..1464022486 100644 --- a/packages/core/src/main/start-main-application/runnables/show-initial-window.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/show-initial-window.injectable.ts @@ -18,33 +18,30 @@ const getDeepLinkUrl = (commandLineArguments: string[]) => ( const showInitialWindowInjectable = getInjectable({ id: "show-initial-window", - instantiate: (di) => { - const shouldStartHidden = di.inject(shouldStartHiddenInjectable); - const shouldStartWindow = !shouldStartHidden; - const createFirstApplicationWindow = di.inject(createFirstApplicationWindowInjectable); - const splashWindow = di.inject(splashWindowInjectable); - const openDeepLink = di.inject(openDeepLinkInjectable); - const commandLineArguments = di.inject(commandLineArgumentsInjectable); + instantiate: (di) => ({ + run: async () => { + const shouldStartHidden = di.inject(shouldStartHiddenInjectable); + const shouldStartWindow = !shouldStartHidden; + const createFirstApplicationWindow = di.inject(createFirstApplicationWindowInjectable); + const splashWindow = di.inject(splashWindowInjectable); + const openDeepLink = di.inject(openDeepLinkInjectable); + const commandLineArguments = di.inject(commandLineArgumentsInjectable); - return { - id: "show-initial-window", - run: async () => { - if (shouldStartWindow) { - const deepLinkUrl = getDeepLinkUrl(commandLineArguments); + if (shouldStartWindow) { + const deepLinkUrl = getDeepLinkUrl(commandLineArguments); - if (deepLinkUrl) { - await openDeepLink(deepLinkUrl); - } else { - const applicationWindow = createFirstApplicationWindow(); + if (deepLinkUrl) { + await openDeepLink(deepLinkUrl); + } else { + const applicationWindow = createFirstApplicationWindow(); - await applicationWindow.start(); - } - - splashWindow.close(); + await applicationWindow.start(); } - }, - }; - }, + + splashWindow.close(); + } + }, + }), injectionToken: afterApplicationIsLoadedInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/show-loading.injectable.ts b/packages/core/src/main/start-main-application/runnables/show-loading.injectable.ts index f12dd3fe09..337084a7d2 100644 --- a/packages/core/src/main/start-main-application/runnables/show-loading.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/show-loading.injectable.ts @@ -9,20 +9,18 @@ import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; const showLoadingInjectable = getInjectable({ id: "show-loading", - instantiate: (di) => { - const shouldStartHidden = di.inject(shouldStartHiddenInjectable); - const shouldShowLoadingWindow = !shouldStartHidden; - const splashWindow = di.inject(splashWindowInjectable); - return { - id: "show-loading", - run: async () => { - if (shouldShowLoadingWindow) { - await splashWindow.start(); - } - }, - }; - }, + instantiate: (di) => ({ + run: async () => { + const shouldStartHidden = di.inject(shouldStartHiddenInjectable); + const shouldShowLoadingWindow = !shouldStartHidden; + const splashWindow = di.inject(splashWindowInjectable); + + if (shouldShowLoadingWindow) { + await splashWindow.start(); + } + }, + }), injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/stop-cluster-manager.injectable.ts b/packages/core/src/main/start-main-application/runnables/stop-cluster-manager.injectable.ts index c0a39c51ae..f26feb01d7 100644 --- a/packages/core/src/main/start-main-application/runnables/stop-cluster-manager.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/stop-cluster-manager.injectable.ts @@ -4,23 +4,20 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import clusterManagerInjectable from "../../cluster/manager.injectable"; -import { beforeQuitOfFrontEndInjectionToken } from "../runnable-tokens/before-quit-of-front-end-injection-token"; +import { beforeQuitOfFrontEndInjectionToken } from "../runnable-tokens/phases"; const stopClusterManagerInjectable = getInjectable({ id: "stop-cluster-manager", - instantiate: (di) => { - const clusterManager = di.inject(clusterManagerInjectable); + instantiate: (di) => ({ + run: () => { + const clusterManager = di.inject(clusterManagerInjectable); - return { - id: "stop-cluster-manager", - run: () => { - clusterManager.stop(); + clusterManager.stop(); - return undefined; - }, - }; - }, + return undefined; + }, + }), injectionToken: beforeQuitOfFrontEndInjectionToken, }); diff --git a/packages/core/src/main/stores/init-user-store.injectable.ts b/packages/core/src/main/stores/init-user-store.injectable.ts index 58ac61f86d..b7d1dac33d 100644 --- a/packages/core/src/main/stores/init-user-store.injectable.ts +++ b/packages/core/src/main/stores/init-user-store.injectable.ts @@ -10,19 +10,16 @@ import initDefaultUpdateChannelInjectable from "../vars/default-update-channel/i const initUserStoreInjectable = getInjectable({ id: "init-user-store", - instantiate: (di) => { - const userStore = di.inject(userStoreInjectable); - const userStoreFileNameMigration = di.inject(userStoreFileNameMigrationInjectable); + instantiate: (di) => ({ + run: async () => { + const userStore = di.inject(userStoreInjectable); + const userStoreFileNameMigration = di.inject(userStoreFileNameMigrationInjectable); - return { - id: "init-user-store", - run: async () => { - await userStoreFileNameMigration(); - userStore.load(); - }, - runAfter: di.inject(initDefaultUpdateChannelInjectable), - }; - }, + await userStoreFileNameMigration(); + userStore.load(); + }, + runAfter: initDefaultUpdateChannelInjectable, + }), injectionToken: beforeApplicationIsLoadingInjectionToken, }); diff --git a/packages/core/src/main/theme/sync-theme-from-os/start-syncing-theme-from-operating-system.injectable.ts b/packages/core/src/main/theme/sync-theme-from-os/start-syncing-theme-from-operating-system.injectable.ts index d037f539a7..4bed8c41e3 100644 --- a/packages/core/src/main/theme/sync-theme-from-os/start-syncing-theme-from-operating-system.injectable.ts +++ b/packages/core/src/main/theme/sync-theme-from-os/start-syncing-theme-from-operating-system.injectable.ts @@ -9,16 +9,13 @@ import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; const startSyncingThemeFromOperatingSystemInjectable = getInjectable({ id: "start-syncing-theme-from-operating-system", - instantiate: (di) => { - const syncTheme = di.inject(syncThemeFromOperatingSystemInjectable); + instantiate: (di) => ({ + run: () => { + const syncTheme = di.inject(syncThemeFromOperatingSystemInjectable); - return { - id: "start-syncing-theme-from-operating-system", - run: () => { - syncTheme.start(); - }, - }; - }, + syncTheme.start(); + }, + }), injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/main/theme/sync-theme-from-os/stop-syncing-theme-from-operating-system.injectable.ts b/packages/core/src/main/theme/sync-theme-from-os/stop-syncing-theme-from-operating-system.injectable.ts index b45184a3bd..f50a298822 100644 --- a/packages/core/src/main/theme/sync-theme-from-os/stop-syncing-theme-from-operating-system.injectable.ts +++ b/packages/core/src/main/theme/sync-theme-from-os/stop-syncing-theme-from-operating-system.injectable.ts @@ -4,19 +4,20 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import syncThemeFromOperatingSystemInjectable from "../../electron-app/features/sync-theme-from-operating-system.injectable"; -import { beforeQuitOfBackEndInjectionToken } from "../../start-main-application/runnable-tokens/before-quit-of-back-end-injection-token"; +import { beforeQuitOfBackEndInjectionToken } from "../../start-main-application/runnable-tokens/phases"; const stopSyncingThemeFromOperatingSystemInjectable = getInjectable({ id: "stop-syncing-theme-from-operating-system", - instantiate: (di) => { - const syncTheme = di.inject(syncThemeFromOperatingSystemInjectable); + instantiate: (di) => ({ + run: () => { + const syncTheme = di.inject(syncThemeFromOperatingSystemInjectable); - return { - id: "stop-syncing-theme-from-operating-system", - run: () => void syncTheme.stop(), - }; - }, + syncTheme.stop(); + + return undefined; + }, + }), injectionToken: beforeQuitOfBackEndInjectionToken, }); diff --git a/packages/core/src/main/tray/electron-tray/start-tray.injectable.ts b/packages/core/src/main/tray/electron-tray/start-tray.injectable.ts index 3bd61a6997..5aa8eecc2f 100644 --- a/packages/core/src/main/tray/electron-tray/start-tray.injectable.ts +++ b/packages/core/src/main/tray/electron-tray/start-tray.injectable.ts @@ -9,16 +9,13 @@ import electronTrayInjectable from "./electron-tray.injectable"; const startTrayInjectable = getInjectable({ id: "start-tray", - instantiate: (di) => { - const electronTray = di.inject(electronTrayInjectable); + instantiate: (di) => ({ + run: () => { + const electronTray = di.inject(electronTrayInjectable); - return { - id: "start-tray", - run: () => { - electronTray.start(); - }, - }; - }, + electronTray.start(); + }, + }), injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/main/tray/electron-tray/stop-tray.injectable.ts b/packages/core/src/main/tray/electron-tray/stop-tray.injectable.ts index d2e58be039..4bd6bd6c3a 100644 --- a/packages/core/src/main/tray/electron-tray/stop-tray.injectable.ts +++ b/packages/core/src/main/tray/electron-tray/stop-tray.injectable.ts @@ -4,21 +4,22 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import electronTrayInjectable from "./electron-tray.injectable"; -import { beforeQuitOfBackEndInjectionToken } from "../../start-main-application/runnable-tokens/before-quit-of-back-end-injection-token"; +import { beforeQuitOfBackEndInjectionToken } from "../../start-main-application/runnable-tokens/phases"; import stopReactiveTrayMenuItemsInjectable from "../reactive-tray-menu-items/stop-reactive-tray-menu-items.injectable"; const stopTrayInjectable = getInjectable({ id: "stop-tray", - instantiate: (di) => { - const electronTray = di.inject(electronTrayInjectable); + instantiate: (di) => ({ + run: () => { + const electronTray = di.inject(electronTrayInjectable); - return { - id: "stop-tray", - run: () => void electronTray.stop(), - runAfter: di.inject(stopReactiveTrayMenuItemsInjectable), - }; - }, + electronTray.stop(); + + return undefined; + }, + runAfter: stopReactiveTrayMenuItemsInjectable, + }), injectionToken: beforeQuitOfBackEndInjectionToken, }); diff --git a/packages/core/src/main/tray/menu-icon/start-reactivity.injectable.ts b/packages/core/src/main/tray/menu-icon/start-reactivity.injectable.ts index 0bb94b53af..74ee3c13a6 100644 --- a/packages/core/src/main/tray/menu-icon/start-reactivity.injectable.ts +++ b/packages/core/src/main/tray/menu-icon/start-reactivity.injectable.ts @@ -10,18 +10,15 @@ import reactiveTrayMenuIconInjectable from "./reactive.injectable"; const startReactiveTrayMenuIconInjectable = getInjectable({ id: "start-reactive-tray-menu-icon", - instantiate: (di) => { - const reactiveTrayMenuIcon = di.inject(reactiveTrayMenuIconInjectable); + instantiate: (di) => ({ + run: () => { + const reactiveTrayMenuIcon = di.inject(reactiveTrayMenuIconInjectable); - return { - id: "start-reactive-tray-menu-icon", - run: () => { - reactiveTrayMenuIcon.start(); - }, + reactiveTrayMenuIcon.start(); + }, - runAfter: di.inject(startTrayInjectable), - }; - }, + runAfter: startTrayInjectable, + }), injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/main/tray/menu-icon/stop-reactivity.injectable.ts b/packages/core/src/main/tray/menu-icon/stop-reactivity.injectable.ts index 94e91ec607..b5908104d2 100644 --- a/packages/core/src/main/tray/menu-icon/stop-reactivity.injectable.ts +++ b/packages/core/src/main/tray/menu-icon/stop-reactivity.injectable.ts @@ -3,20 +3,21 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { beforeQuitOfBackEndInjectionToken } from "../../start-main-application/runnable-tokens/before-quit-of-back-end-injection-token"; +import { beforeQuitOfBackEndInjectionToken } from "../../start-main-application/runnable-tokens/phases"; import reactiveTrayMenuIconInjectable from "./reactive.injectable"; const stopReactiveTrayMenuIconInjectable = getInjectable({ id: "stop-reactive-tray-menu-icon", - instantiate: (di) => { - const reactiveTrayMenuIcon = di.inject(reactiveTrayMenuIconInjectable); + instantiate: (di) => ({ + run: () => { + const reactiveTrayMenuIcon = di.inject(reactiveTrayMenuIconInjectable); - return { - id: "stop-reactive-tray-menu-icon", - run: () => void reactiveTrayMenuIcon.stop(), - }; - }, + reactiveTrayMenuIcon.stop(); + + return undefined; + }, + }), injectionToken: beforeQuitOfBackEndInjectionToken, }); diff --git a/packages/core/src/main/tray/reactive-tray-menu-items/start-reactive-tray-menu-items.injectable.ts b/packages/core/src/main/tray/reactive-tray-menu-items/start-reactive-tray-menu-items.injectable.ts index 9164afee3b..d95abc222c 100644 --- a/packages/core/src/main/tray/reactive-tray-menu-items/start-reactive-tray-menu-items.injectable.ts +++ b/packages/core/src/main/tray/reactive-tray-menu-items/start-reactive-tray-menu-items.injectable.ts @@ -10,18 +10,14 @@ import startTrayInjectable from "../electron-tray/start-tray.injectable"; const startReactiveTrayMenuItemsInjectable = getInjectable({ id: "start-reactive-tray-menu-items", - instantiate: (di) => { - const reactiveTrayMenuItems = di.inject(reactiveTrayMenuItemsInjectable); + instantiate: (di) => ({ + run: () => { + const reactiveTrayMenuItems = di.inject(reactiveTrayMenuItemsInjectable); - return { - id: "start-reactive-tray-menu-items", - run: () => { - reactiveTrayMenuItems.start(); - }, - - runAfter: di.inject(startTrayInjectable), - }; - }, + reactiveTrayMenuItems.start(); + }, + runAfter: startTrayInjectable, + }), injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/main/tray/reactive-tray-menu-items/stop-reactive-tray-menu-items.injectable.ts b/packages/core/src/main/tray/reactive-tray-menu-items/stop-reactive-tray-menu-items.injectable.ts index 122e9c059a..d5e5063e92 100644 --- a/packages/core/src/main/tray/reactive-tray-menu-items/stop-reactive-tray-menu-items.injectable.ts +++ b/packages/core/src/main/tray/reactive-tray-menu-items/stop-reactive-tray-menu-items.injectable.ts @@ -4,19 +4,20 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import reactiveTrayMenuItemsInjectable from "./reactive-tray-menu-items.injectable"; -import { beforeQuitOfBackEndInjectionToken } from "../../start-main-application/runnable-tokens/before-quit-of-back-end-injection-token"; +import { beforeQuitOfBackEndInjectionToken } from "../../start-main-application/runnable-tokens/phases"; const stopReactiveTrayMenuItemsInjectable = getInjectable({ id: "stop-reactive-tray-menu-items", - instantiate: (di) => { - const reactiveTrayMenuItems = di.inject(reactiveTrayMenuItemsInjectable); + instantiate: (di) => ({ + run: () => { + const reactiveTrayMenuItems = di.inject(reactiveTrayMenuItemsInjectable); - return { - id: "stop-reactive-tray-menu-items", - run: () => void reactiveTrayMenuItems.stop(), - }; - }, + reactiveTrayMenuItems.stop(); + + return undefined; + }, + }), injectionToken: beforeQuitOfBackEndInjectionToken, }); diff --git a/packages/core/src/main/tray/tray-menu-item/tray-menu-item-registrator.injectable.ts b/packages/core/src/main/tray/tray-menu-item/tray-menu-item-registrator.injectable.ts index 573af2f545..f1eb3e7e50 100644 --- a/packages/core/src/main/tray/tray-menu-item/tray-menu-item-registrator.injectable.ts +++ b/packages/core/src/main/tray/tray-menu-item/tray-menu-item-registrator.injectable.ts @@ -15,7 +15,7 @@ import { withErrorSuppression } from "../../../common/utils/with-error-suppressi import type { WithErrorLoggingFor } from "../../../common/utils/with-error-logging/with-error-logging.injectable"; import withErrorLoggingInjectable from "../../../common/utils/with-error-logging/with-error-logging.injectable"; import getRandomIdInjectable from "../../../common/utils/get-random-id.injectable"; -import { isBoolean, isString } from "../../../common/utils"; +import { isBoolean, isString } from "@k8slens/utilities"; const trayMenuItemRegistratorInjectable = getInjectable({ id: "tray-menu-item-registrator", diff --git a/packages/core/src/main/user-store/migrations/5.0.3-beta.1.injectable.ts b/packages/core/src/main/user-store/migrations/5.0.3-beta.1.injectable.ts index 1367037c6d..7739c67e66 100644 --- a/packages/core/src/main/user-store/migrations/5.0.3-beta.1.injectable.ts +++ b/packages/core/src/main/user-store/migrations/5.0.3-beta.1.injectable.ts @@ -5,7 +5,7 @@ import type { ClusterStoreModel } from "../../../common/cluster-store/cluster-store"; import type { KubeconfigSyncEntry, UserPreferencesModel } from "../../../common/user-store"; -import { isErrnoException } from "../../../common/utils"; +import { isErrnoException } from "@k8slens/utilities"; import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; import directoryForKubeConfigsInjectable from "../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable"; import joinPathsInjectable from "../../../common/path/join-paths.injectable"; diff --git a/packages/core/src/main/user-store/sync-open-at-login-with-os.injectable.ts b/packages/core/src/main/user-store/sync-open-at-login-with-os.injectable.ts index 2a92ac8c7a..a06d65163e 100644 --- a/packages/core/src/main/user-store/sync-open-at-login-with-os.injectable.ts +++ b/packages/core/src/main/user-store/sync-open-at-login-with-os.injectable.ts @@ -10,25 +10,22 @@ import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; const setupSyncOpenAtLoginWithOsInjectable = getInjectable({ id: "setup-sync-open-at-login-with-os", - instantiate: (di) => { - const setLoginItemSettings = di.inject(setLoginItemSettingsInjectable); - const userStore = di.inject(userStoreInjectable); + instantiate: (di) => ({ + run: () => { + const setLoginItemSettings = di.inject(setLoginItemSettingsInjectable); + const userStore = di.inject(userStoreInjectable); - return { - id: "setup-sync-open-at-login-with-os", - run: () => { - reaction(() => userStore.openAtLogin, openAtLogin => { - setLoginItemSettings({ - openAtLogin, - openAsHidden: true, - args: ["--hidden"], - }); - }, { - fireImmediately: true, + reaction(() => userStore.openAtLogin, openAtLogin => { + setLoginItemSettings({ + openAtLogin, + openAsHidden: true, + args: ["--hidden"], }); - }, - }; - }, + }, { + fireImmediately: true, + }); + }, + }), injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.injectable.ts b/packages/core/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.injectable.ts index 1af1b6fb55..08a600297c 100644 --- a/packages/core/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.injectable.ts +++ b/packages/core/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import type { IpcMainInvokeEvent } from "electron"; -import type { Disposer } from "../../../../common/utils"; +import type { Disposer } from "@k8slens/utilities"; import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; import type { RequestChannelListener } from "./listener-tokens"; import ipcMainInjectionToken from "../../../../common/ipc/ipc-main-injection-token"; diff --git a/packages/core/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.test.ts b/packages/core/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.test.ts index 66b81c67d9..188a11866b 100644 --- a/packages/core/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.test.ts +++ b/packages/core/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.test.ts @@ -5,7 +5,7 @@ import { getDiForUnitTesting } from "../../../getDiForUnitTesting"; import ipcMainInjectable from "../ipc-main/ipc-main.injectable"; import type { IpcMain, IpcMainInvokeEvent } from "electron"; -import { getPromiseStatus } from "../../../../common/test-utils/get-promise-status"; +import { getPromiseStatus } from "@k8slens/test-utils"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; 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 index 80b94fbe0e..1e6d0f296c 100644 --- 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 @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { disposer } from "../../../../common/utils"; +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"; 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 index 5e029a16d6..c83425109c 100644 --- 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 @@ -10,18 +10,15 @@ import listeningOnRequestChannelsInjectable from "./listening-on-request-channel const startListeningOnChannelsInjectable = getInjectable({ id: "start-listening-on-channels-main", - instantiate: (di) => { - const listeningOnMessageChannels = di.inject(listeningOnMessageChannelsInjectable); - const listeningOnRequestChannels = di.inject(listeningOnRequestChannelsInjectable); + instantiate: (di) => ({ + run: () => { + const listeningOnMessageChannels = di.inject(listeningOnMessageChannelsInjectable); + const listeningOnRequestChannels = di.inject(listeningOnRequestChannelsInjectable); - return { - id: "start-listening-on-channels-main", - run: () => { - listeningOnMessageChannels.start(); - listeningOnRequestChannels.start(); - }, - }; - }, + listeningOnMessageChannels.start(); + listeningOnRequestChannels.start(); + }, + }), injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/main/utils/channel/ipc-main/ipc-main.global-override-for-injectable.ts b/packages/core/src/main/utils/channel/ipc-main/ipc-main.global-override-for-injectable.ts index e770ccdf35..ccb773ab06 100644 --- a/packages/core/src/main/utils/channel/ipc-main/ipc-main.global-override-for-injectable.ts +++ b/packages/core/src/main/utils/channel/ipc-main/ipc-main.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import type { IpcMain } from "electron"; -import { getGlobalOverride } from "../../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import ipcMainInjectable from "./ipc-main.injectable"; export default getGlobalOverride(ipcMainInjectable, () => ({ diff --git a/packages/core/src/main/utils/command-line-arguments.global-override-for-injectable.ts b/packages/core/src/main/utils/command-line-arguments.global-override-for-injectable.ts index edd33d824a..ffa52c8608 100644 --- a/packages/core/src/main/utils/command-line-arguments.global-override-for-injectable.ts +++ b/packages/core/src/main/utils/command-line-arguments.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import commandLineArgumentsInjectable from "./command-line-arguments.injectable"; export default getGlobalOverride(commandLineArgumentsInjectable, () => []); 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 9c395dca5b..c197566a10 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 @@ -9,7 +9,7 @@ import electronInjectable from "./electron.injectable"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; import type electron from "electron"; -import { getPromiseStatus } from "../../../common/test-utils/get-promise-status"; +import { getPromiseStatus } from "@k8slens/test-utils"; import logErrorInjectable from "../../../common/log-error.injectable"; import type { DiContainer } from "@ogre-tools/injectable"; diff --git a/packages/core/src/main/vars/build-version/init.injectable.ts b/packages/core/src/main/vars/build-version/init.injectable.ts index fc08dce920..509c0262d1 100644 --- a/packages/core/src/main/vars/build-version/init.injectable.ts +++ b/packages/core/src/main/vars/build-version/init.injectable.ts @@ -8,14 +8,13 @@ import buildVersionInjectable from "./build-version.injectable"; const initializeBuildVersionInjectable = getInjectable({ id: "initialize-build-version", - instantiate: (di) => { - const buildVersion = di.inject(buildVersionInjectable); + instantiate: (di) => ({ + run: async () => { + const buildVersion = di.inject(buildVersionInjectable); - return { - id: "initialize-build-version", - run: () => buildVersion.init(), - }; - }, + await buildVersion.init(); + }, + }), injectionToken: beforeApplicationIsLoadingInjectionToken, }); diff --git a/packages/core/src/main/vars/default-update-channel/init.injectable.ts b/packages/core/src/main/vars/default-update-channel/init.injectable.ts index 0a156e8dee..b0643149a4 100644 --- a/packages/core/src/main/vars/default-update-channel/init.injectable.ts +++ b/packages/core/src/main/vars/default-update-channel/init.injectable.ts @@ -9,15 +9,14 @@ import defaultUpdateChannelInjectable from "../../../features/application-update const initDefaultUpdateChannelInjectable = getInjectable({ id: "init-default-update-channel", - instantiate: (di) => { - const defaultUpdateChannel = di.inject(defaultUpdateChannelInjectable); + instantiate: (di) => ({ + run: async () => { + const defaultUpdateChannel = di.inject(defaultUpdateChannelInjectable); - return { - id: "init-default-update-channel", - run: () => defaultUpdateChannel.init(), - runAfter: di.inject(initReleaseChannelInjectable), - }; - }, + await defaultUpdateChannel.init(); + }, + runAfter: initReleaseChannelInjectable, + }), injectionToken: beforeApplicationIsLoadingInjectionToken, }); diff --git a/packages/core/src/main/vars/hardware-acceleration-should-be-disabled.global-override-for-injectable.ts b/packages/core/src/main/vars/hardware-acceleration-should-be-disabled.global-override-for-injectable.ts index 2f66f9fc18..53c6c692fd 100644 --- a/packages/core/src/main/vars/hardware-acceleration-should-be-disabled.global-override-for-injectable.ts +++ b/packages/core/src/main/vars/hardware-acceleration-should-be-disabled.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import hardwareAccelerationShouldBeDisabledInjectable from "./hardware-acceleration-should-be-disabled.injectable"; export default getGlobalOverride(hardwareAccelerationShouldBeDisabledInjectable, () => false); diff --git a/packages/core/src/main/vars/release-channel/init.injectable.ts b/packages/core/src/main/vars/release-channel/init.injectable.ts index fe8a838a89..4871025132 100644 --- a/packages/core/src/main/vars/release-channel/init.injectable.ts +++ b/packages/core/src/main/vars/release-channel/init.injectable.ts @@ -9,15 +9,14 @@ import initSemanticBuildVersionInjectable from "../semantic-build-version/init.i const initReleaseChannelInjectable = getInjectable({ id: "init-release-channel", - instantiate: (di) => { - const releaseChannel = di.inject(releaseChannelInjectable); + instantiate: (di) => ({ + run: async () => { + const releaseChannel = di.inject(releaseChannelInjectable); - return { - id: "init-release-channel", - run: () => releaseChannel.init(), - runAfter: di.inject(initSemanticBuildVersionInjectable), - }; - }, + await releaseChannel.init(); + }, + runAfter: initSemanticBuildVersionInjectable, + }), injectionToken: beforeApplicationIsLoadingInjectionToken, }); diff --git a/packages/core/src/main/vars/semantic-build-version/init.injectable.ts b/packages/core/src/main/vars/semantic-build-version/init.injectable.ts index c39c3b51a2..8f0dcb7387 100644 --- a/packages/core/src/main/vars/semantic-build-version/init.injectable.ts +++ b/packages/core/src/main/vars/semantic-build-version/init.injectable.ts @@ -10,12 +10,13 @@ import initializeBuildVersionInjectable from "../build-version/init.injectable"; const initSemanticBuildVersionInjectable = getInjectable({ id: "init-semantic-build-version", instantiate: (di) => { - const buildSemanticVersion = di.inject(buildSemanticVersionInjectable); - return { - id: "init-semantic-build-version", - run: () => buildSemanticVersion.init(), - runAfter: di.inject(initializeBuildVersionInjectable), + run: async () => { + const buildSemanticVersion = di.inject(buildSemanticVersionInjectable); + + await buildSemanticVersion.init(); + }, + runAfter: initializeBuildVersionInjectable, }; }, injectionToken: beforeApplicationIsLoadingInjectionToken, diff --git a/packages/core/src/renderer/api/catalog/entity/get-active-cluster-entity.injectable.ts b/packages/core/src/renderer/api/catalog/entity/get-active-cluster-entity.injectable.ts index d5a2d1f3f8..b856c15ffd 100644 --- a/packages/core/src/renderer/api/catalog/entity/get-active-cluster-entity.injectable.ts +++ b/packages/core/src/renderer/api/catalog/entity/get-active-cluster-entity.injectable.ts @@ -3,20 +3,18 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; +import { computed } from "mobx"; import clusterStoreInjectable from "../../../../common/cluster-store/cluster-store.injectable"; -import type { Cluster } from "../../../../common/cluster/cluster"; import catalogEntityRegistryInjectable from "./registry.injectable"; -export type GetActiveClusterEntity = () => Cluster | undefined; - -const getActiveClusterEntityInjectable = getInjectable({ - id: "get-active-cluster-entity", - instantiate: (di): GetActiveClusterEntity => { +const activeEntityInternalClusterInjectable = getInjectable({ + id: "active-entity-internal-cluster", + instantiate: (di) => { const store = di.inject(clusterStoreInjectable); const entityRegistry = di.inject(catalogEntityRegistryInjectable); - return () => store.getById(entityRegistry.activeEntity?.getId()); + return computed(() => store.getById(entityRegistry.activeEntity?.getId())); }, }); -export default getActiveClusterEntityInjectable; +export default activeEntityInternalClusterInjectable; diff --git a/packages/core/src/renderer/api/catalog/entity/metrics-enabled.injectable.ts b/packages/core/src/renderer/api/catalog/entity/metrics-enabled.injectable.ts index d267132fcd..0954259d98 100644 --- a/packages/core/src/renderer/api/catalog/entity/metrics-enabled.injectable.ts +++ b/packages/core/src/renderer/api/catalog/entity/metrics-enabled.injectable.ts @@ -5,14 +5,22 @@ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; import { computed } from "mobx"; import type { ClusterMetricsResourceType } from "../../../../common/cluster-types"; -import getActiveClusterEntityInjectable from "./get-active-cluster-entity.injectable"; +import activeEntityInternalClusterInjectable from "./get-active-cluster-entity.injectable"; const enabledMetricsInjectable = getInjectable({ id: "enabled-metrics", instantiate: (di, kind) => { - const getActiveClusterEntity = di.inject(getActiveClusterEntityInjectable); + const activeEntityInternalCluster = di.inject(activeEntityInternalClusterInjectable); - return computed(() => !getActiveClusterEntity()?.isMetricHidden(kind)); + return computed(() => { + const cluster = activeEntityInternalCluster.get(); + + if (!cluster?.preferences.hiddenMetrics) { + return false; + } + + return cluster.preferences.hiddenMetrics.includes(kind); + }); }, lifecycle: lifecycleEnum.keyedSingleton({ getInstanceKey: (di, kind: ClusterMetricsResourceType) => kind, diff --git a/packages/core/src/renderer/api/catalog/entity/registry.ts b/packages/core/src/renderer/api/catalog/entity/registry.ts index ad23b2aa94..d3f205a094 100644 --- a/packages/core/src/renderer/api/catalog/entity/registry.ts +++ b/packages/core/src/renderer/api/catalog/entity/registry.ts @@ -7,8 +7,8 @@ import { computed, observable, makeObservable, action } from "mobx"; import { ipcRendererOn } from "../../../../common/ipc"; import type { CatalogCategory, CatalogEntity, CatalogEntityData, CatalogCategoryRegistry, CatalogEntityKindData } from "../../../../common/catalog"; import "../../../../common/catalog-entities"; -import { iter } from "../../../utils"; -import type { Disposer } from "../../../utils"; +import { iter } from "@k8slens/utilities"; +import type { Disposer } from "@k8slens/utilities"; import { once } from "lodash"; import { CatalogRunEvent } from "../../../../common/catalog/catalog-run-event"; import { ipcRenderer } from "electron"; diff --git a/packages/core/src/renderer/api/helpers/watch-for-general-entity-navigation.injectable.ts b/packages/core/src/renderer/api/helpers/watch-for-general-entity-navigation.injectable.ts index 0e73acfcd1..70b7a61eae 100644 --- a/packages/core/src/renderer/api/helpers/watch-for-general-entity-navigation.injectable.ts +++ b/packages/core/src/renderer/api/helpers/watch-for-general-entity-navigation.injectable.ts @@ -8,8 +8,8 @@ import type { GeneralEntity } from "../../../common/catalog-entities"; import generalCategoryInjectable from "../../../common/catalog/categories/general.injectable"; import isActiveRouteInjectable from "../../navigation/is-route-active.injectable"; import observableHistoryInjectable from "../../navigation/observable-history.injectable"; -import type { Disposer } from "../../utils"; -import { disposer } from "../../utils"; +import type { Disposer } from "@k8slens/utilities"; +import { disposer } from "@k8slens/utilities"; import catalogEntityRegistryInjectable from "../catalog/entity/registry.injectable"; export type WatchForGeneralEntityNavigation = () => Disposer; diff --git a/packages/core/src/renderer/api/websocket-api.ts b/packages/core/src/renderer/api/websocket-api.ts index b172655dab..eddeda0049 100644 --- a/packages/core/src/renderer/api/websocket-api.ts +++ b/packages/core/src/renderer/api/websocket-api.ts @@ -7,7 +7,7 @@ import { observable, makeObservable } from "mobx"; import EventEmitter from "events"; import type TypedEventEmitter from "typed-emitter"; import type { Arguments } from "typed-emitter"; -import type { Defaulted } from "../utils"; +import type { Defaulted } from "@k8slens/utilities"; import type { DefaultWebsocketApiParams } from "./default-websocket-api-params.injectable"; interface WebsocketApiParams { 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 d69d8dcbab..d80cc668ac 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 @@ -12,7 +12,6 @@ const setupAppPathsInjectable = getInjectable({ id: "setup-app-paths", instantiate: (di) => ({ - id: "setup-app-paths", run: async () => { const requestFromChannel = di.inject(requestFromChannelInjectionToken); const appPathsState = di.inject(appPathsStateInjectable); diff --git a/packages/core/src/renderer/base-store/persist-state-to-config.injectable.ts b/packages/core/src/renderer/base-store/persist-state-to-config.injectable.ts index a1c8c5919a..0cf594062a 100644 --- a/packages/core/src/renderer/base-store/persist-state-to-config.injectable.ts +++ b/packages/core/src/renderer/base-store/persist-state-to-config.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { persistStateToConfigInjectionToken } from "../../common/base-store/save-to-file"; -import { noop } from "../utils"; +import { noop } from "@k8slens/utilities"; const persistStateToConfigInjectable = getInjectable({ id: "persist-state-to-config", diff --git a/packages/core/src/renderer/before-frame-starts/runnables/configure-immer.injectable.ts b/packages/core/src/renderer/before-frame-starts/runnables/configure-immer.injectable.ts index 73ec9f99bc..a52ed6bc48 100644 --- a/packages/core/src/renderer/before-frame-starts/runnables/configure-immer.injectable.ts +++ b/packages/core/src/renderer/before-frame-starts/runnables/configure-immer.injectable.ts @@ -9,7 +9,6 @@ import { beforeFrameStartsFirstInjectionToken } from "../tokens"; const configureImmerInjectable = getInjectable({ id: "configure-immer", instantiate: () => ({ - id: "configure-immer", run: () => { // Docs: https://immerjs.github.io/immer/ // Required in `utils/storage-helper.ts` diff --git a/packages/core/src/renderer/before-frame-starts/runnables/configure-mobx.injectable.ts b/packages/core/src/renderer/before-frame-starts/runnables/configure-mobx.injectable.ts index 20953b8a8a..9c91f76a6d 100644 --- a/packages/core/src/renderer/before-frame-starts/runnables/configure-mobx.injectable.ts +++ b/packages/core/src/renderer/before-frame-starts/runnables/configure-mobx.injectable.ts @@ -9,7 +9,6 @@ import { beforeFrameStartsFirstInjectionToken } from "../tokens"; const configureMobxInjectable = getInjectable({ id: "configure-mobx", instantiate: () => ({ - id: "configure-mobx", run: () => { // Docs: https://mobx.js.org/configuration.html configure({ diff --git a/packages/core/src/renderer/before-frame-starts/runnables/load-monaco-themes.injectable.ts b/packages/core/src/renderer/before-frame-starts/runnables/load-monaco-themes.injectable.ts index ef85a84cd0..f8456bdca6 100644 --- a/packages/core/src/renderer/before-frame-starts/runnables/load-monaco-themes.injectable.ts +++ b/packages/core/src/renderer/before-frame-starts/runnables/load-monaco-themes.injectable.ts @@ -10,7 +10,6 @@ import { beforeFrameStartsSecondInjectionToken } from "../tokens"; const loadMonacoThemesInjectable = getInjectable({ id: "load-monaco-themes", instantiate: (di) => ({ - id: "load-monaco-themes", run: () => { const customThemes = di.injectMany(customMonacoThemeInjectionToken); const addNewMonacoTheme = di.inject(addNewMonacoThemeInjectable); 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 64bc9dee58..dbc77a92b8 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 @@ -19,7 +19,6 @@ import maybeKubeApiInjectable from "../../../common/k8s-api/maybe-kube-api.injec const setupAutoRegistrationInjectable = getInjectable({ id: "setup-auto-registration", instantiate: (di) => ({ - id: "setup-auto-registration", run: () => { const autoRegistrationEmitter = di.inject(autoRegistrationEmitterInjectable); const beforeApiManagerInitializationCrds: CustomResourceDefinition[] = []; 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 a89ba58ec2..0d9c8bc65a 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 @@ -12,7 +12,6 @@ import { beforeMainFrameStartsFirstInjectionToken } from "../tokens"; const setupCurrentClusterBroadcastInjectable = getInjectable({ id: "setup-current-cluster-broadcast", instantiate: (di) => ({ - id: "setup-current-cluster-broadcast", run: () => { const matchedClusterId = di.inject(matchedClusterIdInjectable); const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken); diff --git a/packages/core/src/renderer/before-frame-starts/runnables/setup-kubernetes-cluster-catalog-add-menu.injectable.ts b/packages/core/src/renderer/before-frame-starts/runnables/setup-kubernetes-cluster-catalog-add-menu.injectable.ts index 5d6efad5eb..e62fb6d830 100644 --- a/packages/core/src/renderer/before-frame-starts/runnables/setup-kubernetes-cluster-catalog-add-menu.injectable.ts +++ b/packages/core/src/renderer/before-frame-starts/runnables/setup-kubernetes-cluster-catalog-add-menu.injectable.ts @@ -14,7 +14,6 @@ import { beforeFrameStartsSecondInjectionToken } from "../tokens"; const setupKubernetesClusterCatalogAddMenuListenerInjectable = getInjectable({ id: "setup-kubernetes-cluster-catalog-add-menu-listener", instantiate: (di) => ({ - id: "setup-kubernetes-cluster-catalog-add-menu-listener", run: () => { const navigateToAddCluster = di.inject(navigateToAddClusterInjectable); const addSyncEntries = di.inject(addSyncEntriesInjectable); diff --git a/packages/core/src/renderer/before-frame-starts/runnables/setup-kubernetes-cluster-context-menu-open.injectable.ts b/packages/core/src/renderer/before-frame-starts/runnables/setup-kubernetes-cluster-context-menu-open.injectable.ts index 99a3bfa9f3..0775b501b5 100644 --- a/packages/core/src/renderer/before-frame-starts/runnables/setup-kubernetes-cluster-context-menu-open.injectable.ts +++ b/packages/core/src/renderer/before-frame-starts/runnables/setup-kubernetes-cluster-context-menu-open.injectable.ts @@ -5,8 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import catalogCategoryRegistryInjectable from "../../../common/catalog/category-registry.injectable"; import getClusterByIdInjectable from "../../../common/cluster-store/get-by-id.injectable"; -import readFileInjectable from "../../../common/fs/read-file.injectable"; -import { loadConfigFromString } from "../../../common/kube-helpers"; +import loadKubeconfigInjectable from "../../../common/cluster/load-kubeconfig.injectable"; import loggerInjectable from "../../../common/logger.injectable"; import openDeleteClusterDialogInjectable from "../../components/delete-cluster-dialog/open.injectable"; import { beforeFrameStartsSecondInjectionToken } from "../tokens"; @@ -14,11 +13,9 @@ import { beforeFrameStartsSecondInjectionToken } from "../tokens"; const setupKubernetesClusterContextMenuOpenInjectable = getInjectable({ id: "setup-kubernetes-cluster-context-menu-open", instantiate: (di) => ({ - id: "setup-kubernetes-cluster-context-menu-open", run: () => { const catalogCategoryRegistry = di.inject(catalogCategoryRegistryInjectable); const openDeleteClusterDialog = di.inject(openDeleteClusterDialogInjectable); - const readFile = di.inject(readFileInjectable); const getClusterById = di.inject(getClusterByIdInjectable); const logger = di.inject(loggerInjectable); @@ -37,7 +34,9 @@ const setupKubernetesClusterContextMenuOpenInjectable = getInjectable({ return logger.warn("[KUBERNETES-CLUSTER]: cannot delete cluster, does not exist in store", { clusterId }); } - const result = loadConfigFromString(await readFile(cluster.kubeConfigPath)); + const loadKubeconfig = di.inject(loadKubeconfigInjectable, cluster); + + const result = await loadKubeconfig(true); if (result.error) { logger.error("[KUBERNETES-CLUSTER]: failed to parse kubeconfig file", result.error); diff --git a/packages/core/src/renderer/before-frame-starts/runnables/setup-lens-proxy-certificate.injectable.ts b/packages/core/src/renderer/before-frame-starts/runnables/setup-lens-proxy-certificate.injectable.ts index e698eda6dd..d3a01a3eea 100644 --- a/packages/core/src/renderer/before-frame-starts/runnables/setup-lens-proxy-certificate.injectable.ts +++ b/packages/core/src/renderer/before-frame-starts/runnables/setup-lens-proxy-certificate.injectable.ts @@ -10,7 +10,6 @@ import requestLensProxyCertificateInjectable from "../../certificate/request-len const setupLensProxyCertificateInjectable = getInjectable({ id: "setup-lens-proxy-certificate", instantiate: (di) => ({ - id: "setup-lens-proxy-certificate", run: async () => { const requestLensProxyCertificate = di.inject(requestLensProxyCertificateInjectable); const lensProxyCertificate = di.inject(lensProxyCertificateInjectable); diff --git a/packages/core/src/renderer/before-frame-starts/runnables/setup-root-mac-class.injectable.ts b/packages/core/src/renderer/before-frame-starts/runnables/setup-root-mac-class.injectable.ts index 56b9ce66fa..241628fe42 100644 --- a/packages/core/src/renderer/before-frame-starts/runnables/setup-root-mac-class.injectable.ts +++ b/packages/core/src/renderer/before-frame-starts/runnables/setup-root-mac-class.injectable.ts @@ -9,7 +9,6 @@ import { beforeFrameStartsSecondInjectionToken } from "../tokens"; const setupRootMacClassnameInjectable = getInjectable({ id: "setup-root-mac-classname", instantiate: (di) => ({ - id: "setup-root-mac-classname", run: () => { const isMac = di.inject(isMacInjectable); const rootElem = document.getElementById("app"); diff --git a/packages/core/src/renderer/before-frame-starts/runnables/setup-sentry.injectable.ts b/packages/core/src/renderer/before-frame-starts/runnables/setup-sentry.injectable.ts index c6af3b7614..0472144249 100644 --- a/packages/core/src/renderer/before-frame-starts/runnables/setup-sentry.injectable.ts +++ b/packages/core/src/renderer/before-frame-starts/runnables/setup-sentry.injectable.ts @@ -10,7 +10,6 @@ import { init } from "@sentry/electron/renderer"; const setupSentryInjectable = getInjectable({ id: "setup-sentry", instantiate: (di) => ({ - id: "setup-sentry", run: () => { const initializeSentryReportingWith = di.inject(initializeSentryReportingWithInjectable); diff --git a/packages/core/src/renderer/before-frame-starts/runnables/setup-weblink-context-menu-open.injectable.tsx b/packages/core/src/renderer/before-frame-starts/runnables/setup-weblink-context-menu-open.injectable.tsx index 7bf8f29422..ce620894e1 100644 --- a/packages/core/src/renderer/before-frame-starts/runnables/setup-weblink-context-menu-open.injectable.tsx +++ b/packages/core/src/renderer/before-frame-starts/runnables/setup-weblink-context-menu-open.injectable.tsx @@ -9,10 +9,9 @@ import { WeblinkAddCommand } from "../../components/catalog-entities/weblink-add import commandOverlayInjectable from "../../components/command-palette/command-overlay.injectable"; import { beforeFrameStartsSecondInjectionToken } from "../tokens"; -const setupWeblickContextMenuOpenInjectable = getInjectable({ - id: "setup-weblick-context-menu-open", +const setupWeblinkContextMenuOpenInjectable = getInjectable({ + id: "setup-weblink-context-menu-open", instantiate: (di) => ({ - id: "setup-weblick-context-menu-open", run: () => { const catalogCategoryRegistry = di.inject(catalogCategoryRegistryInjectable); const commandOverlay = di.inject(commandOverlayInjectable); @@ -31,4 +30,4 @@ const setupWeblickContextMenuOpenInjectable = getInjectable({ injectionToken: beforeFrameStartsSecondInjectionToken, }); -export default setupWeblickContextMenuOpenInjectable; +export default setupWeblinkContextMenuOpenInjectable; diff --git a/packages/core/src/renderer/before-frame-starts/tokens.ts b/packages/core/src/renderer/before-frame-starts/tokens.ts index 460c44cde9..26cbce9133 100644 --- a/packages/core/src/renderer/before-frame-starts/tokens.ts +++ b/packages/core/src/renderer/before-frame-starts/tokens.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectionToken } from "@ogre-tools/injectable"; -import type { Runnable } from "../../common/runnable/run-many-for"; +import type { Runnable } from "@k8slens/run-many"; // NOTE: these are run before any other token, mostly to set up things that all other runnables need export const beforeFrameStartsFirstInjectionToken = getInjectionToken({ diff --git a/packages/core/src/renderer/bootstrap.global-override-for-injectable.ts b/packages/core/src/renderer/bootstrap.global-override-for-injectable.ts index a706ea765f..0e15e59078 100644 --- a/packages/core/src/renderer/bootstrap.global-override-for-injectable.ts +++ b/packages/core/src/renderer/bootstrap.global-override-for-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 { getGlobalOverride } from "../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import bootstrapInjectable from "./bootstrap.injectable"; export default getGlobalOverride(bootstrapInjectable, () => ({ diff --git a/packages/core/src/renderer/bootstrap.injectable.ts b/packages/core/src/renderer/bootstrap.injectable.ts index 9bfb492aa9..7cc172e3f1 100644 --- a/packages/core/src/renderer/bootstrap.injectable.ts +++ b/packages/core/src/renderer/bootstrap.injectable.ts @@ -17,7 +17,7 @@ const bootstrapInjectable = getInjectable({ await bootstrap(di); }, - runAfter: di.inject(startFrameInjectable), + runAfter: startFrameInjectable, }), causesSideEffects: true, diff --git a/packages/core/src/renderer/cluster-frame-context/for-namespaced-resources.injectable.ts b/packages/core/src/renderer/cluster-frame-context/for-namespaced-resources.injectable.ts index f4795f8523..bc8c9f38e8 100644 --- a/packages/core/src/renderer/cluster-frame-context/for-namespaced-resources.injectable.ts +++ b/packages/core/src/renderer/cluster-frame-context/for-namespaced-resources.injectable.ts @@ -55,7 +55,7 @@ const clusterFrameContextForNamespacedResourcesInjectable = getInjectable({ && cluster.accessibleNamespaces.length === 0 && allNamespaces.get().every(ns => namespaces.includes(ns)) ), - isGlobalWatchEnabled: () => cluster.isGlobalWatchEnabled, + isGlobalWatchEnabled: () => cluster.isGlobalWatchEnabled.get(), get allNamespaces() { return allNamespaces.get(); }, diff --git a/packages/core/src/renderer/cluster-frame-context/should-show-resource.injectable.ts b/packages/core/src/renderer/cluster-frame-context/should-show-resource.injectable.ts index 2ec4132045..6258796a0b 100644 --- a/packages/core/src/renderer/cluster-frame-context/should-show-resource.injectable.ts +++ b/packages/core/src/renderer/cluster-frame-context/should-show-resource.injectable.ts @@ -15,7 +15,7 @@ const shouldShowResourceInjectable = getInjectable({ const cluster = di.inject(hostedClusterInjectable); return cluster - ? computed(() => cluster.shouldShowResource(resource)) + ? computed(() => cluster.resourcesToShow.has(formatKubeApiResource(resource))) : computed(() => false); }, injectionToken: shouldShowResourceInjectionToken, diff --git a/packages/core/src/renderer/cluster/create-cluster.injectable.ts b/packages/core/src/renderer/cluster/create-cluster.injectable.ts deleted file mode 100644 index ff8ea38fff..0000000000 --- a/packages/core/src/renderer/cluster/create-cluster.injectable.ts +++ /dev/null @@ -1,46 +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 { ClusterDependencies } from "../../common/cluster/cluster"; -import { Cluster } from "../../common/cluster/cluster"; -import directoryForKubeConfigsInjectable from "../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable"; -import { createClusterInjectionToken } from "../../common/cluster/create-cluster-injection-token"; -import loggerInjectable from "../../common/logger.injectable"; -import broadcastMessageInjectable from "../../common/ipc/broadcast-message.injectable"; -import loadConfigfromFileInjectable from "../../common/kube-helpers/load-config-from-file.injectable"; - -const createClusterInjectable = getInjectable({ - id: "create-cluster", - - instantiate: (di) => { - const dependencies: ClusterDependencies = { - directoryForKubeConfigs: di.inject(directoryForKubeConfigsInjectable), - logger: di.inject(loggerInjectable), - broadcastMessage: di.inject(broadcastMessageInjectable), - loadConfigfromFile: di.inject(loadConfigfromFileInjectable), - - // TODO: Dismantle wrong abstraction - // Note: "as never" to get around strictness in unnatural scenario - createKubeconfigManager: () => undefined as never, - createKubectl: () => { throw new Error("Tried to access back-end feature in front-end.");}, - createContextHandler: () => undefined as never, - createAuthorizationReview: () => { throw new Error("Tried to access back-end feature in front-end."); }, - requestNamespaceListPermissionsFor: () => { throw new Error("Tried to access back-end feature in front-end."); }, - createListNamespaces: () => { throw new Error("Tried to access back-end feature in front-end."); }, - requestApiResources: () => { throw new Error("Tried to access back-end feature in front-end."); }, - detectClusterMetadata: () => { throw new Error("Tried to access back-end feature in front-end."); }, - clusterVersionDetector: { - detect: () => { throw new Error("Tried to access back-end feature in front-end."); }, - key: "irrelavent", - }, - }; - - return (model, configData) => new Cluster(dependencies, model, configData); - }, - - injectionToken: createClusterInjectionToken, -}); - -export default createClusterInjectable; diff --git a/packages/core/src/renderer/components/+add-cluster/add-cluster.tsx b/packages/core/src/renderer/components/+add-cluster/add-cluster.tsx index 92fa0b7a03..4ec5ced863 100644 --- a/packages/core/src/renderer/components/+add-cluster/add-cluster.tsx +++ b/packages/core/src/renderer/components/+add-cluster/add-cluster.tsx @@ -14,7 +14,7 @@ import React from "react"; import * as uuid from "uuid"; import { loadConfigFromString, splitConfig } from "../../../common/kube-helpers"; import { docsUrl } from "../../../common/vars"; -import { isDefined, iter } from "../../utils"; +import { isDefined, iter } from "@k8slens/utilities"; import { Button } from "../button"; import type { ShowNotification } from "../notifications"; import { SettingLayout } from "../layout/setting-layout"; diff --git a/packages/core/src/renderer/components/+catalog/__tests__/catalog-entity-store.test.ts b/packages/core/src/renderer/components/+catalog/__tests__/catalog-entity-store.test.ts index 79deff6544..a18b13d311 100644 --- a/packages/core/src/renderer/components/+catalog/__tests__/catalog-entity-store.test.ts +++ b/packages/core/src/renderer/components/+catalog/__tests__/catalog-entity-store.test.ts @@ -10,9 +10,9 @@ import catalogCategoryRegistryInjectable from "../../../../common/catalog/catego import { CatalogCategory } from "../../../api/catalog-entity"; import catalogEntityRegistryInjectable from "../../../api/catalog/entity/registry.injectable"; import { getDiForUnitTesting } from "../../../getDiForUnitTesting"; -import { noop } from "../../../utils"; import type { CatalogEntityStore } from "../catalog-entity-store.injectable"; import catalogEntityStoreInjectable from "../catalog-entity-store.injectable"; +import { noop } from "@k8slens/utilities"; class TestEntityOne extends CatalogEntity { public static readonly apiVersion: string = "entity.k8slens.dev/v1alpha1"; diff --git a/packages/core/src/renderer/components/+catalog/catalog-add-button.tsx b/packages/core/src/renderer/components/+catalog/catalog-add-button.tsx index ee7ca30757..0e4531077d 100644 --- a/packages/core/src/renderer/components/+catalog/catalog-add-button.tsx +++ b/packages/core/src/renderer/components/+catalog/catalog-add-button.tsx @@ -9,7 +9,6 @@ import { SpeedDial, SpeedDialAction } from "@material-ui/lab"; import { Icon } from "../icon"; import { observer } from "mobx-react"; import { observable, makeObservable, action } from "mobx"; -import { autoBind } from "../../../common/utils"; import type { CatalogCategory, CatalogEntityAddMenu } from "../../api/catalog-entity"; import { EventEmitter } from "events"; import type { CatalogCategoryRegistry } from "../../../common/catalog"; @@ -17,6 +16,7 @@ import { withInjectables } from "@ogre-tools/injectable-react"; import catalogCategoryRegistryInjectable from "../../../common/catalog/category-registry.injectable"; import type { Navigate } from "../../navigation/navigate.injectable"; import navigateInjectable from "../../navigation/navigate.injectable"; +import autoBindReact from "auto-bind/react"; export interface CatalogAddButtonProps { category: CatalogCategory; @@ -37,7 +37,7 @@ class NonInjectedCatalogAddButton extends React.Component; diff --git a/packages/core/src/renderer/components/+catalog/columns/named-category.injectable.tsx b/packages/core/src/renderer/components/+catalog/columns/named-category.injectable.tsx index 1f782d7b6f..0f7544ffc1 100644 --- a/packages/core/src/renderer/components/+catalog/columns/named-category.injectable.tsx +++ b/packages/core/src/renderer/components/+catalog/columns/named-category.injectable.tsx @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import styles from "../catalog.module.scss"; import type { CatalogEntity } from "../../../../common/catalog"; -import { prevDefault } from "../../../utils"; +import { prevDefault } from "@k8slens/utilities"; import { Avatar } from "../../avatar"; import { Icon } from "../../icon"; import React from "react"; diff --git a/packages/core/src/renderer/components/+catalog/custom-category-columns.injectable.tsx b/packages/core/src/renderer/components/+catalog/custom-category-columns.injectable.tsx index 1c0d13964d..da0da81503 100644 --- a/packages/core/src/renderer/components/+catalog/custom-category-columns.injectable.tsx +++ b/packages/core/src/renderer/components/+catalog/custom-category-columns.injectable.tsx @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import { computedInjectManyInjectable } from "@ogre-tools/injectable-extension-for-mobx"; import { computed } from "mobx"; -import { getOrInsert, getOrInsertMap } from "../../utils"; +import { getOrInsert, getOrInsertMap } from "@k8slens/utilities"; import { customCatalogCategoryColumnInjectionToken } from "./columns/custom-token"; import type { RegisteredAdditionalCategoryColumn } from "./custom-category-columns"; diff --git a/packages/core/src/renderer/components/+catalog/custom-views.injectable.ts b/packages/core/src/renderer/components/+catalog/custom-views.injectable.ts index c6200f80c6..bccb4d75bf 100644 --- a/packages/core/src/renderer/components/+catalog/custom-views.injectable.ts +++ b/packages/core/src/renderer/components/+catalog/custom-views.injectable.ts @@ -8,7 +8,7 @@ import type { IComputedValue } from "mobx"; import { computed } from "mobx"; import type { LensRendererExtension } from "../../../extensions/lens-renderer-extension"; import rendererExtensionsInjectable from "../../../extensions/renderer-extensions.injectable"; -import { getOrInsert, getOrInsertMap } from "../../utils"; +import { getOrInsert, getOrInsertMap } from "@k8slens/utilities"; import type { CustomCategoryViewComponents } from "./custom-views"; interface Dependencies { diff --git a/packages/core/src/renderer/components/+catalog/entity-details/registrator.injectable.ts b/packages/core/src/renderer/components/+catalog/entity-details/registrator.injectable.ts index 02a6a7ed23..9dfb83cce0 100644 --- a/packages/core/src/renderer/components/+catalog/entity-details/registrator.injectable.ts +++ b/packages/core/src/renderer/components/+catalog/entity-details/registrator.injectable.ts @@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import { extensionRegistratorInjectionToken } from "../../../../extensions/extension-loader/extension-registrator-injection-token"; import type { LensRendererExtension } from "../../../../extensions/lens-renderer-extension"; import type { CatalogEntity } from "../../../api/catalog-entity"; -import { getRandId } from "../../../utils"; +import * as uuid from "uuid"; import type { CatalogEntityDetailRegistration } from "./token"; import { catalogEntityDetailItemInjectionToken } from "./token"; @@ -28,7 +28,7 @@ const getRegistratorFor = (extension: LensRendererExtension) => ({ kind, priority, }: CatalogEntityDetailRegistration) => getInjectable({ - id: `catalog-entity-detail-item-for-${extension.sanitizedExtensionId}-${getRandId({ sep: "-" })}`, + id: `catalog-entity-detail-item-for-${extension.sanitizedExtensionId}-${uuid.v4()}`, instantiate: () => ({ apiVersions: new Set(apiVersions), components, diff --git a/packages/core/src/renderer/components/+catalog/entity-details/view.tsx b/packages/core/src/renderer/components/+catalog/entity-details/view.tsx index 6b9b92247d..b846e20009 100644 --- a/packages/core/src/renderer/components/+catalog/entity-details/view.tsx +++ b/packages/core/src/renderer/components/+catalog/entity-details/view.tsx @@ -10,7 +10,7 @@ import { Drawer, DrawerItem } from "../../drawer"; import type { CatalogCategory, CatalogEntity } from "../../../../common/catalog"; import { Icon } from "../../icon"; import { CatalogEntityDrawerMenu } from "../catalog-entity-drawer-menu"; -import { cssNames } from "../../../utils"; +import { cssNames } from "@k8slens/utilities"; import { Avatar } from "../../avatar"; import type { GetLabelBadges } from "../get-label-badges.injectable"; import { withInjectables } from "@ogre-tools/injectable-react"; diff --git a/packages/core/src/renderer/components/+cluster/cluster-issues.tsx b/packages/core/src/renderer/components/+cluster/cluster-issues.tsx index 829d7c5c54..d338f23f73 100644 --- a/packages/core/src/renderer/components/+cluster/cluster-issues.tsx +++ b/packages/core/src/renderer/components/+cluster/cluster-issues.tsx @@ -12,7 +12,7 @@ import { computed, makeObservable } from "mobx"; import { Icon } from "../icon"; import { SubHeader } from "../layout/sub-header"; import { Table, TableCell, TableHead, TableRow } from "../table"; -import { cssNames, prevDefault } from "../../utils"; +import { cssNames, prevDefault } from "@k8slens/utilities"; import type { ItemObject } from "../../../common/item.store"; import { Spinner } from "../spinner"; import type { ApiManager } from "../../../common/k8s-api/api-manager"; diff --git a/packages/core/src/renderer/components/+cluster/cluster-metrics.tsx b/packages/core/src/renderer/components/+cluster/cluster-metrics.tsx index 028885e7f3..726e37d76e 100644 --- a/packages/core/src/renderer/components/+cluster/cluster-metrics.tsx +++ b/packages/core/src/renderer/components/+cluster/cluster-metrics.tsx @@ -11,7 +11,7 @@ import type { ChartOptions, ChartPoint } from "chart.js"; import type { ClusterOverviewStore } from "./cluster-overview-store/cluster-overview-store"; import { MetricType } from "./cluster-overview-store/cluster-overview-store"; import { BarChart } from "../chart"; -import { bytesToUnits, cssNames } from "../../utils"; +import { bytesToUnits, cssNames } from "@k8slens/utilities"; import { Spinner } from "../spinner"; import { ZebraStripesPlugin } from "../chart/zebra-stripes.plugin"; import { ClusterNoMetrics } from "./cluster-no-metrics"; diff --git a/packages/core/src/renderer/components/+cluster/cluster-no-metrics.tsx b/packages/core/src/renderer/components/+cluster/cluster-no-metrics.tsx index ec039835fc..8e90c7f72f 100644 --- a/packages/core/src/renderer/components/+cluster/cluster-no-metrics.tsx +++ b/packages/core/src/renderer/components/+cluster/cluster-no-metrics.tsx @@ -7,7 +7,7 @@ import styles from "./cluster-no-metrics.module.scss"; import React from "react"; import { Icon } from "../icon"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import type { NavigateToEntitySettings } from "../../../common/front-end-routing/routes/entity-settings/navigate-to-entity-settings.injectable"; import { withInjectables } from "@ogre-tools/injectable-react"; import navigateToEntitySettingsInjectable from "../../../common/front-end-routing/routes/entity-settings/navigate-to-entity-settings.injectable"; diff --git a/packages/core/src/renderer/components/+cluster/cluster-overview-store/cluster-overview-store.ts b/packages/core/src/renderer/components/+cluster/cluster-overview-store/cluster-overview-store.ts index 943b14dbf9..f417d3219e 100644 --- a/packages/core/src/renderer/components/+cluster/cluster-overview-store/cluster-overview-store.ts +++ b/packages/core/src/renderer/components/+cluster/cluster-overview-store/cluster-overview-store.ts @@ -7,12 +7,12 @@ import { action, observable, reaction, when, makeObservable } from "mobx"; import type { KubeObjectStoreDependencies } from "../../../../common/k8s-api/kube-object.store"; import { KubeObjectStore } from "../../../../common/k8s-api/kube-object.store"; import type { Cluster, ClusterApi } from "../../../../common/k8s-api/endpoints"; -import type { StorageLayer } from "../../../utils"; -import { autoBind } from "../../../utils"; +import type { StorageLayer } from "../../../utils/storage-helper"; import type { NodeStore } from "../../+nodes/store"; import type { ClusterMetricData, RequestClusterMetricsByNodeNames } from "../../../../common/k8s-api/endpoints/metrics.api/request-cluster-metrics-by-node-names.injectable"; import type { RequestMetricsParams } from "../../../../common/k8s-api/endpoints/metrics.api/request-metrics.injectable"; import { normalizeMetrics } from "../../../../common/k8s-api/endpoints/metrics.api"; +import autoBind from "auto-bind"; export enum MetricType { MEMORY = "memory", diff --git a/packages/core/src/renderer/components/+cluster/cluster-overview.tsx b/packages/core/src/renderer/components/+cluster/cluster-overview.tsx index f1cb9ad461..516a2f9114 100644 --- a/packages/core/src/renderer/components/+cluster/cluster-overview.tsx +++ b/packages/core/src/renderer/components/+cluster/cluster-overview.tsx @@ -6,11 +6,12 @@ import styles from "./cluster-overview.module.scss"; import React from "react"; +import type { IComputedValue } from "mobx"; import { reaction } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; import type { NodeStore } from "../+nodes/store"; import type { PodStore } from "../+workloads-pods/store"; -import { interval } from "../../utils"; +import { interval } from "@k8slens/utilities"; import { TabLayout } from "../layout/tab-layout"; import { Spinner } from "../spinner"; import { ClusterIssues } from "./cluster-issues"; @@ -22,32 +23,30 @@ import type { EventStore } from "../+events/store"; import { withInjectables } from "@ogre-tools/injectable-react"; import clusterOverviewStoreInjectable from "./cluster-overview-store/cluster-overview-store.injectable"; import type { SubscribeStores } from "../../kube-watch-api/kube-watch-api"; -import type { Cluster } from "../../../common/cluster/cluster"; -import hostedClusterInjectable from "../../cluster-frame-context/hosted-cluster.injectable"; -import assert from "assert"; import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable"; import podStoreInjectable from "../+workloads-pods/store.injectable"; import eventStoreInjectable from "../+events/store.injectable"; import nodeStoreInjectable from "../+nodes/store.injectable"; +import enabledMetricsInjectable from "../../api/catalog/entity/metrics-enabled.injectable"; interface Dependencies { subscribeStores: SubscribeStores; clusterOverviewStore: ClusterOverviewStore; - hostedCluster: Cluster; podStore: PodStore; eventStore: EventStore; nodeStore: NodeStore; + clusterMetricsAreVisible: IComputedValue; } @observer class NonInjectedClusterOverview extends React.Component { - private metricPoller = interval(60, () => this.loadMetrics()); - - loadMetrics() { - if (this.props.hostedCluster.available) { - this.props.clusterOverviewStore.loadMetrics(); + private readonly metricPoller = interval(60, async () => { + try { + await this.props.clusterOverviewStore.loadMetrics(); + } catch { + // ignore } - } + }); componentDidMount() { this.metricPoller.start(true); @@ -97,14 +96,13 @@ class NonInjectedClusterOverview extends React.Component { } render() { - const { eventStore, nodeStore, hostedCluster } = this.props; + const { eventStore, nodeStore, clusterMetricsAreVisible } = this.props; const isLoaded = nodeStore.isLoaded && eventStore.isLoaded; - const isMetricHidden = hostedCluster.isMetricHidden(ClusterMetricsResourceType.Cluster); return (
- {this.renderClusterOverview(isLoaded, isMetricHidden)} + {this.renderClusterOverview(isLoaded, clusterMetricsAreVisible.get())}
); @@ -112,18 +110,12 @@ class NonInjectedClusterOverview extends React.Component { } export const ClusterOverview = withInjectables(NonInjectedClusterOverview, { - getProps: (di) => { - const hostedCluster = di.inject(hostedClusterInjectable); - - assert(hostedCluster, "Only allowed to renderer ClusterOverview within cluster frame"); - - return { - subscribeStores: di.inject(subscribeStoresInjectable), - clusterOverviewStore: di.inject(clusterOverviewStoreInjectable), - hostedCluster, - podStore: di.inject(podStoreInjectable), - eventStore: di.inject(eventStoreInjectable), - nodeStore: di.inject(nodeStoreInjectable), - }; - }, + getProps: (di) => ({ + subscribeStores: di.inject(subscribeStoresInjectable), + clusterOverviewStore: di.inject(clusterOverviewStoreInjectable), + clusterMetricsAreVisible: di.inject(enabledMetricsInjectable, ClusterMetricsResourceType.Cluster), + podStore: di.inject(podStoreInjectable), + eventStore: di.inject(eventStoreInjectable), + nodeStore: di.inject(nodeStoreInjectable), + }), }); diff --git a/packages/core/src/renderer/components/+cluster/cluster-pie-charts.tsx b/packages/core/src/renderer/components/+cluster/cluster-pie-charts.tsx index e0203dd878..6ae370f052 100644 --- a/packages/core/src/renderer/components/+cluster/cluster-pie-charts.tsx +++ b/packages/core/src/renderer/components/+cluster/cluster-pie-charts.tsx @@ -15,7 +15,7 @@ import type { NodeStore } from "../+nodes/store"; import type { PieChartData } from "../chart"; import { PieChart } from "../chart"; import { ClusterNoMetrics } from "./cluster-no-metrics"; -import { bytesToUnits, cssNames } from "../../utils"; +import { bytesToUnits, cssNames } from "@k8slens/utilities"; import type { LensTheme } from "../../themes/lens-theme"; import { getMetricLastPoints } from "../../../common/k8s-api/endpoints/metrics.api"; import { withInjectables } from "@ogre-tools/injectable-react"; diff --git a/packages/core/src/renderer/components/+config-horizontal-pod-autoscalers/hpa-details.tsx b/packages/core/src/renderer/components/+config-horizontal-pod-autoscalers/hpa-details.tsx index 49130991a5..d57c8a3323 100644 --- a/packages/core/src/renderer/components/+config-horizontal-pod-autoscalers/hpa-details.tsx +++ b/packages/core/src/renderer/components/+config-horizontal-pod-autoscalers/hpa-details.tsx @@ -11,7 +11,7 @@ import { Link } from "react-router-dom"; import { DrawerItem, DrawerTitle } from "../drawer"; import { Badge } from "../badge"; import type { KubeObjectDetailsProps } from "../kube-object-details"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import type { HorizontalPodAutoscalerMetricSpec, HorizontalPodAutoscalerMetricTarget } from "../../../common/k8s-api/endpoints/horizontal-pod-autoscaler.api"; import { HorizontalPodAutoscaler, HpaMetricType } from "../../../common/k8s-api/endpoints/horizontal-pod-autoscaler.api"; import { Table, TableCell, TableHead, TableRow } from "../table"; diff --git a/packages/core/src/renderer/components/+config-horizontal-pod-autoscalers/hpa.tsx b/packages/core/src/renderer/components/+config-horizontal-pod-autoscalers/hpa.tsx index e7a456b3f1..68ee6671d7 100644 --- a/packages/core/src/renderer/components/+config-horizontal-pod-autoscalers/hpa.tsx +++ b/packages/core/src/renderer/components/+config-horizontal-pod-autoscalers/hpa.tsx @@ -10,7 +10,7 @@ import { observer } from "mobx-react"; import { KubeObjectListLayout } from "../kube-object-list-layout"; import type { HorizontalPodAutoscaler } from "../../../common/k8s-api/endpoints/horizontal-pod-autoscaler.api"; import { Badge } from "../badge"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; import { SiblingsInTabLayout } from "../layout/siblings-in-tab-layout"; import { KubeObjectAge } from "../kube-object/age"; diff --git a/packages/core/src/renderer/components/+config-priority-classes/priority-classes.tsx b/packages/core/src/renderer/components/+config-priority-classes/priority-classes.tsx index 4706fd0269..23a1dc6267 100644 --- a/packages/core/src/renderer/components/+config-priority-classes/priority-classes.tsx +++ b/packages/core/src/renderer/components/+config-priority-classes/priority-classes.tsx @@ -13,10 +13,10 @@ import type { KubeObjectDetailsProps } from "../kube-object-details"; import { KubeObjectListLayout } from "../kube-object-list-layout"; import { SiblingsInTabLayout } from "../layout/siblings-in-tab-layout"; import { KubeObjectAge } from "../kube-object/age"; -import { autoBind } from "../../../common/utils"; import { withInjectables } from "@ogre-tools/injectable-react"; import priorityClassStoreInjectable from "./store.injectable"; import type { PriorityClassStore } from "./store"; +import autoBindReact from "auto-bind/react"; enum columnId { name = "name", @@ -36,7 +36,7 @@ interface Dependencies { class NonInjectedPriorityClasses extends React.Component { constructor(props: PriorityClassesProps & Dependencies) { super(props); - autoBind(this); + autoBindReact(this); } render() { diff --git a/packages/core/src/renderer/components/+config-resource-quotas/resource-quota-details.tsx b/packages/core/src/renderer/components/+config-resource-quotas/resource-quota-details.tsx index 55ae188cbf..c032de2a25 100644 --- a/packages/core/src/renderer/components/+config-resource-quotas/resource-quota-details.tsx +++ b/packages/core/src/renderer/components/+config-resource-quotas/resource-quota-details.tsx @@ -8,7 +8,7 @@ import React from "react"; import kebabCase from "lodash/kebabCase"; import { observer } from "mobx-react"; import { DrawerItem, DrawerTitle } from "../drawer"; -import { cpuUnitsToNumber, cssNames, unitsToBytes, metricUnitsToNumber, object, hasDefinedTupleValue } from "../../utils"; +import { cpuUnitsToNumber, cssNames, unitsToBytes, metricUnitsToNumber, object, hasDefinedTupleValue } from "@k8slens/utilities"; import type { KubeObjectDetailsProps } from "../kube-object-details"; import { ResourceQuota } from "../../../common/k8s-api/endpoints/resource-quota.api"; import { LineProgress } from "../line-progress"; diff --git a/packages/core/src/renderer/components/+config-runtime-classes/runtime-classes.tsx b/packages/core/src/renderer/components/+config-runtime-classes/runtime-classes.tsx index 990912f2d4..d66c9da92f 100644 --- a/packages/core/src/renderer/components/+config-runtime-classes/runtime-classes.tsx +++ b/packages/core/src/renderer/components/+config-runtime-classes/runtime-classes.tsx @@ -13,10 +13,10 @@ import type { KubeObjectDetailsProps } from "../kube-object-details"; import { KubeObjectListLayout } from "../kube-object-list-layout"; import { SiblingsInTabLayout } from "../layout/siblings-in-tab-layout"; import { KubeObjectAge } from "../kube-object/age"; -import { autoBind } from "../../../common/utils"; import { withInjectables } from "@ogre-tools/injectable-react"; import runtimeClassStoreInjectable from "./store.injectable"; import type { RuntimeClassStore } from "./store"; +import autoBindReact from "auto-bind/react"; enum columnId { name = "name", @@ -35,7 +35,7 @@ interface Dependencies { class NonInjectedRuntimeClasses extends React.Component { constructor(props: RuntimeClassesProps & Dependencies) { super(props); - autoBind(this); + autoBindReact(this); } render() { diff --git a/packages/core/src/renderer/components/+config-secrets/__tests__/secret-details.test.tsx b/packages/core/src/renderer/components/+config-secrets/__tests__/secret-details.test.tsx index ddd5604785..e110056ab0 100644 --- a/packages/core/src/renderer/components/+config-secrets/__tests__/secret-details.test.tsx +++ b/packages/core/src/renderer/components/+config-secrets/__tests__/secret-details.test.tsx @@ -11,8 +11,8 @@ import { renderFor } from "../../test-utils/renderFor"; import storesAndApisCanBeCreatedInjectable from "../../../stores-apis-can-be-created.injectable"; import directoryForUserDataInjectable from "../../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; import hostedClusterInjectable from "../../../cluster-frame-context/hosted-cluster.injectable"; -import createClusterInjectable from "../../../cluster/create-cluster.injectable"; import directoryForKubeConfigsInjectable from "../../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable"; +import { Cluster } from "../../../../common/cluster/cluster"; jest.mock("../../kube-object-meta/kube-object-meta", () => ({ KubeObjectMeta: () => null, @@ -27,9 +27,7 @@ describe("SecretDetails tests", () => { di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs"); di.override(storesAndApisCanBeCreatedInjectable, () => true); - const createCluster = di.inject(createClusterInjectable); - - di.override(hostedClusterInjectable, () => createCluster({ + di.override(hostedClusterInjectable, () => new Cluster({ contextName: "some-context-name", id: "some-cluster-id", kubeConfigPath: "/some-path-to-a-kubeconfig", diff --git a/packages/core/src/renderer/components/+config-secrets/add-dialog/view.tsx b/packages/core/src/renderer/components/+config-secrets/add-dialog/view.tsx index cf68db93be..e25fe172b6 100644 --- a/packages/core/src/renderer/components/+config-secrets/add-dialog/view.tsx +++ b/packages/core/src/renderer/components/+config-secrets/add-dialog/view.tsx @@ -20,9 +20,8 @@ import { SubTitle } from "../../layout/sub-title"; import { NamespaceSelect } from "../../+namespaces/namespace-select"; import { Select } from "../../select"; import { Icon } from "../../icon"; -import { base64, iter } from "../../../utils"; +import { base64, iter, object } from "@k8slens/utilities"; import upperFirst from "lodash/upperFirst"; -import { fromEntries } from "../../../../common/utils/objects"; import type { ShowDetails } from "../../kube-detail-params/show-details.injectable"; import { withInjectables } from "@ogre-tools/injectable-react"; import closeAddSecretDialogInjectable from "./close.injectable"; @@ -96,7 +95,7 @@ class NonInjectedAddSecretDialog extends React.Component { diff --git a/packages/core/src/renderer/components/+config-secrets/secret-details.tsx b/packages/core/src/renderer/components/+config-secrets/secret-details.tsx index 6b4873f187..57a7a51063 100644 --- a/packages/core/src/renderer/components/+config-secrets/secret-details.tsx +++ b/packages/core/src/renderer/components/+config-secrets/secret-details.tsx @@ -12,7 +12,7 @@ import { DrawerItem, DrawerTitle } from "../drawer"; import { Input } from "../input"; import { Button } from "../button"; import type { ShowNotification } from "../notifications"; -import { base64, toggle } from "../../utils"; +import { base64, toggle } from "@k8slens/utilities"; import { Icon } from "../icon"; import type { KubeObjectDetailsProps } from "../kube-object-details"; import { Secret } from "../../../common/k8s-api/endpoints"; diff --git a/packages/core/src/renderer/components/+config-vertical-pod-autoscalers/vpa-details.tsx b/packages/core/src/renderer/components/+config-vertical-pod-autoscalers/vpa-details.tsx index f008fe3350..532ecf39aa 100644 --- a/packages/core/src/renderer/components/+config-vertical-pod-autoscalers/vpa-details.tsx +++ b/packages/core/src/renderer/components/+config-vertical-pod-autoscalers/vpa-details.tsx @@ -12,7 +12,7 @@ import { Link } from "react-router-dom"; import { DrawerItem, DrawerTitle } from "../drawer"; import { Badge } from "../badge"; import type { KubeObjectDetailsProps } from "../kube-object-details"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import { ContainerScalingMode, ControlledValues, ResourceName, UpdateMode, VerticalPodAutoscaler } from "../../../common/k8s-api/endpoints/vertical-pod-autoscaler.api"; import type { PodUpdatePolicy, PodResourcePolicy, VerticalPodAutoscalerStatus } from "../../../common/k8s-api/endpoints/vertical-pod-autoscaler.api"; import type { ApiManager } from "../../../common/k8s-api/api-manager"; @@ -165,7 +165,7 @@ class NonInjectedVpaDetails extends React.Component ); } - + render() { const { object: vpa, apiManager, getDetailsUrl, logger } = this.props; diff --git a/packages/core/src/renderer/components/+config-vertical-pod-autoscalers/vpa.tsx b/packages/core/src/renderer/components/+config-vertical-pod-autoscalers/vpa.tsx index b2bdb4d249..05e3b8cc47 100644 --- a/packages/core/src/renderer/components/+config-vertical-pod-autoscalers/vpa.tsx +++ b/packages/core/src/renderer/components/+config-vertical-pod-autoscalers/vpa.tsx @@ -9,7 +9,7 @@ import React from "react"; import { observer } from "mobx-react"; import { KubeObjectListLayout } from "../kube-object-list-layout"; import { Badge } from "../badge"; -import { cssNames, prevDefault } from "../../utils"; +import { cssNames, prevDefault } from "@k8slens/utilities"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; import { SiblingsInTabLayout } from "../layout/siblings-in-tab-layout"; import { KubeObjectAge } from "../kube-object/age"; diff --git a/packages/core/src/renderer/components/+custom-resources/crd-list.tsx b/packages/core/src/renderer/components/+custom-resources/crd-list.tsx index 669ca3e374..3008ca175e 100644 --- a/packages/core/src/renderer/components/+custom-resources/crd-list.tsx +++ b/packages/core/src/renderer/components/+custom-resources/crd-list.tsx @@ -9,7 +9,7 @@ import React from "react"; import { computed, makeObservable, observable } from "mobx"; import { observer } from "mobx-react"; import { Link } from "react-router-dom"; -import { iter, stopPropagation } from "../../utils"; +import { iter, stopPropagation } from "@k8slens/utilities"; import { KubeObjectListLayout } from "../kube-object-list-layout"; import { Select } from "../select"; import { Icon } from "../icon"; diff --git a/packages/core/src/renderer/components/+custom-resources/crd-resource-details.tsx b/packages/core/src/renderer/components/+custom-resources/crd-resource-details.tsx index 149812f663..6b899563a9 100644 --- a/packages/core/src/renderer/components/+custom-resources/crd-resource-details.tsx +++ b/packages/core/src/renderer/components/+custom-resources/crd-resource-details.tsx @@ -7,14 +7,13 @@ import "./crd-resource-details.scss"; import React from "react"; import { observer } from "mobx-react"; -import { cssNames } from "../../utils"; +import { cssNames, safeJSONPathValue } from "@k8slens/utilities"; import { Badge } from "../badge"; import { DrawerItem } from "../drawer"; import type { KubeObjectDetailsProps } from "../kube-object-details"; import { Input } from "../input"; import type { AdditionalPrinterColumnsV1 } from "../../../common/k8s-api/endpoints/custom-resource-definition.api"; import { CustomResourceDefinition } from "../../../common/k8s-api/endpoints/custom-resource-definition.api"; -import { safeJSONPathValue } from "../../utils/jsonPath"; import type { KubeObjectMetadata, KubeObjectStatus } from "../../../common/k8s-api/kube-object"; import { KubeObject } from "../../../common/k8s-api/kube-object"; import type { Logger } from "../../../common/logger"; diff --git a/packages/core/src/renderer/components/+custom-resources/crd-resources.tsx b/packages/core/src/renderer/components/+custom-resources/crd-resources.tsx index 3cd0864c36..3f89254d2a 100644 --- a/packages/core/src/renderer/components/+custom-resources/crd-resources.tsx +++ b/packages/core/src/renderer/components/+custom-resources/crd-resources.tsx @@ -11,7 +11,7 @@ import { KubeObjectListLayout } from "../kube-object-list-layout"; import type { IComputedValue } from "mobx"; import { computed, makeObservable } from "mobx"; import type { ApiManager } from "../../../common/k8s-api/api-manager"; -import { formatJSONValue, safeJSONPathValue } from "../../utils/jsonPath"; +import { formatJSONValue, safeJSONPathValue } from "@k8slens/utilities"; import { TabLayout } from "../layout/tab-layout-2"; import { withInjectables } from "@ogre-tools/injectable-react"; import customResourcesRouteParametersInjectable from "./custom-resources-route-parameters.injectable"; 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 bef5c2323e..310e51709a 100644 --- a/packages/core/src/renderer/components/+custom-resources/definition.store.ts +++ b/packages/core/src/renderer/components/+custom-resources/definition.store.ts @@ -6,11 +6,11 @@ import { computed, reaction, makeObservable } from "mobx"; import type { KubeObjectStoreDependencies, KubeObjectStoreOptions } from "../../../common/k8s-api/kube-object.store"; import { KubeObjectStore } from "../../../common/k8s-api/kube-object.store"; -import { autoBind } from "../../utils"; 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; diff --git a/packages/core/src/renderer/components/+events/event-details.tsx b/packages/core/src/renderer/components/+events/event-details.tsx index afe2af1dc5..1e825993c4 100644 --- a/packages/core/src/renderer/components/+events/event-details.tsx +++ b/packages/core/src/renderer/components/+events/event-details.tsx @@ -20,7 +20,7 @@ import { withInjectables } from "@ogre-tools/injectable-react"; import type { GetDetailsUrl } from "../kube-detail-params/get-details-url.injectable"; import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable"; import getDetailsUrlInjectable from "../kube-detail-params/get-details-url.injectable"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import loggerInjectable from "../../../common/logger.injectable"; export interface EventDetailsProps extends KubeObjectDetailsProps { diff --git a/packages/core/src/renderer/components/+events/events.tsx b/packages/core/src/renderer/components/+events/events.tsx index d68bb21a53..657e10436d 100644 --- a/packages/core/src/renderer/components/+events/events.tsx +++ b/packages/core/src/renderer/components/+events/events.tsx @@ -18,8 +18,8 @@ import type { TableSortCallbacks, TableSortParams } from "../table"; import type { HeaderCustomizer } from "../item-object-list"; import { Tooltip } from "../tooltip"; import { Link } from "react-router-dom"; -import type { IClassName } from "../../utils"; -import { cssNames, stopPropagation } from "../../utils"; +import type { IClassName } from "@k8slens/utilities"; +import { cssNames, stopPropagation } from "@k8slens/utilities"; import { Icon } from "../icon"; import type { ApiManager } from "../../../common/k8s-api/api-manager"; import { withInjectables } from "@ogre-tools/injectable-react"; diff --git a/packages/core/src/renderer/components/+events/kube-event-details.tsx b/packages/core/src/renderer/components/+events/kube-event-details.tsx index 80c6938630..76010a8e14 100644 --- a/packages/core/src/renderer/components/+events/kube-event-details.tsx +++ b/packages/core/src/renderer/components/+events/kube-event-details.tsx @@ -9,7 +9,7 @@ import React from "react"; import { disposeOnUnmount, observer } from "mobx-react"; import { KubeObject } from "../../../common/k8s-api/kube-object"; import { DrawerItem, DrawerTitle } from "../drawer"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import { LocaleDate } from "../locale-date"; import type { EventStore } from "./store"; import type { Logger } from "../../../common/logger"; diff --git a/packages/core/src/renderer/components/+events/kube-event-icon.tsx b/packages/core/src/renderer/components/+events/kube-event-icon.tsx index 659a65ae39..7a68d951b4 100644 --- a/packages/core/src/renderer/components/+events/kube-event-icon.tsx +++ b/packages/core/src/renderer/components/+events/kube-event-icon.tsx @@ -8,7 +8,7 @@ import "./kube-event-icon.scss"; import React from "react"; import { Icon } from "../icon"; import type { KubeObject } from "../../../common/k8s-api/kube-object"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import type { KubeEvent } from "../../../common/k8s-api/endpoints/events.api"; import { KubeObjectAge } from "../kube-object/age"; import type { EventStore } from "./store"; diff --git a/packages/core/src/renderer/components/+events/store.ts b/packages/core/src/renderer/components/+events/store.ts index 3bb9e0b062..7e14110049 100644 --- a/packages/core/src/renderer/components/+events/store.ts +++ b/packages/core/src/renderer/components/+events/store.ts @@ -7,11 +7,11 @@ import groupBy from "lodash/groupBy"; import compact from "lodash/compact"; import type { KubeObjectStoreDependencies, KubeObjectStoreOptions } from "../../../common/k8s-api/kube-object.store"; import { KubeObjectStore } from "../../../common/k8s-api/kube-object.store"; -import { autoBind } from "../../utils"; import type { KubeEvent, KubeEventApi } from "../../../common/k8s-api/endpoints/events.api"; import type { KubeObject } from "../../../common/k8s-api/kube-object"; import { Pod } from "../../../common/k8s-api/endpoints/pod.api"; import type { GetPodById } from "../+workloads-pods/get-pod-by-id.injectable"; +import autoBind from "auto-bind"; export interface EventStoreDependencies extends KubeObjectStoreDependencies { getPodById: GetPodById; 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 1f3d65c802..523a91596e 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 @@ -2,7 +2,7 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { isObject } from "../../../common/utils"; +import { isObject } from "@k8slens/utilities"; import React from "react"; import { SemVer } from "semver"; import URLParse from "url-parse"; diff --git a/packages/core/src/renderer/components/+extensions/attempt-install/attempt-install.injectable.tsx b/packages/core/src/renderer/components/+extensions/attempt-install/attempt-install.injectable.tsx index 47b18a3772..589c4b704e 100644 --- a/packages/core/src/renderer/components/+extensions/attempt-install/attempt-install.injectable.tsx +++ b/packages/core/src/renderer/components/+extensions/attempt-install/attempt-install.injectable.tsx @@ -12,8 +12,8 @@ import getExtensionDestFolderInjectable from "./get-extension-dest-folder.inject import type { CreateTempFilesAndValidate } from "./create-temp-files-and-validate.injectable"; import createTempFilesAndValidateInjectable from "./create-temp-files-and-validate.injectable"; import extensionInstallationStateStoreInjectable from "../../../../extensions/extension-installation-state-store/extension-installation-state-store.injectable"; -import type { Disposer } from "../../../../common/utils"; -import { disposer } from "../../../../common/utils"; +import type { Disposer } from "@k8slens/utilities"; +import { disposer } from "@k8slens/utilities"; import type { ShowNotification } from "../../notifications"; import { Button } from "../../button"; import type { ExtensionLoader } from "../../../../extensions/extension-loader"; diff --git a/packages/core/src/renderer/components/+extensions/attempt-install/unpack-extension.injectable.tsx b/packages/core/src/renderer/components/+extensions/attempt-install/unpack-extension.injectable.tsx index c81a69f9b0..5317fbfc48 100644 --- a/packages/core/src/renderer/components/+extensions/attempt-install/unpack-extension.injectable.tsx +++ b/packages/core/src/renderer/components/+extensions/attempt-install/unpack-extension.injectable.tsx @@ -6,8 +6,8 @@ import { getInjectable } from "@ogre-tools/injectable"; import extensionLoaderInjectable from "../../../../extensions/extension-loader/extension-loader.injectable"; import getExtensionDestFolderInjectable from "./get-extension-dest-folder.injectable"; import extensionInstallationStateStoreInjectable from "../../../../extensions/extension-installation-state-store/extension-installation-state-store.injectable"; -import type { Disposer } from "../../../../common/utils"; -import { noop } from "../../../../common/utils"; +import type { Disposer } from "@k8slens/utilities"; +import { noop } from "@k8slens/utilities"; import { extensionDisplayName } from "../../../../extensions/lens-extension"; import { getMessageFromError } from "../get-message-from-error/get-message-from-error"; import path from "path"; diff --git a/packages/core/src/renderer/components/+extensions/attempt-install/validate-package.tsx b/packages/core/src/renderer/components/+extensions/attempt-install/validate-package.tsx index e9597b2d10..ee30bda6b4 100644 --- a/packages/core/src/renderer/components/+extensions/attempt-install/validate-package.tsx +++ b/packages/core/src/renderer/components/+extensions/attempt-install/validate-package.tsx @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import type { LensExtensionManifest } from "../../../../extensions/lens-extension"; -import { hasTypedProperty, isObject, isString, listTarEntries, readFileFromTar } from "../../../../common/utils"; +import { hasTypedProperty, isObject, isString, listTarEntries, readFileFromTar } from "@k8slens/utilities"; import { manifestFilename } from "../../../../extensions/extension-discovery/extension-discovery"; import path from "path"; diff --git a/packages/core/src/renderer/components/+extensions/get-message-from-error/get-message-from-error.ts b/packages/core/src/renderer/components/+extensions/get-message-from-error/get-message-from-error.ts index ecbb4f9145..ecebfb6e80 100644 --- a/packages/core/src/renderer/components/+extensions/get-message-from-error/get-message-from-error.ts +++ b/packages/core/src/renderer/components/+extensions/get-message-from-error/get-message-from-error.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { hasTypedProperty, isDefined } from "../../../utils"; +import { hasTypedProperty, isDefined } from "@k8slens/utilities"; export function getMessageFromError(error: unknown): string { if (!error || typeof error !== "object") { diff --git a/packages/core/src/renderer/components/+extensions/install-extension-from-input.injectable.tsx b/packages/core/src/renderer/components/+extensions/install-extension-from-input.injectable.tsx index 3f9e5b0949..e879599299 100644 --- a/packages/core/src/renderer/components/+extensions/install-extension-from-input.injectable.tsx +++ b/packages/core/src/renderer/components/+extensions/install-extension-from-input.injectable.tsx @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import React from "react"; -import type { ExtendableDisposer } from "../../../common/utils"; +import type { ExtendableDisposer } from "@k8slens/utilities"; import { InputValidators } from "../input"; import { getMessageFromError } from "./get-message-from-error/get-message-from-error"; import { getInjectable } from "@ogre-tools/injectable"; diff --git a/packages/core/src/renderer/components/+extensions/install.tsx b/packages/core/src/renderer/components/+extensions/install.tsx index 7572063796..63c09f8b18 100644 --- a/packages/core/src/renderer/components/+extensions/install.tsx +++ b/packages/core/src/renderer/components/+extensions/install.tsx @@ -5,7 +5,7 @@ import styles from "./install.module.scss"; import React from "react"; -import { prevDefault } from "../../utils"; +import { prevDefault } from "@k8slens/utilities"; import { Button } from "../button"; import { Icon } from "../icon"; import { observer } from "mobx-react"; diff --git a/packages/core/src/renderer/components/+extensions/installed-extensions.tsx b/packages/core/src/renderer/components/+extensions/installed-extensions.tsx index 60579ca3ec..8447f0656f 100644 --- a/packages/core/src/renderer/components/+extensions/installed-extensions.tsx +++ b/packages/core/src/renderer/components/+extensions/installed-extensions.tsx @@ -13,7 +13,7 @@ import { Icon } from "../icon"; import { List } from "../list/list"; import { MenuActions, MenuItem } from "../menu"; import { Spinner } from "../spinner"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import { observer } from "mobx-react"; import type { Row } from "react-table"; import type { LensExtensionId } from "../../../extensions/lens-extension"; diff --git a/packages/core/src/renderer/components/+extensions/notice.tsx b/packages/core/src/renderer/components/+extensions/notice.tsx index 6626a2233a..af4de297c2 100644 --- a/packages/core/src/renderer/components/+extensions/notice.tsx +++ b/packages/core/src/renderer/components/+extensions/notice.tsx @@ -6,7 +6,7 @@ import styles from "./notice.module.scss"; import type { DOMAttributes } from "react"; import React from "react"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; export interface NoticeProps extends DOMAttributes { className?: string; diff --git a/packages/core/src/renderer/components/+helm-charts/helm-chart-details.tsx b/packages/core/src/renderer/components/+helm-charts/helm-chart-details.tsx index cf2b781e66..2004a8704c 100644 --- a/packages/core/src/renderer/components/+helm-charts/helm-chart-details.tsx +++ b/packages/core/src/renderer/components/+helm-charts/helm-chart-details.tsx @@ -9,7 +9,7 @@ import React, { Component } from "react"; import type { HelmChart } from "../../../common/k8s-api/endpoints/helm-charts.api"; import { observer } from "mobx-react"; import { Drawer, DrawerItem } from "../drawer"; -import { autoBind, stopPropagation } from "../../utils"; +import { stopPropagation } from "@k8slens/utilities"; import { MarkdownViewer } from "../markdown-viewer"; import { Spinner } from "../spinner"; import { Button } from "../button"; @@ -25,6 +25,7 @@ import versionsOfSelectedHelmChartInjectable from "./details/versions-of-selecte import type { HelmChartDetailsVersionSelection } from "./details/versions/helm-chart-details-version-selection.injectable"; import helmChartDetailsVersionSelectionInjectable from "./details/versions/helm-chart-details-version-selection.injectable"; import assert from "assert"; +import autoBindReact from "auto-bind/react"; export interface HelmChartDetailsProps { hideDetails(): void; @@ -48,7 +49,7 @@ interface Dependencies { class NonInjectedHelmChartDetails extends Component { constructor(props: HelmChartDetailsProps & Dependencies) { super(props); - autoBind(this); + autoBindReact(this); } get chart() { diff --git a/packages/core/src/renderer/components/+helm-charts/helm-charts/request-versions-of-chart-for-release.injectable.ts b/packages/core/src/renderer/components/+helm-charts/helm-charts/request-versions-of-chart-for-release.injectable.ts index b49d94fb10..ab646d3b03 100644 --- a/packages/core/src/renderer/components/+helm-charts/helm-charts/request-versions-of-chart-for-release.injectable.ts +++ b/packages/core/src/renderer/components/+helm-charts/helm-charts/request-versions-of-chart-for-release.injectable.ts @@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { HelmChart } from "../../../../common/k8s-api/endpoints/helm-charts.api"; import requestHelmChartVersionsInjectable from "../../../../common/k8s-api/endpoints/helm-charts.api/request-versions.injectable"; import type { HelmRelease } from "../../../../common/k8s-api/endpoints/helm-releases.api"; -import { sortBySemverVersion } from "../../../utils"; +import { sortBySemverVersion } from "@k8slens/utilities"; import type { HelmChartVersion } from "./versions"; /** diff --git a/packages/core/src/renderer/components/+helm-releases/release-details/release-details-content.tsx b/packages/core/src/renderer/components/+helm-releases/release-details/release-details-content.tsx index ebfb51c6ef..5f7a3bda70 100644 --- a/packages/core/src/renderer/components/+helm-releases/release-details/release-details-content.tsx +++ b/packages/core/src/renderer/components/+helm-releases/release-details/release-details-content.tsx @@ -9,7 +9,7 @@ import React from "react"; import { Link } from "react-router-dom"; import { DrawerItem, DrawerTitle } from "../../drawer"; -import { stopPropagation } from "../../../utils"; +import { stopPropagation } from "@k8slens/utilities"; import { observer } from "mobx-react"; import { withInjectables } from "@ogre-tools/injectable-react"; import type { ConfigurationInput, MinimalResourceGroup, OnlyUserSuppliedValuesAreShownToggle, ReleaseDetailsModel } from "./release-details-model/release-details-model.injectable"; diff --git a/packages/core/src/renderer/components/+helm-releases/release-details/release-details-drawer.tsx b/packages/core/src/renderer/components/+helm-releases/release-details/release-details-drawer.tsx index 67676ce337..dc740c4c41 100644 --- a/packages/core/src/renderer/components/+helm-releases/release-details/release-details-drawer.tsx +++ b/packages/core/src/renderer/components/+helm-releases/release-details/release-details-drawer.tsx @@ -8,7 +8,7 @@ import "./release-details.scss"; import React from "react"; import { Drawer } from "../../drawer"; -import { cssNames } from "../../../utils"; +import { cssNames } from "@k8slens/utilities"; import { observer } from "mobx-react"; import { withInjectables } from "@ogre-tools/injectable-react"; import type { TargetHelmRelease } from "./target-helm-release.injectable"; diff --git a/packages/core/src/renderer/components/+helm-releases/release-details/release-details-model/request-detailed-helm-release.injectable.ts b/packages/core/src/renderer/components/+helm-releases/release-details/release-details-model/request-detailed-helm-release.injectable.ts index aa5a2e9121..43125a87b0 100644 --- a/packages/core/src/renderer/components/+helm-releases/release-details/release-details-model/request-detailed-helm-release.injectable.ts +++ b/packages/core/src/renderer/components/+helm-releases/release-details/release-details-model/request-detailed-helm-release.injectable.ts @@ -7,7 +7,7 @@ import type { HelmReleaseDto } from "../../../../../common/k8s-api/endpoints/hel import requestHelmReleasesInjectable from "../../../../../common/k8s-api/endpoints/helm-releases.api/request-releases.injectable"; import type { HelmReleaseDetails } from "../../../../../common/k8s-api/endpoints/helm-releases.api/request-details.injectable"; import requestHelmReleaseDetailsInjectable from "../../../../../common/k8s-api/endpoints/helm-releases.api/request-details.injectable"; -import type { AsyncResult } from "../../../../../common/utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; export interface DetailedHelmRelease { release: HelmReleaseDto; @@ -17,7 +17,7 @@ export interface DetailedHelmRelease { export type RequestDetailedHelmRelease = ( name: string, namespace: string -) => Promise>; +) => AsyncResult; const requestDetailedHelmReleaseInjectable = getInjectable({ id: "request-detailed-helm-release", diff --git a/packages/core/src/renderer/components/+helm-releases/release-menu.tsx b/packages/core/src/renderer/components/+helm-releases/release-menu.tsx index 694dd69b3c..be40e59b11 100644 --- a/packages/core/src/renderer/components/+helm-releases/release-menu.tsx +++ b/packages/core/src/renderer/components/+helm-releases/release-menu.tsx @@ -5,7 +5,7 @@ import React from "react"; import type { HelmRelease } from "../../../common/k8s-api/endpoints/helm-releases.api"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import type { MenuActionsProps } from "../menu/menu-actions"; import { MenuActions } from "../menu/menu-actions"; import { MenuItem } from "../menu"; diff --git a/packages/core/src/renderer/components/+helm-releases/to-helm-release.injectable.ts b/packages/core/src/renderer/components/+helm-releases/to-helm-release.injectable.ts index d8b27625e6..d069eb5929 100644 --- a/packages/core/src/renderer/components/+helm-releases/to-helm-release.injectable.ts +++ b/packages/core/src/renderer/components/+helm-releases/to-helm-release.injectable.ts @@ -8,7 +8,7 @@ import { when } from "mobx"; import helmChartVersionsInjectable from "../+helm-charts/helm-charts/versions.injectable"; import type { HelmRelease, HelmReleaseDto } from "../../../common/k8s-api/endpoints/helm-releases.api"; import { getMillisecondsFromUnixEpoch } from "../../../common/utils/date/get-current-date-time"; -import { formatDuration } from "../../utils"; +import { formatDuration } from "@k8slens/utilities"; export type ToHelmRelease = (release: HelmReleaseDto) => HelmRelease; diff --git a/packages/core/src/renderer/components/+namespaces/add-dialog/dialog.tsx b/packages/core/src/renderer/components/+namespaces/add-dialog/dialog.tsx index 6f85253ce9..3dabbdf572 100644 --- a/packages/core/src/renderer/components/+namespaces/add-dialog/dialog.tsx +++ b/packages/core/src/renderer/components/+namespaces/add-dialog/dialog.tsx @@ -20,9 +20,9 @@ import namespaceStoreInjectable from "../store.injectable"; import addNamespaceDialogStateInjectable from "./state.injectable"; import type { NamespaceStore } from "../store"; -import { autoBind } from "../../../utils"; import type { ShowCheckedErrorNotification } from "../../notifications/show-checked-error.injectable"; import showCheckedErrorNotificationInjectable from "../../notifications/show-checked-error.injectable"; +import autoBindReact from "auto-bind/react"; export interface AddNamespaceDialogProps extends DialogProps { onSuccess?(ns: Namespace): void; @@ -42,7 +42,7 @@ class NonInjectedAddNamespaceDialog extends React.Component", () => { fetchMock = asyncFn(); di.override(fetchInjectable, () => fetchMock); - const createCluster = di.inject(createClusterInjectable); - - di.override(hostedClusterInjectable, () => createCluster({ + di.override(hostedClusterInjectable, () => new Cluster({ contextName: "some-context-name", id: "some-cluster-id", kubeConfigPath: "/some-path-to-a-kubeconfig", diff --git a/packages/core/src/renderer/components/+namespaces/namespace-select.tsx b/packages/core/src/renderer/components/+namespaces/namespace-select.tsx index baf2ba2d92..2e2c2926b8 100644 --- a/packages/core/src/renderer/components/+namespaces/namespace-select.tsx +++ b/packages/core/src/renderer/components/+namespaces/namespace-select.tsx @@ -10,7 +10,7 @@ import { computed } from "mobx"; import { observer } from "mobx-react"; import type { SelectProps } from "../select"; import { Select } from "../select"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import { Icon } from "../icon"; import { withInjectables } from "@ogre-tools/injectable-react"; import clusterFrameContextForNamespacedResourcesInjectable from "../../cluster-frame-context/for-namespaced-resources.injectable"; diff --git a/packages/core/src/renderer/components/+namespaces/namespace-store.test.ts b/packages/core/src/renderer/components/+namespaces/namespace-store.test.ts index 7e43118c1b..26491b36c1 100644 --- a/packages/core/src/renderer/components/+namespaces/namespace-store.test.ts +++ b/packages/core/src/renderer/components/+namespaces/namespace-store.test.ts @@ -11,13 +11,13 @@ import directoryForKubeConfigsInjectable from "../../../common/app-paths/directo import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; import type { Fetch } from "../../../common/fetch/fetch.injectable"; import fetchInjectable from "../../../common/fetch/fetch.injectable"; +import { Cluster } from "../../../common/cluster/cluster"; import { Namespace } from "../../../common/k8s-api/endpoints"; import namespaceApiInjectable from "../../../common/k8s-api/endpoints/namespace.api.injectable"; import type { DeleteResourceDescriptor } from "../../../common/k8s-api/kube-api"; import type { KubeJsonApiData } from "../../../common/k8s-api/kube-json-api"; import type { KubeJsonApiObjectMetadata, KubeObjectScope } from "../../../common/k8s-api/kube-object"; import hostedClusterInjectable from "../../cluster-frame-context/hosted-cluster.injectable"; -import createClusterInjectable from "../../cluster/create-cluster.injectable"; import { getDiForUnitTesting } from "../../getDiForUnitTesting"; import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable"; import removeSubnamespaceInjectable from "./remove-subnamespace.injectable"; @@ -134,9 +134,7 @@ describe("NamespaceStore", () => { delete: deleteNamespaceMock, } as any)); - const createCluster = di.inject(createClusterInjectable); - - di.override(hostedClusterInjectable, () => createCluster({ + di.override(hostedClusterInjectable, () => new Cluster({ contextName: "some-context-name", id: "some-cluster-id", kubeConfigPath: "/some-path-to-a-kubeconfig", diff --git a/packages/core/src/renderer/components/+namespaces/namespace-tree-view.tsx b/packages/core/src/renderer/components/+namespaces/namespace-tree-view.tsx index 8d69e1aba7..efb378c31b 100644 --- a/packages/core/src/renderer/components/+namespaces/namespace-tree-view.tsx +++ b/packages/core/src/renderer/components/+namespaces/namespace-tree-view.tsx @@ -16,7 +16,7 @@ import type { GetDetailsUrl } from "../kube-detail-params/get-details-url.inject import getDetailsUrlInjectable from "../kube-detail-params/get-details-url.injectable"; import { SubnamespaceBadge } from "./subnamespace-badge"; import hierarchicalNamespacesInjectable from "./hierarchical-namespaces.injectable"; -import { prevDefault } from "../../utils"; +import { prevDefault } from "@k8slens/utilities"; import type { NamespaceTree } from "./store"; interface NamespaceTreeViewProps { diff --git a/packages/core/src/renderer/components/+namespaces/store.ts b/packages/core/src/renderer/components/+namespaces/store.ts index 0d8e63c257..9337de28b6 100644 --- a/packages/core/src/renderer/components/+namespaces/store.ts +++ b/packages/core/src/renderer/components/+namespaces/store.ts @@ -5,12 +5,13 @@ import type { IComputedValue, IReactionDisposer } from "mobx"; import { action, comparer, computed, makeObservable, reaction } from "mobx"; -import type { StorageLayer } from "../../utils"; -import { autoBind, noop, toggle } from "../../utils"; +import type { StorageLayer } from "../../utils/storage-helper"; +import { noop, toggle } from "@k8slens/utilities"; import type { KubeObjectStoreDependencies, KubeObjectStoreLoadingParams } from "../../../common/k8s-api/kube-object.store"; import { KubeObjectStore } from "../../../common/k8s-api/kube-object.store"; import type { NamespaceApi } from "../../../common/k8s-api/endpoints/namespace.api"; import { Namespace } from "../../../common/k8s-api/endpoints/namespace.api"; +import autoBind from "auto-bind"; export interface NamespaceTree { id: string; diff --git a/packages/core/src/renderer/components/+namespaces/subnamespace-badge.tsx b/packages/core/src/renderer/components/+namespaces/subnamespace-badge.tsx index 4ae652acc6..74e7c02031 100644 --- a/packages/core/src/renderer/components/+namespaces/subnamespace-badge.tsx +++ b/packages/core/src/renderer/components/+namespaces/subnamespace-badge.tsx @@ -6,7 +6,7 @@ import styles from "./subnamespace-badge.module.scss"; import React from "react"; import { Tooltip } from "../tooltip"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; interface SubnamespaceBadgeProps extends React.HTMLAttributes { id: string; diff --git a/packages/core/src/renderer/components/+network-endpoints/endpoint-subset-list.tsx b/packages/core/src/renderer/components/+network-endpoints/endpoint-subset-list.tsx index 700f1fdbf8..11b353536c 100644 --- a/packages/core/src/renderer/components/+network-endpoints/endpoint-subset-list.tsx +++ b/packages/core/src/renderer/components/+network-endpoints/endpoint-subset-list.tsx @@ -11,11 +11,11 @@ import type { EndpointSubset, Endpoints, EndpointAddress } from "../../../common import { Table, TableCell, TableHead, TableRow } from "../table"; import type { ApiManager } from "../../../common/k8s-api/api-manager"; import { Link } from "react-router-dom"; -import { autoBind } from "../../../common/utils"; import { withInjectables } from "@ogre-tools/injectable-react"; import type { GetDetailsUrl } from "../kube-detail-params/get-details-url.injectable"; import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable"; import getDetailsUrlInjectable from "../kube-detail-params/get-details-url.injectable"; +import autoBindReact from "auto-bind/react"; export interface EndpointSubsetListProps { subset: Required; @@ -31,7 +31,7 @@ interface Dependencies { class NonInjectedEndpointSubsetList extends React.Component { constructor(props: EndpointSubsetListProps & Dependencies) { super(props); - autoBind(this); + autoBindReact(this); } getAddressTableRow(ip: string) { diff --git a/packages/core/src/renderer/components/+network-ingresses/ingress-classes.tsx b/packages/core/src/renderer/components/+network-ingresses/ingress-classes.tsx index 7b7fe8c0de..a4745e9a8f 100644 --- a/packages/core/src/renderer/components/+network-ingresses/ingress-classes.tsx +++ b/packages/core/src/renderer/components/+network-ingresses/ingress-classes.tsx @@ -13,7 +13,7 @@ import { withInjectables } from "@ogre-tools/injectable-react"; import type { IngressClassStore } from "./ingress-class-store"; import ingressClassStoreInjectable from "./ingress-class-store.injectable"; import type { IngressClass } from "../../../common/k8s-api/endpoints/ingress-class.api"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import { Icon } from "../icon"; enum columnId { diff --git a/packages/core/src/renderer/components/+network-port-forwards/port-forward-details.tsx b/packages/core/src/renderer/components/+network-port-forwards/port-forward-details.tsx index ba59ad7c10..b36ce40ea1 100644 --- a/packages/core/src/renderer/components/+network-port-forwards/port-forward-details.tsx +++ b/packages/core/src/renderer/components/+network-port-forwards/port-forward-details.tsx @@ -10,7 +10,7 @@ import { Link } from "react-router-dom"; import type { PortForwardItem } from "../../port-forward"; import { portForwardAddress } from "../../port-forward"; import { Drawer, DrawerItem } from "../drawer"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import type { PodApi, ServiceApi } from "../../../common/k8s-api/endpoints"; import { PortForwardMenu } from "./port-forward-menu"; import { withInjectables } from "@ogre-tools/injectable-react"; diff --git a/packages/core/src/renderer/components/+network-port-forwards/port-forward-menu.tsx b/packages/core/src/renderer/components/+network-port-forwards/port-forward-menu.tsx index 5fe46e1994..81e15b1746 100644 --- a/packages/core/src/renderer/components/+network-port-forwards/port-forward-menu.tsx +++ b/packages/core/src/renderer/components/+network-port-forwards/port-forward-menu.tsx @@ -4,7 +4,7 @@ */ import React from "react"; -import { autoBind, cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import type { PortForwardItem, PortForwardStore } from "../../port-forward"; import type { MenuActionsProps } from "../menu/menu-actions"; import { MenuActions } from "../menu/menu-actions"; @@ -17,6 +17,7 @@ import portForwardStoreInjectable from "../../port-forward/port-forward-store/po import type { OpenPortForward } from "../../port-forward/open-port-forward.injectable"; import openPortForwardInjectable from "../../port-forward/open-port-forward.injectable"; import showErrorNotificationInjectable from "../notifications/show-error-notification.injectable"; +import autoBindReact from "auto-bind/react"; export interface PortForwardMenuProps extends MenuActionsProps { portForward: PortForwardItem; @@ -33,7 +34,7 @@ interface Dependencies { class NonInjectedPortForwardMenu extends React.Component { constructor(props: Props) { super(props); - autoBind(this); + autoBindReact(this); } remove() { diff --git a/packages/core/src/renderer/components/+network-services/service-details-endpoint.tsx b/packages/core/src/renderer/components/+network-services/service-details-endpoint.tsx index 7e3eaaf34b..324f035fa7 100644 --- a/packages/core/src/renderer/components/+network-services/service-details-endpoint.tsx +++ b/packages/core/src/renderer/components/+network-services/service-details-endpoint.tsx @@ -6,7 +6,7 @@ import { observer } from "mobx-react"; import React from "react"; import { Table, TableHead, TableCell, TableRow } from "../table"; -import { prevDefault } from "../../utils"; +import { prevDefault } from "@k8slens/utilities"; import type { Logger } from "../../../common/logger"; import { Endpoints } from "../../../common/k8s-api/endpoints"; import type { ShowDetails } from "../kube-detail-params/show-details.injectable"; diff --git a/packages/core/src/renderer/components/+network-services/service-port-component.tsx b/packages/core/src/renderer/components/+network-services/service-port-component.tsx index b81ef1350d..7b2c5bdfba 100644 --- a/packages/core/src/renderer/components/+network-services/service-port-component.tsx +++ b/packages/core/src/renderer/components/+network-services/service-port-component.tsx @@ -9,7 +9,7 @@ import React from "react"; import { disposeOnUnmount, observer } from "mobx-react"; import type { Service, ServicePort } from "../../../common/k8s-api/endpoints"; import { action, makeObservable, observable, reaction } from "mobx"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import type { ShowNotification } from "../notifications"; import { Button } from "../button"; import type { ForwardedPort, PortForwardStore } from "../../port-forward"; diff --git a/packages/core/src/renderer/components/+nodes/route.tsx b/packages/core/src/renderer/components/+nodes/route.tsx index a868dda39b..99e5900c87 100644 --- a/packages/core/src/renderer/components/+nodes/route.tsx +++ b/packages/core/src/renderer/components/+nodes/route.tsx @@ -6,13 +6,12 @@ import "./nodes.scss"; import React from "react"; import { observer } from "mobx-react"; -import { cssNames, interval } from "../../utils"; +import { bytesToUnits, cssNames, interval } from "@k8slens/utilities"; import { TabLayout } from "../layout/tab-layout-2"; import { KubeObjectListLayout } from "../kube-object-list-layout"; import type { Node } from "../../../common/k8s-api/endpoints/node.api"; import { formatNodeTaint } from "../../../common/k8s-api/endpoints/node.api"; import { LineProgress } from "../line-progress"; -import { bytesToUnits } from "../../../common/utils/convertMemory"; import { Tooltip, TooltipPosition } from "../tooltip"; import kebabCase from "lodash/kebabCase"; import upperFirst from "lodash/upperFirst"; diff --git a/packages/core/src/renderer/components/+nodes/store.ts b/packages/core/src/renderer/components/+nodes/store.ts index 87fafa9256..6cfedd7dfc 100644 --- a/packages/core/src/renderer/components/+nodes/store.ts +++ b/packages/core/src/renderer/components/+nodes/store.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 autoBind from "auto-bind"; import { sum } from "lodash"; import { computed, makeObservable } from "mobx"; import type { Node, NodeApi } from "../../../common/k8s-api/endpoints"; import type { KubeObjectStoreDependencies, KubeObjectStoreOptions } from "../../../common/k8s-api/kube-object.store"; import { KubeObjectStore } from "../../../common/k8s-api/kube-object.store"; -import { autoBind } from "../../utils"; export class NodeStore extends KubeObjectStore { constructor(dependencies: KubeObjectStoreDependencies, api: NodeApi, opts?: KubeObjectStoreOptions) { diff --git a/packages/core/src/renderer/components/+storage-volume-claims/volume-claim-details.tsx b/packages/core/src/renderer/components/+storage-volume-claims/volume-claim-details.tsx index 954bad9bc5..6447faa4f4 100644 --- a/packages/core/src/renderer/components/+storage-volume-claims/volume-claim-details.tsx +++ b/packages/core/src/renderer/components/+storage-volume-claims/volume-claim-details.tsx @@ -19,7 +19,7 @@ import type { GetDetailsUrl } from "../kube-detail-params/get-details-url.inject import type { PodStore } from "../+workloads-pods/store"; import getDetailsUrlInjectable from "../kube-detail-params/get-details-url.injectable"; import podStoreInjectable from "../+workloads-pods/store.injectable"; -import { stopPropagation } from "../../../renderer/utils"; +import { stopPropagation } from "@k8slens/utilities"; import storageClassApiInjectable from "../../../common/k8s-api/endpoints/storage-class.api.injectable"; import loggerInjectable from "../../../common/logger.injectable"; diff --git a/packages/core/src/renderer/components/+storage-volume-claims/volume-claims.tsx b/packages/core/src/renderer/components/+storage-volume-claims/volume-claims.tsx index 39ec81f8de..0e04c92f49 100644 --- a/packages/core/src/renderer/components/+storage-volume-claims/volume-claims.tsx +++ b/packages/core/src/renderer/components/+storage-volume-claims/volume-claims.tsx @@ -9,8 +9,7 @@ import React from "react"; import { observer } from "mobx-react"; import { Link } from "react-router-dom"; import { KubeObjectListLayout } from "../kube-object-list-layout"; -import { unitsToBytes } from "../../../common/utils/convertMemory"; -import { stopPropagation } from "../../utils"; +import { unitsToBytes, stopPropagation } from "@k8slens/utilities"; import type { StorageClassApi } from "../../../common/k8s-api/endpoints"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; import { SiblingsInTabLayout } from "../layout/siblings-in-tab-layout"; diff --git a/packages/core/src/renderer/components/+storage-volumes/volume-details-list.tsx b/packages/core/src/renderer/components/+storage-volumes/volume-details-list.tsx index ebc471a933..2d2acfb615 100644 --- a/packages/core/src/renderer/components/+storage-volumes/volume-details-list.tsx +++ b/packages/core/src/renderer/components/+storage-volumes/volume-details-list.tsx @@ -9,7 +9,7 @@ import React from "react"; import { observer } from "mobx-react"; import type { PersistentVolume } from "../../../common/k8s-api/endpoints/persistent-volume.api"; import { TableRow } from "../table/table-row"; -import { cssNames, prevDefault } from "../../utils"; +import { cssNames, prevDefault } from "@k8slens/utilities"; import { TableCell } from "../table/table-cell"; import { Spinner } from "../spinner/spinner"; import { DrawerTitle } from "../drawer/drawer-title"; diff --git a/packages/core/src/renderer/components/+storage-volumes/volume-details.tsx b/packages/core/src/renderer/components/+storage-volumes/volume-details.tsx index 93b3a40195..ab7e1e48b2 100644 --- a/packages/core/src/renderer/components/+storage-volumes/volume-details.tsx +++ b/packages/core/src/renderer/components/+storage-volumes/volume-details.tsx @@ -15,7 +15,7 @@ import type { PersistentVolumeClaimApi, StorageClassApi } from "../../../common/ import { PersistentVolume } from "../../../common/k8s-api/endpoints"; import type { KubeObjectDetailsProps } from "../kube-object-details"; import type { Logger } from "../../../common/logger"; -import { stopPropagation } from "../../../renderer/utils"; +import { stopPropagation } from "@k8slens/utilities"; import { withInjectables } from "@ogre-tools/injectable-react"; import loggerInjectable from "../../../common/logger.injectable"; import type { GetDetailsUrl } from "../kube-detail-params/get-details-url.injectable"; diff --git a/packages/core/src/renderer/components/+storage-volumes/volumes.tsx b/packages/core/src/renderer/components/+storage-volumes/volumes.tsx index ac3bf08e5a..c1cdd3d09a 100644 --- a/packages/core/src/renderer/components/+storage-volumes/volumes.tsx +++ b/packages/core/src/renderer/components/+storage-volumes/volumes.tsx @@ -9,7 +9,7 @@ import React from "react"; import { observer } from "mobx-react"; import { Link } from "react-router-dom"; import { KubeObjectListLayout } from "../kube-object-list-layout"; -import { stopPropagation } from "../../utils"; +import { stopPropagation } from "@k8slens/utilities"; import type { PersistentVolumeClaimApi, StorageClassApi } from "../../../common/k8s-api/endpoints"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; import { SiblingsInTabLayout } from "../layout/siblings-in-tab-layout"; diff --git a/packages/core/src/renderer/components/+user-management/+cluster-role-bindings/__tests__/dialog.test.tsx b/packages/core/src/renderer/components/+user-management/+cluster-role-bindings/__tests__/dialog.test.tsx index d9a007bed1..04cf657606 100644 --- a/packages/core/src/renderer/components/+user-management/+cluster-role-bindings/__tests__/dialog.test.tsx +++ b/packages/core/src/renderer/components/+user-management/+cluster-role-bindings/__tests__/dialog.test.tsx @@ -15,11 +15,11 @@ import storesAndApisCanBeCreatedInjectable from "../../../../stores-apis-can-be- import directoryForUserDataInjectable from "../../../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; import directoryForKubeConfigsInjectable from "../../../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable"; import hostedClusterInjectable from "../../../../cluster-frame-context/hosted-cluster.injectable"; -import createClusterInjectable from "../../../../cluster/create-cluster.injectable"; import type { CloseClusterRoleBindingDialog } from "../dialog/close.injectable"; import closeClusterRoleBindingDialogInjectable from "../dialog/close.injectable"; import type { OpenClusterRoleBindingDialog } from "../dialog/open.injectable"; import openClusterRoleBindingDialogInjectable from "../dialog/open.injectable"; +import { Cluster } from "../../../../../common/cluster/cluster"; describe("ClusterRoleBindingDialog tests", () => { let render: DiRender; @@ -36,9 +36,7 @@ describe("ClusterRoleBindingDialog tests", () => { closeClusterRoleBindingDialog = di.inject(closeClusterRoleBindingDialogInjectable); openClusterRoleBindingDialog = di.inject(openClusterRoleBindingDialogInjectable); - const createCluster = di.inject(createClusterInjectable); - - di.override(hostedClusterInjectable, () => createCluster({ + di.override(hostedClusterInjectable, () => new Cluster({ contextName: "some-context-name", id: "some-cluster-id", kubeConfigPath: "/some-path-to-a-kubeconfig", diff --git a/packages/core/src/renderer/components/+user-management/+cluster-role-bindings/details.tsx b/packages/core/src/renderer/components/+user-management/+cluster-role-bindings/details.tsx index 87de375bed..8c0b39f590 100644 --- a/packages/core/src/renderer/components/+user-management/+cluster-role-bindings/details.tsx +++ b/packages/core/src/renderer/components/+user-management/+cluster-role-bindings/details.tsx @@ -10,7 +10,7 @@ import { disposeOnUnmount, observer } from "mobx-react"; import React from "react"; import type { ClusterRoleBinding } from "../../../../common/k8s-api/endpoints"; -import { autoBind, ObservableHashSet, prevDefault } from "../../../utils"; +import { ObservableHashSet, prevDefault } from "@k8slens/utilities"; import { AddRemoveButtons } from "../../add-remove-buttons"; import { DrawerTitle } from "../../drawer"; import type { KubeObjectDetailsProps } from "../../kube-object-details"; @@ -23,6 +23,7 @@ import type { ClusterRoleBindingStore } from "./store"; import type { OpenClusterRoleBindingDialog } from "./dialog/open.injectable"; import openClusterRoleBindingDialogInjectable from "./dialog/open.injectable"; import clusterRoleBindingStoreInjectable from "./store.injectable"; +import autoBindReact from "auto-bind/react"; export interface ClusterRoleBindingDetailsProps extends KubeObjectDetailsProps { } @@ -39,7 +40,7 @@ class NonInjectedClusterRoleBindingDetails extends React.Component item.getName() === binding.roleRef.name); - const [saSubjects, uSubjects, gSubjects] = nFircate(binding.getSubjects(), "kind", ["ServiceAccount", "User", "Group"]); + const [saSubjects, uSubjects, gSubjects] = iter.nFircate(binding.getSubjects(), "kind", ["ServiceAccount", "User", "Group"]); const accountNames = new Set(saSubjects.map(acc => acc.name)); this.selectedAccounts.replace( diff --git a/packages/core/src/renderer/components/+user-management/+cluster-role-bindings/store.ts b/packages/core/src/renderer/components/+user-management/+cluster-role-bindings/store.ts index 01637aa815..e1e6a43fbf 100644 --- a/packages/core/src/renderer/components/+user-management/+cluster-role-bindings/store.ts +++ b/packages/core/src/renderer/components/+user-management/+cluster-role-bindings/store.ts @@ -6,7 +6,7 @@ import type { ClusterRoleBinding, ClusterRoleBindingApi, ClusterRoleBindingData } from "../../../../common/k8s-api/endpoints"; import type { Subject } from "../../../../common/k8s-api/endpoints/types/subject"; import { KubeObjectStore } from "../../../../common/k8s-api/kube-object.store"; -import { HashSet } from "../../../utils"; +import { HashSet } from "@k8slens/utilities"; import { hashSubject } from "../hashers"; export class ClusterRoleBindingStore extends KubeObjectStore { diff --git a/packages/core/src/renderer/components/+user-management/+role-bindings/__tests__/dialog.test.tsx b/packages/core/src/renderer/components/+user-management/+role-bindings/__tests__/dialog.test.tsx index add1ba98af..96f7bb5b68 100644 --- a/packages/core/src/renderer/components/+user-management/+role-bindings/__tests__/dialog.test.tsx +++ b/packages/core/src/renderer/components/+user-management/+role-bindings/__tests__/dialog.test.tsx @@ -15,9 +15,9 @@ import clusterRoleStoreInjectable from "../../+cluster-roles/store.injectable"; import storesAndApisCanBeCreatedInjectable from "../../../../stores-apis-can-be-created.injectable"; import directoryForKubeConfigsInjectable from "../../../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable"; import hostedClusterInjectable from "../../../../cluster-frame-context/hosted-cluster.injectable"; -import createClusterInjectable from "../../../../cluster/create-cluster.injectable"; import type { OpenRoleBindingDialog } from "../dialog/open.injectable"; import openRoleBindingDialogInjectable from "../dialog/open.injectable"; +import { Cluster } from "../../../../../common/cluster/cluster"; describe("RoleBindingDialog tests", () => { let render: DiRender; @@ -32,9 +32,7 @@ describe("RoleBindingDialog tests", () => { openRoleBindingDialog = di.inject(openRoleBindingDialogInjectable); - const createCluster = di.inject(createClusterInjectable); - - di.override(hostedClusterInjectable, () => createCluster({ + di.override(hostedClusterInjectable, () => new Cluster({ contextName: "some-context-name", id: "some-cluster-id", kubeConfigPath: "/some-path-to-a-kubeconfig", diff --git a/packages/core/src/renderer/components/+user-management/+role-bindings/details.tsx b/packages/core/src/renderer/components/+user-management/+role-bindings/details.tsx index c83caddeec..474e071d86 100644 --- a/packages/core/src/renderer/components/+user-management/+role-bindings/details.tsx +++ b/packages/core/src/renderer/components/+user-management/+role-bindings/details.tsx @@ -9,12 +9,11 @@ import { reaction } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; import React from "react"; import type { RoleBinding } from "../../../../common/k8s-api/endpoints"; -import { prevDefault } from "../../../utils"; +import { prevDefault, ObservableHashSet } from "@k8slens/utilities"; import { AddRemoveButtons } from "../../add-remove-buttons"; import { DrawerTitle } from "../../drawer"; import type { KubeObjectDetailsProps } from "../../kube-object-details"; import { Table, TableCell, TableHead, TableRow } from "../../table"; -import { ObservableHashSet } from "../../../../common/utils/hash-set"; import { hashSubject } from "../hashers"; import type { OpenConfirmDialog } from "../../confirm-dialog/open.injectable"; import { withInjectables } from "@ogre-tools/injectable-react"; diff --git a/packages/core/src/renderer/components/+user-management/+role-bindings/dialog/view.tsx b/packages/core/src/renderer/components/+user-management/+role-bindings/dialog/view.tsx index 77f1724708..ada6080c0d 100644 --- a/packages/core/src/renderer/components/+user-management/+role-bindings/dialog/view.tsx +++ b/packages/core/src/renderer/components/+user-management/+role-bindings/dialog/view.tsx @@ -20,7 +20,7 @@ import type { SelectOption } from "../../../select"; import { onMultiSelectFor, Select } from "../../../select"; import { Wizard, WizardStep } from "../../../wizard"; import { Input } from "../../../input"; -import { ObservableHashSet, nFircate } from "../../../../utils"; +import { ObservableHashSet, iter } from "@k8slens/utilities"; import type { Subject } from "../../../../../common/k8s-api/endpoints/types/subject"; import type { RoleBindingDialogState } from "./state.injectable"; import type { RoleBindingStore } from "../store"; @@ -147,7 +147,7 @@ class NonInjectedRoleBindingDialog extends React.Component acc.name)); this.selectedAccounts.replace( diff --git a/packages/core/src/renderer/components/+user-management/+role-bindings/store.ts b/packages/core/src/renderer/components/+user-management/+role-bindings/store.ts index 937497113c..f3a4c1e54a 100644 --- a/packages/core/src/renderer/components/+user-management/+role-bindings/store.ts +++ b/packages/core/src/renderer/components/+user-management/+role-bindings/store.ts @@ -6,7 +6,7 @@ import type { RoleBinding, RoleBindingApi, RoleBindingData } from "../../../../common/k8s-api/endpoints"; import type { Subject } from "../../../../common/k8s-api/endpoints/types/subject"; import { KubeObjectStore } from "../../../../common/k8s-api/kube-object.store"; -import { HashSet } from "../../../utils"; +import { HashSet } from "@k8slens/utilities"; import { hashSubject } from "../hashers"; export class RoleBindingStore extends KubeObjectStore { diff --git a/packages/core/src/renderer/components/+user-management/+service-accounts/secret.tsx b/packages/core/src/renderer/components/+user-management/+service-accounts/secret.tsx index 49acaa9ca8..6e645abbf9 100644 --- a/packages/core/src/renderer/components/+user-management/+service-accounts/secret.tsx +++ b/packages/core/src/renderer/components/+user-management/+service-accounts/secret.tsx @@ -9,7 +9,7 @@ import moment from "moment"; import React from "react"; import type { Secret } from "../../../../common/k8s-api/endpoints/secret.api"; -import { prevDefault } from "../../../utils"; +import { prevDefault } from "@k8slens/utilities"; import { Icon } from "../../icon"; export interface ServiceAccountsSecretProps { diff --git a/packages/core/src/renderer/components/+workloads-cronjobs/trigger-dialog/view.tsx b/packages/core/src/renderer/components/+workloads-cronjobs/trigger-dialog/view.tsx index 48ff80dc28..f95d41fc27 100644 --- a/packages/core/src/renderer/components/+workloads-cronjobs/trigger-dialog/view.tsx +++ b/packages/core/src/renderer/components/+workloads-cronjobs/trigger-dialog/view.tsx @@ -14,7 +14,7 @@ import { Dialog } from "../../dialog"; import { Wizard, WizardStep } from "../../wizard"; import type { CronJob, JobApi } from "../../../../common/k8s-api/endpoints"; import type { ShowNotification } from "../../notifications"; -import { cssNames } from "../../../utils"; +import { cssNames } from "@k8slens/utilities"; import { Input } from "../../input"; import { systemName, maxLength } from "../../input/input_validators"; import { withInjectables } from "@ogre-tools/injectable-react"; diff --git a/packages/core/src/renderer/components/+workloads-daemonsets/daemonset-details.tsx b/packages/core/src/renderer/components/+workloads-daemonsets/daemonset-details.tsx index e159d72ab3..260a2e8333 100644 --- a/packages/core/src/renderer/components/+workloads-daemonsets/daemonset-details.tsx +++ b/packages/core/src/renderer/components/+workloads-daemonsets/daemonset-details.tsx @@ -23,8 +23,6 @@ import type { SubscribeStores } from "../../kube-watch-api/kube-watch-api"; import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable"; import daemonSetStoreInjectable from "./store.injectable"; import podStoreInjectable from "../+workloads-pods/store.injectable"; -import getActiveClusterEntityInjectable from "../../api/catalog/entity/get-active-cluster-entity.injectable"; -import requestPodMetricsForDaemonSetsInjectable from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics-for-daemon-sets.injectable"; import loggerInjectable from "../../../common/logger.injectable"; export interface DaemonSetDetailsProps extends KubeObjectDetailsProps { @@ -109,8 +107,6 @@ export const DaemonSetDetails = withInjectables; } @observer @@ -84,7 +84,7 @@ class NonInjectedPodDetailsContainer extends React.Component c.name == name); - const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.Container); + const isMetricHidden = containerMetricsVisible.get(); return (
@@ -217,6 +217,6 @@ export const PodDetailsContainer = withInjectables ({ ...props, portForwardStore: di.inject(portForwardStoreInjectable), - getActiveClusterEntity: di.inject(getActiveClusterEntityInjectable), + containerMetricsVisible: di.inject(enabledMetricsInjectable, ClusterMetricsResourceType.Container), }), }); diff --git a/packages/core/src/renderer/components/+workloads-pods/pod-details-list.tsx b/packages/core/src/renderer/components/+workloads-pods/pod-details-list.tsx index 2eb291ac7c..06cfa5a2a7 100644 --- a/packages/core/src/renderer/components/+workloads-pods/pod-details-list.tsx +++ b/packages/core/src/renderer/components/+workloads-pods/pod-details-list.tsx @@ -10,7 +10,7 @@ import kebabCase from "lodash/kebabCase"; import { reaction } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; import type { Pod } from "../../../common/k8s-api/endpoints"; -import { autoBind, bytesToUnits, cssNames, interval, prevDefault } from "../../utils"; +import { bytesToUnits, cssNames, interval, prevDefault } from "@k8slens/utilities"; import { LineProgress } from "../line-progress"; import type { KubeObject } from "../../../common/k8s-api/kube-object"; import { Table, TableCell, TableHead, TableRow } from "../table"; @@ -22,6 +22,7 @@ import { withInjectables } from "@ogre-tools/injectable-react"; import podStoreInjectable from "./store.injectable"; import type { ShowDetails } from "../kube-detail-params/show-details.injectable"; import showDetailsInjectable from "../kube-detail-params/show-details.injectable"; +import autoBindReact from "auto-bind/react"; enum sortBy { name = "name", @@ -47,7 +48,7 @@ interface Dependencies { class NonInjectedPodDetailsList extends React.Component { constructor(props: PodDetailsListProps & Dependencies) { super(props); - autoBind(this); + autoBindReact(this); } private metricsWatcher = interval(120, () => { diff --git a/packages/core/src/renderer/components/+workloads-pods/pod-details.tsx b/packages/core/src/renderer/components/+workloads-pods/pod-details.tsx index 604cec5cd5..7707dd6b1d 100644 --- a/packages/core/src/renderer/components/+workloads-pods/pod-details.tsx +++ b/packages/core/src/renderer/components/+workloads-pods/pod-details.tsx @@ -13,7 +13,7 @@ import { Pod } from "../../../common/k8s-api/endpoints"; import type { NodeApi, PriorityClassApi, RuntimeClassApi, ServiceAccountApi } from "../../../common/k8s-api/endpoints"; import { DrawerItem, DrawerTitle } from "../drawer"; import { Badge } from "../badge"; -import { cssNames, stopPropagation, toJS } from "../../utils"; +import { cssNames, stopPropagation } from "@k8slens/utilities"; import { PodDetailsContainer } from "./pod-details-container"; import { PodDetailsAffinities } from "./pod-details-affinities"; import { PodDetailsTolerations } from "./pod-details-tolerations"; @@ -33,6 +33,7 @@ import priorityClassApiInjectable from "../../../common/k8s-api/endpoints/priori import loggerInjectable from "../../../common/logger.injectable"; import type { PodMetricData } from "../../../common/k8s-api/endpoints/metrics.api/request-pod-metrics.injectable"; import podContainerMetricsInjectable from "./container-metrics.injectable"; +import { toJS } from "../../../common/utils"; export interface PodDetailsProps extends KubeObjectDetailsProps { } diff --git a/packages/core/src/renderer/components/+workloads-pods/pods.tsx b/packages/core/src/renderer/components/+workloads-pods/pods.tsx index ab793359b0..849a101ae1 100644 --- a/packages/core/src/renderer/components/+workloads-pods/pods.tsx +++ b/packages/core/src/renderer/components/+workloads-pods/pods.tsx @@ -5,13 +5,13 @@ import "./pods.scss"; -import React, { Fragment } from "react"; +import React from "react"; import { observer } from "mobx-react"; import { Link } from "react-router-dom"; import { KubeObjectListLayout } from "../kube-object-list-layout"; -import type { NodeApi, Pod } from "../../../common/k8s-api/endpoints"; +import type { ContainerStateValues, NodeApi, Pod } from "../../../common/k8s-api/endpoints"; import { StatusBrick } from "../status-brick"; -import { cssNames, getConvertedParts, object, stopPropagation } from "../../utils"; +import { cssNames, getConvertedParts, object, stopPropagation } from "@k8slens/utilities"; import startCase from "lodash/startCase"; import kebabCase from "lodash/kebabCase"; import type { ApiManager } from "../../../common/k8s-api/api-manager"; @@ -21,8 +21,8 @@ import { SiblingsInTabLayout } from "../layout/siblings-in-tab-layout"; import { KubeObjectAge } from "../kube-object/age"; import { withInjectables } from "@ogre-tools/injectable-react"; import type { GetDetailsUrl } from "../kube-detail-params/get-details-url.injectable"; -import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable"; import getDetailsUrlInjectable from "../kube-detail-params/get-details-url.injectable"; +import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable"; import type { EventStore } from "../+events/store"; import type { PodStore } from "./store"; import nodeApiInjectable from "../../../common/k8s-api/endpoints/node.api.injectable"; @@ -52,8 +52,12 @@ interface Dependencies { @observer class NonInjectedPods extends React.Component { - renderState(name: string, ready: boolean, key: string, data: Partial> | undefined) { - return data && ( + renderState(name: string, ready: boolean, key: string, data?: ContainerStateValues) { + if (!data) { + return; + } + + return ( <>
{name} @@ -64,40 +68,37 @@ class NonInjectedPods extends React.Component {
{object.entries(data).map(([name, value]) => ( -
-
- {startCase(name)} -
-
- {value} -
-
+ +
{startCase(name)}
+
{value}
+
))} ); } renderContainersStatus(pod: Pod) { - return pod.getContainerStatuses() - .map(({ name, state = {}, ready }) => ( - - - {this.renderState(name, ready, "running", state.running)} - {this.renderState(name, ready, "waiting", state.waiting)} - {this.renderState(name, ready, "terminated", state.terminated)} - - ), - }} - /> - - )); + return pod.getContainerStatuses().map(({ name, state, ready }) => { + return ( + + {this.renderState(name, ready, "running", state?.running)} + {this.renderState(name, ready, "waiting", state?.waiting)} + {this.renderState(name, ready, "terminated", state?.terminated)} + + ), + }} + /> + ); + }); } render() { diff --git a/packages/core/src/renderer/components/+workloads-pods/store.ts b/packages/core/src/renderer/components/+workloads-pods/store.ts index 5ce9dca041..18c98fc4ab 100644 --- a/packages/core/src/renderer/components/+workloads-pods/store.ts +++ b/packages/core/src/renderer/components/+workloads-pods/store.ts @@ -7,7 +7,7 @@ import countBy from "lodash/countBy"; import { observable } from "mobx"; import type { KubeObjectStoreDependencies, KubeObjectStoreOptions } from "../../../common/k8s-api/kube-object.store"; import { KubeObjectStore } from "../../../common/k8s-api/kube-object.store"; -import { cpuUnitsToNumber, unitsToBytes } from "../../utils"; +import { cpuUnitsToNumber, unitsToBytes } from "@k8slens/utilities"; import type { Pod, PodMetrics, PodApi, PodMetricsApi } from "../../../common/k8s-api/endpoints"; import type { KubeObject, NamespaceScopedMetadata } from "../../../common/k8s-api/kube-object"; diff --git a/packages/core/src/renderer/components/+workloads-replicasets/scale-dialog/dialog.tsx b/packages/core/src/renderer/components/+workloads-replicasets/scale-dialog/dialog.tsx index 9999917bdb..bb060890e8 100644 --- a/packages/core/src/renderer/components/+workloads-replicasets/scale-dialog/dialog.tsx +++ b/packages/core/src/renderer/components/+workloads-replicasets/scale-dialog/dialog.tsx @@ -14,7 +14,7 @@ import { Dialog } from "../../dialog"; import { Wizard, WizardStep } from "../../wizard"; import { Icon } from "../../icon"; import { Slider } from "../../slider"; -import { cssNames } from "../../../utils"; +import { cssNames } from "@k8slens/utilities"; import type { ReplicaSet, ReplicaSetApi } from "../../../../common/k8s-api/endpoints"; import { withInjectables } from "@ogre-tools/injectable-react"; import replicaSetApiInjectable from "../../../../common/k8s-api/endpoints/replica-set.api.injectable"; diff --git a/packages/core/src/renderer/components/+workloads-statefulsets/scale/dialog.tsx b/packages/core/src/renderer/components/+workloads-statefulsets/scale/dialog.tsx index 39d8969e03..a7ebe915c6 100644 --- a/packages/core/src/renderer/components/+workloads-statefulsets/scale/dialog.tsx +++ b/packages/core/src/renderer/components/+workloads-statefulsets/scale/dialog.tsx @@ -15,7 +15,7 @@ import { Dialog } from "../../dialog"; import { Wizard, WizardStep } from "../../wizard"; import { Icon } from "../../icon"; import { Slider } from "../../slider"; -import { cssNames } from "../../../utils"; +import { cssNames } from "@k8slens/utilities"; import { withInjectables } from "@ogre-tools/injectable-react"; import statefulSetApiInjectable from "../../../../common/k8s-api/endpoints/stateful-set.api.injectable"; import statefulSetDialogStateInjectable from "./dialog-state.injectable"; diff --git a/packages/core/src/renderer/components/__tests__/cronjob.store.test.ts b/packages/core/src/renderer/components/__tests__/cronjob.store.test.ts index b704d24598..4e27c286eb 100644 --- a/packages/core/src/renderer/components/__tests__/cronjob.store.test.ts +++ b/packages/core/src/renderer/components/__tests__/cronjob.store.test.ts @@ -10,7 +10,7 @@ import { getDiForUnitTesting } from "../../getDiForUnitTesting"; import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; import directoryForKubeConfigsInjectable from "../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable"; import hostedClusterInjectable from "../../cluster-frame-context/hosted-cluster.injectable"; -import createClusterInjectable from "../../cluster/create-cluster.injectable"; +import { Cluster } from "../../../common/cluster/cluster"; const scheduledCronJob = new CronJob({ apiVersion: "foo", @@ -127,9 +127,7 @@ describe("CronJob Store tests", () => { di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs"); di.override(storesAndApisCanBeCreatedInjectable, () => true); - const createCluster = di.inject(createClusterInjectable); - - di.override(hostedClusterInjectable, () => createCluster({ + di.override(hostedClusterInjectable, () => new Cluster({ contextName: "some-context-name", id: "some-cluster-id", kubeConfigPath: "/some-path-to-a-kubeconfig", diff --git a/packages/core/src/renderer/components/__tests__/daemonset.store.test.ts b/packages/core/src/renderer/components/__tests__/daemonset.store.test.ts index 755c666b85..bfd4861f48 100644 --- a/packages/core/src/renderer/components/__tests__/daemonset.store.test.ts +++ b/packages/core/src/renderer/components/__tests__/daemonset.store.test.ts @@ -13,7 +13,7 @@ import { getDiForUnitTesting } from "../../getDiForUnitTesting"; import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; import directoryForKubeConfigsInjectable from "../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable"; import hostedClusterInjectable from "../../cluster-frame-context/hosted-cluster.injectable"; -import createClusterInjectable from "../../cluster/create-cluster.injectable"; +import { Cluster } from "../../../common/cluster/cluster"; const runningDaemonSet = new DaemonSet({ apiVersion: "foo", @@ -144,9 +144,7 @@ describe("DaemonSet Store tests", () => { di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs"); di.override(storesAndApisCanBeCreatedInjectable, () => true); - const createCluster = di.inject(createClusterInjectable); - - di.override(hostedClusterInjectable, () => createCluster({ + di.override(hostedClusterInjectable, () => new Cluster({ contextName: "some-context-name", id: "some-cluster-id", kubeConfigPath: "/some-path-to-a-kubeconfig", diff --git a/packages/core/src/renderer/components/__tests__/deployments.store.test.ts b/packages/core/src/renderer/components/__tests__/deployments.store.test.ts index 1991c30691..23987ccd37 100644 --- a/packages/core/src/renderer/components/__tests__/deployments.store.test.ts +++ b/packages/core/src/renderer/components/__tests__/deployments.store.test.ts @@ -14,7 +14,7 @@ import { getDiForUnitTesting } from "../../getDiForUnitTesting"; import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; import directoryForKubeConfigsInjectable from "../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable"; import hostedClusterInjectable from "../../cluster-frame-context/hosted-cluster.injectable"; -import createClusterInjectable from "../../cluster/create-cluster.injectable"; +import { Cluster } from "../../../common/cluster/cluster"; const spec: PodSpec = { containers: [{ @@ -216,9 +216,7 @@ describe("Deployment Store tests", () => { di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs"); di.override(storesAndApisCanBeCreatedInjectable, () => true); - const createCluster = di.inject(createClusterInjectable); - - di.override(hostedClusterInjectable, () => createCluster({ + di.override(hostedClusterInjectable, () => new Cluster({ contextName: "some-context-name", id: "some-cluster-id", kubeConfigPath: "/some-path-to-a-kubeconfig", diff --git a/packages/core/src/renderer/components/__tests__/job.store.test.ts b/packages/core/src/renderer/components/__tests__/job.store.test.ts index 74a25f2b8f..73a5cade8f 100644 --- a/packages/core/src/renderer/components/__tests__/job.store.test.ts +++ b/packages/core/src/renderer/components/__tests__/job.store.test.ts @@ -13,7 +13,7 @@ import { getDiForUnitTesting } from "../../getDiForUnitTesting"; import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; import directoryForKubeConfigsInjectable from "../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable"; import hostedClusterInjectable from "../../cluster-frame-context/hosted-cluster.injectable"; -import createClusterInjectable from "../../cluster/create-cluster.injectable"; +import { Cluster } from "../../../common/cluster/cluster"; const runningJob = new Job({ apiVersion: "foo", @@ -181,9 +181,7 @@ describe("Job Store tests", () => { di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs"); di.override(storesAndApisCanBeCreatedInjectable, () => true); - const createCluster = di.inject(createClusterInjectable); - - di.override(hostedClusterInjectable, () => createCluster({ + di.override(hostedClusterInjectable, () => new Cluster({ contextName: "some-context-name", id: "some-cluster-id", kubeConfigPath: "/some-path-to-a-kubeconfig", diff --git a/packages/core/src/renderer/components/__tests__/pods.store.test.ts b/packages/core/src/renderer/components/__tests__/pods.store.test.ts index e45697eeae..03a057458d 100644 --- a/packages/core/src/renderer/components/__tests__/pods.store.test.ts +++ b/packages/core/src/renderer/components/__tests__/pods.store.test.ts @@ -11,7 +11,7 @@ import { getDiForUnitTesting } from "../../getDiForUnitTesting"; import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; import directoryForKubeConfigsInjectable from "../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable"; import hostedClusterInjectable from "../../cluster-frame-context/hosted-cluster.injectable"; -import createClusterInjectable from "../../cluster/create-cluster.injectable"; +import { Cluster } from "../../../common/cluster/cluster"; const runningPod = new Pod({ apiVersion: "foo", @@ -127,9 +127,7 @@ describe("Pod Store tests", () => { di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs"); di.override(storesAndApisCanBeCreatedInjectable, () => true); - const createCluster = di.inject(createClusterInjectable); - - di.override(hostedClusterInjectable, () => createCluster({ + di.override(hostedClusterInjectable, () => new Cluster({ contextName: "some-context-name", id: "some-cluster-id", kubeConfigPath: "/some-path-to-a-kubeconfig", diff --git a/packages/core/src/renderer/components/__tests__/replicaset.store.test.ts b/packages/core/src/renderer/components/__tests__/replicaset.store.test.ts index 99c3dd8067..aea690a507 100644 --- a/packages/core/src/renderer/components/__tests__/replicaset.store.test.ts +++ b/packages/core/src/renderer/components/__tests__/replicaset.store.test.ts @@ -13,7 +13,7 @@ import { getDiForUnitTesting } from "../../getDiForUnitTesting"; import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; import directoryForKubeConfigsInjectable from "../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable"; import hostedClusterInjectable from "../../cluster-frame-context/hosted-cluster.injectable"; -import createClusterInjectable from "../../cluster/create-cluster.injectable"; +import { Cluster } from "../../../common/cluster/cluster"; const runningReplicaSet = new ReplicaSet({ apiVersion: "foo", @@ -144,9 +144,7 @@ describe("ReplicaSet Store tests", () => { di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs"); di.override(storesAndApisCanBeCreatedInjectable, () => true); - const createCluster = di.inject(createClusterInjectable); - - di.override(hostedClusterInjectable, () => createCluster({ + di.override(hostedClusterInjectable, () => new Cluster({ contextName: "some-context-name", id: "some-cluster-id", kubeConfigPath: "/some-path-to-a-kubeconfig", diff --git a/packages/core/src/renderer/components/__tests__/statefulset.store.test.ts b/packages/core/src/renderer/components/__tests__/statefulset.store.test.ts index 92d8f94aed..9e7ada1aa1 100644 --- a/packages/core/src/renderer/components/__tests__/statefulset.store.test.ts +++ b/packages/core/src/renderer/components/__tests__/statefulset.store.test.ts @@ -13,7 +13,7 @@ import { getDiForUnitTesting } from "../../getDiForUnitTesting"; import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; import directoryForKubeConfigsInjectable from "../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable"; import hostedClusterInjectable from "../../cluster-frame-context/hosted-cluster.injectable"; -import createClusterInjectable from "../../cluster/create-cluster.injectable"; +import { Cluster } from "../../../common/cluster/cluster"; const runningStatefulSet = new StatefulSet({ apiVersion: "foo", @@ -144,9 +144,7 @@ describe("StatefulSet Store tests", () => { di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs"); di.override(storesAndApisCanBeCreatedInjectable, () => true); - const createCluster = di.inject(createClusterInjectable); - - di.override(hostedClusterInjectable, () => createCluster({ + di.override(hostedClusterInjectable, () => new Cluster({ contextName: "some-context-name", id: "some-cluster-id", kubeConfigPath: "/some-path-to-a-kubeconfig", diff --git a/packages/core/src/renderer/components/add-remove-buttons/add-remove-buttons.tsx b/packages/core/src/renderer/components/add-remove-buttons/add-remove-buttons.tsx index e38e0ffe67..b1d7b68d32 100644 --- a/packages/core/src/renderer/components/add-remove-buttons/add-remove-buttons.tsx +++ b/packages/core/src/renderer/components/add-remove-buttons/add-remove-buttons.tsx @@ -6,7 +6,7 @@ import "./add-remove-buttons.scss"; import React from "react"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import { Button } from "../button"; import { Icon } from "../icon"; diff --git a/packages/core/src/renderer/components/animate/animate.tsx b/packages/core/src/renderer/components/animate/animate.tsx index aa0d673570..6a7870e336 100644 --- a/packages/core/src/renderer/components/animate/animate.tsx +++ b/packages/core/src/renderer/components/animate/animate.tsx @@ -5,7 +5,7 @@ import "./animate.scss"; import React, { useEffect, useState } from "react"; -import { cssNames, noop } from "../../utils"; +import { cssNames, noop } from "@k8slens/utilities"; import { withInjectables } from "@ogre-tools/injectable-react"; import type { RequestAnimationFrame } from "./request-animation-frame.injectable"; import requestAnimationFrameInjectable from "./request-animation-frame.injectable"; diff --git a/packages/core/src/renderer/components/avatar/avatar.tsx b/packages/core/src/renderer/components/avatar/avatar.tsx index a3b9837295..84892b081c 100644 --- a/packages/core/src/renderer/components/avatar/avatar.tsx +++ b/packages/core/src/renderer/components/avatar/avatar.tsx @@ -9,8 +9,8 @@ import type { ImgHTMLAttributes, MouseEventHandler } from "react"; import React from "react"; import randomColor from "randomcolor"; import GraphemeSplitter from "grapheme-splitter"; -import type { SingleOrMany } from "../../utils"; -import { cssNames, isDefined, iter } from "../../utils"; +import type { SingleOrMany } from "@k8slens/utilities"; +import { cssNames, isDefined, iter } from "@k8slens/utilities"; export interface AvatarProps { title: string; diff --git a/packages/core/src/renderer/components/badge/badge.tsx b/packages/core/src/renderer/components/badge/badge.tsx index f0efb701bd..5fe12ade09 100644 --- a/packages/core/src/renderer/components/badge/badge.tsx +++ b/packages/core/src/renderer/components/badge/badge.tsx @@ -8,7 +8,7 @@ import styles from "./badge.module.scss"; import React, { useEffect, useRef, useState } from "react"; import { action, observable } from "mobx"; import { observer } from "mobx-react"; -import { cssNames } from "../../utils/cssNames"; +import { cssNames } from "@k8slens/utilities"; import { withTooltip } from "../tooltip"; export interface BadgeProps extends React.HTMLAttributes { diff --git a/packages/core/src/renderer/components/button/button.tsx b/packages/core/src/renderer/components/button/button.tsx index 8168c2abf3..e72a874641 100644 --- a/packages/core/src/renderer/components/button/button.tsx +++ b/packages/core/src/renderer/components/button/button.tsx @@ -6,7 +6,7 @@ import "./button.scss"; import type { ButtonHTMLAttributes } from "react"; import React from "react"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import { withTooltip } from "../tooltip"; export interface ButtonProps extends ButtonHTMLAttributes { diff --git a/packages/core/src/renderer/components/chart/bar-chart.tsx b/packages/core/src/renderer/components/chart/bar-chart.tsx index e5c0e901d8..49a656cbf7 100644 --- a/packages/core/src/renderer/components/chart/bar-chart.tsx +++ b/packages/core/src/renderer/components/chart/bar-chart.tsx @@ -11,7 +11,7 @@ import { observer } from "mobx-react"; import type { ChartOptions, ChartTooltipCallback, ChartTooltipItem, Scriptable } from "chart.js"; import type { ChartProps } from "./chart"; import { Chart, ChartKind } from "./chart"; -import { bytesToUnits, cssNames, isObject } from "../../utils"; +import { bytesToUnits, cssNames, isObject } from "@k8slens/utilities"; import { ZebraStripesPlugin } from "./zebra-stripes.plugin"; import type { LensTheme } from "../../themes/lens-theme"; import { NoMetrics } from "../resource-metrics/no-metrics"; diff --git a/packages/core/src/renderer/components/chart/chart.tsx b/packages/core/src/renderer/components/chart/chart.tsx index 3d54b90302..27ab820a19 100644 --- a/packages/core/src/renderer/components/chart/chart.tsx +++ b/packages/core/src/renderer/components/chart/chart.tsx @@ -9,7 +9,7 @@ import React from "react"; import type { PluginServiceRegistrationOptions } from "chart.js"; import ChartJS from "chart.js"; import { remove } from "lodash"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import { StatusBrick } from "../status-brick"; import { Badge } from "../badge"; diff --git a/packages/core/src/renderer/components/chart/options.ts b/packages/core/src/renderer/components/chart/options.ts index 106664d26d..24a6dc5fd4 100644 --- a/packages/core/src/renderer/components/chart/options.ts +++ b/packages/core/src/renderer/components/chart/options.ts @@ -4,7 +4,7 @@ */ import type { ChartOptions, ChartPoint } from "chart.js"; -import { bytesToUnits, isDefined } from "../../utils"; +import { bytesToUnits, isDefined } from "@k8slens/utilities"; export type MetricsTab = "CPU" | "Memory" | "Disk" | "Pods" | "Network" | "Filesystem" | "Duration"; diff --git a/packages/core/src/renderer/components/chart/pie-chart.tsx b/packages/core/src/renderer/components/chart/pie-chart.tsx index de1461631a..9db4bca62f 100644 --- a/packages/core/src/renderer/components/chart/pie-chart.tsx +++ b/packages/core/src/renderer/components/chart/pie-chart.tsx @@ -10,7 +10,7 @@ import type { ChartOptions } from "chart.js"; import ChartJS from "chart.js"; import type { ChartProps } from "./chart"; import { Chart } from "./chart"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import type { LensTheme } from "../../themes/lens-theme"; import { withInjectables } from "@ogre-tools/injectable-react"; import type { IComputedValue } from "mobx"; diff --git a/packages/core/src/renderer/components/checkbox/checkbox.tsx b/packages/core/src/renderer/components/checkbox/checkbox.tsx index ecba55378e..4193f1d283 100644 --- a/packages/core/src/renderer/components/checkbox/checkbox.tsx +++ b/packages/core/src/renderer/components/checkbox/checkbox.tsx @@ -5,8 +5,8 @@ import "./checkbox.scss"; import React from "react"; -import type { SingleOrMany } from "../../utils"; -import { cssNames, noop } from "../../utils"; +import type { SingleOrMany } from "@k8slens/utilities"; +import { cssNames, noop } from "@k8slens/utilities"; export interface CheckboxProps { className?: string; diff --git a/packages/core/src/renderer/components/cluster-manager/cluster-frame-handler.ts b/packages/core/src/renderer/components/cluster-manager/cluster-frame-handler.ts index f1b169915f..08a49bb496 100644 --- a/packages/core/src/renderer/components/cluster-manager/cluster-frame-handler.ts +++ b/packages/core/src/renderer/components/cluster-manager/cluster-frame-handler.ts @@ -5,12 +5,13 @@ import { action, makeObservable, observable, when } from "mobx"; import type { ClusterId } from "../../../common/cluster-types"; -import type { Disposer } from "../../utils"; -import { getClusterFrameUrl, onceDefined } from "../../utils"; +import type { Disposer } from "@k8slens/utilities"; +import { onceDefined } from "@k8slens/utilities"; import assert from "assert"; import type { Logger } from "../../../common/logger"; import type { GetClusterById } from "../../../common/cluster-store/get-by-id.injectable"; import type { EmitClusterVisibility } from "./emit-cluster-visibility.injectable"; +import { getClusterFrameUrl } from "../../../common/utils"; export interface LensView { isLoaded: boolean; @@ -56,7 +57,7 @@ export class ClusterFrameHandler { const iframe = document.createElement("iframe"); iframe.id = `cluster-frame-${cluster.id}`; - iframe.name = cluster.contextName; + iframe.name = cluster.contextName.get(); iframe.setAttribute("src", getClusterFrameUrl(clusterId)); iframe.addEventListener("load", action(() => { this.dependencies.logger.info(`[LENS-VIEW]: frame for clusterId=${clusterId} has loaded`); @@ -71,19 +72,19 @@ export class ClusterFrameHandler { this.dependencies.logger.info(`[LENS-VIEW]: waiting cluster to be ready, clusterId=${clusterId}`); const dispose = when( - () => cluster.ready, + () => cluster.ready.get(), () => this.dependencies.logger.info(`[LENS-VIEW]: cluster is ready, clusterId=${clusterId}`), ); when( // cluster.disconnect is set to `false` when the cluster starts to connect - () => !cluster.disconnected, + () => !cluster.disconnected.get(), () => { when( () => { const cluster = this.dependencies.getClusterById(clusterId); - return Boolean(!cluster || (cluster.disconnected && this.views.get(clusterId)?.isLoaded)); + return Boolean(!cluster || (cluster.disconnected.get() && this.views.get(clusterId)?.isLoaded)); }, () => { this.dependencies.logger.info(`[LENS-VIEW]: remove dashboard, clusterId=${clusterId}`); @@ -126,7 +127,7 @@ export class ClusterFrameHandler { () => { const view = this.views.get(clusterId); - if (cluster.available && cluster.ready && view?.isLoaded) { + if (cluster.available.get() && cluster.ready.get() && view?.isLoaded) { return view; } diff --git a/packages/core/src/renderer/components/cluster-manager/cluster-manager.tsx b/packages/core/src/renderer/components/cluster-manager/cluster-manager.tsx index ab418ec827..68dea9a2d3 100644 --- a/packages/core/src/renderer/components/cluster-manager/cluster-manager.tsx +++ b/packages/core/src/renderer/components/cluster-manager/cluster-manager.tsx @@ -17,11 +17,11 @@ import catalogPreviousActiveTabStorageInjectable from "../+catalog/catalog-previ import type { IComputedValue } from "mobx"; import currentRouteComponentInjectable from "../../routes/current-route-component.injectable"; import welcomeRouteInjectable from "../../../common/front-end-routing/routes/welcome/welcome-route.injectable"; -import { buildURL } from "../../../common/utils/buildUrl"; -import type { StorageLayer } from "../../utils"; +import { buildURL } from "@k8slens/utilities"; import type { WatchForGeneralEntityNavigation } from "../../api/helpers/watch-for-general-entity-navigation.injectable"; import watchForGeneralEntityNavigationInjectable from "../../api/helpers/watch-for-general-entity-navigation.injectable"; import currentPathInjectable from "../../routes/current-path.injectable"; +import type { StorageLayer } from "../../utils/storage-helper"; interface Dependencies { catalogPreviousActiveTabStorage: StorageLayer; diff --git a/packages/core/src/renderer/components/cluster-manager/cluster-status.tsx b/packages/core/src/renderer/components/cluster-manager/cluster-status.tsx index 940218ecad..36e5f2e37c 100644 --- a/packages/core/src/renderer/components/cluster-manager/cluster-status.tsx +++ b/packages/core/src/renderer/components/cluster-manager/cluster-status.tsx @@ -10,8 +10,8 @@ import { disposeOnUnmount, observer } from "mobx-react"; import React from "react"; import { ipcRendererOn } from "../../../common/ipc"; import type { Cluster } from "../../../common/cluster/cluster"; -import type { IClassName } from "../../utils"; -import { hasTypedProperty, isObject, isString, cssNames } from "../../utils"; +import type { IClassName } from "@k8slens/utilities"; +import { hasTypedProperty, isObject, isString, cssNames } from "@k8slens/utilities"; import { Button } from "../button"; import { Icon } from "../icon"; import { Spinner } from "../spinner"; @@ -158,7 +158,7 @@ class NonInjectedClusterStatus extends React.Component
-

{this.entity?.getName() ?? this.cluster.name}

+

{this.entity?.getName() ?? this.cluster.name.get()}

{this.renderStatusIcon()} {this.renderAuthenticationOutput()} {this.renderReconnectionHelp()} diff --git a/packages/core/src/renderer/components/cluster-manager/cluster-view.tsx b/packages/core/src/renderer/components/cluster-manager/cluster-view.tsx index 23cd98fed2..60170e1741 100644 --- a/packages/core/src/renderer/components/cluster-manager/cluster-view.tsx +++ b/packages/core/src/renderer/components/cluster-manager/cluster-view.tsx @@ -53,7 +53,11 @@ class NonInjectedClusterView extends React.Component { @computed get isReady(): boolean { const { cluster } = this; - return (cluster?.ready && cluster?.available && this.isViewLoaded.get()) ?? false; + if (!cluster) { + return false; + } + + return cluster.ready.get() && cluster.available.get() && this.isViewLoaded.get(); } componentDidMount() { diff --git a/packages/core/src/renderer/components/cluster-settings/__tests__/cluster-local-terminal-settings.test.tsx b/packages/core/src/renderer/components/cluster-settings/__tests__/cluster-local-terminal-settings.test.tsx index 50fba67427..ae807bab0a 100644 --- a/packages/core/src/renderer/components/cluster-settings/__tests__/cluster-local-terminal-settings.test.tsx +++ b/packages/core/src/renderer/components/cluster-settings/__tests__/cluster-local-terminal-settings.test.tsx @@ -8,17 +8,19 @@ import { waitFor } from "@testing-library/react"; import { ClusterLocalTerminalSetting } from "../local-terminal-settings"; import userEvent from "@testing-library/user-event"; import type { Stats } from "fs"; -import type { Cluster } from "../../../../common/cluster/cluster"; +import { Cluster } from "../../../../common/cluster/cluster"; import { getDiForUnitTesting } from "../../../getDiForUnitTesting"; import type { DiRender } from "../../test-utils/renderFor"; import { renderFor } from "../../test-utils/renderFor"; import showErrorNotificationInjectable from "../../notifications/show-error-notification.injectable"; import statInjectable from "../../../../common/fs/stat.injectable"; +import loadKubeconfigInjectable from "../../../../common/cluster/load-kubeconfig.injectable"; describe("ClusterLocalTerminalSettings", () => { let render: DiRender; let showErrorNotificationMock: jest.Mock; let statMock: jest.Mock; + let loadKubeconfigMock: jest.Mock; beforeEach(() => { const di = getDiForUnitTesting(); @@ -34,27 +36,28 @@ describe("ClusterLocalTerminalSettings", () => { () => showErrorNotificationMock, ); + loadKubeconfigMock = jest.fn(); + di.override(loadKubeconfigInjectable, () => loadKubeconfigMock); + render = renderFor(di); - - jest.resetAllMocks(); - }); - - it("should render without errors", () => { - const dom = render(); - - expect(dom.container).toBeInstanceOf(HTMLElement); }); it("should render the current settings", async () => { - const cluster = { + loadKubeconfigMock.mockImplementation(() => ({ + getContextObject: () => ({}), + })); + + const cluster = new Cluster({ + contextName: "some-context-name", + id: "some-cluster-id", + kubeConfigPath: "/some/path", preferences: { terminalCWD: "/foobar", defaultNamespace: "kube-system", }, - getKubeconfig: jest.fn(() => ({ - getContextObject: jest.fn(() => ({})), - })), - } as unknown as Cluster; + }, { + clusterServerUrl: "https://localhost:12345", + }); const dom = render(); expect(await dom.findByDisplayValue("/foobar")).toBeDefined(); @@ -62,16 +65,21 @@ describe("ClusterLocalTerminalSettings", () => { }); it("should change placeholder for 'Default Namespace' to be the namespace from the kubeconfig", async () => { - const cluster = { + loadKubeconfigMock.mockImplementation(() => ({ + getContextObject: () => ({ namespace: "blat" }), + })); + + const cluster = new Cluster({ + contextName: "some-context-name", + id: "some-cluster-id", + kubeConfigPath: "/some/path", preferences: { terminalCWD: "/foobar", }, - getKubeconfig: jest.fn(() => ({ - getContextObject: jest.fn(() => ({ - namespace: "blat", - })), - })), - } as unknown as Cluster; + }, { + clusterServerUrl: "https://localhost:12345", + }); + const dom = render(); expect(await dom.findByDisplayValue("/foobar")).toBeDefined(); @@ -79,14 +87,20 @@ describe("ClusterLocalTerminalSettings", () => { }); it("should save the new default namespace after clicking away", async () => { - const cluster = { + loadKubeconfigMock.mockImplementation(() => ({ + getContextObject: () => ({}), + })); + + const cluster = new Cluster({ + contextName: "some-context-name", + id: "some-cluster-id", + kubeConfigPath: "/some/path", preferences: { terminalCWD: "/foobar", }, - getKubeconfig: jest.fn(() => ({ - getContextObject: jest.fn(() => ({})), - })), - } as unknown as Cluster; + }, { + clusterServerUrl: "https://localhost:12345", + }); const dom = render(); const dn = await dom.findByTestId("default-namespace"); @@ -107,11 +121,17 @@ describe("ClusterLocalTerminalSettings", () => { } as Stats; }); - const cluster = { - getKubeconfig: jest.fn(() => ({ - getContextObject: jest.fn(() => ({})), - })), - } as unknown as Cluster; + loadKubeconfigMock.mockImplementation(() => ({ + getContextObject: () => ({}), + })); + + const cluster = new Cluster({ + contextName: "some-context-name", + id: "some-cluster-id", + kubeConfigPath: "/some/path", + }, { + clusterServerUrl: "https://localhost:12345", + }); const dom = render(); const dn = await dom.findByTestId("working-directory"); @@ -133,11 +153,17 @@ describe("ClusterLocalTerminalSettings", () => { } as Stats; }); - const cluster = { - getKubeconfig: jest.fn(() => ({ - getContextObject: jest.fn(() => ({})), - })), - } as unknown as Cluster; + loadKubeconfigMock.mockImplementation(() => ({ + getContextObject: () => ({}), + })); + + const cluster = new Cluster({ + contextName: "some-context-name", + id: "some-cluster-id", + kubeConfigPath: "/some/path", + }, { + clusterServerUrl: "https://localhost:12345", + }); const dom = render(); const dn = await dom.findByTestId("working-directory"); diff --git a/packages/core/src/renderer/components/cluster-settings/icon-settings.tsx b/packages/core/src/renderer/components/cluster-settings/icon-settings.tsx index 55e4b21828..f5813368e8 100644 --- a/packages/core/src/renderer/components/cluster-settings/icon-settings.tsx +++ b/packages/core/src/renderer/components/cluster-settings/icon-settings.tsx @@ -5,13 +5,13 @@ import React from "react"; import type { Cluster } from "../../../common/cluster/cluster"; -import { autoBind } from "../../utils"; import { observable } from "mobx"; import { observer } from "mobx-react"; import type { KubernetesCluster } from "../../../common/catalog-entities"; import { FilePicker, OverSizeLimitStyle } from "../file-picker"; import { MenuActions, MenuItem } from "../menu"; import { Avatar } from "../avatar"; +import autoBindReact from "auto-bind/react"; enum GeneralInputStatus { CLEAN = "clean", @@ -30,7 +30,7 @@ export class ClusterIconSetting extends React.Component constructor(props: ClusterIconSettingProps) { super(props); - autoBind(this); + autoBindReact(this); } private element = React.createRef(); diff --git a/packages/core/src/renderer/components/cluster-settings/kubeconfig.tsx b/packages/core/src/renderer/components/cluster-settings/kubeconfig.tsx index 251185ba89..f17390a588 100644 --- a/packages/core/src/renderer/components/cluster-settings/kubeconfig.tsx +++ b/packages/core/src/renderer/components/cluster-settings/kubeconfig.tsx @@ -19,7 +19,7 @@ export class ClusterKubeconfig extends React.Component { openKubeconfig = () => { const { cluster } = this.props; - shell.showItemInFolder(cluster.kubeConfigPath); + shell.showItemInFolder(cluster.kubeConfigPath.get()); }; render() { @@ -27,7 +27,9 @@ export class ClusterKubeconfig extends React.Component { - {this.props.cluster.kubeConfigPath} + + {this.props.cluster.kubeConfigPath.get()} + ); diff --git a/packages/core/src/renderer/components/cluster-settings/local-terminal-setting-presenter.injectable.ts b/packages/core/src/renderer/components/cluster-settings/local-terminal-setting-presenter.injectable.ts new file mode 100644 index 0000000000..caa5021dac --- /dev/null +++ b/packages/core/src/renderer/components/cluster-settings/local-terminal-setting-presenter.injectable.ts @@ -0,0 +1,48 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import { observable } from "mobx"; +import type { Cluster } from "../../../common/cluster/cluster"; +import loadKubeconfigInjectable from "../../../common/cluster/load-kubeconfig.injectable"; + +export interface LocalTerminalSettingPresenter { + readonly directory: { + get: () => string; + set: (value: string) => void; + }; + readonly defaultNamespace: { + get: () => string; + set: (value: string) => void; + }; + readonly placeholderDefaultNamespace: string; +} + +const localTerminalSettingPresenterInjectable = getInjectable({ + id: "local-terminal-setting-presenter", + instantiate: async (di, cluster: Cluster): Promise => { + const loadKubeconfig = di.inject(loadKubeconfigInjectable, cluster); + + const kubeconfig = await loadKubeconfig(); + + const directory = observable.box(cluster.preferences.terminalCWD || ""); + const defaultNamespace = observable.box(cluster.preferences.defaultNamespace || ""); + const placeholderDefaultNamespace = kubeconfig.getContextObject(cluster.contextName.get())?.namespace || "default"; + + return { + directory: { + get: () => directory.get(), + set: (value) => directory.set(value), + }, + defaultNamespace: { + get: () => defaultNamespace.get(), + set: (value) => defaultNamespace.set(value), + }, + placeholderDefaultNamespace, + }; + }, + lifecycle: lifecycleEnum.transient, +}); + +export default localTerminalSettingPresenterInjectable; diff --git a/packages/core/src/renderer/components/cluster-settings/local-terminal-settings.tsx b/packages/core/src/renderer/components/cluster-settings/local-terminal-settings.tsx index 64dde94c00..4e10831ac1 100644 --- a/packages/core/src/renderer/components/cluster-settings/local-terminal-settings.tsx +++ b/packages/core/src/renderer/components/cluster-settings/local-terminal-settings.tsx @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import React, { useEffect, useState } from "react"; +import React from "react"; import { observer } from "mobx-react"; import type { Cluster } from "../../../common/cluster/cluster"; import { Input } from "../input"; @@ -20,6 +20,10 @@ import Gutter from "../gutter/gutter"; import isWindowsInjectable from "../../../common/vars/is-windows.injectable"; import type { OpenPathPickingDialog } from "../../../features/path-picking-dialog/renderer/pick-paths.injectable"; import openPathPickingDialogInjectable from "../../../features/path-picking-dialog/renderer/pick-paths.injectable"; +import type { LocalTerminalSettingPresenter } from "./local-terminal-setting-presenter.injectable"; +import localTerminalSettingPresenterInjectable from "./local-terminal-setting-presenter.injectable"; +import { Spinner } from "../spinner"; +import { action, runInAction } from "mobx"; export interface ClusterLocalTerminalSettingProps { cluster: Cluster; @@ -30,70 +34,57 @@ interface Dependencies { resolveTilde: ResolveTilde; openPathPickingDialog: OpenPathPickingDialog; isWindows: boolean; + presenter: LocalTerminalSettingPresenter; } -const NonInjectedClusterLocalTerminalSetting = observer(({ - cluster, - showErrorNotification, - validateDirectory, - resolveTilde, - isWindows, - openPathPickingDialog, -}: Dependencies & ClusterLocalTerminalSettingProps) => { - if (!cluster) { - return null; - } - - const [directory, setDirectory] = useState(cluster.preferences?.terminalCWD || ""); - const [defaultNamespace, setDefaultNamespaces] = useState(cluster.preferences?.defaultNamespace || ""); - const [placeholderDefaultNamespace, setPlaceholderDefaultNamespace] = useState("default"); - - useEffect(() => { - (async () => { - const kubeconfig = await cluster.getKubeconfig(); - const { namespace } = kubeconfig.getContextObject(cluster.contextName) ?? {}; - - if (namespace) { - setPlaceholderDefaultNamespace(namespace); - } - })(); - setDirectory(cluster.preferences?.terminalCWD || ""); - setDefaultNamespaces(cluster.preferences?.defaultNamespace || ""); - }, [cluster]); - +const NonInjectedClusterLocalTerminalSetting = observer((props: Dependencies & ClusterLocalTerminalSettingProps) => { + const { + cluster, + showErrorNotification, + validateDirectory, + resolveTilde, + isWindows, + openPathPickingDialog, + presenter, + } = props; const commitDirectory = async (directory: string) => { - cluster.preferences ??= {}; - if (!directory) { - cluster.preferences.terminalCWD = undefined; - } else { - const dir = resolveTilde(directory); - const result = await validateDirectory(dir); + runInAction(() => { + cluster.preferences.terminalCWD = undefined; + }); - if (!result.callWasSuccessful) { - showErrorNotification( - <> - Terminal Working Directory -

- {"Your changes were not saved because "} - {result.error} -

- , - ); - } else { - cluster.preferences.terminalCWD = dir; - setDirectory(dir); - } + return; } + + const dir = resolveTilde(directory); + const result = await validateDirectory(dir); + + if (result.callWasSuccessful) { + runInAction(() => { + cluster.preferences.terminalCWD = dir; + presenter.directory.set(dir); + }); + + return; + } + + showErrorNotification( + <> + Terminal Working Directory +

+ {"Your changes were not saved because "} + {result.error} +

+ , + ); }; - const commitDefaultNamespace = () => { - cluster.preferences ??= {}; - cluster.preferences.defaultNamespace = defaultNamespace || undefined; - }; + const commitDefaultNamespace = action(() => { + cluster.preferences.defaultNamespace = presenter.defaultNamespace.get() || undefined; + }); const setAndCommitDirectory = (newPath: string) => { - setDirectory(newPath); + presenter.directory.set(newPath); commitDirectory(newPath); }; @@ -112,15 +103,15 @@ const NonInjectedClusterLocalTerminalSetting = observer(({ commitDirectory(directory)} + onChange={value => presenter.directory.set(value)} + onBlur={() => commitDirectory(presenter.directory.get())} placeholder={isWindows ? "$USERPROFILE" : "$HOME"} iconRight={( <> { - directory && ( + presenter.directory.get() && ( presenter.defaultNamespace.set(value)} onBlur={commitDefaultNamespace} - placeholder={placeholderDefaultNamespace} + placeholder={presenter.placeholderDefaultNamespace} /> Default namespace used for kubectl. @@ -165,12 +156,14 @@ const NonInjectedClusterLocalTerminalSetting = observer(({ }); export const ClusterLocalTerminalSetting = withInjectables(NonInjectedClusterLocalTerminalSetting, { - getProps: (di, props) => ({ + getPlaceholder: () => , + getProps: async (di, props) => ({ ...props, showErrorNotification: di.inject(showErrorNotificationInjectable), validateDirectory: di.inject(validateDirectoryInjectable), resolveTilde: di.inject(resolveTildeInjectable), isWindows: di.inject(isWindowsInjectable), openPathPickingDialog: di.inject(openPathPickingDialogInjectable), + presenter: await di.inject(localTerminalSettingPresenterInjectable, props.cluster), }), }); diff --git a/packages/core/src/renderer/components/cluster-settings/node-shell-setting.tsx b/packages/core/src/renderer/components/cluster-settings/node-shell-setting.tsx index 858ae9d20e..841d04299e 100644 --- a/packages/core/src/renderer/components/cluster-settings/node-shell-setting.tsx +++ b/packages/core/src/renderer/components/cluster-settings/node-shell-setting.tsx @@ -4,7 +4,7 @@ */ import type { Cluster } from "../../../common/cluster/cluster"; -import { makeObservable, observable } from "mobx"; +import { makeObservable, observable, runInAction } from "mobx"; import { SubTitle } from "../layout/sub-title"; import React from "react"; import { Input } from "../input/input"; @@ -28,9 +28,10 @@ export class ClusterNodeShellSetting extends React.Component { + this.props.cluster.preferences.nodeShellImage = this.nodeShellImage || undefined; + this.props.cluster.preferences.imagePullSecret = this.imagePullSecret || undefined; + }); } render() { diff --git a/packages/core/src/renderer/components/command-palette/command-container.tsx b/packages/core/src/renderer/components/command-palette/command-container.tsx index ca3d36bb00..bc8f38141b 100644 --- a/packages/core/src/renderer/components/command-palette/command-container.tsx +++ b/packages/core/src/renderer/components/command-palette/command-container.tsx @@ -22,7 +22,7 @@ import matchedClusterIdInjectable from "../../navigation/matched-cluster-id.inje import hostedClusterIdInjectable from "../../cluster-frame-context/hosted-cluster-id.injectable"; import isMacInjectable from "../../../common/vars/is-mac.injectable"; import legacyOnChannelListenInjectable from "../../ipc/legacy-channel-listen.injectable"; -import { onKeyboardShortcut } from "../../utils/on-keyboard-shortcut"; +import { onKeyboardShortcut } from "@k8slens/utilities"; interface Dependencies { addWindowEventListener: AddWindowEventListener; diff --git a/packages/core/src/renderer/components/command-palette/command-dialog.tsx b/packages/core/src/renderer/components/command-palette/command-dialog.tsx index ba4036f4c5..7a4a44651f 100644 --- a/packages/core/src/renderer/components/command-palette/command-dialog.tsx +++ b/packages/core/src/renderer/components/command-palette/command-dialog.tsx @@ -13,7 +13,7 @@ import type { CatalogEntity } from "../../../common/catalog"; import { broadcastMessage } from "../../../common/ipc"; import { IpcRendererNavigationEvents } from "../../../common/ipc/navigation-events"; import type { RegisteredCommand } from "./registered-commands/commands"; -import { iter } from "../../utils"; +import { iter } from "@k8slens/utilities"; import { withInjectables } from "@ogre-tools/injectable-react"; import registeredCommandsInjectable from "./registered-commands/registered-commands.injectable"; import type { SingleValue } from "react-select"; diff --git a/packages/core/src/renderer/components/confirm-dialog/confirm-dialog.tsx b/packages/core/src/renderer/components/confirm-dialog/confirm-dialog.tsx index d63b8dcc44..3524d33450 100644 --- a/packages/core/src/renderer/components/confirm-dialog/confirm-dialog.tsx +++ b/packages/core/src/renderer/components/confirm-dialog/confirm-dialog.tsx @@ -10,7 +10,7 @@ import React from "react"; import type { IObservableValue } from "mobx"; import { observable, makeObservable, computed } from "mobx"; import { observer } from "mobx-react"; -import { cssNames, noop, prevDefault } from "../../utils"; +import { cssNames, noop, prevDefault } from "@k8slens/utilities"; import type { ButtonProps } from "../button"; import { Button } from "../button"; import type { DialogProps } from "../dialog"; diff --git a/packages/core/src/renderer/components/countdown/countdown.test.tsx b/packages/core/src/renderer/components/countdown/countdown.test.tsx index 6a84e6970e..cdf46ce38e 100644 --- a/packages/core/src/renderer/components/countdown/countdown.test.tsx +++ b/packages/core/src/renderer/components/countdown/countdown.test.tsx @@ -10,10 +10,10 @@ import { renderFor } from "../test-utils/renderFor"; import { Countdown } from "./countdown"; import React from "react"; import type { RenderResult } from "@testing-library/react"; -import { advanceFakeTime, testUsingFakeTime } from "../../../common/test-utils/use-fake-time"; import type { IComputedValue } from "mobx"; import { observe } from "mobx"; -import { noop } from "../../../common/utils"; +import { noop } from "@k8slens/utilities"; +import { testUsingFakeTime, advanceFakeTime } from "../../../test-utils/use-fake-time"; describe("countdown", () => { let di: DiContainer; diff --git a/packages/core/src/renderer/components/delete-cluster-dialog/is-current-context.tsx b/packages/core/src/renderer/components/delete-cluster-dialog/is-current-context.tsx index e0eebcea63..cbd18ad358 100644 --- a/packages/core/src/renderer/components/delete-cluster-dialog/is-current-context.tsx +++ b/packages/core/src/renderer/components/delete-cluster-dialog/is-current-context.tsx @@ -6,5 +6,5 @@ import type { KubeConfig } from "@kubernetes/client-node"; import type { Cluster } from "../../../common/cluster/cluster"; export function isCurrentContext(config: KubeConfig, cluster: Cluster) { - return config.currentContext == cluster.contextName; + return config.currentContext == cluster.contextName.get(); } diff --git a/packages/core/src/renderer/components/delete-cluster-dialog/is-in-local-kubeconfig.injectable.ts b/packages/core/src/renderer/components/delete-cluster-dialog/is-in-local-kubeconfig.injectable.ts new file mode 100644 index 0000000000..65e43fbb85 --- /dev/null +++ b/packages/core/src/renderer/components/delete-cluster-dialog/is-in-local-kubeconfig.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 directoryForKubeConfigsInjectable from "../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable"; +import type { Cluster } from "../../../common/cluster/cluster"; + +export type IsInLocalKubeconfig = (cluster: Cluster) => boolean; + +const isInLocalKubeconfigInjectable = getInjectable({ + id: "is-in-local-kubeconfig", + instantiate: (di): IsInLocalKubeconfig => { + const directoryForKubeConfigs = di.inject(directoryForKubeConfigsInjectable); + + return cluster => cluster.kubeConfigPath.get().startsWith(directoryForKubeConfigs); + }, +}); + +export default isInLocalKubeconfigInjectable; diff --git a/packages/core/src/renderer/components/delete-cluster-dialog/save-kubeconfig.global-override-for-injectable.ts b/packages/core/src/renderer/components/delete-cluster-dialog/save-kubeconfig.global-override-for-injectable.ts index 6fca6db49b..7fce77a2b1 100644 --- a/packages/core/src/renderer/components/delete-cluster-dialog/save-kubeconfig.global-override-for-injectable.ts +++ b/packages/core/src/renderer/components/delete-cluster-dialog/save-kubeconfig.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import saveKubeconfigInjectable from "./save-kubeconfig.injectable"; export default getGlobalOverride(saveKubeconfigInjectable, () => async () => { diff --git a/packages/core/src/renderer/components/delete-cluster-dialog/view.tsx b/packages/core/src/renderer/components/delete-cluster-dialog/view.tsx index 78b06c7fe2..b1548354fd 100644 --- a/packages/core/src/renderer/components/delete-cluster-dialog/view.tsx +++ b/packages/core/src/renderer/components/delete-cluster-dialog/view.tsx @@ -30,6 +30,8 @@ import type { SaveKubeconfig } from "./save-kubeconfig.injectable"; import saveKubeconfigInjectable from "./save-kubeconfig.injectable"; import showErrorNotificationInjectable from "../notifications/show-error-notification.injectable"; import { isCurrentContext } from "./is-current-context"; +import type { IsInLocalKubeconfig } from "./is-in-local-kubeconfig.injectable"; +import isInLocalKubeconfigInjectable from "./is-in-local-kubeconfig.injectable"; interface Dependencies { state: IObservableValue; @@ -39,6 +41,7 @@ interface Dependencies { requestClearClusterAsDeleting: RequestClearClusterAsDeleting; showErrorNotification: ShowNotification; saveKubeconfig: SaveKubeconfig; + isInLocalKubeconfig: IsInLocalKubeconfig; } @observer @@ -52,7 +55,7 @@ class NonInjectedDeleteClusterDialog extends React.Component { this.props.state.set({ ...state, config: Object.assign(config, { - contexts: config.contexts.filter(item => item.name !== state.cluster.contextName), + contexts: config.contexts.filter(item => item.name !== state.cluster.contextName.get()), currentContext: newCurrentContext && showContextSwitch ? newCurrentContext : config.currentContext, @@ -61,7 +64,7 @@ class NonInjectedDeleteClusterDialog extends React.Component { }); try { - await this.props.saveKubeconfig(config, cluster.kubeConfigPath); + await this.props.saveKubeconfig(config, cluster.kubeConfigPath.get()); this.props.hotbarStore.removeAllHotbarItems(cluster.id); await this.props.requestDeleteCluster(cluster.id); } catch(error) { @@ -73,7 +76,7 @@ class NonInjectedDeleteClusterDialog extends React.Component { } shouldDeleteBeDisabled({ cluster, config, newCurrentContext, showContextSwitch }: DeleteClusterDialogState): boolean { - const noContextsAvailable = config.contexts.filter(context => context.name !== cluster.contextName).length == 0; + const noContextsAvailable = config.contexts.filter(context => context.name !== cluster.contextName.get()).length == 0; const newContextNotSelected = newCurrentContext === ""; if (noContextsAvailable) { @@ -92,7 +95,7 @@ class NonInjectedDeleteClusterDialog extends React.Component { const selectOptions = config .contexts - .filter(context => context.name !== cluster.contextName) + .filter(context => context.name !== cluster.contextName.get()) .map(context => ({ value: context.name, label: context.name, @@ -121,7 +124,7 @@ class NonInjectedDeleteClusterDialog extends React.Component { } renderDeleteMessage({ cluster }: DeleteClusterDialogState) { - if (cluster.isInLocalKubeconfig()) { + if (this.props.isInLocalKubeconfig(cluster)) { return (
{"Delete the "} @@ -141,7 +144,7 @@ class NonInjectedDeleteClusterDialog extends React.Component { {" context from "} - {cluster.kubeConfigPath} + {cluster.kubeConfigPath.get()} ?
@@ -149,7 +152,7 @@ class NonInjectedDeleteClusterDialog extends React.Component { } getWarningMessage({ cluster, config }: DeleteClusterDialogState) { - if (cluster.isInLocalKubeconfig()) { + if (this.props.isInLocalKubeconfig(cluster)) { return (

Are you sure you want to delete it? It can be re-added through the copy/paste mechanism. @@ -157,7 +160,7 @@ class NonInjectedDeleteClusterDialog extends React.Component { ); } - const contexts = config.contexts.filter(context => context.name !== cluster.contextName); + const contexts = config.contexts.filter(context => context.name !== cluster.contextName.get()); if (!contexts.length) { return ( @@ -191,7 +194,7 @@ class NonInjectedDeleteClusterDialog extends React.Component { renderContents(state: DeleteClusterDialogState) { const { config, cluster, showContextSwitch } = state; - const contexts = state.config.contexts.filter(context => context.name !== state.cluster.contextName); + const contexts = state.config.contexts.filter(context => context.name !== state.cluster.contextName.get()); const disableDelete = this.shouldDeleteBeDisabled(state); const currentContext = isCurrentContext(config, cluster); @@ -271,5 +274,6 @@ export const DeleteClusterDialog = withInjectables(NonInjectedDele requestDeleteCluster: di.inject(requestDeleteClusterInjectable), saveKubeconfig: di.inject(saveKubeconfigInjectable), showErrorNotification: di.inject(showErrorNotificationInjectable), + isInLocalKubeconfig: di.inject(isInLocalKubeconfigInjectable), }), }); diff --git a/packages/core/src/renderer/components/dialog/dialog.tsx b/packages/core/src/renderer/components/dialog/dialog.tsx index 0d7bfb24c7..765d9b7317 100644 --- a/packages/core/src/renderer/components/dialog/dialog.tsx +++ b/packages/core/src/renderer/components/dialog/dialog.tsx @@ -10,7 +10,7 @@ import { createPortal } from "react-dom"; import { disposeOnUnmount, observer } from "mobx-react"; import { reaction } from "mobx"; import { Animate } from "../animate"; -import { cssNames, noop, stopPropagation } from "../../utils"; +import { cssNames, noop, stopPropagation } from "@k8slens/utilities"; import type { ObservableHistory } from "mobx-observable-history"; import { withInjectables } from "@ogre-tools/injectable-react"; import observableHistoryInjectable from "../../navigation/observable-history.injectable"; diff --git a/packages/core/src/renderer/components/dock/create-resource/user-templates.injectable.ts b/packages/core/src/renderer/components/dock/create-resource/user-templates.injectable.ts index 65b896f95d..d69b5b0772 100644 --- a/packages/core/src/renderer/components/dock/create-resource/user-templates.injectable.ts +++ b/packages/core/src/renderer/components/dock/create-resource/user-templates.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { computed, observable } from "mobx"; -import { delay, getOrInsert, isErrnoException, waitForPath } from "../../../utils"; +import { delay, getOrInsert, isErrnoException } from "@k8slens/utilities"; import { readFile } from "fs/promises"; import { hasCorrectExtension } from "./has-correct-extension"; import type { RawTemplates } from "./create-resource-templates.injectable"; @@ -15,6 +15,7 @@ import homeDirectoryPathInjectable from "../../../../common/os/home-directory-pa import getDirnameOfPathInjectable from "../../../../common/path/get-dirname.injectable"; import loggerInjectable from "../../../../common/logger.injectable"; import parsePathInjectable from "../../../../common/path/parse.injectable"; +import { waitForPath } from "../../../../common/utils/wait-for-path"; const userCreateResourceTemplatesInjectable = getInjectable({ id: "user-create-resource-templates", diff --git a/packages/core/src/renderer/components/dock/create-resource/view.tsx b/packages/core/src/renderer/components/dock/create-resource/view.tsx index 63db3068ab..73d6989b82 100644 --- a/packages/core/src/renderer/components/dock/create-resource/view.tsx +++ b/packages/core/src/renderer/components/dock/create-resource/view.tsx @@ -16,7 +16,7 @@ import { InfoPanel } from "../info-panel"; import type { ShowNotification } from "../../notifications"; import type { Logger } from "../../../../common/logger"; import type { ApiManager } from "../../../../common/k8s-api/api-manager"; -import { isObject, prevDefault } from "../../../utils"; +import { isObject, prevDefault } from "@k8slens/utilities"; import { withInjectables } from "@ogre-tools/injectable-react"; import createResourceTabStoreInjectable from "./store.injectable"; import createResourceTemplatesInjectable from "./create-resource-templates.injectable"; diff --git a/packages/core/src/renderer/components/dock/dock-tab-store/dock-tab.store.ts b/packages/core/src/renderer/components/dock/dock-tab-store/dock-tab.store.ts index d6ec705d2a..4a713a4a35 100644 --- a/packages/core/src/renderer/components/dock/dock-tab-store/dock-tab.store.ts +++ b/packages/core/src/renderer/components/dock/dock-tab-store/dock-tab.store.ts @@ -4,10 +4,11 @@ */ import { action, observable, reaction } from "mobx"; -import type { StorageLayer } from "../../../utils"; -import { autoBind, toJS } from "../../../utils"; +import type { StorageLayer } from "../../../utils/storage-helper"; import type { CreateStorage } from "../../../utils/create-storage/create-storage.injectable"; import type { TabId } from "../dock/store"; +import autoBind from "auto-bind"; +import { toJS } from "../../../../common/utils"; export interface DockTabStoreOptions { autoInit?: boolean; // load data from storage when `storageKey` is provided and bind events, default: true diff --git a/packages/core/src/renderer/components/dock/dock-tab.tsx b/packages/core/src/renderer/components/dock/dock-tab.tsx index 5a672e2fb3..c65ea76ac9 100644 --- a/packages/core/src/renderer/components/dock/dock-tab.tsx +++ b/packages/core/src/renderer/components/dock/dock-tab.tsx @@ -7,7 +7,7 @@ import styles from "./dock-tab.module.scss"; import React from "react"; import { observer } from "mobx-react"; -import { autoBind, cssNames, prevDefault, isMiddleClick } from "../../utils"; +import { cssNames, prevDefault, isMiddleClick } from "@k8slens/utilities"; import type { DockStore, DockTab as DockTabModel } from "./dock/store"; import type { TabProps } from "../tabs"; import { Tab } from "../tabs"; @@ -18,6 +18,7 @@ import { withInjectables } from "@ogre-tools/injectable-react"; import dockStoreInjectable from "./dock/store.injectable"; import { Tooltip, TooltipPosition } from "../tooltip"; import isMacInjectable from "../../../common/vars/is-mac.injectable"; +import autoBindReact from "auto-bind/react"; export interface DockTabProps extends TabProps { moreActions?: React.ReactNode; @@ -34,7 +35,7 @@ class NonInjectedDockTab extends React.Component { constructor(props: DockTabProps & Dependencies) { super(props); - autoBind(this); + autoBindReact(this); } close(id: string) { diff --git a/packages/core/src/renderer/components/dock/dock-tabs.tsx b/packages/core/src/renderer/components/dock/dock-tabs.tsx index 87b4aa756b..1dd274c4db 100644 --- a/packages/core/src/renderer/components/dock/dock-tabs.tsx +++ b/packages/core/src/renderer/components/dock/dock-tabs.tsx @@ -11,7 +11,7 @@ import { DockTab } from "./dock-tab"; import type { DockTab as DockTabModel } from "./dock/store"; import { TabKind } from "./dock/store"; import { TerminalTab } from "./terminal/dock-tab"; -import { cssVar } from "../../utils"; +import { cssVar } from "@k8slens/utilities"; import { useResizeObserver } from "../../hooks"; export interface DockTabsProps { diff --git a/packages/core/src/renderer/components/dock/dock.tsx b/packages/core/src/renderer/components/dock/dock.tsx index ee4ff542b3..b0e2b010c6 100644 --- a/packages/core/src/renderer/components/dock/dock.tsx +++ b/packages/core/src/renderer/components/dock/dock.tsx @@ -6,7 +6,7 @@ import "./dock.scss"; import React from "react"; import { observer } from "mobx-react"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import { Icon } from "../icon"; import { MenuItem } from "../menu"; import { MenuActions } from "../menu/menu-actions"; diff --git a/packages/core/src/renderer/components/dock/dock/store.ts b/packages/core/src/renderer/components/dock/dock/store.ts index 48e04c3a76..b71f0e1093 100644 --- a/packages/core/src/renderer/components/dock/dock/store.ts +++ b/packages/core/src/renderer/components/dock/dock/store.ts @@ -5,9 +5,9 @@ import * as uuid from "uuid"; import { action, comparer, computed, makeObservable, observable, reaction, runInAction } from "mobx"; -import type { StorageLayer } from "../../../utils"; -import { autoBind } from "../../../utils"; import throttle from "lodash/throttle"; +import type { StorageLayer } from "../../../utils/storage-helper"; +import autoBind from "auto-bind"; export type TabId = string; diff --git a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource/call-for-patch-resource.global-override-for-injectable.ts b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource/call-for-patch-resource.global-override-for-injectable.ts index ca999211f5..c85ebb53cd 100644 --- a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource/call-for-patch-resource.global-override-for-injectable.ts +++ b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource/call-for-patch-resource.global-override-for-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 { getGlobalOverride } from "../../../../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import callForPatchResourceInjectable from "./call-for-patch-resource.injectable"; export default getGlobalOverride(callForPatchResourceInjectable, () => () => { diff --git a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource/call-for-patch-resource.injectable.ts b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource/call-for-patch-resource.injectable.ts index 097ef1ccf3..ddee1e6810 100644 --- a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource/call-for-patch-resource.injectable.ts +++ b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource/call-for-patch-resource.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 type { AsyncResult } from "../../../../../../common/utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; import apiManagerInjectable from "../../../../../../common/k8s-api/api-manager/manager.injectable"; import type { JsonPatch } from "../../../../../../common/k8s-api/kube-object.store"; import type { KubeObject } from "../../../../../../common/k8s-api/kube-object"; @@ -13,7 +13,7 @@ import { getErrorMessage } from "../../../../../../common/utils/get-error-messag export type CallForPatchResource = ( item: KubeObject, patch: JsonPatch -) => Promise>; +) => AsyncResult<{ name: string; kind: string }>; const callForPatchResourceInjectable = getInjectable({ id: "call-for-patch-resource", diff --git a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource/call-for-resource.global-override-for-injectable.ts b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource/call-for-resource.global-override-for-injectable.ts index a4e768da9a..6eca686d3f 100644 --- a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource/call-for-resource.global-override-for-injectable.ts +++ b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource/call-for-resource.global-override-for-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 { getGlobalOverride } from "../../../../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import callForResourceInjectable from "./call-for-resource.injectable"; export default getGlobalOverride(callForResourceInjectable, () => () => { diff --git a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource/call-for-resource.injectable.ts b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource/call-for-resource.injectable.ts index a74da59c78..af9fd15a26 100644 --- a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource/call-for-resource.injectable.ts +++ b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource/call-for-resource.injectable.ts @@ -5,14 +5,14 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { KubeObject } from "../../../../../../common/k8s-api/kube-object"; import { parseKubeApi } from "../../../../../../common/k8s-api/kube-api-parse"; -import type { AsyncResult } from "../../../../../../common/utils/async-result"; +import type { AsyncResult } from "@k8slens/utilities"; import { getErrorMessage } from "../../../../../../common/utils/get-error-message"; import apiManagerInjectable from "../../../../../../common/k8s-api/api-manager/manager.injectable"; -import { waitUntilDefined } from "../../../../../../common/utils"; +import { waitUntilDefined } from "@k8slens/utilities"; export type CallForResource = ( selfLink: string -) => Promise>; +) => AsyncResult; const callForResourceInjectable = getInjectable({ id: "call-for-resource", diff --git a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/edit-resource-model.injectable.tsx b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/edit-resource-model.injectable.tsx index a6ffe22423..7b2386e189 100644 --- a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/edit-resource-model.injectable.tsx +++ b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/edit-resource-model.injectable.tsx @@ -5,7 +5,7 @@ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; import type { CallForResource } from "./call-for-resource/call-for-resource.injectable"; import callForResourceInjectable from "./call-for-resource/call-for-resource.injectable"; -import { waitUntilDefined } from "../../../../../common/utils"; +import { waitUntilDefined } from "@k8slens/utilities"; import editResourceTabStoreInjectable from "../store.injectable"; import type { EditResourceTabStore } from "../store"; import { action, computed, makeObservable, observable, runInAction } from "mobx"; diff --git a/packages/core/src/renderer/components/dock/editor-panel.tsx b/packages/core/src/renderer/components/dock/editor-panel.tsx index d9eca59159..1d009a356d 100644 --- a/packages/core/src/renderer/components/dock/editor-panel.tsx +++ b/packages/core/src/renderer/components/dock/editor-panel.tsx @@ -9,7 +9,7 @@ import React, { createRef, useEffect } from "react"; import { reaction } from "mobx"; import { observer } from "mobx-react"; import type { DockStore, TabId } from "./dock/store"; -import { cssNames, disposer } from "../../utils"; +import { cssNames, disposer } from "@k8slens/utilities"; import { MonacoEditor } from "../monaco-editor"; import type { MonacoEditorProps, MonacoEditorRef } from "../monaco-editor"; import { withInjectables } from "@ogre-tools/injectable-react"; diff --git a/packages/core/src/renderer/components/dock/info-panel.tsx b/packages/core/src/renderer/components/dock/info-panel.tsx index 8f1ac32266..0b951d8722 100644 --- a/packages/core/src/renderer/components/dock/info-panel.tsx +++ b/packages/core/src/renderer/components/dock/info-panel.tsx @@ -9,7 +9,7 @@ import type { ReactNode } from "react"; import React, { Component } from "react"; import { computed, observable, reaction, makeObservable } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import { Button } from "../button"; import { Icon } from "../icon"; import { Spinner } from "../spinner"; diff --git a/packages/core/src/renderer/components/dock/install-chart/install-chart-model.injectable.tsx b/packages/core/src/renderer/components/dock/install-chart/install-chart-model.injectable.tsx index b0bfcfcacc..e9c7f6cbcb 100644 --- a/packages/core/src/renderer/components/dock/install-chart/install-chart-model.injectable.tsx +++ b/packages/core/src/renderer/components/dock/install-chart/install-chart-model.injectable.tsx @@ -4,7 +4,7 @@ */ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; import installChartTabStoreInjectable from "./store.injectable"; -import { waitUntilDefined } from "../../../../common/utils"; +import { waitUntilDefined } from "@k8slens/utilities"; import type { IChartInstallData, InstallChartTabStore } from "./store"; import type { HelmChart } from "../../../../common/k8s-api/endpoints/helm-charts.api"; import React from "react"; @@ -131,7 +131,7 @@ export class InstallChartModel { if (!chartValuesRequest.callWasSuccessful) { throw chartValuesRequest.error; } - + runInAction(() => { this.configuration.onChange(chartValuesRequest.response); this.configuration.isLoading.set(false); diff --git a/packages/core/src/renderer/components/dock/install-chart/view.tsx b/packages/core/src/renderer/components/dock/install-chart/view.tsx index 714259bd85..d478febd55 100644 --- a/packages/core/src/renderer/components/dock/install-chart/view.tsx +++ b/packages/core/src/renderer/components/dock/install-chart/view.tsx @@ -10,7 +10,7 @@ import { observer } from "mobx-react"; import { InfoPanel } from "../info-panel"; import { Badge } from "../../badge"; import { NamespaceSelect } from "../../+namespaces/namespace-select"; -import { prevDefault } from "../../../utils"; +import { prevDefault } from "@k8slens/utilities"; import { Icon } from "../../icon"; import { Button } from "../../button"; import { LogsDialog } from "../../dialog/logs-dialog"; diff --git a/packages/core/src/renderer/components/dock/logs/__test__/to-bottom.test.tsx b/packages/core/src/renderer/components/dock/logs/__test__/to-bottom.test.tsx index 2aa43bb13b..9b864f1fed 100644 --- a/packages/core/src/renderer/components/dock/logs/__test__/to-bottom.test.tsx +++ b/packages/core/src/renderer/components/dock/logs/__test__/to-bottom.test.tsx @@ -6,7 +6,7 @@ import React from "react"; import "@testing-library/jest-dom/extend-expect"; import { fireEvent } from "@testing-library/react"; import { ToBottom } from "../to-bottom"; -import { noop } from "../../../../utils"; +import { noop } from "@k8slens/utilities"; import type { DiRender } from "../../../test-utils/renderFor"; import { renderFor } from "../../../test-utils/renderFor"; import { getDiForUnitTesting } from "../../../../getDiForUnitTesting"; diff --git a/packages/core/src/renderer/components/dock/logs/list.tsx b/packages/core/src/renderer/components/dock/logs/list.tsx index 0290049ccc..6b3eded365 100644 --- a/packages/core/src/renderer/components/dock/logs/list.tsx +++ b/packages/core/src/renderer/components/dock/logs/list.tsx @@ -16,7 +16,7 @@ import moment from "moment-timezone"; import type { Align, ListOnScrollProps } from "react-window"; import { SearchStore } from "../../../search-store/search-store"; import type { UserStore } from "../../../../common/user-store"; -import { array, autoBind, cssNames } from "../../../utils"; +import { array, cssNames } from "@k8slens/utilities"; import type { VirtualListRef } from "../../virtual-list"; import { VirtualList } from "../../virtual-list"; import { ToBottom } from "./to-bottom"; @@ -24,6 +24,7 @@ import type { LogTabViewModel } from "../logs/logs-view-model"; import { Spinner } from "../../spinner"; import { withInjectables } from "@ogre-tools/injectable-react"; import userStoreInjectable from "../../../../common/user-store/user-store.injectable"; +import autoBindReact from "auto-bind/react"; export interface LogListProps { model: LogTabViewModel; @@ -51,7 +52,7 @@ class NonForwardedLogList extends React.Component extends React.Component { constructor(props: Props) { super(props); - autoBind(this); + autoBindReact(this); } componentDidMount() { diff --git a/packages/core/src/renderer/components/dock/terminal/send-command.injectable.ts b/packages/core/src/renderer/components/dock/terminal/send-command.injectable.ts index 63902d34e1..c3fc64c7df 100644 --- a/packages/core/src/renderer/components/dock/terminal/send-command.injectable.ts +++ b/packages/core/src/renderer/components/dock/terminal/send-command.injectable.ts @@ -6,8 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import { when } from "mobx"; import loggerInjectable from "../../../../common/logger.injectable"; import { TerminalChannels } from "../../../../common/terminal/channels"; -import { waitUntilDefined } from "../../../../common/utils/wait"; -import { noop } from "../../../utils"; +import { waitUntilDefined, noop } from "@k8slens/utilities"; import showSuccessNotificationInjectable from "../../notifications/show-success-notification.injectable"; import selectDockTabInjectable from "../dock/select-dock-tab.injectable"; import type { TabId } from "../dock/store"; @@ -21,7 +20,7 @@ export interface SendCommandOptions { enter?: boolean; /** - * @deprecated This option is ignored and infered to be `true` if `tabId` is not provided + * @deprecated This option is ignored and inferred to be `true` if `tabId` is not provided */ newTab?: any; diff --git a/packages/core/src/renderer/components/dock/terminal/terminal.ts b/packages/core/src/renderer/components/dock/terminal/terminal.ts index 5f49882f1c..9e307aa7dc 100644 --- a/packages/core/src/renderer/components/dock/terminal/terminal.ts +++ b/packages/core/src/renderer/components/dock/terminal/terminal.ts @@ -10,7 +10,7 @@ import { Terminal as XTerm } from "xterm"; import { FitAddon } from "xterm-addon-fit"; import type { TabId } from "../dock/store"; import type { TerminalApi } from "../../../api/terminal-api"; -import { disposer } from "../../../utils"; +import { disposer } from "@k8slens/utilities"; import { once } from "lodash"; import { clipboard } from "electron"; import type { Logger } from "../../../../common/logger"; diff --git a/packages/core/src/renderer/components/dock/terminal/view.tsx b/packages/core/src/renderer/components/dock/terminal/view.tsx index b85824cc30..4bdde69f89 100644 --- a/packages/core/src/renderer/components/dock/terminal/view.tsx +++ b/packages/core/src/renderer/components/dock/terminal/view.tsx @@ -7,7 +7,7 @@ import "./terminal-window.scss"; import React from "react"; import { disposeOnUnmount, observer } from "mobx-react"; -import { cssNames } from "../../../utils"; +import { cssNames } from "@k8slens/utilities"; import type { Terminal } from "./terminal"; import type { TerminalStore } from "./store"; import type { LensTheme } from "../../../themes/lens-theme"; diff --git a/packages/core/src/renderer/components/dock/upgrade-chart/tab-data.injectable.ts b/packages/core/src/renderer/components/dock/upgrade-chart/tab-data.injectable.ts index 0189ecf6a7..38c8491fb5 100644 --- a/packages/core/src/renderer/components/dock/upgrade-chart/tab-data.injectable.ts +++ b/packages/core/src/renderer/components/dock/upgrade-chart/tab-data.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; -import { waitUntilDefined } from "../../../utils"; +import { waitUntilDefined } from "@k8slens/utilities"; import upgradeChartTabStoreInjectable from "./store.injectable"; const upgradeChartTabDataInjectable = getInjectable({ diff --git a/packages/core/src/renderer/components/dock/upgrade-chart/upgrade-chart-model.injectable.ts b/packages/core/src/renderer/components/dock/upgrade-chart/upgrade-chart-model.injectable.ts index bf3d9a0214..4683410f8b 100644 --- a/packages/core/src/renderer/components/dock/upgrade-chart/upgrade-chart-model.injectable.ts +++ b/packages/core/src/renderer/components/dock/upgrade-chart/upgrade-chart-model.injectable.ts @@ -13,8 +13,8 @@ import releasesInjectable from "../../+helm-releases/releases.injectable"; import updateReleaseInjectable from "../../+helm-releases/update-release/update-release.injectable"; import type { HelmRelease } from "../../../../common/k8s-api/endpoints/helm-releases.api"; import requestHelmReleaseConfigurationInjectable from "../../../../common/k8s-api/endpoints/helm-releases.api/request-configuration.injectable"; -import type { AsyncResult } from "../../../../common/utils/async-result"; -import { waitUntilDefined } from "../../../utils"; +import type { AsyncResult } from "@k8slens/utilities"; +import { waitUntilDefined } from "@k8slens/utilities"; import type { SelectOption } from "../../select"; import type { DockTab } from "../dock/store"; import upgradeChartTabDataInjectable from "./tab-data.injectable"; @@ -22,7 +22,7 @@ import upgradeChartTabDataInjectable from "./tab-data.injectable"; export interface UpgradeChartModel { readonly release: HelmRelease; readonly versionOptions: IComputedValue[]>; - readonly configration: { + readonly configuration: { readonly value: IComputedValue; set: (value: string) => void; readonly error: IComputedValue; @@ -32,7 +32,7 @@ export interface UpgradeChartModel { readonly value: IComputedValue; set: (value: SingleValue>) => void; }; - submit: () => Promise>; + submit: () => AsyncResult; } const upgradeChartModelInjectable = getInjectable({ @@ -69,7 +69,7 @@ const upgradeChartModelInjectable = getInjectable({ const configrationValue = observable.box(); const configrationEditError = observable.box(); - const configration: UpgradeChartModel["configration"] = { + const configration: UpgradeChartModel["configuration"] = { value: computed(() => configrationValue.get() ?? storedConfiguration.value.get()), set: action((value) => { configrationValue.set(value); @@ -97,7 +97,7 @@ const upgradeChartModelInjectable = getInjectable({ return { release, versionOptions, - configration, + configuration: configration, version, submit: async () => { const selectedVersion = version.value.get(); diff --git a/packages/core/src/renderer/components/dock/upgrade-chart/view.tsx b/packages/core/src/renderer/components/dock/upgrade-chart/view.tsx index 35dbd0242b..16e6b641c4 100644 --- a/packages/core/src/renderer/components/dock/upgrade-chart/view.tsx +++ b/packages/core/src/renderer/components/dock/upgrade-chart/view.tsx @@ -7,7 +7,7 @@ import "./upgrade-chart.scss"; import React from "react"; import { observer } from "mobx-react"; -import { cssNames } from "../../../utils"; +import { cssNames } from "@k8slens/utilities"; import type { DockTab } from "../dock/store"; import { InfoPanel } from "../info-panel"; import { Spinner } from "../../spinner"; @@ -61,7 +61,7 @@ export class NonInjectedUpgradeChart extends React.Component

); diff --git a/packages/core/src/renderer/components/drawer/drawer-item.tsx b/packages/core/src/renderer/components/drawer/drawer-item.tsx index 72a311794c..8c17d1ae91 100644 --- a/packages/core/src/renderer/components/drawer/drawer-item.tsx +++ b/packages/core/src/renderer/components/drawer/drawer-item.tsx @@ -5,7 +5,7 @@ import "./drawer-item.scss"; import React from "react"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; export interface DrawerItemProps extends React.HTMLAttributes { name: React.ReactNode; diff --git a/packages/core/src/renderer/components/drawer/drawer-param-toggler.tsx b/packages/core/src/renderer/components/drawer/drawer-param-toggler.tsx index 42d4c056e9..2c4702fcde 100644 --- a/packages/core/src/renderer/components/drawer/drawer-param-toggler.tsx +++ b/packages/core/src/renderer/components/drawer/drawer-param-toggler.tsx @@ -6,7 +6,7 @@ import "./drawer-param-toggler.scss"; import React from "react"; import { Icon } from "../icon"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; export interface DrawerParamTogglerProps { label: string | number; diff --git a/packages/core/src/renderer/components/drawer/drawer-title.tsx b/packages/core/src/renderer/components/drawer/drawer-title.tsx index d920a9cef9..1b3b6d3d0f 100644 --- a/packages/core/src/renderer/components/drawer/drawer-title.tsx +++ b/packages/core/src/renderer/components/drawer/drawer-title.tsx @@ -5,7 +5,7 @@ import styles from "./drawer-title.module.css"; import React from "react"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; export interface DrawerTitleProps { className?: string; diff --git a/packages/core/src/renderer/components/drawer/drawer.tsx b/packages/core/src/renderer/components/drawer/drawer.tsx index 7a87d1a47f..5959c0c098 100644 --- a/packages/core/src/renderer/components/drawer/drawer.tsx +++ b/packages/core/src/renderer/components/drawer/drawer.tsx @@ -8,8 +8,8 @@ import "./drawer.scss"; import React from "react"; import { clipboard } from "electron"; import { createPortal } from "react-dom"; -import type { SingleOrMany, StorageLayer } from "../../utils"; -import { cssNames, noop } from "../../utils"; +import type { SingleOrMany } from "@k8slens/utilities"; +import { cssNames, noop } from "@k8slens/utilities"; import { Icon } from "../icon"; import type { AnimateName } from "../animate"; import { Animate } from "../animate"; @@ -18,6 +18,7 @@ import drawerStorageInjectable, { defaultDrawerWidth } from "./drawer-storage/dr import { withInjectables } from "@ogre-tools/injectable-react"; import historyInjectable from "../../navigation/history.injectable"; import type { History } from "history"; +import type { StorageLayer } from "../../utils/storage-helper"; export type DrawerPosition = "top" | "left" | "right" | "bottom"; diff --git a/packages/core/src/renderer/components/duration/reactive-duration.tsx b/packages/core/src/renderer/components/duration/reactive-duration.tsx index 42a6b0949b..57eed992f7 100644 --- a/packages/core/src/renderer/components/duration/reactive-duration.tsx +++ b/packages/core/src/renderer/components/duration/reactive-duration.tsx @@ -5,7 +5,7 @@ import { observer } from "mobx-react"; import React from "react"; -import { formatDuration } from "../../utils"; +import { formatDuration } from "@k8slens/utilities"; import { reactiveNow } from "../../../common/utils/reactive-now/reactive-now"; export interface ReactiveDurationProps { diff --git a/packages/core/src/renderer/components/editable-list/editable-list.tsx b/packages/core/src/renderer/components/editable-list/editable-list.tsx index 48d19a7006..7a11df7749 100644 --- a/packages/core/src/renderer/components/editable-list/editable-list.tsx +++ b/packages/core/src/renderer/components/editable-list/editable-list.tsx @@ -11,8 +11,8 @@ import React from "react"; import { Icon } from "../icon"; import type { InputProps, InputValidator } from "../input"; import { Input } from "../input"; -import { autoBind } from "../../utils"; -import type { SingleOrMany } from "../../utils"; +import type { SingleOrMany } from "@k8slens/utilities"; +import autoBindReact from "auto-bind/react"; export interface EditableListProps { items: T[]; @@ -39,7 +39,7 @@ class DefaultedEditableList extends React.Component & ty constructor(props: EditableListProps & typeof defaultProps) { super(props); - autoBind(this); + autoBindReact(this); } onSubmit(val: string, evt: React.KeyboardEvent) { diff --git a/packages/core/src/renderer/components/error-boundary/error-boundary.tsx b/packages/core/src/renderer/components/error-boundary/error-boundary.tsx index 6e39867109..4d732a3ded 100644 --- a/packages/core/src/renderer/components/error-boundary/error-boundary.tsx +++ b/packages/core/src/renderer/components/error-boundary/error-boundary.tsx @@ -10,7 +10,7 @@ import React from "react"; import { observer } from "mobx-react"; import { Button } from "../button"; import { issuesTrackerUrl, forumsUrl } from "../../../common/vars"; -import type { SingleOrMany } from "../../utils"; +import type { SingleOrMany } from "@k8slens/utilities"; import type { ObservableHistory } from "mobx-observable-history"; import { withInjectables } from "@ogre-tools/injectable-react"; import observableHistoryInjectable from "../../navigation/observable-history.injectable"; diff --git a/packages/core/src/renderer/components/gutter/gutter.tsx b/packages/core/src/renderer/components/gutter/gutter.tsx index c0fce2b6ba..0627235bf2 100644 --- a/packages/core/src/renderer/components/gutter/gutter.tsx +++ b/packages/core/src/renderer/components/gutter/gutter.tsx @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import React from "react"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import styles from "./gutter.module.scss"; interface GutterProps { diff --git a/packages/core/src/renderer/components/horizontal-line/horizontal-line.tsx b/packages/core/src/renderer/components/horizontal-line/horizontal-line.tsx index 107a269b35..d9861482b0 100644 --- a/packages/core/src/renderer/components/horizontal-line/horizontal-line.tsx +++ b/packages/core/src/renderer/components/horizontal-line/horizontal-line.tsx @@ -4,7 +4,7 @@ */ import React from "react"; import styles from "./horizontal-line.module.scss"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; interface HorizontalLineProps { size?: "sm" | "md" | "xl"; diff --git a/packages/core/src/renderer/components/hotbar/hotbar-cell.tsx b/packages/core/src/renderer/components/hotbar/hotbar-cell.tsx index 90dfc49000..29466a9de5 100644 --- a/packages/core/src/renderer/components/hotbar/hotbar-cell.tsx +++ b/packages/core/src/renderer/components/hotbar/hotbar-cell.tsx @@ -7,7 +7,7 @@ import "./hotbar-menu.scss"; import type { HTMLAttributes, ReactNode } from "react"; import React, { useState } from "react"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; export interface HotbarCellProps extends HTMLAttributes { children?: ReactNode; diff --git a/packages/core/src/renderer/components/hotbar/hotbar-entity-icon.tsx b/packages/core/src/renderer/components/hotbar/hotbar-entity-icon.tsx index b3f635acb5..0a1987e576 100644 --- a/packages/core/src/renderer/components/hotbar/hotbar-entity-icon.tsx +++ b/packages/core/src/renderer/components/hotbar/hotbar-entity-icon.tsx @@ -11,8 +11,8 @@ import { observable } from "mobx"; import { observer } from "mobx-react"; import type { CatalogCategoryRegistry, CatalogEntity, CatalogEntityContextMenu } from "../../../common/catalog"; -import type { IClassName } from "../../utils"; -import { cssNames } from "../../utils"; +import type { IClassName } from "@k8slens/utilities"; +import { cssNames } from "@k8slens/utilities"; import { Icon } from "../icon"; import { HotbarIcon } from "./hotbar-icon"; import { LensKubernetesClusterStatus } from "../../../common/catalog-entities/kubernetes-cluster"; diff --git a/packages/core/src/renderer/components/hotbar/hotbar-icon.tsx b/packages/core/src/renderer/components/hotbar/hotbar-icon.tsx index 3bbe644c88..ee9d4fb04e 100644 --- a/packages/core/src/renderer/components/hotbar/hotbar-icon.tsx +++ b/packages/core/src/renderer/components/hotbar/hotbar-icon.tsx @@ -8,7 +8,7 @@ import styles from "./hotbar-icon.module.scss"; import React, { useState } from "react"; import type { CatalogEntityContextMenu } from "../../../common/catalog"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import { Menu, MenuItem } from "../menu"; import { observer } from "mobx-react"; import type { AvatarProps } from "../avatar"; diff --git a/packages/core/src/renderer/components/hotbar/hotbar-menu.tsx b/packages/core/src/renderer/components/hotbar/hotbar-menu.tsx index 53191c2d87..e83848cdfd 100644 --- a/packages/core/src/renderer/components/hotbar/hotbar-menu.tsx +++ b/packages/core/src/renderer/components/hotbar/hotbar-menu.tsx @@ -8,8 +8,8 @@ import "./hotbar-menu.scss"; import React from "react"; import { observer } from "mobx-react"; import { HotbarEntityIcon } from "./hotbar-entity-icon"; -import type { IClassName } from "../../utils"; -import { cssNames } from "../../utils"; +import type { IClassName } from "@k8slens/utilities"; +import { cssNames } from "@k8slens/utilities"; import type { CatalogEntityRegistry } from "../../api/catalog/entity/registry"; import type { CatalogEntity } from "../../api/catalog-entity"; import { DragDropContext, Draggable, Droppable, type DropResult } from "react-beautiful-dnd"; diff --git a/packages/core/src/renderer/components/hotbar/hotbar-selector.tsx b/packages/core/src/renderer/components/hotbar/hotbar-selector.tsx index 4d6104b5b3..7e7b609300 100644 --- a/packages/core/src/renderer/components/hotbar/hotbar-selector.tsx +++ b/packages/core/src/renderer/components/hotbar/hotbar-selector.tsx @@ -14,7 +14,7 @@ import { observer } from "mobx-react"; import type { Hotbar } from "../../../common/hotbars/types"; import { withInjectables } from "@ogre-tools/injectable-react"; import commandOverlayInjectable from "../command-palette/command-overlay.injectable"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import type { HotbarStore } from "../../../common/hotbars/store"; interface Dependencies { diff --git a/packages/core/src/renderer/components/icon/icon.tsx b/packages/core/src/renderer/components/icon/icon.tsx index b51299ba15..6da23f247e 100644 --- a/packages/core/src/renderer/components/icon/icon.tsx +++ b/packages/core/src/renderer/components/icon/icon.tsx @@ -9,7 +9,7 @@ import type { ReactNode } from "react"; import React, { createRef } from "react"; import { NavLink } from "react-router-dom"; import type { LocationDescriptor } from "history"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import { withTooltip } from "../tooltip"; import isNumber from "lodash/isNumber"; import Configuration from "./configuration.svg"; diff --git a/packages/core/src/renderer/components/input/drop-file-input.tsx b/packages/core/src/renderer/components/input/drop-file-input.tsx index 41461a27c9..85b3e8d369 100644 --- a/packages/core/src/renderer/components/input/drop-file-input.tsx +++ b/packages/core/src/renderer/components/input/drop-file-input.tsx @@ -5,13 +5,14 @@ import "./drop-file-input.scss"; import React from "react"; -import type { IClassName } from "../../utils"; -import { autoBind, cssNames } from "../../utils"; +import type { IClassName } from "@k8slens/utilities"; +import { cssNames } from "@k8slens/utilities"; import { observable, makeObservable } from "mobx"; import { observer } from "mobx-react"; import type { Logger } from "../../../common/logger"; import { withInjectables } from "@ogre-tools/injectable-react"; import loggerInjectable from "../../../common/logger.injectable"; +import autoBindReact from "auto-bind/react"; export interface DropFileInputProps extends React.DOMAttributes { className?: IClassName; @@ -35,7 +36,7 @@ class NonInjectedDropFileInput extends React.Component & Dependencies) { super(props); makeObservable(this); - autoBind(this); + autoBindReact(this); } onDragEnter() { diff --git a/packages/core/src/renderer/components/input/input.tsx b/packages/core/src/renderer/components/input/input.tsx index bbbfa60a86..ef4e52f3ed 100644 --- a/packages/core/src/renderer/components/input/input.tsx +++ b/packages/core/src/renderer/components/input/input.tsx @@ -7,8 +7,8 @@ import "./input.scss"; import type { DOMAttributes, InputHTMLAttributes, TextareaHTMLAttributes } from "react"; import React from "react"; -import type { SingleOrMany } from "../../utils"; -import { autoBind, cssNames, debouncePromise, getRandId, isPromiseSettledFulfilled } from "../../utils"; +import type { SingleOrMany } from "@k8slens/utilities"; +import { debouncePromise, isPromiseSettledFulfilled, cssNames } from "@k8slens/utilities"; import { Icon } from "../icon"; import type { TooltipProps } from "../tooltip"; import { Tooltip } from "../tooltip"; @@ -16,6 +16,8 @@ import * as Validators from "./input_validators"; import type { InputValidator, InputValidation, InputValidationResult, SyncValidationMessage } from "./input_validators"; import uniqueId from "lodash/uniqueId"; import { debounce } from "lodash"; +import * as uuid from "uuid"; +import autoBindReact from "auto-bind/react"; const { conditionalValidators, @@ -113,7 +115,7 @@ export class Input extends React.Component { constructor(props: InputProps) { super(props); - autoBind(this); + autoBindReact(this); } componentWillUnmount(): void { @@ -428,7 +430,7 @@ export class Input extends React.Component {
); const componentId = id || showErrorsAsTooltip - ? getRandId({ prefix: "input_tooltip_id" }) + ? `input_tooltip_id_${uuid.v4()}` : undefined; let tooltipError: React.ReactNode; diff --git a/packages/core/src/renderer/components/input/search-input.tsx b/packages/core/src/renderer/components/input/search-input.tsx index 4aff4a6ffa..d0365ba5e9 100644 --- a/packages/core/src/renderer/components/input/search-input.tsx +++ b/packages/core/src/renderer/components/input/search-input.tsx @@ -7,12 +7,13 @@ import "./search-input.scss"; import React, { createRef } from "react"; import { observer } from "mobx-react"; -import { cssNames, autoBind } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import { Icon } from "../icon"; import type { InputProps } from "./input"; import { Input } from "./input"; import { withInjectables } from "@ogre-tools/injectable-react"; import isMacInjectable from "../../../common/vars/is-mac.injectable"; +import autoBindReact from "auto-bind/react"; export interface SearchInputProps extends InputProps { compact?: boolean; // show only search-icon when not focused @@ -40,7 +41,7 @@ class NonInjectedSearchInput extends React.Component { getFilters: () => Filter[]; @@ -86,7 +87,7 @@ class NonInjectedItemListLayoutContent< constructor(props: ItemListLayoutContentProps & Dependencies) { super(props); makeObservable(this); - autoBind(this); + autoBindReact(this); } @computed get failedToLoad() { diff --git a/packages/core/src/renderer/components/item-object-list/header.tsx b/packages/core/src/renderer/components/item-object-list/header.tsx index 2b60b3858f..6da69312f5 100644 --- a/packages/core/src/renderer/components/item-object-list/header.tsx +++ b/packages/core/src/renderer/components/item-object-list/header.tsx @@ -8,8 +8,8 @@ import "./item-list-layout.scss"; import type { ReactNode } from "react"; import React from "react"; import { observer } from "mobx-react"; -import type { IClassName } from "../../utils"; -import { cssNames, isDefined } from "../../utils"; +import type { IClassName } from "@k8slens/utilities"; +import { cssNames, isDefined } from "@k8slens/utilities"; import type { ItemObject } from "../../../common/item.store"; import type { Filter } from "./page-filters/store"; import type { HeaderCustomizer, HeaderPlaceholders, ItemListStore, SearchFilter } from "./list-layout"; diff --git a/packages/core/src/renderer/components/item-object-list/list-layout.tsx b/packages/core/src/renderer/components/item-object-list/list-layout.tsx index 2d3a9ae17b..525558f533 100644 --- a/packages/core/src/renderer/components/item-object-list/list-layout.tsx +++ b/packages/core/src/renderer/components/item-object-list/list-layout.tsx @@ -11,8 +11,8 @@ import type { IComputedValue } from "mobx"; import { computed, makeObservable, untracked } from "mobx"; import type { ConfirmDialogParams } from "../confirm-dialog"; import type { TableCellProps, TableProps, TableRowProps, TableSortCallbacks } from "../table"; -import type { IClassName, SingleOrMany, StorageLayer } from "../../utils"; -import { autoBind, cssNames, noop } from "../../utils"; +import type { IClassName, SingleOrMany } from "@k8slens/utilities"; +import { cssNames, noop } from "@k8slens/utilities"; import type { AddRemoveButtonsProps } from "../add-remove-buttons"; import type { ItemObject } from "../../../common/item.store"; import type { SearchInputUrlProps } from "../input"; @@ -30,6 +30,8 @@ import type { Primitive } from "type-fest"; import type { SubscribableStore } from "../../kube-watch-api/kube-watch-api"; import selectedFilterNamespacesInjectable from "../../../common/k8s-api/selected-filter-namespaces.injectable"; import pageFiltersStoreInjectable from "./page-filters/store.injectable"; +import type { StorageLayer } from "../../utils/storage-helper"; +import autoBindReact from "auto-bind/react"; export type SearchFilter = (item: I) => SingleOrMany; export type SearchFilters = Record>; @@ -176,7 +178,7 @@ class NonInjectedItemListLayout & Dependencies) { super(props); makeObservable(this); - autoBind(this); + autoBindReact(this); } async componentDidMount() { diff --git a/packages/core/src/renderer/components/item-object-list/page-filters/list.tsx b/packages/core/src/renderer/components/item-object-list/page-filters/list.tsx index 58c4463b65..51590adb23 100644 --- a/packages/core/src/renderer/components/item-object-list/page-filters/list.tsx +++ b/packages/core/src/renderer/components/item-object-list/page-filters/list.tsx @@ -7,7 +7,7 @@ import "./list.scss"; import React from "react"; import { observer } from "mobx-react"; import { Badge } from "../../badge"; -import { cssNames } from "../../../utils"; +import { cssNames } from "@k8slens/utilities"; import type { Filter, PageFiltersStore } from "./store"; import { FilterIcon } from "../filter-icon"; import { Icon } from "../../icon"; diff --git a/packages/core/src/renderer/components/item-object-list/page-filters/store.ts b/packages/core/src/renderer/components/item-object-list/page-filters/store.ts index d9a088f539..4988f10a12 100644 --- a/packages/core/src/renderer/components/item-object-list/page-filters/store.ts +++ b/packages/core/src/renderer/components/item-object-list/page-filters/store.ts @@ -3,9 +3,9 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ +import autoBind from "auto-bind"; import { computed, observable, reaction, makeObservable, action } from "mobx"; import type { PageParam } from "../../../navigation/page-param"; -import { autoBind } from "../../../utils"; export enum FilterType { SEARCH = "search", diff --git a/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/kube-object-detail-items.injectable.ts b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/kube-object-detail-items.injectable.ts index 4d312eb30b..77223c06c1 100644 --- a/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/kube-object-detail-items.injectable.ts +++ b/packages/core/src/renderer/components/kube-object-details/kube-object-detail-items/kube-object-detail-items.injectable.ts @@ -7,7 +7,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import { computed } from "mobx"; import { computedInjectManyInjectable } from "@ogre-tools/injectable-extension-for-mobx"; import { kubeObjectDetailItemInjectionToken } from "./kube-object-detail-item-injection-token"; -import { byValue } from "../../../../common/utils/sort-function"; +import { byValue } from "@k8slens/utilities"; const kubeObjectDetailItemsInjectable = getInjectable({ id: "kube-object-detail-items", diff --git a/packages/core/src/renderer/components/kube-object-list-layout/kube-object-list-layout.test.tsx b/packages/core/src/renderer/components/kube-object-list-layout/kube-object-list-layout.test.tsx index fa06a6d2a0..74f31ff3dd 100644 --- a/packages/core/src/renderer/components/kube-object-list-layout/kube-object-list-layout.test.tsx +++ b/packages/core/src/renderer/components/kube-object-list-layout/kube-object-list-layout.test.tsx @@ -20,7 +20,7 @@ import directoryForUserDataInjectable from "../../../common/app-paths/directory- import directoryForKubeConfigsInjectable from "../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable"; import hostedClusterInjectable from "../../cluster-frame-context/hosted-cluster.injectable"; import type { PodStore } from "../+workloads-pods/store"; -import { createClusterInjectionToken } from "../../../common/cluster/create-cluster-injection-token"; +import { Cluster } from "../../../common/cluster/cluster"; describe("kube-object-list-layout", () => { let di: DiContainer; @@ -34,9 +34,7 @@ describe("kube-object-list-layout", () => { di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs"); di.override(storesAndApisCanBeCreatedInjectable, () => true); - const createCluster = di.inject(createClusterInjectionToken); - - di.override(hostedClusterInjectable, () => createCluster({ + di.override(hostedClusterInjectable, () => new Cluster({ contextName: "some-context-name", id: "some-cluster-id", kubeConfigPath: "/some-path-to-a-kubeconfig", diff --git a/packages/core/src/renderer/components/kube-object-list-layout/kube-object-list-layout.tsx b/packages/core/src/renderer/components/kube-object-list-layout/kube-object-list-layout.tsx index 4394902072..8d12c8a57a 100644 --- a/packages/core/src/renderer/components/kube-object-list-layout/kube-object-list-layout.tsx +++ b/packages/core/src/renderer/components/kube-object-list-layout/kube-object-list-layout.tsx @@ -8,8 +8,8 @@ import "./kube-object-list-layout.scss"; import React from "react"; import { computed, observable, reaction } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; -import type { Disposer } from "../../utils"; -import { hasTypedProperty, isObject, isString, cssNames, isDefined } from "../../utils"; +import type { Disposer } from "@k8slens/utilities"; +import { hasTypedProperty, isObject, isString, cssNames, isDefined } from "@k8slens/utilities"; import type { KubeJsonApiDataFor, KubeObject } from "../../../common/k8s-api/kube-object"; import type { ItemListLayoutProps } from "../item-object-list/list-layout"; import { ItemListLayout } from "../item-object-list/list-layout"; diff --git a/packages/core/src/renderer/components/kube-object-menu/cluster-name.injectable.ts b/packages/core/src/renderer/components/kube-object-menu/cluster-name.injectable.ts new file mode 100644 index 0000000000..f66d0458b0 --- /dev/null +++ b/packages/core/src/renderer/components/kube-object-menu/cluster-name.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 { getInjectable } from "@ogre-tools/injectable"; +import { computed } from "mobx"; +import activeEntityInternalClusterInjectable from "../../api/catalog/entity/get-active-cluster-entity.injectable"; + +const clusterNameInjectable = getInjectable({ + id: "cluster-name", + instantiate: (di) => { + const activeEntityInternalCluster = di.inject(activeEntityInternalClusterInjectable); + + return computed(() => activeEntityInternalCluster.get()?.name.get()); + }, +}); + +export default clusterNameInjectable; diff --git a/packages/core/src/renderer/components/kube-object-menu/dependencies/cluster-name.injectable.ts b/packages/core/src/renderer/components/kube-object-menu/dependencies/cluster-name.injectable.ts deleted file mode 100644 index ad7c5c0e80..0000000000 --- a/packages/core/src/renderer/components/kube-object-menu/dependencies/cluster-name.injectable.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; -import clusterInjectable from "./cluster.injectable"; - -const clusterNameInjectable = getInjectable({ - id: "cluster-name", - - instantiate: (di) => { - const cluster = di.inject(clusterInjectable); - - return cluster?.name; - }, - - lifecycle: lifecycleEnum.transient, -}); - -export default clusterNameInjectable; diff --git a/packages/core/src/renderer/components/kube-object-menu/dependencies/cluster.injectable.ts b/packages/core/src/renderer/components/kube-object-menu/dependencies/cluster.injectable.ts deleted file mode 100644 index 5a2fb7c086..0000000000 --- a/packages/core/src/renderer/components/kube-object-menu/dependencies/cluster.injectable.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; -import getActiveClusterEntityInjectable from "../../../api/catalog/entity/get-active-cluster-entity.injectable"; - -const clusterInjectable = getInjectable({ - id: "cluster", - instantiate: (di) => { - const getActiveClusterEntity = di.inject(getActiveClusterEntityInjectable); - - return getActiveClusterEntity(); - }, - lifecycle: lifecycleEnum.transient, -}); - -export default clusterInjectable; diff --git a/packages/core/src/renderer/components/kube-object-menu/kube-object-menu.test.tsx b/packages/core/src/renderer/components/kube-object-menu/kube-object-menu.test.tsx index 56841c2136..1741811a49 100644 --- a/packages/core/src/renderer/components/kube-object-menu/kube-object-menu.test.tsx +++ b/packages/core/src/renderer/components/kube-object-menu/kube-object-menu.test.tsx @@ -15,7 +15,6 @@ import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; import { getDiForUnitTesting } from "../../getDiForUnitTesting"; import { computed, runInAction } from "mobx"; -import clusterInjectable from "./dependencies/cluster.injectable"; import type { DiRender } from "../test-utils/renderFor"; import { renderFor } from "../test-utils/renderFor"; import type { Cluster } from "../../../common/cluster/cluster"; @@ -25,6 +24,7 @@ import { KubeObjectMenu } from "./index"; import createEditResourceTabInjectable from "../dock/edit-resource/edit-resource-tab.injectable"; import hideDetailsInjectable from "../kube-detail-params/hide-details.injectable"; import { kubeObjectMenuItemInjectionToken } from "./kube-object-menu-item-injection-token"; +import activeEntityInternalClusterInjectable from "../../api/catalog/entity/get-active-cluster-entity.injectable"; // TODO: make `animated={false}` not required to make tests deterministic describe("kube-object-menu", () => { @@ -45,11 +45,10 @@ describe("kube-object-menu", () => { render = renderFor(di); di.override( - clusterInjectable, - () => - ({ - name: "Some name", - } as Cluster), + activeEntityInternalClusterInjectable, + () => computed(() => ({ + name: computed(() => "Some name"), + } as Cluster)), ); di.override( @@ -66,7 +65,11 @@ describe("kube-object-menu", () => { }); it("given no cluster, does not crash", () => { - di.override(clusterInjectable, () => null); + + di.override( + activeEntityInternalClusterInjectable, + () => computed(() => undefined), + ); expect(() => { render(); diff --git a/packages/core/src/renderer/components/kube-object-menu/kube-object-menu.tsx b/packages/core/src/renderer/components/kube-object-menu/kube-object-menu.tsx index eb0dc025b9..8535006f46 100644 --- a/packages/core/src/renderer/components/kube-object-menu/kube-object-menu.tsx +++ b/packages/core/src/renderer/components/kube-object-menu/kube-object-menu.tsx @@ -4,14 +4,14 @@ */ import React from "react"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import type { KubeObject } from "../../../common/k8s-api/kube-object"; import type { MenuActionsProps } from "../menu"; import { MenuItem, MenuActions } from "../menu"; import identity from "lodash/identity"; import type { ApiManager } from "../../../common/k8s-api/api-manager"; import { withInjectables } from "@ogre-tools/injectable-react"; -import clusterNameInjectable from "./dependencies/cluster-name.injectable"; +import clusterNameInjectable from "./cluster-name.injectable"; import createEditResourceTabInjectable from "../dock/edit-resource/edit-resource-tab.injectable"; import kubeObjectMenuItemsInjectable from "./kube-object-menu-items.injectable"; import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable"; @@ -38,7 +38,7 @@ export interface KubeObjectMenuProps extends Men interface Dependencies { apiManager: ApiManager; kubeObjectMenuItems: IComputedValue; - clusterName: string | undefined; + clusterName: IComputedValue; hideDetails: HideDetails; createEditResourceTab: (kubeObject: KubeObject) => void; onContextMenuOpen: OnKubeObjectContextMenuOpen; @@ -65,7 +65,7 @@ class NonInjectedKubeObjectMenu extends React.Component {`Remove ${object.kind} `} {breadcrumb} {" from "} - {this.props.clusterName} + {this.props.clusterName.get()} ?

); diff --git a/packages/core/src/renderer/components/kube-object-status-icon/kube-object-status-icon.tsx b/packages/core/src/renderer/components/kube-object-status-icon/kube-object-status-icon.tsx index dd9e68d3f8..c3a5852e0a 100644 --- a/packages/core/src/renderer/components/kube-object-status-icon/kube-object-status-icon.tsx +++ b/packages/core/src/renderer/components/kube-object-status-icon/kube-object-status-icon.tsx @@ -7,7 +7,7 @@ import "./kube-object-status-icon.scss"; import React from "react"; import { Icon } from "../icon"; -import { cssNames, formatDuration, getOrInsert, isDefined } from "../../utils"; +import { cssNames, formatDuration, getOrInsert, isDefined } from "@k8slens/utilities"; import { withInjectables } from "@ogre-tools/injectable-react"; import kubeObjectStatusTextsForObjectInjectable from "./kube-object-status-texts-for-object.injectable"; import type { KubeObject } from "../../../common/k8s-api/kube-object"; diff --git a/packages/core/src/renderer/components/kubeconfig-dialog/kubeconfig-dialog.tsx b/packages/core/src/renderer/components/kubeconfig-dialog/kubeconfig-dialog.tsx index fd497c9c35..69a6cdcbd2 100644 --- a/packages/core/src/renderer/components/kubeconfig-dialog/kubeconfig-dialog.tsx +++ b/packages/core/src/renderer/components/kubeconfig-dialog/kubeconfig-dialog.tsx @@ -7,7 +7,7 @@ import styles from "./kubeconfig-dialog.module.scss"; import React from "react"; import type { IObservableValue } from "mobx"; import { observer } from "mobx-react"; -import { cssNames, saveFileDialog } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import { Button } from "../button"; import type { DialogProps } from "../dialog"; import { Dialog } from "../dialog"; @@ -19,6 +19,7 @@ import { clipboard } from "electron"; import { withInjectables } from "@ogre-tools/injectable-react"; import showSuccessNotificationInjectable from "../notifications/show-success-notification.injectable"; import kubeconfigDialogStateInjectable from "./state.injectable"; +import { saveFileDialog } from "../../utils/saveFile"; export interface KubeconfigDialogData { title?: React.ReactNode; diff --git a/packages/core/src/renderer/components/kubeconfig-dialog/open-service-account-kube-config-dialog.injectable.ts b/packages/core/src/renderer/components/kubeconfig-dialog/open-service-account-kube-config-dialog.injectable.ts index 4c0e4255b1..658331fe9e 100644 --- a/packages/core/src/renderer/components/kubeconfig-dialog/open-service-account-kube-config-dialog.injectable.ts +++ b/packages/core/src/renderer/components/kubeconfig-dialog/open-service-account-kube-config-dialog.injectable.ts @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import apiBaseInjectable from "../../../common/k8s-api/api-base.injectable"; import type { ServiceAccount } from "../../../common/k8s-api/endpoints"; -import { urlBuilderFor } from "../../../common/utils/buildUrl"; +import { urlBuilderFor } from "@k8slens/utilities"; import openKubeconfigDialogInjectable from "./open.injectable"; export type OpenServiceAccountKubeConfigDialog = (account: ServiceAccount) => void; diff --git a/packages/core/src/renderer/components/layout/main-layout.tsx b/packages/core/src/renderer/components/layout/main-layout.tsx index 9a5ff95549..a078ac7b74 100755 --- a/packages/core/src/renderer/components/layout/main-layout.tsx +++ b/packages/core/src/renderer/components/layout/main-layout.tsx @@ -7,13 +7,13 @@ import styles from "./main-layout.module.scss"; import React from "react"; import { observer } from "mobx-react"; -import type { StorageLayer } from "../../utils"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import { ErrorBoundary } from "../error-boundary"; import { ResizeDirection, ResizeGrowthDirection, ResizeSide, ResizingAnchor } from "../resizing-anchor"; import { withInjectables } from "@ogre-tools/injectable-react"; import type { SidebarStorageState } from "./sidebar-storage/sidebar-storage.injectable"; import sidebarStorageInjectable, { defaultSidebarWidth } from "./sidebar-storage/sidebar-storage.injectable"; +import type { StorageLayer } from "../../utils/storage-helper"; export interface MainLayoutProps { sidebar: React.ReactNode; diff --git a/packages/core/src/renderer/components/layout/setting-layout.tsx b/packages/core/src/renderer/components/layout/setting-layout.tsx index b6e0e58ec2..09ceba9a5d 100644 --- a/packages/core/src/renderer/components/layout/setting-layout.tsx +++ b/packages/core/src/renderer/components/layout/setting-layout.tsx @@ -7,8 +7,8 @@ import "./setting-layout.scss"; import React from "react"; import { observer } from "mobx-react"; -import type { IClassName } from "../../utils"; -import { cssNames } from "../../utils"; +import type { IClassName } from "@k8slens/utilities"; +import { cssNames } from "@k8slens/utilities"; import { CloseButton } from "./close-button"; import { getLegacyGlobalDiForExtensionApi } from "../../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; import navigateToCatalogInjectable from "../../../common/front-end-routing/routes/catalog/navigate-to-catalog.injectable"; diff --git a/packages/core/src/renderer/components/layout/sidebar-item.tsx b/packages/core/src/renderer/components/layout/sidebar-item.tsx index f3e171fc4b..da1ee8b670 100644 --- a/packages/core/src/renderer/components/layout/sidebar-item.tsx +++ b/packages/core/src/renderer/components/layout/sidebar-item.tsx @@ -7,8 +7,7 @@ import styles from "./sidebar-items.module.scss"; import React from "react"; import { computed, makeObservable } from "mobx"; -import type { StorageLayer } from "../../utils"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import { observer } from "mobx-react"; import { NavLink } from "react-router-dom"; import { Icon } from "../icon"; @@ -16,6 +15,7 @@ import { withInjectables } from "@ogre-tools/injectable-react"; import type { SidebarStorageState } from "./sidebar-storage/sidebar-storage.injectable"; import sidebarStorageInjectable from "./sidebar-storage/sidebar-storage.injectable"; import type { HierarchicalSidebarItem } from "./sidebar-items.injectable"; +import type { StorageLayer } from "../../utils/storage-helper"; interface Dependencies { sidebarStorage: StorageLayer; diff --git a/packages/core/src/renderer/components/layout/sidebar.tsx b/packages/core/src/renderer/components/layout/sidebar.tsx index 7fcd1b6793..9230ce4b5d 100644 --- a/packages/core/src/renderer/components/layout/sidebar.tsx +++ b/packages/core/src/renderer/components/layout/sidebar.tsx @@ -7,7 +7,7 @@ import styles from "./sidebar.module.scss"; import React from "react"; import { observer } from "mobx-react"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import { SidebarItem } from "./sidebar-item"; import type { CatalogEntityRegistry } from "../../api/catalog/entity/registry"; import { SidebarCluster } from "./sidebar-cluster"; diff --git a/packages/core/src/renderer/components/layout/sub-header.tsx b/packages/core/src/renderer/components/layout/sub-header.tsx index 0530fef944..7a782d1123 100644 --- a/packages/core/src/renderer/components/layout/sub-header.tsx +++ b/packages/core/src/renderer/components/layout/sub-header.tsx @@ -5,8 +5,8 @@ import "./sub-header.scss"; import React from "react"; -import type { SingleOrMany } from "../../utils"; -import { cssNames } from "../../utils"; +import type { SingleOrMany } from "@k8slens/utilities"; +import { cssNames } from "@k8slens/utilities"; export interface SubHeaderProps { className?: string; diff --git a/packages/core/src/renderer/components/layout/sub-title.tsx b/packages/core/src/renderer/components/layout/sub-title.tsx index 3ee50d44e9..90ab8dc3e7 100644 --- a/packages/core/src/renderer/components/layout/sub-title.tsx +++ b/packages/core/src/renderer/components/layout/sub-title.tsx @@ -5,8 +5,8 @@ import "./sub-title.scss"; import React from "react"; -import type { SingleOrMany } from "../../utils"; -import { cssNames } from "../../utils"; +import type { SingleOrMany } from "@k8slens/utilities"; +import { cssNames } from "@k8slens/utilities"; export interface SubTitleProps { className?: string; diff --git a/packages/core/src/renderer/components/layout/tab-layout-2.tsx b/packages/core/src/renderer/components/layout/tab-layout-2.tsx index 7d81c58d34..a9f720aef2 100644 --- a/packages/core/src/renderer/components/layout/tab-layout-2.tsx +++ b/packages/core/src/renderer/components/layout/tab-layout-2.tsx @@ -7,7 +7,7 @@ import "./tab-layout.scss"; import React from "react"; import { observer } from "mobx-react"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import { Tab, Tabs } from "../tabs"; import { ErrorBoundary } from "../error-boundary"; import type { HierarchicalSidebarItem } from "./sidebar-items.injectable"; diff --git a/packages/core/src/renderer/components/layout/tab-layout.tsx b/packages/core/src/renderer/components/layout/tab-layout.tsx index ddbbeea691..d91a31d5e8 100644 --- a/packages/core/src/renderer/components/layout/tab-layout.tsx +++ b/packages/core/src/renderer/components/layout/tab-layout.tsx @@ -9,8 +9,8 @@ import type { ReactNode } from "react"; import React from "react"; import { matchPath, Redirect, Route, Switch } from "react-router"; import { observer } from "mobx-react"; -import type { IClassName } from "../../utils"; -import { cssNames } from "../../utils"; +import type { IClassName } from "@k8slens/utilities"; +import { cssNames } from "@k8slens/utilities"; import { Tab, Tabs } from "../tabs"; import { ErrorBoundary } from "../error-boundary"; import type { ObservableHistory } from "mobx-observable-history"; diff --git a/packages/core/src/renderer/components/layout/top-bar/start-state-sync.injectable.ts b/packages/core/src/renderer/components/layout/top-bar/start-state-sync.injectable.ts index 92488851c5..aca3e9ff76 100644 --- a/packages/core/src/renderer/components/layout/top-bar/start-state-sync.injectable.ts +++ b/packages/core/src/renderer/components/layout/top-bar/start-state-sync.injectable.ts @@ -12,7 +12,6 @@ import topBarStateInjectable from "./state.injectable"; const startTopbarStateSyncInjectable = getInjectable({ id: "start-topbar-state-sync", instantiate: (di) => ({ - id: "start-topbar-state-sync", run: () => { const state = di.inject(topBarStateInjectable); const ipcRenderer = di.inject(ipcRendererInjectable); diff --git a/packages/core/src/renderer/components/layout/top-bar/toggle-maximize-window/toggle-maximize-window.global-override-for-injectable.ts b/packages/core/src/renderer/components/layout/top-bar/toggle-maximize-window/toggle-maximize-window.global-override-for-injectable.ts index e7584a243b..ab457b4f17 100644 --- a/packages/core/src/renderer/components/layout/top-bar/toggle-maximize-window/toggle-maximize-window.global-override-for-injectable.ts +++ b/packages/core/src/renderer/components/layout/top-bar/toggle-maximize-window/toggle-maximize-window.global-override-for-injectable.ts @@ -3,6 +3,6 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import toggleMaximizeWindowInjectable from "./toggle-maximize-window.injectable"; -import { getGlobalOverrideForFunction } from "../../../../../common/test-utils/get-global-override-for-function"; +import { getGlobalOverrideForFunction } from "@k8slens/test-utils"; export default getGlobalOverrideForFunction(toggleMaximizeWindowInjectable); diff --git a/packages/core/src/renderer/components/layout/top-bar/top-bar-items/context-menu/open-app-context-menu/open-app-context-menu.global-override-for-injectable.ts b/packages/core/src/renderer/components/layout/top-bar/top-bar-items/context-menu/open-app-context-menu/open-app-context-menu.global-override-for-injectable.ts index 2dfd22bb5e..cac2d6b182 100644 --- a/packages/core/src/renderer/components/layout/top-bar/top-bar-items/context-menu/open-app-context-menu/open-app-context-menu.global-override-for-injectable.ts +++ b/packages/core/src/renderer/components/layout/top-bar/top-bar-items/context-menu/open-app-context-menu/open-app-context-menu.global-override-for-injectable.ts @@ -3,6 +3,6 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import openAppContextMenuInjectable from "./open-app-context-menu.injectable"; -import { getGlobalOverrideForFunction } from "../../../../../../../common/test-utils/get-global-override-for-function"; +import { getGlobalOverrideForFunction } from "@k8slens/test-utils"; export default getGlobalOverrideForFunction(openAppContextMenuInjectable); diff --git a/packages/core/src/renderer/components/layout/top-bar/top-bar-items/navigation-to-back/go-back/go-back.global-override-for-injectable.ts b/packages/core/src/renderer/components/layout/top-bar/top-bar-items/navigation-to-back/go-back/go-back.global-override-for-injectable.ts index f0d421a883..1b0f4f6741 100644 --- a/packages/core/src/renderer/components/layout/top-bar/top-bar-items/navigation-to-back/go-back/go-back.global-override-for-injectable.ts +++ b/packages/core/src/renderer/components/layout/top-bar/top-bar-items/navigation-to-back/go-back/go-back.global-override-for-injectable.ts @@ -3,6 +3,6 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import goBackInjectable from "./go-back.injectable"; -import { getGlobalOverrideForFunction } from "../../../../../../../common/test-utils/get-global-override-for-function"; +import { getGlobalOverrideForFunction } from "@k8slens/test-utils"; export default getGlobalOverrideForFunction(goBackInjectable); diff --git a/packages/core/src/renderer/components/layout/top-bar/top-bar-items/navigation-to-forward/go-forward/go-forward.global-override-for-injectable.ts b/packages/core/src/renderer/components/layout/top-bar/top-bar-items/navigation-to-forward/go-forward/go-forward.global-override-for-injectable.ts index f4e2520381..0808279e4f 100644 --- a/packages/core/src/renderer/components/layout/top-bar/top-bar-items/navigation-to-forward/go-forward/go-forward.global-override-for-injectable.ts +++ b/packages/core/src/renderer/components/layout/top-bar/top-bar-items/navigation-to-forward/go-forward/go-forward.global-override-for-injectable.ts @@ -3,6 +3,6 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import goForwardInjectable from "./go-forward.injectable"; -import { getGlobalOverrideForFunction } from "../../../../../../../common/test-utils/get-global-override-for-function"; +import { getGlobalOverrideForFunction } from "@k8slens/test-utils"; export default getGlobalOverrideForFunction(goForwardInjectable); diff --git a/packages/core/src/renderer/components/layout/top-bar/top-bar-items/window-controls/close-window/close-window.global-override-for-injectable.ts b/packages/core/src/renderer/components/layout/top-bar/top-bar-items/window-controls/close-window/close-window.global-override-for-injectable.ts index f8124bbbe5..1d42413183 100644 --- a/packages/core/src/renderer/components/layout/top-bar/top-bar-items/window-controls/close-window/close-window.global-override-for-injectable.ts +++ b/packages/core/src/renderer/components/layout/top-bar/top-bar-items/window-controls/close-window/close-window.global-override-for-injectable.ts @@ -3,6 +3,6 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import closeWindowInjectable from "./close-window.injectable"; -import { getGlobalOverrideForFunction } from "../../../../../../../common/test-utils/get-global-override-for-function"; +import { getGlobalOverrideForFunction } from "@k8slens/test-utils"; export default getGlobalOverrideForFunction(closeWindowInjectable); diff --git a/packages/core/src/renderer/components/layout/top-bar/top-bar-items/window-controls/maximize-window/maximize-window.global-override-for-injectable.ts b/packages/core/src/renderer/components/layout/top-bar/top-bar-items/window-controls/maximize-window/maximize-window.global-override-for-injectable.ts index e0056a6ee8..12a702c7dd 100644 --- a/packages/core/src/renderer/components/layout/top-bar/top-bar-items/window-controls/maximize-window/maximize-window.global-override-for-injectable.ts +++ b/packages/core/src/renderer/components/layout/top-bar/top-bar-items/window-controls/maximize-window/maximize-window.global-override-for-injectable.ts @@ -3,6 +3,6 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import maximizeWindowInjectable from "./maximize-window.injectable"; -import { getGlobalOverrideForFunction } from "../../../../../../../common/test-utils/get-global-override-for-function"; +import { getGlobalOverrideForFunction } from "@k8slens/test-utils"; export default getGlobalOverrideForFunction(maximizeWindowInjectable); diff --git a/packages/core/src/renderer/components/layout/top-bar/top-bar-items/window-controls/window-controls.tsx b/packages/core/src/renderer/components/layout/top-bar/top-bar-items/window-controls/window-controls.tsx index 08cdee837f..7c1665395a 100644 --- a/packages/core/src/renderer/components/layout/top-bar/top-bar-items/window-controls/window-controls.tsx +++ b/packages/core/src/renderer/components/layout/top-bar/top-bar-items/window-controls/window-controls.tsx @@ -4,7 +4,7 @@ */ import React from "react"; import { withInjectables } from "@ogre-tools/injectable-react"; -import { cssNames } from "../../../../../utils"; +import { cssNames } from "@k8slens/utilities"; import styles from "../../top-bar.module.scss"; import isLinuxInjectable from "../../../../../../common/vars/is-linux.injectable"; import toggleMaximizeWindowInjectable from "../../toggle-maximize-window/toggle-maximize-window.injectable"; diff --git a/packages/core/src/renderer/components/layout/wizard-layout.tsx b/packages/core/src/renderer/components/layout/wizard-layout.tsx index 9012a0f66f..bcdb47f9c5 100644 --- a/packages/core/src/renderer/components/layout/wizard-layout.tsx +++ b/packages/core/src/renderer/components/layout/wizard-layout.tsx @@ -6,8 +6,8 @@ import "./wizard-layout.scss"; import React from "react"; import { observer } from "mobx-react"; -import type { IClassName } from "../../utils"; -import { cssNames } from "../../utils"; +import type { IClassName } from "@k8slens/utilities"; +import { cssNames } from "@k8slens/utilities"; export interface WizardLayoutProps extends React.DOMAttributes { className?: IClassName; diff --git a/packages/core/src/renderer/components/line-progress/line-progress.tsx b/packages/core/src/renderer/components/line-progress/line-progress.tsx index 24ef169176..22e2e6437a 100644 --- a/packages/core/src/renderer/components/line-progress/line-progress.tsx +++ b/packages/core/src/renderer/components/line-progress/line-progress.tsx @@ -5,7 +5,7 @@ import "./line-progress.scss"; import React from "react"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import { withTooltip } from "../tooltip"; export interface LineProgressProps extends React.HTMLProps { diff --git a/packages/core/src/renderer/components/markdown-viewer/markdown-viewer.tsx b/packages/core/src/renderer/components/markdown-viewer/markdown-viewer.tsx index 66261cd7e4..62b223ccf3 100644 --- a/packages/core/src/renderer/components/markdown-viewer/markdown-viewer.tsx +++ b/packages/core/src/renderer/components/markdown-viewer/markdown-viewer.tsx @@ -10,7 +10,7 @@ import "./markdown-viewer.scss"; import React, { Component } from "react"; import { marked } from "marked"; import DOMPurify from "dompurify"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; DOMPurify.addHook("afterSanitizeAttributes", function (node) { // Set all elements owning target to target=_blank diff --git a/packages/core/src/renderer/components/menu/menu-actions.tsx b/packages/core/src/renderer/components/menu/menu-actions.tsx index 0e77446caf..2eebf36778 100644 --- a/packages/core/src/renderer/components/menu/menu-actions.tsx +++ b/packages/core/src/renderer/components/menu/menu-actions.tsx @@ -8,7 +8,7 @@ import "./menu-actions.scss"; import React, { isValidElement } from "react"; import { observable, makeObservable, reaction } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; -import { autoBind, cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import type { IconProps } from "../icon"; import { Icon } from "../icon"; import type { MenuProps } from "./menu"; @@ -19,6 +19,7 @@ import type { OpenConfirmDialog } from "../confirm-dialog/open.injectable"; import { withInjectables } from "@ogre-tools/injectable-react"; import openConfirmDialogInjectable from "../confirm-dialog/open.injectable"; import getRandomIdInjectable from "../../../common/utils/get-random-id.injectable"; +import autoBindReact from "auto-bind/react"; export interface MenuActionsProps extends Partial { className?: string; @@ -61,7 +62,7 @@ class NonInjectedMenuActions extends React.Component(null); export interface MenuContextValue { @@ -78,7 +79,7 @@ class NonInjectedMenu extends React.Component { constructor(props: MenuProps & Dependencies) { super(props); - autoBind(this); + autoBindReact(this); } private opener: HTMLElement | null = null; private elem: HTMLUListElement | null = null; @@ -431,7 +432,7 @@ export class MenuItem extends React.Component { constructor(props: MenuItemProps) { super(props); - autoBind(this); + autoBindReact(this); } get isFocusable() { diff --git a/packages/core/src/renderer/components/monaco-editor/monaco-editor.tsx b/packages/core/src/renderer/components/monaco-editor/monaco-editor.tsx index debb076ab8..d41ab4157b 100644 --- a/packages/core/src/renderer/components/monaco-editor/monaco-editor.tsx +++ b/packages/core/src/renderer/components/monaco-editor/monaco-editor.tsx @@ -12,7 +12,7 @@ import { editor, Uri } from "monaco-editor"; import type { MonacoTheme } from "./monaco-themes"; import { type MonacoValidator, monacoValidators } from "./monaco-validators"; import { debounce, merge } from "lodash"; -import { autoBind, cssNames, disposer } from "../../utils"; +import { cssNames, disposer } from "@k8slens/utilities"; import type { UserStore } from "../../../common/user-store"; import type { LensTheme } from "../../themes/lens-theme"; import { withInjectables } from "@ogre-tools/injectable-react"; @@ -21,6 +21,7 @@ import activeThemeInjectable from "../../themes/active.injectable"; import getEditorHeightFromLinesCountInjectable from "./get-editor-height-from-lines-number.injectable"; import type { Logger } from "../../../common/logger"; import loggerInjectable from "../../../common/logger.injectable"; +import autoBindReact from "auto-bind/react"; export type MonacoEditorId = string; @@ -82,7 +83,7 @@ class NonInjectedMonacoEditor extends React.Component { className?: string; diff --git a/packages/core/src/renderer/components/render-delay/__tests__/render-delay.test.tsx b/packages/core/src/renderer/components/render-delay/__tests__/render-delay.test.tsx index 4e410a18a1..472310d0d8 100644 --- a/packages/core/src/renderer/components/render-delay/__tests__/render-delay.test.tsx +++ b/packages/core/src/renderer/components/render-delay/__tests__/render-delay.test.tsx @@ -7,11 +7,11 @@ import { RenderDelay } from "../render-delay"; import type { DiRender } from "../../test-utils/renderFor"; import { renderFor } from "../../test-utils/renderFor"; import { getDiForUnitTesting } from "../../../getDiForUnitTesting"; -import { advanceFakeTime, testUsingFakeTime } from "../../../../common/test-utils/use-fake-time"; import cancelIdleCallbackInjectable from "../cancel-idle-callback.injectable"; import requestIdleCallbackInjectable from "../request-idle-callback.injectable"; import type { RenderResult } from "@testing-library/react"; import idleCallbackTimeoutInjectable from "../idle-callback-timeout.injectable"; +import { testUsingFakeTime, advanceFakeTime } from "../../../../test-utils/use-fake-time"; describe("", () => { let render: DiRender; diff --git a/packages/core/src/renderer/components/render-delay/cancel-idle-callback.global-override-for-injectable.ts b/packages/core/src/renderer/components/render-delay/cancel-idle-callback.global-override-for-injectable.ts index 2bd7d0047f..48e144ec70 100644 --- a/packages/core/src/renderer/components/render-delay/cancel-idle-callback.global-override-for-injectable.ts +++ b/packages/core/src/renderer/components/render-delay/cancel-idle-callback.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import cancelIdleCallbackInjectable from "./cancel-idle-callback.injectable"; export default getGlobalOverride(cancelIdleCallbackInjectable, () => () => {}); diff --git a/packages/core/src/renderer/components/render-delay/render-delay.tsx b/packages/core/src/renderer/components/render-delay/render-delay.tsx index 5951babe6d..7d65b68071 100644 --- a/packages/core/src/renderer/components/render-delay/render-delay.tsx +++ b/packages/core/src/renderer/components/render-delay/render-delay.tsx @@ -4,7 +4,7 @@ */ import React, { useEffect, useState } from "react"; -import type { SingleOrMany } from "../../utils"; +import type { SingleOrMany } from "@k8slens/utilities"; import type { RequestIdleCallback } from "./request-idle-callback.injectable"; import type { CancelIdleCallback } from "./cancel-idle-callback.injectable"; import { withInjectables } from "@ogre-tools/injectable-react"; diff --git a/packages/core/src/renderer/components/render-delay/request-idle-callback.global-override-for-injectable.ts b/packages/core/src/renderer/components/render-delay/request-idle-callback.global-override-for-injectable.ts index 5dc3d7d916..c9a901e813 100644 --- a/packages/core/src/renderer/components/render-delay/request-idle-callback.global-override-for-injectable.ts +++ b/packages/core/src/renderer/components/render-delay/request-idle-callback.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import requestIdleCallbackInjectable from "./request-idle-callback.injectable"; export default getGlobalOverride(requestIdleCallbackInjectable, () => (callback) => { diff --git a/packages/core/src/renderer/components/resizing-anchor/resizing-anchor.tsx b/packages/core/src/renderer/components/resizing-anchor/resizing-anchor.tsx index c65d4c4bf8..212366b628 100644 --- a/packages/core/src/renderer/components/resizing-anchor/resizing-anchor.tsx +++ b/packages/core/src/renderer/components/resizing-anchor/resizing-anchor.tsx @@ -7,7 +7,7 @@ import "./resizing-anchor.scss"; import React from "react"; import { action, observable, makeObservable } from "mobx"; import _ from "lodash"; -import { cssNames, noop } from "../../utils"; +import { cssNames, noop } from "@k8slens/utilities"; import { observer } from "mobx-react"; export enum ResizeDirection { diff --git a/packages/core/src/renderer/components/resource-metrics/resource-metrics.tsx b/packages/core/src/renderer/components/resource-metrics/resource-metrics.tsx index c10075ac6d..7c737027e3 100644 --- a/packages/core/src/renderer/components/resource-metrics/resource-metrics.tsx +++ b/packages/core/src/renderer/components/resource-metrics/resource-metrics.tsx @@ -8,7 +8,7 @@ import "./resource-metrics.scss"; import React, { createContext, useState } from "react"; import { Radio, RadioGroup } from "../radio"; import type { KubeObject } from "../../../common/k8s-api/kube-object"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import { Spinner } from "../spinner"; import type { MetricsTab } from "../chart/options"; import type { MetricData } from "../../../common/k8s-api/endpoints/metrics.api"; diff --git a/packages/core/src/renderer/components/select/select.tsx b/packages/core/src/renderer/components/select/select.tsx index 2d07442b1f..891fa59aa4 100644 --- a/packages/core/src/renderer/components/select/select.tsx +++ b/packages/core/src/renderer/components/select/select.tsx @@ -14,9 +14,10 @@ import { observer } from "mobx-react"; import ReactSelect, { components, createFilter } from "react-select"; import type { Props as ReactSelectProps, GroupBase, MultiValue, OptionsOrGroups, PropsValue, SingleValue } from "react-select"; import type { LensTheme } from "../../themes/lens-theme"; -import { autoBind, cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import { withInjectables } from "@ogre-tools/injectable-react"; import activeThemeInjectable from "../../themes/active.injectable"; +import autoBindReact from "auto-bind/react"; const { Menu } = components; @@ -120,7 +121,7 @@ class NonInjectedSelect< constructor(props: SelectProps & Dependencies) { super(props); makeObservable(this); - autoBind(this); + autoBindReact(this); } @computed get themeClass() { diff --git a/packages/core/src/renderer/components/slider/slider.tsx b/packages/core/src/renderer/components/slider/slider.tsx index a026826036..8a696a95df 100644 --- a/packages/core/src/renderer/components/slider/slider.tsx +++ b/packages/core/src/renderer/components/slider/slider.tsx @@ -8,7 +8,7 @@ import "./slider.scss"; import React, { Component } from "react"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import type { SliderClassKey, SliderProps as MaterialSliderProps } from "@material-ui/core/Slider"; import MaterialSlider from "@material-ui/core/Slider"; import assert from "assert"; diff --git a/packages/core/src/renderer/components/spinner/spinner.tsx b/packages/core/src/renderer/components/spinner/spinner.tsx index 3cf46baa9c..20fa9ebfdd 100644 --- a/packages/core/src/renderer/components/spinner/spinner.tsx +++ b/packages/core/src/renderer/components/spinner/spinner.tsx @@ -6,7 +6,7 @@ import "./spinner.scss"; import React from "react"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; export interface SpinnerProps extends React.HTMLProps { singleColor?: boolean; diff --git a/packages/core/src/renderer/components/status-brick/status-brick.tsx b/packages/core/src/renderer/components/status-brick/status-brick.tsx index a9cc89fed2..858cdd8580 100644 --- a/packages/core/src/renderer/components/status-brick/status-brick.tsx +++ b/packages/core/src/renderer/components/status-brick/status-brick.tsx @@ -6,7 +6,7 @@ import "./status-brick.scss"; import React from "react"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import { withTooltip } from "../tooltip"; export interface StatusBrickProps extends React.HTMLAttributes { diff --git a/packages/core/src/renderer/components/stepper/stepper.tsx b/packages/core/src/renderer/components/stepper/stepper.tsx index 725cb1d827..301d3716f8 100644 --- a/packages/core/src/renderer/components/stepper/stepper.tsx +++ b/packages/core/src/renderer/components/stepper/stepper.tsx @@ -5,7 +5,7 @@ import "./stepper.scss"; import React from "react"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; export interface StepperProps extends React.HTMLProps { step: number; diff --git a/packages/core/src/renderer/components/switch/switch.tsx b/packages/core/src/renderer/components/switch/switch.tsx index 2f91faf1a9..7bef386dd5 100644 --- a/packages/core/src/renderer/components/switch/switch.tsx +++ b/packages/core/src/renderer/components/switch/switch.tsx @@ -7,7 +7,7 @@ import styles from "./switch.module.scss"; import type { ChangeEvent, HTMLProps } from "react"; import React from "react"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; export interface SwitchProps extends Omit, "onChange"> { onChange?: (checked: boolean, event: ChangeEvent) => void; diff --git a/packages/core/src/renderer/components/table/react-table.tsx b/packages/core/src/renderer/components/table/react-table.tsx index e1dcc59ab9..68835e1741 100644 --- a/packages/core/src/renderer/components/table/react-table.tsx +++ b/packages/core/src/renderer/components/table/react-table.tsx @@ -8,7 +8,7 @@ import React, { useCallback, useMemo } from "react"; import type { Row, UseTableOptions } from "react-table"; import { useFlexLayout, useSortBy, useTable } from "react-table"; import { Icon } from "../icon"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; export interface ReactTableProps extends UseTableOptions { headless?: boolean; diff --git a/packages/core/src/renderer/components/table/sorting.ts b/packages/core/src/renderer/components/table/sorting.ts index 828ae1e378..81ca0786c9 100644 --- a/packages/core/src/renderer/components/table/sorting.ts +++ b/packages/core/src/renderer/components/table/sorting.ts @@ -4,7 +4,7 @@ */ import type { TableOrderBy, TableSortCallback } from "./table"; -import { Ordering, rectifyOrdering, sortCompare, tuple } from "../../utils"; +import { Ordering, rectifyOrdering, sortCompare, tuple } from "@k8slens/utilities"; export function getSorted(rawItems: T[], sortingCallback: TableSortCallback | undefined, orderBy: TableOrderBy = "asc"): T[] { if (typeof sortingCallback !== "function") { diff --git a/packages/core/src/renderer/components/table/table-cell.tsx b/packages/core/src/renderer/components/table/table-cell.tsx index 758c5cd951..69f45936f8 100644 --- a/packages/core/src/renderer/components/table/table-cell.tsx +++ b/packages/core/src/renderer/components/table/table-cell.tsx @@ -8,9 +8,10 @@ import type { TableSortBy, TableSortParams } from "./table"; import type { ReactNode } from "react"; import React from "react"; -import { autoBind, cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import { Icon } from "../icon"; import { Checkbox } from "../checkbox"; +import autoBindReact from "auto-bind/react"; export type TableCellElem = React.ReactElement; @@ -75,7 +76,7 @@ export interface TableCellProps extends React.DOMAttributes { export class TableCell extends React.Component { constructor(props: TableCellProps) { super(props); - autoBind(this); + autoBindReact(this); } onClick(evt: React.MouseEvent) { diff --git a/packages/core/src/renderer/components/table/table-head.tsx b/packages/core/src/renderer/components/table/table-head.tsx index 6424d43041..a336c19b5d 100644 --- a/packages/core/src/renderer/components/table/table-head.tsx +++ b/packages/core/src/renderer/components/table/table-head.tsx @@ -6,7 +6,7 @@ import "./table-head.scss"; import React from "react"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; export type TableHeadElem = React.ReactElement; diff --git a/packages/core/src/renderer/components/table/table-model/table-model.ts b/packages/core/src/renderer/components/table/table-model/table-model.ts index 4349ada20c..cc95c0b742 100644 --- a/packages/core/src/renderer/components/table/table-model/table-model.ts +++ b/packages/core/src/renderer/components/table/table-model/table-model.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 { StorageLayer } from "../../../utils"; +import type { StorageLayer } from "../../../utils/storage-helper"; import type { TableSortParams } from "../table"; export interface TableStorageModel { diff --git a/packages/core/src/renderer/components/table/table-row.tsx b/packages/core/src/renderer/components/table/table-row.tsx index 9725c7112d..aaf4a0a2fb 100644 --- a/packages/core/src/renderer/components/table/table-row.tsx +++ b/packages/core/src/renderer/components/table/table-row.tsx @@ -7,7 +7,7 @@ import "./table-row.scss"; import type { CSSProperties } from "react"; import React from "react"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; export type TableRowElem = React.ReactElement>; diff --git a/packages/core/src/renderer/components/table/table.tsx b/packages/core/src/renderer/components/table/table.tsx index b35aae742c..9c1cbcae70 100644 --- a/packages/core/src/renderer/components/table/table.tsx +++ b/packages/core/src/renderer/components/table/table.tsx @@ -7,7 +7,7 @@ import "./table.scss"; import React from "react"; import { observer } from "mobx-react"; -import { autoBind, cssNames, isDefined } from "../../utils"; +import { cssNames, isDefined } from "@k8slens/utilities"; import type { TableRowElem, TableRowProps } from "./table-row"; import { TableRow } from "./table-row"; import type { TableHeadElem } from "./table-head"; @@ -24,6 +24,7 @@ import type { ItemObject } from "../../../common/item.store"; import assert from "assert"; import orderByUrlParamInjectable from "./order-by-url-param.injectable"; import sortByUrlParamInjectable from "./sort-by-url-param.injectable"; +import autoBindReact from "auto-bind/react"; export type TableSortBy = string; export type TableOrderBy = "asc" | "desc"; @@ -97,7 +98,7 @@ class NonInjectedTable extends React.Component & Dependencies) { super(props); makeObservable(this); - autoBind(this); + autoBindReact(this); } componentDidMount() { diff --git a/packages/core/src/renderer/components/tabs/tabs.tsx b/packages/core/src/renderer/components/tabs/tabs.tsx index 7b08b63159..4e76184f3c 100644 --- a/packages/core/src/renderer/components/tabs/tabs.tsx +++ b/packages/core/src/renderer/components/tabs/tabs.tsx @@ -6,8 +6,9 @@ import "./tabs.scss"; import type { DOMAttributes } from "react"; import React from "react"; -import { autoBind, cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import { Icon } from "../icon"; +import autoBindReact from "auto-bind/react"; const TabsContext = React.createContext>({}); @@ -66,7 +67,7 @@ export class Tab extends React.PureComponent> { constructor(props: TabProps) { super(props); - autoBind(this); + autoBindReact(this); } get isActive() { diff --git a/packages/core/src/renderer/components/test-utils/get-application-builder.tsx b/packages/core/src/renderer/components/test-utils/get-application-builder.tsx index 4ba9c42778..627fe86fd7 100644 --- a/packages/core/src/renderer/components/test-utils/get-application-builder.tsx +++ b/packages/core/src/renderer/components/test-utils/get-application-builder.tsx @@ -22,7 +22,7 @@ import navigateToPreferencesInjectable from "../../../features/preferences/commo import type { NavigateToHelmCharts } from "../../../common/front-end-routing/routes/cluster/helm/charts/navigate-to-helm-charts.injectable"; import navigateToHelmChartsInjectable from "../../../common/front-end-routing/routes/cluster/helm/charts/navigate-to-helm-charts.injectable"; import hostedClusterInjectable from "../../cluster-frame-context/hosted-cluster.injectable"; -import type { Cluster } from "../../../common/cluster/cluster"; +import { Cluster } from "../../../common/cluster/cluster"; import type { NamespaceStore } from "../+namespaces/store"; import historyInjectable from "../../navigation/history.injectable"; import type { MinimalTrayMenuItem } from "../../../main/tray/electron-tray/electron-tray.injectable"; @@ -66,18 +66,11 @@ import shouldStartHiddenInjectable from "../../../main/electron-app/features/sho import fsInjectable from "../../../common/fs/fs.injectable"; import joinPathsInjectable from "../../../common/path/join-paths.injectable"; import homeDirectoryPathInjectable from "../../../common/os/home-directory-path.injectable"; -import { testUsingFakeTime } from "../../../common/test-utils/use-fake-time"; import selectedNamespacesStorageInjectable from "../../../features/namespace-filtering/renderer/storage.injectable"; import { registerFeature } from "@k8slens/feature-core"; -import { - applicationFeatureForElectronMain, - testUtils as applicationForElectronTestUtils, -} from "@k8slens/application-for-electron-main"; -import { - applicationFeature, - startApplicationInjectionToken, -} from "@k8slens/application"; - +import { applicationFeatureForElectronMain, testUtils as applicationForElectronTestUtils } from "@k8slens/application-for-electron-main"; +import { applicationFeature, startApplicationInjectionToken } from "@k8slens/application"; +import { testUsingFakeTime } from "../../../test-utils/use-fake-time"; type Callback = (di: DiContainer) => void | Promise; @@ -228,8 +221,6 @@ export const getApplicationBuilder = () => { }, })); - const allowedResourcesState = observable.set(); - const windowHelpers = new Map RenderResult }>(); const createElectronWindowFake: CreateElectronWindow = (configuration) => { @@ -526,19 +517,20 @@ export const getApplicationBuilder = () => { environment = environments.clusterFrame; builder.beforeWindowStart((windowDi) => { - const clusterStub = { + const cluster = new Cluster({ id: "some-cluster-id", - accessibleNamespaces: observable.array(), - allowedNamespaces: observable.array(), - shouldShowResource: (kind) => allowedResourcesState.has(formatKubeApiResource(kind)), - } as Partial as Cluster; + contextName: "some-context-name", + kubeConfigPath: "/some-path-to-kube-config", + }, { + clusterServerUrl: "https://localhost:12345", + }); windowDi.override(activeKubernetesClusterInjectable, () => - computed(() => catalogEntityFromCluster(clusterStub)), + computed(() => catalogEntityFromCluster(cluster)), ); - windowDi.override(hostedClusterIdInjectable, () => clusterStub.id); - windowDi.override(hostedClusterInjectable, () => clusterStub); + windowDi.override(hostedClusterIdInjectable, () => cluster.id); + windowDi.override(hostedClusterInjectable, () => cluster); // TODO: Figure out a way to remove this stub. windowDi.override(namespaceStoreInjectable, () => ({ @@ -645,8 +637,11 @@ export const getApplicationBuilder = () => { allowKubeResource: (resource) => { environment.onAllowKubeResource(); + const windowDi = builder.applicationWindow.only.di; + const cluster = windowDi.inject(hostedClusterInjectable); + runInAction(() => { - allowedResourcesState.add(formatKubeApiResource(resource)); + cluster?.resourcesToShow.add(formatKubeApiResource(resource)); }); return builder; diff --git a/packages/core/src/renderer/components/tooltip/tooltip.scss b/packages/core/src/renderer/components/tooltip/tooltip.scss index 10b7669679..d90d91f52e 100644 --- a/packages/core/src/renderer/components/tooltip/tooltip.scss +++ b/packages/core/src/renderer/components/tooltip/tooltip.scss @@ -63,27 +63,36 @@ } &.tableView { - min-width: 200px; + display: grid; + gap: var(--padding); + grid-template-columns: max-content 1fr; + grid-template-rows: repeat(2, 1fr); - > :not(:last-child) { - margin-bottom: var(--flex-gap); + // backward compatibility: skips element in DOM to consider only children in grid-flow + > .flex { + display: contents; + } + + > * { + white-space: pre-wrap; + word-break: break-word; } .title { + grid-column: 1 / 3; // merge color: var(--textColorAccent); text-align: center; + font-weight: bold; } .name { - color: var(--textColorAccent); text-align: right; - flex: 0 0 35%; + color: var(--textColorAccent); } .value { text-align: left; - max-width: 300px; - word-break: break-word; + color: var(--textColorSecondary); } } } diff --git a/packages/core/src/renderer/components/tooltip/tooltip.tsx b/packages/core/src/renderer/components/tooltip/tooltip.tsx index 7fc1abddbf..5c2f512f2f 100644 --- a/packages/core/src/renderer/components/tooltip/tooltip.tsx +++ b/packages/core/src/renderer/components/tooltip/tooltip.tsx @@ -8,9 +8,10 @@ import "./tooltip.scss"; import React from "react"; import { createPortal } from "react-dom"; import { observer } from "mobx-react"; -import type { IClassName } from "../../utils"; -import { cssNames, autoBind } from "../../utils"; +import type { IClassName } from "@k8slens/utilities"; +import { cssNames } from "@k8slens/utilities"; import { observable, makeObservable, action } from "mobx"; +import autoBindReact from "auto-bind/react"; export enum TooltipPosition { TOP = "top", @@ -61,7 +62,7 @@ export class Tooltip extends React.Component { constructor(props: TooltipProps) { super(props); makeObservable(this); - autoBind(this); + autoBindReact(this); } get targetElem(): HTMLElement | null { diff --git a/packages/core/src/renderer/components/tooltip/withTooltip.tsx b/packages/core/src/renderer/components/tooltip/withTooltip.tsx index 931653dc8e..533fbecf44 100644 --- a/packages/core/src/renderer/components/tooltip/withTooltip.tsx +++ b/packages/core/src/renderer/components/tooltip/withTooltip.tsx @@ -9,9 +9,9 @@ import type { ReactNode } from "react"; import React, { useState } from "react"; import type { TooltipProps } from "./tooltip"; import { Tooltip } from "./tooltip"; -import { isReactNode } from "../../utils/isReactNode"; +import { isReactNode } from "@k8slens/utilities"; import uniqueId from "lodash/uniqueId"; -import type { SingleOrMany } from "../../utils"; +import type { SingleOrMany } from "@k8slens/utilities"; export interface TooltipDecoratorProps { tooltip?: ReactNode | Omit; diff --git a/packages/core/src/renderer/components/tree-view/tree-view.tsx b/packages/core/src/renderer/components/tree-view/tree-view.tsx index 8672f9597f..c7fc813199 100644 --- a/packages/core/src/renderer/components/tree-view/tree-view.tsx +++ b/packages/core/src/renderer/components/tree-view/tree-view.tsx @@ -9,7 +9,7 @@ import React, { useEffect, useRef } from "react"; import { Icon } from "../icon"; import TreeView from "@material-ui/lab/TreeView"; import TreeItem from "@material-ui/lab/TreeItem"; -import { cssNames } from "../../utils"; +import { cssNames } from "@k8slens/utilities"; import _ from "lodash"; import getDeepDash from "deepdash"; diff --git a/packages/core/src/renderer/components/virtual-list/virtual-list.tsx b/packages/core/src/renderer/components/virtual-list/virtual-list.tsx index 3ea0aebb1c..2a27376a37 100644 --- a/packages/core/src/renderer/components/virtual-list/virtual-list.tsx +++ b/packages/core/src/renderer/components/virtual-list/virtual-list.tsx @@ -12,7 +12,7 @@ import React, { createRef, forwardRef, useCallback, useEffect, useImperativeHand import { observer } from "mobx-react"; import type { Align, ListChildComponentProps, ListOnScrollProps } from "react-window"; import { VariableSizeList } from "react-window"; -import { cssNames, noop } from "../../utils"; +import { cssNames, noop } from "@k8slens/utilities"; import type { TableRowProps } from "../table/table-row"; import isEqual from "lodash/isEqual"; import AutoSizer from "react-virtualized-auto-sizer"; diff --git a/packages/core/src/renderer/components/wizard/wizard.tsx b/packages/core/src/renderer/components/wizard/wizard.tsx index 5a1e5af789..0e58e12ece 100755 --- a/packages/core/src/renderer/components/wizard/wizard.tsx +++ b/packages/core/src/renderer/components/wizard/wizard.tsx @@ -5,7 +5,7 @@ import "./wizard.scss"; import React from "react"; -import { cssNames, prevDefault } from "../../utils"; +import { cssNames, prevDefault } from "@k8slens/utilities"; import { Button } from "../button"; import { Stepper } from "../stepper"; import { SubTitle } from "../layout/sub-title"; diff --git a/packages/core/src/renderer/frames/cluster-frame/cluster-frame.test.tsx b/packages/core/src/renderer/frames/cluster-frame/cluster-frame.test.tsx index 138f6141e0..4ad315ab98 100644 --- a/packages/core/src/renderer/frames/cluster-frame/cluster-frame.test.tsx +++ b/packages/core/src/renderer/frames/cluster-frame/cluster-frame.test.tsx @@ -14,8 +14,7 @@ import { DefaultProps } from "../../mui-base-theme"; import { ClusterFrame } from "./cluster-frame"; import historyInjectable from "../../navigation/history.injectable"; import { computed } from "mobx"; -import type { Cluster } from "../../../common/cluster/cluster"; -import createClusterInjectable from "../../cluster/create-cluster.injectable"; +import { Cluster } from "../../../common/cluster/cluster"; import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable"; import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable"; @@ -23,8 +22,8 @@ import legacyOnChannelListenInjectable from "../../ipc/legacy-channel-listen.inj import currentRouteComponentInjectable from "../../routes/current-route-component.injectable"; import hostedClusterIdInjectable from "../../cluster-frame-context/hosted-cluster-id.injectable"; import hostedClusterInjectable from "../../cluster-frame-context/hosted-cluster.injectable"; -import { testUsingFakeTime } from "../../../common/test-utils/use-fake-time"; import currentlyInClusterFrameInjectable from "../../routes/currently-in-cluster-frame.injectable"; +import { testUsingFakeTime } from "../../../test-utils/use-fake-time"; describe("", () => { let render: () => RenderResult; @@ -49,9 +48,7 @@ describe("", () => { testUsingFakeTime("2000-01-01 12:00:00am"); - const createCluster = di.inject(createClusterInjectable); - - cluster = createCluster( + cluster = new Cluster( { contextName: "my-cluster", id: "123456", @@ -68,8 +65,7 @@ describe("", () => { describe("given cluster with list nodes and namespaces permissions", () => { beforeEach(() => { - // TODO: replace with not using private info - (cluster as unknown as { readonly allowedResources: Cluster["allowedResources"] }).allowedResources.replace(["nodes", "namespaces"]); + cluster.resourcesToShow.replace(["nodes", "namespaces"]); }); it("renders", () => { @@ -110,7 +106,7 @@ describe("", () => { describe("given cluster without list nodes, but with namespaces permissions", () => { beforeEach(() => { - (cluster as unknown as { readonly allowedResources: Cluster["allowedResources"] }).allowedResources.replace(["namespaces"]); + cluster.resourcesToShow.replace(["namespaces"]); }); it("renders", () => { diff --git a/packages/core/src/renderer/frames/cluster-frame/cluster-frame.tsx b/packages/core/src/renderer/frames/cluster-frame/cluster-frame.tsx index 097ebbb87c..dd9d087769 100755 --- a/packages/core/src/renderer/frames/cluster-frame/cluster-frame.tsx +++ b/packages/core/src/renderer/frames/cluster-frame/cluster-frame.tsx @@ -9,7 +9,7 @@ import type { NamespaceStore } from "../../components/+namespaces/store"; import { withInjectables } from "@ogre-tools/injectable-react"; import namespaceStoreInjectable from "../../components/+namespaces/store.injectable"; import type { SubscribeStores } from "../../kube-watch-api/kube-watch-api"; -import { disposer } from "../../utils"; +import { disposer } from "@k8slens/utilities"; import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable"; import type { ClusterFrameChildComponent } from "./cluster-frame-child-component-injection-token"; import { clusterFrameChildComponentInjectionToken } from "./cluster-frame-child-component-injection-token"; diff --git a/packages/core/src/renderer/frames/cluster-frame/init-cluster-frame/init-cluster-frame.ts b/packages/core/src/renderer/frames/cluster-frame/init-cluster-frame/init-cluster-frame.ts index 109ae0f0bc..9bd0a26a3c 100644 --- a/packages/core/src/renderer/frames/cluster-frame/init-cluster-frame/init-cluster-frame.ts +++ b/packages/core/src/renderer/frames/cluster-frame/init-cluster-frame/init-cluster-frame.ts @@ -40,7 +40,7 @@ export const initClusterFrame = ({ ); await requestSetClusterFrameId(hostedCluster.id); - await hostedCluster.whenReady; // cluster.activate() is done at this point + await when(() => hostedCluster.ready.get()); // cluster.activate() is done at this point catalogEntityRegistry.activeEntity = hostedCluster.id; diff --git a/packages/core/src/renderer/frames/root-frame/init-root-frame.injectable.ts b/packages/core/src/renderer/frames/root-frame/init-root-frame.injectable.ts index 8d2c3a43be..f1e3024d80 100644 --- a/packages/core/src/renderer/frames/root-frame/init-root-frame.injectable.ts +++ b/packages/core/src/renderer/frames/root-frame/init-root-frame.injectable.ts @@ -10,7 +10,7 @@ import catalogEntityRegistryInjectable from "../../api/catalog/entity/registry.i import registerIpcListenersInjectable from "../../ipc/register-ipc-listeners.injectable"; import loadExtensionsInjectable from "../load-extensions.injectable"; import loggerInjectable from "../../../common/logger.injectable"; -import { delay } from "../../../common/utils"; +import { delay } from "@k8slens/utilities"; import { broadcastMessage } from "../../../common/ipc"; import { bundledExtensionsLoaded } from "../../../common/ipc/extension-handling"; diff --git a/packages/core/src/renderer/frames/root-frame/setup-system-ca.injectable.ts b/packages/core/src/renderer/frames/root-frame/setup-system-ca.injectable.ts index 4fe4d07758..43ace24cc2 100644 --- a/packages/core/src/renderer/frames/root-frame/setup-system-ca.injectable.ts +++ b/packages/core/src/renderer/frames/root-frame/setup-system-ca.injectable.ts @@ -9,8 +9,11 @@ import injectSystemCAsInjectable from "../../../features/certificate-authorities const setupSystemCaInjectable = getInjectable({ id: "setup-system-ca", instantiate: (di) => ({ - id: "setup-system-ca", - run: di.inject(injectSystemCAsInjectable), + run: async () => { + const injectSystemCAs = di.inject(injectSystemCAsInjectable); + + await injectSystemCAs(); + }, }), injectionToken: beforeFrameStartsSecondInjectionToken, }); diff --git a/packages/core/src/renderer/getDiForUnitTesting.tsx b/packages/core/src/renderer/getDiForUnitTesting.tsx index 0ee4a9b66b..fbee046de2 100644 --- a/packages/core/src/renderer/getDiForUnitTesting.tsx +++ b/packages/core/src/renderer/getDiForUnitTesting.tsx @@ -14,14 +14,9 @@ import requestAnimationFrameInjectable from "./components/animate/request-animat import startTopbarStateSyncInjectable from "./components/layout/top-bar/start-state-sync.injectable"; import watchHistoryStateInjectable from "./remote-helpers/watch-history-state.injectable"; import legacyOnChannelListenInjectable from "./ipc/legacy-channel-listen.injectable"; -import type { GlobalOverride } from "../common/test-utils/get-global-override"; - -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 type { GlobalOverride } from "@k8slens/test-utils"; +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 { registerInjectableReact } from "@ogre-tools/injectable-react"; export const getDiForUnitTesting = () => { @@ -46,7 +41,7 @@ export const getDiForUnitTesting = () => { }); for (const globalOverridePath of global.injectablePaths.renderer.globalOverridePaths) { - const globalOverride = require(globalOverridePath).default as GlobalOverride; + const globalOverride = require(globalOverridePath).default as GlobalOverride; di.override(globalOverride.injectable, globalOverride.overridingInstantiate); } diff --git a/packages/core/src/renderer/ipc/index.ts b/packages/core/src/renderer/ipc/index.ts index 4bbf473515..f8ebfc2de0 100644 --- a/packages/core/src/renderer/ipc/index.ts +++ b/packages/core/src/renderer/ipc/index.ts @@ -9,10 +9,10 @@ import { windowActionHandleChannel, windowLocationChangedChannel, windowOpenAppM import { extensionDiscoveryStateChannel, extensionLoaderFromMainChannel } from "../../common/ipc/extension-handling"; import type { InstalledExtension } from "../../extensions/extension-discovery/extension-discovery"; import type { LensExtensionId } from "../../extensions/lens-extension"; -import { toJS } from "../utils"; import type { Location } from "history"; import { getLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; import ipcRendererInjectable from "../utils/channel/ipc-renderer.injectable"; +import { toJS } from "../../common/utils"; function requestMain(channel: string, ...args: any[]) { const di = getLegacyGlobalDiForExtensionApi(); diff --git a/packages/core/src/renderer/ipc/list-namespaces-forbidden-handler.injectable.tsx b/packages/core/src/renderer/ipc/list-namespaces-forbidden-handler.injectable.tsx index 75fb51fe68..4acf8182b1 100644 --- a/packages/core/src/renderer/ipc/list-namespaces-forbidden-handler.injectable.tsx +++ b/packages/core/src/renderer/ipc/list-namespaces-forbidden-handler.injectable.tsx @@ -55,7 +55,7 @@ const listNamespacesForbiddenHandlerInjectable = getInjectable({ Add Accessible Namespaces

{"Cluster "} - {getClusterById(clusterId)?.name ?? ""} + {getClusterById(clusterId)?.name.get() ?? ""} {" does not have permissions to list namespaces. Please add the namespaces you have access to."}

diff --git a/packages/core/src/renderer/kube-object/handlers.injectable.ts b/packages/core/src/renderer/kube-object/handlers.injectable.ts index 8344d94034..b8827e2f8d 100644 --- a/packages/core/src/renderer/kube-object/handlers.injectable.ts +++ b/packages/core/src/renderer/kube-object/handlers.injectable.ts @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import { computed } from "mobx"; import rendererExtensionsInjectable from "../../extensions/renderer-extensions.injectable"; -import { getOrInsert, getOrInsertMap, readonly } from "../utils"; +import { getOrInsert, getOrInsertMap, readonly } from "@k8slens/utilities"; import type { KubeObjectHandlerRegistration, KubeObjectHandlers } from "./handler"; import { staticKubeObjectHandlerInjectionToken } from "./handler"; diff --git a/packages/core/src/renderer/kube-watch-api/kube-watch-api.ts b/packages/core/src/renderer/kube-watch-api/kube-watch-api.ts index 110ed61472..f3dc0ae237 100644 --- a/packages/core/src/renderer/kube-watch-api/kube-watch-api.ts +++ b/packages/core/src/renderer/kube-watch-api/kube-watch-api.ts @@ -3,8 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { comparer, reaction } from "mobx"; -import type { Disposer } from "../../common/utils"; -import { disposer, getOrInsert, noop, WrappedAbortController } from "../../common/utils"; +import type { Disposer } from "@k8slens/utilities"; +import { disposer, getOrInsert, noop, WrappedAbortController } from "@k8slens/utilities"; import { once } from "lodash"; import type { Logger } from "../../common/logger"; import type { KubeObjectStoreLoadAllParams, KubeObjectStoreSubscribeParams } from "../../common/k8s-api/kube-object.store"; diff --git a/packages/core/src/renderer/kube-watch-api/subscribe-stores.global-override-for-injectable.ts b/packages/core/src/renderer/kube-watch-api/subscribe-stores.global-override-for-injectable.ts index 711e9caa17..6390951c1f 100644 --- a/packages/core/src/renderer/kube-watch-api/subscribe-stores.global-override-for-injectable.ts +++ b/packages/core/src/renderer/kube-watch-api/subscribe-stores.global-override-for-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 { getGlobalOverride } from "../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import subscribeStoresInjectable from "./subscribe-stores.injectable"; export default getGlobalOverride( diff --git a/packages/core/src/renderer/monaco/add-new-theme.global-override-for-injectable.ts b/packages/core/src/renderer/monaco/add-new-theme.global-override-for-injectable.ts index 00e034a8b7..abfc721632 100644 --- a/packages/core/src/renderer/monaco/add-new-theme.global-override-for-injectable.ts +++ b/packages/core/src/renderer/monaco/add-new-theme.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import addNewMonacoThemeInjectable from "./add-new-theme.injectable"; export default getGlobalOverride(addNewMonacoThemeInjectable, () => () => {}); diff --git a/packages/core/src/renderer/navigation/focus-window.global-override-for-injectable.ts b/packages/core/src/renderer/navigation/focus-window.global-override-for-injectable.ts index b8972b354a..5da78b0a00 100644 --- a/packages/core/src/renderer/navigation/focus-window.global-override-for-injectable.ts +++ b/packages/core/src/renderer/navigation/focus-window.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import focusWindowInjectable from "./focus-window.injectable"; export default getGlobalOverride(focusWindowInjectable, () => () => {}); diff --git a/packages/core/src/renderer/navigation/history.global-override-for-injectable.ts b/packages/core/src/renderer/navigation/history.global-override-for-injectable.ts index 477e3df397..cc3587d12a 100644 --- a/packages/core/src/renderer/navigation/history.global-override-for-injectable.ts +++ b/packages/core/src/renderer/navigation/history.global-override-for-injectable.ts @@ -4,7 +4,7 @@ */ import { createMemoryHistory } from "history"; -import { getGlobalOverride } from "../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import historyInjectable from "./history.injectable"; export default getGlobalOverride(historyInjectable, () => createMemoryHistory()); diff --git a/packages/core/src/renderer/navigation/setup-logging-for-navigation.injectable.ts b/packages/core/src/renderer/navigation/setup-logging-for-navigation.injectable.ts index e6a1bce903..b56eb979a2 100644 --- a/packages/core/src/renderer/navigation/setup-logging-for-navigation.injectable.ts +++ b/packages/core/src/renderer/navigation/setup-logging-for-navigation.injectable.ts @@ -10,7 +10,6 @@ import observableHistoryInjectable from "./observable-history.injectable"; const setupLoggingForNavigationInjectable = getInjectable({ id: "setup-logging-for-navigation", instantiate: (di) => ({ - id: "setup-logging-for-navigation", run: () => { const logger = di.inject(loggerInjectable); const observableHistory = di.inject(observableHistoryInjectable); diff --git a/packages/core/src/renderer/port-forward/port-forward-dialog.tsx b/packages/core/src/renderer/port-forward/port-forward-dialog.tsx index 831edd2e70..cb85dfc3a9 100644 --- a/packages/core/src/renderer/port-forward/port-forward-dialog.tsx +++ b/packages/core/src/renderer/port-forward/port-forward-dialog.tsx @@ -12,7 +12,7 @@ import type { DialogProps } from "../components/dialog"; import { Dialog } from "../components/dialog"; import { Wizard, WizardStep } from "../components/wizard"; import { Input } from "../components/input"; -import { cssNames } from "../utils"; +import { cssNames } from "@k8slens/utilities"; import type { PortForwardStore } from "./port-forward-store/port-forward-store"; import { Checkbox } from "../components/checkbox"; import { withInjectables } from "@ogre-tools/injectable-react"; diff --git a/packages/core/src/renderer/port-forward/port-forward-item.ts b/packages/core/src/renderer/port-forward/port-forward-item.ts index 84ad444ecf..0ea56bc4cd 100644 --- a/packages/core/src/renderer/port-forward/port-forward-item.ts +++ b/packages/core/src/renderer/port-forward/port-forward-item.ts @@ -4,8 +4,8 @@ */ +import autoBind from "auto-bind"; import type { ItemObject } from "../../common/item.store"; -import { autoBind } from "../../common/utils"; export type ForwardedPortStatus = "Active" | "Disabled"; export interface ForwardedPort { diff --git a/packages/core/src/renderer/port-forward/port-forward-store/port-forward-store.ts b/packages/core/src/renderer/port-forward/port-forward-store/port-forward-store.ts index 288ccd6e08..eaf1711bf3 100644 --- a/packages/core/src/renderer/port-forward/port-forward-store/port-forward-store.ts +++ b/packages/core/src/renderer/port-forward/port-forward-store/port-forward-store.ts @@ -5,14 +5,15 @@ import { action, makeObservable, observable, reaction } from "mobx"; import { ItemStore } from "../../../common/item.store"; -import type { StorageLayer } from "../../utils"; -import { autoBind, disposer } from "../../utils"; +import type { StorageLayer } from "../../utils/storage-helper"; +import { disposer } from "@k8slens/utilities"; import type { ForwardedPort } from "../port-forward-item"; import { PortForwardItem } from "../port-forward-item"; import { waitUntilFree } from "tcp-port-used"; import type { Logger } from "../../../common/logger"; import type { JsonApi } from "../../../common/k8s-api/json-api"; import type { RequestActivePortForward } from "./request-active-port-forward.injectable"; +import autoBind from "auto-bind"; interface Dependencies { readonly storage: StorageLayer; diff --git a/packages/core/src/renderer/port-forward/port-forward-store/request-active-port-forward.injectable.ts b/packages/core/src/renderer/port-forward/port-forward-store/request-active-port-forward.injectable.ts index 90f91320c8..a54eb929a2 100644 --- a/packages/core/src/renderer/port-forward/port-forward-store/request-active-port-forward.injectable.ts +++ b/packages/core/src/renderer/port-forward/port-forward-store/request-active-port-forward.injectable.ts @@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import apiBaseInjectable from "../../../common/k8s-api/api-base.injectable"; import loggerInjectable from "../../../common/logger.injectable"; -import { urlBuilderFor } from "../../../common/utils/buildUrl"; +import { urlBuilderFor } from "@k8slens/utilities"; import type { ForwardedPort } from "../port-forward-item"; export type RequestActivePortForward = (portForward: ForwardedPort) => Promise; diff --git a/packages/core/src/renderer/routes/extension-page-parameters.injectable.ts b/packages/core/src/renderer/routes/extension-page-parameters.injectable.ts index ad6501cd35..d1897f19ab 100644 --- a/packages/core/src/renderer/routes/extension-page-parameters.injectable.ts +++ b/packages/core/src/renderer/routes/extension-page-parameters.injectable.ts @@ -8,7 +8,7 @@ import type { PageParamInit } from "../navigation/page-param"; import type { LensRendererExtension } from "../../extensions/lens-renderer-extension"; import { map } from "lodash/fp"; import createPageParamInjectable from "../navigation/create-page-param.injectable"; -import { object } from "../utils"; +import { object } from "@k8slens/utilities"; import type { PageRegistration } from "./page-registration"; export interface ExtensionPageParametersInstantiationParam { diff --git a/packages/core/src/renderer/routes/navigate-to-route.injectable.ts b/packages/core/src/renderer/routes/navigate-to-route.injectable.ts index 8b57a02613..4a83b2f467 100644 --- a/packages/core/src/renderer/routes/navigate-to-route.injectable.ts +++ b/packages/core/src/renderer/routes/navigate-to-route.injectable.ts @@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import { navigateToUrlInjectionToken } from "../../common/front-end-routing/navigate-to-url-injection-token"; import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token"; import currentlyInClusterFrameInjectable from "./currently-in-cluster-frame.injectable"; -import { buildURL } from "../../common/utils/buildUrl"; +import { buildURL } from "@k8slens/utilities"; const navigateToRouteInjectable = getInjectable({ id: "navigate-to-route", diff --git a/packages/core/src/renderer/start-frame/start-frame.injectable.ts b/packages/core/src/renderer/start-frame/start-frame.injectable.ts index e7311455c0..b4bddc9c30 100644 --- a/packages/core/src/renderer/start-frame/start-frame.injectable.ts +++ b/packages/core/src/renderer/start-frame/start-frame.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 { runManyFor } from "../../common/runnable/run-many-for"; +import { runManyFor } from "@k8slens/run-many"; import * as tokens from "../before-frame-starts/tokens"; import currentlyInClusterFrameInjectable from "../routes/currently-in-cluster-frame.injectable"; import { diff --git a/packages/core/src/renderer/stores/init-user-store.injectable.ts b/packages/core/src/renderer/stores/init-user-store.injectable.ts index fba2287fe0..af192d9b2e 100644 --- a/packages/core/src/renderer/stores/init-user-store.injectable.ts +++ b/packages/core/src/renderer/stores/init-user-store.injectable.ts @@ -10,14 +10,12 @@ import initDefaultUpdateChannelInjectable from "../vars/default-update-channel/i const initUserStoreInjectable = getInjectable({ id: "init-user-store", instantiate: (di) => ({ - id: "init-user-store", run: () => { - // This must be done here so as to actually only be instantiated after the dependencies are const userStore = di.inject(userStoreInjectable); return userStore.load(); }, - runAfter: di.inject(initDefaultUpdateChannelInjectable), + runAfter: initDefaultUpdateChannelInjectable, }), injectionToken: beforeFrameStartsSecondInjectionToken, }); diff --git a/packages/core/src/renderer/themes/apply-lens-theme.injectable.ts b/packages/core/src/renderer/themes/apply-lens-theme.injectable.ts index 72b721aa14..94afd5c531 100644 --- a/packages/core/src/renderer/themes/apply-lens-theme.injectable.ts +++ b/packages/core/src/renderer/themes/apply-lens-theme.injectable.ts @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import loggerInjectable from "../../common/logger.injectable"; import userStoreInjectable from "../../common/user-store/user-store.injectable"; -import { object } from "../utils"; +import { object } from "@k8slens/utilities"; import type { LensTheme } from "./lens-theme"; export type ApplyLensTheme = (theme: LensTheme) => void; diff --git a/packages/core/src/renderer/themes/apply-theme.global-override-for-injectable.ts b/packages/core/src/renderer/themes/apply-theme.global-override-for-injectable.ts index c8283843e1..fe9e3c60c8 100644 --- a/packages/core/src/renderer/themes/apply-theme.global-override-for-injectable.ts +++ b/packages/core/src/renderer/themes/apply-theme.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import applyLensThemeInjectable from "./apply-lens-theme.injectable"; export default getGlobalOverride(applyLensThemeInjectable, () => () => {}); diff --git a/packages/core/src/renderer/themes/setup-apply-active-theme.injectable.ts b/packages/core/src/renderer/themes/setup-apply-active-theme.injectable.ts index 960f5f8764..c71dd5baa7 100644 --- a/packages/core/src/renderer/themes/setup-apply-active-theme.injectable.ts +++ b/packages/core/src/renderer/themes/setup-apply-active-theme.injectable.ts @@ -13,7 +13,6 @@ import applyLensThemeInjectable from "./apply-lens-theme.injectable"; const setupApplyActiveThemeInjectable = getInjectable({ id: "setup-apply-active-theme", instantiate: (di) => ({ - id: "setup-apply-active-theme", run: () => { const activeTheme = di.inject(activeThemeInjectable); const applyLensTheme = di.inject(applyLensThemeInjectable); @@ -27,8 +26,8 @@ const setupApplyActiveThemeInjectable = getInjectable({ ); }, runAfter: [ - di.inject(initializeSystemThemeTypeInjectable), - di.inject(initUserStoreInjectable), + initializeSystemThemeTypeInjectable, + initUserStoreInjectable, ], }), injectionToken: beforeFrameStartsSecondInjectionToken, diff --git a/packages/core/src/renderer/utils/channel/channel-listeners/start-listening-of-channels.injectable.ts b/packages/core/src/renderer/utils/channel/channel-listeners/start-listening-of-channels.injectable.ts index aea98b3360..c11b34e7e3 100644 --- a/packages/core/src/renderer/utils/channel/channel-listeners/start-listening-of-channels.injectable.ts +++ b/packages/core/src/renderer/utils/channel/channel-listeners/start-listening-of-channels.injectable.ts @@ -10,7 +10,6 @@ const startListeningOfChannelsInjectable = getInjectable({ id: "start-listening-of-channels-renderer", instantiate: (di) => ({ - id: "start-listening-of-channels-renderer", run: () => { const listeningOfChannels = di.inject(listeningOnMessageChannelsInjectable); diff --git a/packages/core/src/renderer/utils/channel/ipc-renderer.global-override-for-injectable.ts b/packages/core/src/renderer/utils/channel/ipc-renderer.global-override-for-injectable.ts index 28043f1299..679229f912 100644 --- a/packages/core/src/renderer/utils/channel/ipc-renderer.global-override-for-injectable.ts +++ b/packages/core/src/renderer/utils/channel/ipc-renderer.global-override-for-injectable.ts @@ -4,7 +4,7 @@ */ import type { IpcRenderer } from "electron"; import ipcRendererInjectable from "./ipc-renderer.injectable"; -import { getGlobalOverride } from "../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; export default getGlobalOverride(ipcRendererInjectable, () => ({ invoke: () => {}, diff --git a/packages/core/src/renderer/utils/create-storage/initialize-state.injectable.ts b/packages/core/src/renderer/utils/create-storage/initialize-state.injectable.ts index 2c0d832c9e..75d61908cd 100644 --- a/packages/core/src/renderer/utils/create-storage/initialize-state.injectable.ts +++ b/packages/core/src/renderer/utils/create-storage/initialize-state.injectable.ts @@ -20,7 +20,6 @@ import storageSaveDelayInjectable from "./storage-save-delay.injectable"; const initializeStateInjectable = getInjectable({ id: "initialize-lens-local-storage-state", instantiate: (di) => ({ - id: "initialize-lens-local-storage-state", run: async () => { const joinPaths = di.inject(joinPathsInjectable); const directoryForLensLocalStorage = di.inject(directoryForLensLocalStorageInjectable); @@ -67,7 +66,7 @@ const initializeStateInjectable = getInjectable({ } } }, - runAfter: di.inject(setupAppPathsInjectable), + runAfter: setupAppPathsInjectable, }), injectionToken: beforeFrameStartsFirstInjectionToken, }); diff --git a/packages/core/src/renderer/utils/create-storage/storage-save-delay.global-override-for-injectable.ts b/packages/core/src/renderer/utils/create-storage/storage-save-delay.global-override-for-injectable.ts index f6bcc97ab0..5217018c3e 100644 --- a/packages/core/src/renderer/utils/create-storage/storage-save-delay.global-override-for-injectable.ts +++ b/packages/core/src/renderer/utils/create-storage/storage-save-delay.global-override-for-injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "../../../common/test-utils/get-global-override"; +import { getGlobalOverride } from "@k8slens/test-utils"; import storageSaveDelayInjectable from "./storage-save-delay.injectable"; export default getGlobalOverride(storageSaveDelayInjectable, () => 0); diff --git a/packages/core/src/renderer/utils/index.ts b/packages/core/src/renderer/utils/index.ts deleted file mode 100755 index cde1a70077..0000000000 --- a/packages/core/src/renderer/utils/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -// Common usage utils & helpers -export * from "../../common/utils"; -export * from "../../common/event-emitter"; - -export * from "./cssNames"; -export * from "./cssVar"; -export * from "./display-mode"; -export * from "./interval"; -export * from "./isMiddleClick"; -export * from "./isReactNode"; -export * from "./metricUnitsToNumber"; -export * from "./name-parts"; -export * from "./prevDefault"; -export * from "./saveFile"; -export * from "./storage-helper"; diff --git a/packages/core/src/renderer/utils/rbac.ts b/packages/core/src/renderer/utils/rbac.ts index 18748bcfac..b4aa9a6a81 100644 --- a/packages/core/src/renderer/utils/rbac.ts +++ b/packages/core/src/renderer/utils/rbac.ts @@ -5,7 +5,7 @@ import type { KubeResource } from "../../common/rbac"; import { apiResourceRecord } from "../../common/rbac"; -import { object } from "../../common/utils"; +import { object } from "@k8slens/utilities"; export const ResourceNames: Record = { "namespaces": "Namespaces", diff --git a/packages/core/src/renderer/utils/sync-box/provide-initial-values-for-sync-boxes.injectable.ts b/packages/core/src/renderer/utils/sync-box/provide-initial-values-for-sync-boxes.injectable.ts index 3666bf0840..aceb20cea4 100644 --- a/packages/core/src/renderer/utils/sync-box/provide-initial-values-for-sync-boxes.injectable.ts +++ b/packages/core/src/renderer/utils/sync-box/provide-initial-values-for-sync-boxes.injectable.ts @@ -15,7 +15,6 @@ const provideInitialValuesForSyncBoxesInjectable = getInjectable({ id: "provide-initial-values-for-sync-boxes", instantiate: (di) => ({ - id: "provide-initial-values-for-sync-boxes", run: async () => { const requestFromChannel = di.inject(requestFromChannelInjectionToken); const syncBoxes = di.injectMany(syncBoxInjectionToken); diff --git a/packages/core/src/renderer/vars/build-version/init.injectable.ts b/packages/core/src/renderer/vars/build-version/init.injectable.ts index 0734960289..0eeecaa838 100644 --- a/packages/core/src/renderer/vars/build-version/init.injectable.ts +++ b/packages/core/src/renderer/vars/build-version/init.injectable.ts @@ -9,7 +9,6 @@ import buildVersionInjectable from "./build-version.injectable"; const initializeBuildVersionInjectable = getInjectable({ id: "initialize-build-version", instantiate: (di) => ({ - id: "initialize-build-version", run: async () => { const buildVersion = di.inject(buildVersionInjectable); diff --git a/packages/core/src/renderer/vars/default-update-channel/init.injectable.ts b/packages/core/src/renderer/vars/default-update-channel/init.injectable.ts index a349769815..7624d1f335 100644 --- a/packages/core/src/renderer/vars/default-update-channel/init.injectable.ts +++ b/packages/core/src/renderer/vars/default-update-channel/init.injectable.ts @@ -10,13 +10,12 @@ import defaultUpdateChannelInjectable from "../../../features/application-update const initDefaultUpdateChannelInjectable = getInjectable({ id: "init-default-update-channel", instantiate: (di) => ({ - id: "init-default-update-channel", run: async () => { const defaultUpdateChannel = di.inject(defaultUpdateChannelInjectable); await defaultUpdateChannel.init(); }, - runAfter: di.inject(initReleaseChannelInjectable), + runAfter: initReleaseChannelInjectable, }), injectionToken: beforeFrameStartsSecondInjectionToken, }); diff --git a/packages/core/src/renderer/vars/release-channel/init.injectable.ts b/packages/core/src/renderer/vars/release-channel/init.injectable.ts index e0092abf55..e49b9649a8 100644 --- a/packages/core/src/renderer/vars/release-channel/init.injectable.ts +++ b/packages/core/src/renderer/vars/release-channel/init.injectable.ts @@ -10,13 +10,12 @@ import initSemanticBuildVersionInjectable from "../semantic-build-version/init.i const initReleaseChannelInjectable = getInjectable({ id: "init-release-channel", instantiate: (di) => ({ - id: "init-release-channel", run: async () => { const releaseChannel = di.inject(releaseChannelInjectable); await releaseChannel.init(); }, - runAfter: di.inject(initSemanticBuildVersionInjectable), + runAfter: initSemanticBuildVersionInjectable, }), injectionToken: beforeFrameStartsSecondInjectionToken, }); diff --git a/packages/core/src/renderer/vars/semantic-build-version/init.injectable.ts b/packages/core/src/renderer/vars/semantic-build-version/init.injectable.ts index 62a9a3387f..3ef0a6a496 100644 --- a/packages/core/src/renderer/vars/semantic-build-version/init.injectable.ts +++ b/packages/core/src/renderer/vars/semantic-build-version/init.injectable.ts @@ -10,13 +10,12 @@ import initializeBuildVersionInjectable from "../build-version/init.injectable"; const initSemanticBuildVersionInjectable = getInjectable({ id: "init-semantic-build-version", instantiate: (di) => ({ - id: "init-semantic-build-version", run: async () => { const buildSemanticVersion = di.inject(buildSemanticVersionInjectable); await buildSemanticVersion.init(); }, - runAfter: di.inject(initializeBuildVersionInjectable), + runAfter: initializeBuildVersionInjectable, }), injectionToken: beforeFrameStartsSecondInjectionToken, }); diff --git a/packages/core/src/renderer/window/event-listener.injectable.ts b/packages/core/src/renderer/window/event-listener.injectable.ts index 78a1827e19..631fec116e 100644 --- a/packages/core/src/renderer/window/event-listener.injectable.ts +++ b/packages/core/src/renderer/window/event-listener.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; -import type { Disposer } from "../utils"; +import type { Disposer } from "@k8slens/utilities"; export type AddWindowEventListener = typeof addWindowEventListener; export type WindowEventListener = (this: Window, ev: WindowEventMap[K]) => any; diff --git a/packages/core/src/test-utils/channel-fakes/override-messaging-from-main-to-window.ts b/packages/core/src/test-utils/channel-fakes/override-messaging-from-main-to-window.ts index f9275c18b2..1b69f13016 100644 --- a/packages/core/src/test-utils/channel-fakes/override-messaging-from-main-to-window.ts +++ b/packages/core/src/test-utils/channel-fakes/override-messaging-from-main-to-window.ts @@ -5,7 +5,7 @@ import type { MessageChannelListener } from "../../common/utils/channel/message-channel-listener-injection-token"; import enlistMessageChannelListenerInjectableInRenderer from "../../renderer/utils/channel/channel-listeners/enlist-message-channel-listener.injectable"; import type { DiContainer } from "@ogre-tools/injectable"; -import { getOrInsert, getOrInsertSet } from "../../common/utils"; +import { getOrInsert, getOrInsertSet } from "@k8slens/utilities"; import type { SendToViewArgs } from "../../main/start-main-application/lens-window/application-window/create-lens-window.injectable"; import { deserialize, serialize } from "v8"; diff --git a/packages/core/src/test-utils/channel-fakes/override-messaging-from-window-to-main.ts b/packages/core/src/test-utils/channel-fakes/override-messaging-from-window-to-main.ts index c39731ac8e..8adc35c4d5 100644 --- a/packages/core/src/test-utils/channel-fakes/override-messaging-from-window-to-main.ts +++ b/packages/core/src/test-utils/channel-fakes/override-messaging-from-window-to-main.ts @@ -6,7 +6,7 @@ import type { DiContainer } from "@ogre-tools/injectable"; import { deserialize, serialize } from "v8"; import type { MessageChannel, MessageChannelListener } from "../../common/utils/channel/message-channel-listener-injection-token"; import enlistMessageChannelListenerInjectableInMain from "../../main/utils/channel/channel-listeners/enlist-message-channel-listener.injectable"; -import { getOrInsertSet } from "../../renderer/utils"; +import { getOrInsertSet } from "@k8slens/utilities"; import sendToMainInjectable from "../../renderer/utils/channel/send-to-main.injectable"; export const overrideMessagingFromWindowToMain = (mainDi: DiContainer) => { diff --git a/packages/core/src/test-utils/override-fs-with-fakes.ts b/packages/core/src/test-utils/override-fs-with-fakes.ts index 734170b0c7..87f8dd583a 100644 --- a/packages/core/src/test-utils/override-fs-with-fakes.ts +++ b/packages/core/src/test-utils/override-fs-with-fakes.ts @@ -62,6 +62,7 @@ export const getOverrideFsWithFakes = () => { ensureDirSync, createReadStream: root.createReadStream as any, stat: root.promises.stat as any, + unlink: root.promises.unlink, })); }; }; diff --git a/packages/core/src/common/test-utils/use-fake-time.ts b/packages/core/src/test-utils/use-fake-time.ts similarity index 100% rename from packages/core/src/common/test-utils/use-fake-time.ts rename to packages/core/src/test-utils/use-fake-time.ts diff --git a/packages/infrastructure/eslint-config/README.md b/packages/infrastructure/eslint-config/README.md new file mode 100644 index 0000000000..5a45b678f7 --- /dev/null +++ b/packages/infrastructure/eslint-config/README.md @@ -0,0 +1,32 @@ +# Lens Code Style + +**Note:** This package contains Eslint and Prettier configurations, name of package is `@k8slens/eslint-config` just because Eslint has arbitrary requirement (https://eslint.org/docs/latest/extend/shareable-configs). + +## Usage + +1. Install `@k8slens/eslint-config` +2. Create `.prettierrc` that contains `"@k8slens/eslint-config/prettier"` +3. Add a `.eslintrc.js` that extends `@k8slens/eslint-config/eslint`, for example: + +``` +module.exports = { + extends: "@k8slens/eslint-config/eslint", + parserOptions: { + project: "./tsconfig.json" + } +}; +``` + +4. Add linting and formatting scripts to `package.json` + +``` +{ + "scripts": { + "lint": "lens-lint", + "lint:fix": "lens-lint --fix" + } +} +``` + +6. Run `npm run lint` to lint +7. Run `npm run format` to fix all formatting diff --git a/packages/infrastructure/eslint-config/bin/lint b/packages/infrastructure/eslint-config/bin/lint new file mode 100755 index 0000000000..2abf180561 --- /dev/null +++ b/packages/infrastructure/eslint-config/bin/lint @@ -0,0 +1,20 @@ +#!/usr/bin/env node +const execSync = require("child_process").execSync; + +const argv = process.argv + +const shouldDoTheFix = argv.includes('--fix'); + +try { + execSync(`eslint ${shouldDoTheFix ? "--fix " : " "}--ext ts,tsx --max-warnings=0 .`); +} catch (error) { + console.log(error.stdout.toString()); +} + +try { + const result = execSync(`prettier ${shouldDoTheFix ? "--write" : "--check"} "**/*.{js,ts,tsx}"`); + + console.log(result.toString()); +} catch (error) { + console.log(error.stdout.toString()); +} diff --git a/packages/infrastructure/eslint-config/eslint-config.js b/packages/infrastructure/eslint-config/eslint-config.js new file mode 100644 index 0000000000..561541838d --- /dev/null +++ b/packages/infrastructure/eslint-config/eslint-config.js @@ -0,0 +1,173 @@ +module.exports = { + extends: [ + "plugin:@typescript-eslint/recommended", + "react-app", + "react-app/jest", + "airbnb-typescript", + "prettier", + "plugin:security/recommended", + "plugin:xss/recommended", + "plugin:no-unsanitized/DOM" + ], + plugins: [ + "unused-imports", + "prettier", + "xss", + "no-unsanitized" + ], + rules: { + "react/react-in-jsx-scope": 0, + "security/detect-object-injection": "off", + "security/detect-non-literal-fs-filename": "off" + }, + overrides: [ + { + files: [ + "**/*.ts?(x)", + "**/*.js?(x)", + "**/*.@(m|c)js" + ], + rules: { + "prettier/prettier": 2, + indent: "off", // Let prettier do it + curly: "error", + "import/prefer-default-export": "off", + "class-methods-use-this": "off", + "comma-dangle": "off", + "max-classes-per-file": "off", + "no-shadow": "off", + "no-param-reassign": ["error", { props: false }], + quotes: [ + "error", + "double", + { + "avoidEscape": true, + "allowTemplateLiterals": true + } + ], + "padding-line-between-statements": [ + "error", + { + blankLine: "always", + prev: "*", + next: "return", + }, + { + blankLine: "always", + prev: "*", + next: "block-like", + }, + { + blankLine: "always", + prev: "*", + next: "function", + }, + { + blankLine: "always", + prev: "*", + next: "class", + }, + { + blankLine: "always", + prev: ["const", "let", "var"], + next: "*", + }, + { + blankLine: "any", + prev: ["const", "let", "var"], + next: ["const", "let", "var"], + }, + ], + "import/no-extraneous-dependencies": "off", + "jsx-a11y/no-redundant-roles": ["off"], + "no-restricted-syntax": [ + "error", + { + selector: "ForInStatement", + message: + "for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array.", + }, + { + selector: "WithStatement", + message: + "`with` is disallowed in strict mode because it makes code impossible to predict and optimize.", + }, + ], + "max-len": [ + "error", + 120, + 2, + { + ignoreUrls: true, + ignoreComments: false, + ignoreRegExpLiterals: true, + ignoreStrings: true, + ignoreTemplateLiterals: true, + }, + ], + "unused-imports/no-unused-imports-ts": "error", + "import/extensions": "off", + "linebreak-style": ["error", "unix"], + "eol-last": ["error", "always"], + "object-shorthand": "error", + "prefer-template": "error", + "template-curly-spacing": "error", + "keyword-spacing": "off", + + // testing-library + "testing-library/no-node-access": "off", + "testing-library/no-container": "off", + "testing-library/prefer-screen-queries": "off", + "testing-library/no-render-in-setup": "off", + "testing-library/render-result-naming-convention": "off", + + // Typescript specific rules + "@typescript-eslint/ban-types": "off", + "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/no-empty-interface": "off", + "@typescript-eslint/no-floating-promises": "error", + "@typescript-eslint/interface-name-prefix": "off", + "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-useless-constructor": "off", + "@typescript-eslint/comma-dangle": "off", + "@typescript-eslint/no-shadow": "off", + "@typescript-eslint/quotes": [ + "error", + "double", + { + avoidEscape: true, + allowTemplateLiterals: true, + }, + ], + "@typescript-eslint/no-unused-expressions": [ + "error", + { + allowShortCircuit: true, + }, + ], + "@typescript-eslint/no-unused-vars": "off", + "@typescript-eslint/keyword-spacing": ["error"], + "@typescript-eslint/naming-convention": "off", + + // React specific rules + "react-hooks/rules-of-hooks": "error", + "react-hooks/exhaustive-deps": "warn", + "react/require-default-props": "off", + "react/function-component-definition": "off", + "react/prop-types": "off", + "react/jsx-filename-extension": [1, { extensions: [".tsx"] }], + + // jsx-a11y custom components + "jsx-a11y/label-has-associated-control": [ + 2, + { + controlComponents: ["Select", "StyledInput", "StyledSlider"], + depth: 1, + }, + ], + }, + }, + ], +}; diff --git a/packages/infrastructure/eslint-config/package.json b/packages/infrastructure/eslint-config/package.json new file mode 100644 index 0000000000..83e7e34849 --- /dev/null +++ b/packages/infrastructure/eslint-config/package.json @@ -0,0 +1,48 @@ +{ + "name": "@k8slens/eslint-config", + "version": "^6.5.0-alpha.0", + "description": "Lens eslint and prettier configurations", + "author": { + "name": "OpenLens Authors", + "email": "info@k8slens.dev" + }, + "license": "MIT", + "bin": { + "lens-lint": "bin/lint" + }, + "exports": { + "./eslint": "./eslint-config.js", + "./prettier": "./prettier-config.json" + }, + "files": [ + "./eslint-config.js", + "./prettier-config.json" + ], + "repository": { + "type": "git", + "url": "https://github.com/lensapp/lens" + }, + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": ">= 5", + "@typescript-eslint/parser": ">= 5", + "eslint": ">= 7", + "eslint-config-airbnb-typescript": ">= 17", + "eslint-config-prettier": ">= 8", + "eslint-config-react-app": "^7.0.1", + "eslint-plugin-import": ">= 2", + "eslint-plugin-jest": ">= 27", + "eslint-plugin-jsx-a11y": ">= 6", + "eslint-plugin-no-unsanitized": ">= 4.0.2", + "eslint-plugin-prettier": ">= 4", + "eslint-plugin-react-hooks": ">= 4", + "eslint-plugin-security": ">= 1.6.0", + "eslint-plugin-simple-import-sort": ">= 7", + "eslint-plugin-unused-imports": ">= 2", + "eslint-plugin-xss": ">= 0.1.12", + "prettier": ">= 2" + } +} diff --git a/packages/infrastructure/eslint-config/prettier-config.json b/packages/infrastructure/eslint-config/prettier-config.json new file mode 100644 index 0000000000..c9f2606a59 --- /dev/null +++ b/packages/infrastructure/eslint-config/prettier-config.json @@ -0,0 +1,12 @@ +{ + "printWidth": 100, + "tabWidth": 2, + "useTabs": false, + "semi": true, + "singleQuote": false, + "quoteProps": "as-needed", + "jsxSingleQuote": false, + "trailingComma": "all", + "bracketSpacing": true, + "arrowParens": "always" +} diff --git a/packages/open-lens/integration/helpers/utils.ts b/packages/open-lens/integration/helpers/utils.ts index bbc52e3157..f92a1aad00 100644 --- a/packages/open-lens/integration/helpers/utils.ts +++ b/packages/open-lens/integration/helpers/utils.ts @@ -10,7 +10,7 @@ import * as uuid from "uuid"; import type { ElectronApplication, Frame, Page } from "playwright"; import { _electron as electron } from "playwright"; import { noop } from "lodash"; -import { disposer } from "../../../core/src/common/utils"; +import { disposer } from "@k8slens/utilities"; export const appPaths: Partial> = { "win32": "./dist/win-unpacked/OpenLens.exe", diff --git a/packages/open-lens/package.json b/packages/open-lens/package.json index b7bfb55244..469910408a 100644 --- a/packages/open-lens/package.json +++ b/packages/open-lens/package.json @@ -201,12 +201,14 @@ "@k8slens/core": "^6.5.0-alpha.0", "@k8slens/ensure-binaries": "^6.5.0-alpha.0", "@k8slens/generate-tray-icons": "^6.5.0-alpha.0", + "@k8slens/run-many": "^1.0.0", + "@k8slens/test-utils": "^1.0.0", + "@k8slens/utilities": "^1.0.0", "@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", "@ogre-tools/injectable-react": "^15.1.2", - "@ogre-tools/injectable-utils": "^15.1.2", "mobx": "^6.8.0", "rimraf": "^4.1.2" }, diff --git a/packages/technical-features/application/agnostic/.eslintrc.js b/packages/technical-features/application/agnostic/.eslintrc.js new file mode 100644 index 0000000000..fae474aa7d --- /dev/null +++ b/packages/technical-features/application/agnostic/.eslintrc.js @@ -0,0 +1,6 @@ +module.exports = { + extends: "@k8slens/eslint-config/eslint", + parserOptions: { + project: "./tsconfig.json", + }, +}; diff --git a/packages/technical-features/application/agnostic/.prettierrc b/packages/technical-features/application/agnostic/.prettierrc new file mode 100644 index 0000000000..edd47b479e --- /dev/null +++ b/packages/technical-features/application/agnostic/.prettierrc @@ -0,0 +1 @@ +"@k8slens/eslint-config/prettier" diff --git a/packages/technical-features/application/agnostic/index.ts b/packages/technical-features/application/agnostic/index.ts index 559a91582b..239e938cd2 100644 --- a/packages/technical-features/application/agnostic/index.ts +++ b/packages/technical-features/application/agnostic/index.ts @@ -1,8 +1,6 @@ export { applicationFeature } from "./src/feature"; -export { onLoadOfApplicationInjectionToken } from "./src/start-application/timeslots/on-load-of-application-injection-token"; -export { beforeApplicationIsLoadingInjectionToken } from "./src/start-application/timeslots/before-application-is-loading-injection-token"; -export { afterApplicationIsLoadedInjectionToken } from "./src/start-application/timeslots/after-application-is-loaded-injection-token"; +export * from "./src/start-application/time-slots"; export type { StartApplication } from "./src/start-application/start-application.injectable"; export { startApplicationInjectionToken } from "./src/start-application/start-application.injectable"; diff --git a/packages/technical-features/application/agnostic/jest.config.js b/packages/technical-features/application/agnostic/jest.config.js index 6d3d6ff231..c6074967eb 100644 --- a/packages/technical-features/application/agnostic/jest.config.js +++ b/packages/technical-features/application/agnostic/jest.config.js @@ -1,2 +1 @@ -module.exports = - require("@k8slens/jest").monorepoPackageConfig(__dirname).configForNode; +module.exports = require("@k8slens/jest").monorepoPackageConfig(__dirname).configForNode; diff --git a/packages/technical-features/application/agnostic/package.json b/packages/technical-features/application/agnostic/package.json index 35b555ac2e..0350a0f83e 100644 --- a/packages/technical-features/application/agnostic/package.json +++ b/packages/technical-features/application/agnostic/package.json @@ -26,18 +26,20 @@ "scripts": { "build": "webpack", "dev": "webpack --mode=development --watch", - "test": "jest --coverage --runInBand" + "test": "jest --coverage --runInBand", + "lint": "lens-lint", + "lint:fix": "lens-lint --fix" }, "peerDependencies": { "@k8slens/feature-core": "^6.5.0-alpha.0", "@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-utils": "^15.1.2", "lodash": "^4.17.15" }, "devDependencies": { - "@async-fn/jest": "^1.6.4" + "@async-fn/jest": "^1.6.4", + "@k8slens/eslint-config": "*" } } diff --git a/packages/technical-features/application/agnostic/src/application-information-token.ts b/packages/technical-features/application/agnostic/src/application-information-token.ts index c2035d45a3..ad92e21451 100644 --- a/packages/technical-features/application/agnostic/src/application-information-token.ts +++ b/packages/technical-features/application/agnostic/src/application-information-token.ts @@ -10,15 +10,15 @@ export type ApplicationInformation = { productName: string; copyright: string; description: string; - k8sProxyVersion: string, - bundledKubectlVersion: string, - bundledHelmVersion: string, - sentryDsn: string, - contentSecurityPolicy: string, - welcomeRoute: string, + k8sProxyVersion: string; + bundledKubectlVersion: string; + bundledHelmVersion: string; + sentryDsn: string; + contentSecurityPolicy: string; + welcomeRoute: string; updatingIsEnabled: boolean; dependencies: Partial>; -} +}; export const applicationInformationToken = getInjectionToken({ id: "application-information-token", diff --git a/packages/technical-features/application/agnostic/src/feature.ts b/packages/technical-features/application/agnostic/src/feature.ts index 3ad2a495e6..8a193df498 100644 --- a/packages/technical-features/application/agnostic/src/feature.ts +++ b/packages/technical-features/application/agnostic/src/feature.ts @@ -9,9 +9,7 @@ export const applicationFeature = getFeature({ di, targetModule: module, - getRequireContexts: () => [ - require.context("./", true, /\.injectable\.(ts|tsx)$/), - ], + getRequireContexts: () => [require.context("./", true, /\.injectable\.(ts|tsx)$/)], }); }, }); diff --git a/packages/technical-features/application/agnostic/src/start-application/start-application.injectable.ts b/packages/technical-features/application/agnostic/src/start-application/start-application.injectable.ts index 4d9d8c9da2..895462f08e 100644 --- a/packages/technical-features/application/agnostic/src/start-application/start-application.injectable.ts +++ b/packages/technical-features/application/agnostic/src/start-application/start-application.injectable.ts @@ -1,8 +1,6 @@ import { getInjectable, getInjectionToken } from "@ogre-tools/injectable"; -import { runManyFor } from "@ogre-tools/injectable-utils"; -import { beforeApplicationIsLoadingInjectionToken } from "./timeslots/before-application-is-loading-injection-token"; -import { onLoadOfApplicationInjectionToken } from "./timeslots/on-load-of-application-injection-token"; -import { afterApplicationIsLoadedInjectionToken } from "./timeslots/after-application-is-loaded-injection-token"; +import { runManyFor } from "@k8slens/run-many"; +import * as timeSlots from "./time-slots"; export type StartApplication = () => Promise; @@ -16,22 +14,13 @@ const startApplicationInjectable = getInjectable({ instantiate: (di): StartApplication => { const runManyAsync = runManyFor(di) - - const beforeApplicationIsLoading = runManyAsync( - beforeApplicationIsLoadingInjectionToken - ); - - const onLoadOfApplication = runManyAsync(onLoadOfApplicationInjectionToken); - - const afterApplicationIsLoaded = runManyAsync( - afterApplicationIsLoadedInjectionToken - ); + const beforeApplicationIsLoading = runManyAsync(timeSlots.beforeApplicationIsLoadingInjectionToken); + const onLoadOfApplication = runManyAsync(timeSlots.onLoadOfApplicationInjectionToken); + const afterApplicationIsLoaded = runManyAsync(timeSlots.afterApplicationIsLoadedInjectionToken); return async () => { await beforeApplicationIsLoading(); - await onLoadOfApplication(); - await afterApplicationIsLoaded(); }; }, diff --git a/packages/technical-features/application/agnostic/src/start-application/starting-of-application.test.ts b/packages/technical-features/application/agnostic/src/start-application/starting-of-application.test.ts index 37453d4ba3..69219d4a08 100644 --- a/packages/technical-features/application/agnostic/src/start-application/starting-of-application.test.ts +++ b/packages/technical-features/application/agnostic/src/start-application/starting-of-application.test.ts @@ -1,15 +1,9 @@ -import { - createContainer, - DiContainer, - getInjectable, -} from "@ogre-tools/injectable"; +import { createContainer, DiContainer, getInjectable } from "@ogre-tools/injectable"; import { registerFeature } from "@k8slens/feature-core"; import { applicationFeature } from "../feature"; import { startApplicationInjectionToken } from "./start-application.injectable"; -import { beforeApplicationIsLoadingInjectionToken } from "./timeslots/before-application-is-loading-injection-token"; +import * as timeSlots from "./time-slots"; import asyncFn, { AsyncFnMock } from "@async-fn/jest"; -import { onLoadOfApplicationInjectionToken } from "./timeslots/on-load-of-application-injection-token"; -import { afterApplicationIsLoadedInjectionToken } from "./timeslots/after-application-is-loaded-injection-token"; describe("starting-of-application", () => { let di: DiContainer; @@ -30,25 +24,25 @@ describe("starting-of-application", () => { const beforeApplicationIsLoadingInjectable = getInjectable({ id: "before-application-is-loading", instantiate: () => ({ run: beforeApplicationIsLoadingMock }), - injectionToken: beforeApplicationIsLoadingInjectionToken, + injectionToken: timeSlots.beforeApplicationIsLoadingInjectionToken, }); const onLoadOfApplicationInjectable = getInjectable({ id: "on-load-of-application", instantiate: () => ({ run: onLoadOfApplicationMock }), - injectionToken: onLoadOfApplicationInjectionToken, + injectionToken: timeSlots.onLoadOfApplicationInjectionToken, }); const afterApplicationIsLoadedInjectable = getInjectable({ id: "after-application-is-loaded", instantiate: () => ({ run: afterApplicationIsLoadedMock }), - injectionToken: afterApplicationIsLoadedInjectionToken, + injectionToken: timeSlots.afterApplicationIsLoadedInjectionToken, }); di.register( beforeApplicationIsLoadingInjectable, onLoadOfApplicationInjectable, - afterApplicationIsLoadedInjectable + afterApplicationIsLoadedInjectable, ); }); @@ -56,7 +50,7 @@ describe("starting-of-application", () => { beforeEach(() => { const startApplication = di.inject(startApplicationInjectionToken); - startApplication(); + void startApplication(); }); it("calls runnables registered in before application is loading", () => { diff --git a/packages/technical-features/application/agnostic/src/start-application/time-slots.ts b/packages/technical-features/application/agnostic/src/start-application/time-slots.ts new file mode 100644 index 0000000000..8a8aae65a0 --- /dev/null +++ b/packages/technical-features/application/agnostic/src/start-application/time-slots.ts @@ -0,0 +1,14 @@ +import { getInjectionToken } from "@ogre-tools/injectable"; +import type { Runnable } from "@k8slens/run-many"; + +export const beforeApplicationIsLoadingInjectionToken = getInjectionToken({ + id: "before-application-is-loading-injection-token", +}); + +export const onLoadOfApplicationInjectionToken = getInjectionToken({ + id: "on-load-of-application", +}); + +export const afterApplicationIsLoadedInjectionToken = getInjectionToken({ + id: "after-application-is-loaded-injection-token", +}); diff --git a/packages/technical-features/application/agnostic/src/start-application/timeslots/after-application-is-loaded-injection-token.ts b/packages/technical-features/application/agnostic/src/start-application/timeslots/after-application-is-loaded-injection-token.ts deleted file mode 100644 index 6e04840f6e..0000000000 --- a/packages/technical-features/application/agnostic/src/start-application/timeslots/after-application-is-loaded-injection-token.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { getInjectionToken } from "@ogre-tools/injectable"; -import type { Runnable } from "@ogre-tools/injectable-utils"; - -export const afterApplicationIsLoadedInjectionToken = - getInjectionToken({ - id: "after-application-is-loaded-injection-token", - }); diff --git a/packages/technical-features/application/agnostic/src/start-application/timeslots/before-application-is-loading-injection-token.ts b/packages/technical-features/application/agnostic/src/start-application/timeslots/before-application-is-loading-injection-token.ts deleted file mode 100644 index 54bff82be5..0000000000 --- a/packages/technical-features/application/agnostic/src/start-application/timeslots/before-application-is-loading-injection-token.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { getInjectionToken } from "@ogre-tools/injectable"; -import type { Runnable } from "@ogre-tools/injectable-utils"; - -export const beforeApplicationIsLoadingInjectionToken = - getInjectionToken({ - id: "before-application-is-loading-injection-token", - }); diff --git a/packages/technical-features/application/agnostic/src/start-application/timeslots/on-load-of-application-injection-token.ts b/packages/technical-features/application/agnostic/src/start-application/timeslots/on-load-of-application-injection-token.ts deleted file mode 100644 index c732329e29..0000000000 --- a/packages/technical-features/application/agnostic/src/start-application/timeslots/on-load-of-application-injection-token.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { getInjectionToken } from "@ogre-tools/injectable"; -import type { Runnable } from "@ogre-tools/injectable-utils"; - -export const onLoadOfApplicationInjectionToken = getInjectionToken({ - id: "on-load-of-application", -}); diff --git a/packages/technical-features/application/agnostic/tsconfig.json b/packages/technical-features/application/agnostic/tsconfig.json index a4f6fa613e..1819203dc1 100644 --- a/packages/technical-features/application/agnostic/tsconfig.json +++ b/packages/technical-features/application/agnostic/tsconfig.json @@ -1,3 +1,4 @@ { - "extends": "@k8slens/typescript/config/base.json" + "extends": "@k8slens/typescript/config/base.json", + "include": ["**/*.ts"] } diff --git a/packages/technical-features/application/electron-main/.eslintrc.js b/packages/technical-features/application/electron-main/.eslintrc.js new file mode 100644 index 0000000000..fae474aa7d --- /dev/null +++ b/packages/technical-features/application/electron-main/.eslintrc.js @@ -0,0 +1,6 @@ +module.exports = { + extends: "@k8slens/eslint-config/eslint", + parserOptions: { + project: "./tsconfig.json", + }, +}; diff --git a/packages/technical-features/application/electron-main/.prettierrc b/packages/technical-features/application/electron-main/.prettierrc new file mode 100644 index 0000000000..edd47b479e --- /dev/null +++ b/packages/technical-features/application/electron-main/.prettierrc @@ -0,0 +1 @@ +"@k8slens/eslint-config/prettier" diff --git a/packages/technical-features/application/electron-main/index.ts b/packages/technical-features/application/electron-main/index.ts index d3d92e0aa3..238b564a47 100644 --- a/packages/technical-features/application/electron-main/index.ts +++ b/packages/technical-features/application/electron-main/index.ts @@ -1,8 +1,7 @@ import { overrideSideEffectsWithFakes } from "./src/override-side-effects-with-fakes"; -export { beforeElectronIsReadyInjectionToken } from "./src/start-application/timeslots/before-electron-is-ready-injection-token"; -export { beforeAnythingInjectionToken } from "./src/start-application/timeslots/before-anything-injection-token"; +export * from "./src/start-application/time-slots"; export { applicationFeatureForElectronMain } from "./src/feature"; -export const testUtils = { overrideSideEffectsWithFakes } +export const testUtils = { overrideSideEffectsWithFakes }; diff --git a/packages/technical-features/application/electron-main/jest.config.js b/packages/technical-features/application/electron-main/jest.config.js index 6d3d6ff231..c6074967eb 100644 --- a/packages/technical-features/application/electron-main/jest.config.js +++ b/packages/technical-features/application/electron-main/jest.config.js @@ -1,2 +1 @@ -module.exports = - require("@k8slens/jest").monorepoPackageConfig(__dirname).configForNode; +module.exports = require("@k8slens/jest").monorepoPackageConfig(__dirname).configForNode; diff --git a/packages/technical-features/application/electron-main/package.json b/packages/technical-features/application/electron-main/package.json index eb1b42c2c8..6ee3987e47 100644 --- a/packages/technical-features/application/electron-main/package.json +++ b/packages/technical-features/application/electron-main/package.json @@ -26,19 +26,21 @@ "scripts": { "build": "webpack", "dev": "webpack --mode=development --watch", - "test": "jest --coverage --runInBand" + "test": "jest --coverage --runInBand", + "lint": "lens-lint", + "lint:fix": "lens-lint --fix" }, "peerDependencies": { "@k8slens/feature-core": "^6.5.0-alpha.0", "@k8slens/application": "^6.5.0-alpha.0", "@ogre-tools/injectable": "^15.1.2", "@ogre-tools/injectable-extension-for-auto-registration": "^15.1.2", - "@ogre-tools/injectable-utils": "^15.1.2", "electron": "^19.1.9" }, "devDependencies": { "@async-fn/jest": "^1.6.4", - "@ogre-tools/test-utils": "^15.1.2" + "@ogre-tools/test-utils": "^15.1.2", + "@k8slens/eslint-config": "*" } } diff --git a/packages/technical-features/application/electron-main/src/electron/electron-app.test.ts b/packages/technical-features/application/electron-main/src/electron/electron-app.test.ts index ed3e6d40a6..677141d9f3 100644 --- a/packages/technical-features/application/electron-main/src/electron/electron-app.test.ts +++ b/packages/technical-features/application/electron-main/src/electron/electron-app.test.ts @@ -1,14 +1,14 @@ import electronAppInjectable from "./electron-app.injectable"; -import { app } from 'electron'; +import { app } from "electron"; import { createContainer } from "@ogre-tools/injectable"; import { applicationFeatureForElectronMain } from "../feature"; import { registerFeature } from "@k8slens/feature-core"; -describe('electron-app', () => { - it('is electron app', () => { - const di = createContainer('irrelevant'); +describe("electron-app", () => { + it("is electron app", () => { + const di = createContainer("irrelevant"); - registerFeature(di, applicationFeatureForElectronMain) + registerFeature(di, applicationFeatureForElectronMain); const actual = di.inject(electronAppInjectable); diff --git a/packages/technical-features/application/electron-main/src/feature.ts b/packages/technical-features/application/electron-main/src/feature.ts index 597d7625f9..de65fae5ac 100644 --- a/packages/technical-features/application/electron-main/src/feature.ts +++ b/packages/technical-features/application/electron-main/src/feature.ts @@ -1,6 +1,6 @@ import { getFeature } from "@k8slens/feature-core"; import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration"; -import { applicationFeature } from '@k8slens/application'; +import { applicationFeature } from "@k8slens/application"; export const applicationFeatureForElectronMain = getFeature({ id: "application-for-electron-main", @@ -10,13 +10,9 @@ export const applicationFeatureForElectronMain = getFeature({ di, targetModule: module, - getRequireContexts: () => [ - require.context("./", true, /\.injectable\.(ts|tsx)$/), - ], + getRequireContexts: () => [require.context("./", true, /\.injectable\.(ts|tsx)$/)], }); }, - dependencies: [ - applicationFeature - ] + dependencies: [applicationFeature], }); diff --git a/packages/technical-features/application/electron-main/src/override-side-effects-with-fakes.ts b/packages/technical-features/application/electron-main/src/override-side-effects-with-fakes.ts index 0d33c944d8..a795dbd04b 100644 --- a/packages/technical-features/application/electron-main/src/override-side-effects-with-fakes.ts +++ b/packages/technical-features/application/electron-main/src/override-side-effects-with-fakes.ts @@ -2,5 +2,5 @@ import type { DiContainer } from "@ogre-tools/injectable"; import whenAppIsReadyInjectable from "./start-application/when-app-is-ready.injectable"; export const overrideSideEffectsWithFakes = (di: DiContainer) => { - di.override(whenAppIsReadyInjectable, () => () => Promise.resolve()) + di.override(whenAppIsReadyInjectable, () => () => Promise.resolve()); }; diff --git a/packages/technical-features/application/electron-main/src/start-application/start-electron-application.injectable.ts b/packages/technical-features/application/electron-main/src/start-application/start-electron-application.injectable.ts index 5d5944fbaf..f107ada913 100644 --- a/packages/technical-features/application/electron-main/src/start-application/start-electron-application.injectable.ts +++ b/packages/technical-features/application/electron-main/src/start-application/start-electron-application.injectable.ts @@ -6,32 +6,22 @@ import { } from "@ogre-tools/injectable"; import { startApplicationInjectionToken } from "@k8slens/application"; import whenAppIsReadyInjectable from "./when-app-is-ready.injectable"; -import { beforeAnythingInjectionToken } from "./timeslots/before-anything-injection-token"; -import { beforeElectronIsReadyInjectionToken } from "./timeslots/before-electron-is-ready-injection-token"; -import { runManySyncFor } from "@ogre-tools/injectable-utils"; +import { beforeAnythingInjectionToken, beforeElectronIsReadyInjectionToken } from "./time-slots"; +import { runManySyncFor } from "@k8slens/run-many"; + +type ToBeDecorated = (di: DiContainer, ...args: unknown[]) => (...args: unknown[]) => unknown; const startElectronApplicationInjectable = getInjectable({ id: "start-electron-application", instantiate: () => ({ - decorate: - (toBeDecorated: unknown) => + decorate: (toBeDecorated: unknown) => ( (di: DiContainer, ...args: unknown[]) => { const whenAppIsReady = di.inject(whenAppIsReadyInjectable); const runManySync = runManySyncFor(di); const beforeAnything = runManySync(beforeAnythingInjectionToken); - const beforeElectronIsReady = runManySync( - beforeElectronIsReadyInjectionToken - ); - - const typedToBeDecorated = toBeDecorated as ( - di: DiContainer, - ...args: unknown[] - ) => unknown; - - const startApplication = typedToBeDecorated(di, ...args) as ( - ...args: unknown[] - ) => unknown; + const beforeElectronIsReady = runManySync(beforeElectronIsReadyInjectionToken); + const startApplication = (toBeDecorated as ToBeDecorated)(di, ...args); return (...startApplicationArgs: unknown[]) => { beforeAnything(); @@ -43,8 +33,8 @@ const startElectronApplicationInjectable = getInjectable({ return startApplication(...startApplicationArgs); })() }; - }, - + } + ), target: startApplicationInjectionToken, }), diff --git a/packages/technical-features/application/electron-main/src/start-application/time-slots.ts b/packages/technical-features/application/electron-main/src/start-application/time-slots.ts new file mode 100644 index 0000000000..58673517ae --- /dev/null +++ b/packages/technical-features/application/electron-main/src/start-application/time-slots.ts @@ -0,0 +1,10 @@ +import { getInjectionToken } from "@ogre-tools/injectable"; +import type { RunnableSync } from "@k8slens/run-many"; + +export const beforeAnythingInjectionToken = getInjectionToken({ + id: "before-anything", +}); + +export const beforeElectronIsReadyInjectionToken = getInjectionToken({ + id: "before-electron-is-ready-injection-token", +}); diff --git a/packages/technical-features/application/electron-main/src/start-application/timeslots/before-anything-injection-token.ts b/packages/technical-features/application/electron-main/src/start-application/timeslots/before-anything-injection-token.ts deleted file mode 100644 index f8d2ef9203..0000000000 --- a/packages/technical-features/application/electron-main/src/start-application/timeslots/before-anything-injection-token.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { getInjectionToken } from "@ogre-tools/injectable"; -import type { Runnable } from "@ogre-tools/injectable-utils"; - -export const beforeAnythingInjectionToken = getInjectionToken({ - id: "before-anything", -}); diff --git a/packages/technical-features/application/electron-main/src/start-application/timeslots/before-electron-is-ready-injection-token.ts b/packages/technical-features/application/electron-main/src/start-application/timeslots/before-electron-is-ready-injection-token.ts deleted file mode 100644 index c8c88bddae..0000000000 --- a/packages/technical-features/application/electron-main/src/start-application/timeslots/before-electron-is-ready-injection-token.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { getInjectionToken } from "@ogre-tools/injectable"; -import type { Runnable } from "@ogre-tools/injectable-utils"; - -export const beforeElectronIsReadyInjectionToken = getInjectionToken({ - id: "before-electron-is-ready-injection-token", -}); diff --git a/packages/technical-features/application/electron-main/src/start-application/when-app-is-ready/when-app-is-ready.test.ts b/packages/technical-features/application/electron-main/src/start-application/when-app-is-ready.test.ts similarity index 78% rename from packages/technical-features/application/electron-main/src/start-application/when-app-is-ready/when-app-is-ready.test.ts rename to packages/technical-features/application/electron-main/src/start-application/when-app-is-ready.test.ts index 3e3fe40a52..af65f275e5 100644 --- a/packages/technical-features/application/electron-main/src/start-application/when-app-is-ready/when-app-is-ready.test.ts +++ b/packages/technical-features/application/electron-main/src/start-application/when-app-is-ready.test.ts @@ -1,9 +1,9 @@ import { createContainer, DiContainer } from "@ogre-tools/injectable"; -import { applicationFeatureForElectronMain } from "../../feature"; +import { applicationFeatureForElectronMain } from "../feature"; import { registerFeature } from "@k8slens/feature-core"; -import whenAppIsReadyInjectable from "../when-app-is-ready.injectable"; +import whenAppIsReadyInjectable from "./when-app-is-ready.injectable"; import { getPromiseStatus } from "@ogre-tools/test-utils"; -import electronAppInjectable from "../../electron/electron-app.injectable"; +import electronAppInjectable from "../electron/electron-app.injectable"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; @@ -18,10 +18,7 @@ describe("when-app-is-ready", () => { whenReadyMock = asyncFn(); - di.override( - electronAppInjectable, - () => ({ whenReady: whenReadyMock } as unknown) - ); + di.override(electronAppInjectable, () => ({ whenReady: whenReadyMock } as unknown)); }); describe("when called", () => { diff --git a/packages/technical-features/application/electron-main/src/starting-of-electron-main-application.test.ts b/packages/technical-features/application/electron-main/src/starting-of-electron-main-application.test.ts index fb344a193b..de2bbd2306 100644 --- a/packages/technical-features/application/electron-main/src/starting-of-electron-main-application.test.ts +++ b/packages/technical-features/application/electron-main/src/starting-of-electron-main-application.test.ts @@ -1,8 +1,4 @@ -import { - createContainer, - DiContainer, - getInjectable, -} from "@ogre-tools/injectable"; +import { createContainer, DiContainer, getInjectable } from "@ogre-tools/injectable"; import { registerFeature } from "@k8slens/feature-core"; import { applicationFeatureForElectronMain } from "./feature"; import { @@ -11,8 +7,7 @@ import { } from "@k8slens/application"; import asyncFn, { AsyncFnMock } from "@async-fn/jest"; import whenAppIsReadyInjectable from "./start-application/when-app-is-ready.injectable"; -import { beforeAnythingInjectionToken } from "./start-application/timeslots/before-anything-injection-token"; -import { beforeElectronIsReadyInjectionToken } from "./start-application/timeslots/before-electron-is-ready-injection-token"; +import { beforeAnythingInjectionToken, beforeElectronIsReadyInjectionToken } from "./start-application/time-slots"; describe("starting-of-electron-main-application", () => { let di: DiContainer; @@ -53,7 +48,7 @@ describe("starting-of-electron-main-application", () => { di.register( beforeAnythingIsLoadingInjectable, beforeElectronIsReadyIsLoadingInjectable, - beforeApplicationIsLoadingInjectable + beforeApplicationIsLoadingInjectable, ); di.override(whenAppIsReadyInjectable, () => whenAppIsReadyMock); @@ -63,7 +58,7 @@ describe("starting-of-electron-main-application", () => { beforeEach(() => { const startApplication = di.inject(startApplicationInjectionToken); - startApplication(); + void startApplication(); }); it("calls for synchronous runnables for before anything", () => { diff --git a/packages/technical-features/application/electron-main/tsconfig.json b/packages/technical-features/application/electron-main/tsconfig.json index a4f6fa613e..1819203dc1 100644 --- a/packages/technical-features/application/electron-main/tsconfig.json +++ b/packages/technical-features/application/electron-main/tsconfig.json @@ -1,3 +1,4 @@ { - "extends": "@k8slens/typescript/config/base.json" + "extends": "@k8slens/typescript/config/base.json", + "include": ["**/*.ts"] } diff --git a/packages/technical-features/feature-core/.eslintrc.js b/packages/technical-features/feature-core/.eslintrc.js new file mode 100644 index 0000000000..fae474aa7d --- /dev/null +++ b/packages/technical-features/feature-core/.eslintrc.js @@ -0,0 +1,6 @@ +module.exports = { + extends: "@k8slens/eslint-config/eslint", + parserOptions: { + project: "./tsconfig.json", + }, +}; diff --git a/packages/technical-features/feature-core/.prettierrc b/packages/technical-features/feature-core/.prettierrc new file mode 100644 index 0000000000..edd47b479e --- /dev/null +++ b/packages/technical-features/feature-core/.prettierrc @@ -0,0 +1 @@ +"@k8slens/eslint-config/prettier" diff --git a/packages/technical-features/feature-core/jest.config.js b/packages/technical-features/feature-core/jest.config.js index 23be80353b..38d54ab7b6 100644 --- a/packages/technical-features/feature-core/jest.config.js +++ b/packages/technical-features/feature-core/jest.config.js @@ -1,2 +1 @@ -module.exports = - require("@k8slens/jest").monorepoPackageConfig(__dirname).configForReact; +module.exports = require("@k8slens/jest").monorepoPackageConfig(__dirname).configForReact; diff --git a/packages/technical-features/feature-core/package.json b/packages/technical-features/feature-core/package.json index 506e39d773..99e41c00e4 100644 --- a/packages/technical-features/feature-core/package.json +++ b/packages/technical-features/feature-core/package.json @@ -28,9 +28,15 @@ "scripts": { "build": "webpack", "dev": "webpack --mode=development --watch", - "test": "jest --coverage --runInBand" + "test": "jest --coverage --runInBand", + "lint": "lens-lint", + "lint:fix": "lens-lint --fix" }, "peerDependencies": { "@ogre-tools/injectable": "^15.1.2" + }, + + "devDependencies": { + "@k8slens/eslint-config": "*" } } diff --git a/packages/technical-features/feature-core/src/deregister-feature.ts b/packages/technical-features/feature-core/src/deregister-feature.ts index 3d77759659..4476120ab7 100644 --- a/packages/technical-features/feature-core/src/deregister-feature.ts +++ b/packages/technical-features/feature-core/src/deregister-feature.ts @@ -2,25 +2,31 @@ import type { DiContainer } from "@ogre-tools/injectable"; import type { Feature } from "./feature"; import { featureContextMapInjectable } from "./feature-context-map-injectable"; -export const deregisterFeature = (di: DiContainer, ...features: Feature[]) => { - features.forEach((feature) => { - deregisterFeatureRecursed(di, feature); - }); +const getDependingFeaturesFor = ( + featureContextMap: Map }>, +) => { + const getDependingFeaturesForRecursion = (feature: Feature, atRoot = true): string[] => { + const context = featureContextMap.get(feature); + + if (context?.dependedBy.size) { + return [...context?.dependedBy.entries()].flatMap(([dependant]) => + getDependingFeaturesForRecursion(dependant, false), + ); + } + + return atRoot ? [] : [feature.id]; + }; + + return getDependingFeaturesForRecursion; }; -const deregisterFeatureRecursed = ( - di: DiContainer, - feature: Feature, - dependedBy?: Feature -) => { +const deregisterFeatureRecursed = (di: DiContainer, feature: Feature, dependedBy?: Feature) => { const featureContextMap = di.inject(featureContextMapInjectable); const featureContext = featureContextMap.get(feature); if (!featureContext) { - throw new Error( - `Tried to deregister feature "${feature.id}", but it was not registered.` - ); + throw new Error(`Tried to deregister feature "${feature.id}", but it was not registered.`); } featureContext.numberOfRegistrations--; @@ -33,15 +39,15 @@ const deregisterFeatureRecursed = ( throw new Error( `Tried to deregister Feature "${ feature.id - }", but it is the dependency of Features "${dependingFeatures.join( - ", " - )}"` + }", but it is the dependency of Features "${dependingFeatures.join(", ")}"`, ); } if (dependedBy) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const oldNumberOfDependents = featureContext.dependedBy.get(dependedBy)!; const newNumberOfDependants = oldNumberOfDependents - 1; + featureContext.dependedBy.set(dependedBy, newNumberOfDependants); if (newNumberOfDependants === 0) { @@ -60,23 +66,8 @@ const deregisterFeatureRecursed = ( }); }; -const getDependingFeaturesFor = ( - featureContextMap: Map }> -) => { - const getDependingFeaturesForRecursion = ( - feature: Feature, - atRoot = true - ): string[] => { - const context = featureContextMap.get(feature); - - if (context?.dependedBy.size) { - return [...context!.dependedBy.entries()].flatMap(([dependant]) => - getDependingFeaturesForRecursion(dependant, false) - ); - } - - return atRoot ? [] : [feature.id]; - }; - - return getDependingFeaturesForRecursion; +export const deregisterFeature = (di: DiContainer, ...features: Feature[]) => { + features.forEach((feature) => { + deregisterFeatureRecursed(di, feature); + }); }; diff --git a/packages/technical-features/feature-core/src/feature-context-map-injectable.ts b/packages/technical-features/feature-core/src/feature-context-map-injectable.ts index 8c34524fee..e444c06bba 100644 --- a/packages/technical-features/feature-core/src/feature-context-map-injectable.ts +++ b/packages/technical-features/feature-core/src/feature-context-map-injectable.ts @@ -11,10 +11,9 @@ export type FeatureContextMap = Map< } >; -export const featureContextMapInjectionToken = - getInjectionToken({ - id: "feature-context-map-injection-token", - }); +export const featureContextMapInjectionToken = getInjectionToken({ + id: "feature-context-map-injection-token", +}); const featureContextMapInjectable = getInjectable({ id: "feature-store", diff --git a/packages/technical-features/feature-core/src/feature-dependencies.test.ts b/packages/technical-features/feature-core/src/feature-dependencies.test.ts index cdb7267419..8ddf6e11b8 100644 --- a/packages/technical-features/feature-core/src/feature-dependencies.test.ts +++ b/packages/technical-features/feature-core/src/feature-dependencies.test.ts @@ -1,14 +1,9 @@ -import { - createContainer, - DiContainer, - getInjectable, - Injectable, -} from "@ogre-tools/injectable"; +import { createContainer, DiContainer, getInjectable, Injectable } from "@ogre-tools/injectable"; import type { Feature } from "./feature"; import { registerFeature } from "./register-feature"; import { deregisterFeature } from "./deregister-feature"; -import { getFeature } from "./feature" ; +import { getFeature } from "./feature"; describe("feature-dependencies", () => { describe("given a parent Feature with another Features as dependency", () => { @@ -55,7 +50,7 @@ describe("feature-dependencies", () => { expect(() => { deregisterFeature(di, someDependencyFeature); }).toThrow( - 'Tried to deregister Feature "some-dependency-feature", but it is the dependency of Features "some-feature"' + 'Tried to deregister Feature "some-dependency-feature", but it is the dependency of Features "some-feature"', ); }); @@ -65,7 +60,7 @@ describe("feature-dependencies", () => { expect(() => { deregisterFeature(di, someDependencyFeature); }).toThrow( - 'Tried to deregister feature "some-dependency-feature", but it was not registered.' + 'Tried to deregister feature "some-dependency-feature", but it was not registered.', ); }); @@ -74,9 +69,7 @@ describe("feature-dependencies", () => { expect(() => { di.inject(someInjectableInDependencyFeature); - }).toThrow( - 'Tried to inject non-registered injectable "irrelevant" -> "some-injectable".' - ); + }).toThrow('Tried to inject non-registered injectable "irrelevant" -> "some-injectable".'); }); }); @@ -112,7 +105,7 @@ describe("feature-dependencies", () => { expect(() => { deregisterFeature(di, someFeature1); }).toThrow( - 'Tried to deregister Feature "some-feature-1", but it is the dependency of Features "some-feature-2"' + 'Tried to deregister Feature "some-feature-1", but it is the dependency of Features "some-feature-2"', ); }); @@ -170,7 +163,7 @@ describe("feature-dependencies", () => { expect(() => { deregisterFeature(di, someSharedDependencyFeature); }).toThrow( - 'Tried to deregister Feature "some-dependency-feature", but it is the dependency of Features "some-feature-1, some-feature-2"' + 'Tried to deregister Feature "some-dependency-feature", but it is the dependency of Features "some-feature-1, some-feature-2"', ); }); @@ -188,7 +181,7 @@ describe("feature-dependencies", () => { expect(() => { di.inject(someInjectableInDependencyFeature); }).toThrow( - 'Tried to inject non-registered injectable "irrelevant" -> "some-injectable-in-dependency-feature".' + 'Tried to inject non-registered injectable "irrelevant" -> "some-injectable-in-dependency-feature".', ); }); }); @@ -231,19 +224,14 @@ describe("feature-dependencies", () => { dependencies: [someFeatureForAdditionalHierarchy], }); - registerFeature( - di, - someFeature1, - someFeature2, - someSharedDependencyFeature - ); + registerFeature(di, someFeature1, someFeature2, someSharedDependencyFeature); }); it("when the shared Feature is deregistered, throws", () => { expect(() => { deregisterFeature(di, someSharedDependencyFeature); }).toThrow( - 'Tried to deregister Feature "some-dependency-feature", but it is the dependency of Features "some-feature-1, some-feature-2"' + 'Tried to deregister Feature "some-dependency-feature", but it is the dependency of Features "some-feature-1, some-feature-2"', ); }); @@ -264,17 +252,12 @@ describe("feature-dependencies", () => { }); it("given all of the Features get deregistered, when injecting an injectable from the shared Feature, throws", () => { - deregisterFeature( - di, - someFeature1, - someFeature2, - someSharedDependencyFeature - ); + deregisterFeature(di, someFeature1, someFeature2, someSharedDependencyFeature); expect(() => { di.inject(someInjectableInDependencyFeature); }).toThrow( - 'Tried to inject non-registered injectable "irrelevant" -> "some-injectable-in-dependency-feature".' + 'Tried to inject non-registered injectable "irrelevant" -> "some-injectable-in-dependency-feature".', ); }); }); diff --git a/packages/technical-features/feature-core/src/feature.ts b/packages/technical-features/feature-core/src/feature.ts index 6a8084c92a..2f9814bf68 100644 --- a/packages/technical-features/feature-core/src/feature.ts +++ b/packages/technical-features/feature-core/src/feature.ts @@ -8,5 +8,4 @@ export interface Feature { export interface GetFeatureArgs extends Feature {} -export const getFeature = (getFeatureArgs: GetFeatureArgs): Feature => - getFeatureArgs; +export const getFeature = (getFeatureArgs: GetFeatureArgs): Feature => getFeatureArgs; diff --git a/packages/technical-features/feature-core/src/register-feature.ts b/packages/technical-features/feature-core/src/register-feature.ts index 391bd60fa3..f02b050002 100644 --- a/packages/technical-features/feature-core/src/register-feature.ts +++ b/packages/technical-features/feature-core/src/register-feature.ts @@ -6,58 +6,6 @@ import { featureContextMapInjectionToken, } from "./feature-context-map-injectable"; -export const registerFeature = (di: DiContainer, ...features: Feature[]) => { - features.forEach((feature) => { - registerFeatureRecursed(di, feature); - }); -}; - -const registerFeatureRecursed = ( - di: DiContainer, - feature: Feature, - dependedBy?: Feature -) => { - const featureContextMaps = di.injectMany(featureContextMapInjectionToken); - - if (featureContextMaps.length === 0) { - di.register(featureContextMapInjectable); - } - - const featureContextMap = di.inject(featureContextMapInjectable); - - const existingFeatureContext = featureContextMap.get(feature); - if ( - !dependedBy && - existingFeatureContext && - existingFeatureContext.dependedBy.size === 0 - ) { - throw new Error( - `Tried to register feature "${feature.id}", but it was already registered.` - ); - } - - const featureContext = - existingFeatureContext || createFeatureContext(feature, di); - - featureContext.numberOfRegistrations++; - - if (dependedBy) { - const oldNumberOfDependents = - featureContext.dependedBy.get(dependedBy) || 0; - - const newNumberOfDependants = oldNumberOfDependents + 1; - featureContext.dependedBy.set(dependedBy, newNumberOfDependants); - } - - if (!existingFeatureContext) { - featureContext.register(); - } - - feature.dependencies?.forEach((dependency) => { - registerFeatureRecursed(di, dependency, feature); - }); -}; - const createFeatureContext = (feature: Feature, di: DiContainer) => { const featureContextInjectable = getInjectable({ id: feature.id, @@ -88,3 +36,45 @@ const createFeatureContext = (feature: Feature, di: DiContainer) => { return featureContext; }; + +const registerFeatureRecursed = (di: DiContainer, feature: Feature, dependedBy?: Feature) => { + const featureContextMaps = di.injectMany(featureContextMapInjectionToken); + + if (featureContextMaps.length === 0) { + di.register(featureContextMapInjectable); + } + + const featureContextMap = di.inject(featureContextMapInjectable); + + const existingFeatureContext = featureContextMap.get(feature); + + if (!dependedBy && existingFeatureContext && existingFeatureContext.dependedBy.size === 0) { + throw new Error(`Tried to register feature "${feature.id}", but it was already registered.`); + } + + const featureContext = existingFeatureContext || createFeatureContext(feature, di); + + featureContext.numberOfRegistrations++; + + if (dependedBy) { + const oldNumberOfDependents = featureContext.dependedBy.get(dependedBy) || 0; + + const newNumberOfDependants = oldNumberOfDependents + 1; + + featureContext.dependedBy.set(dependedBy, newNumberOfDependants); + } + + if (!existingFeatureContext) { + featureContext.register(); + } + + feature.dependencies?.forEach((dependency) => { + registerFeatureRecursed(di, dependency, feature); + }); +}; + +export const registerFeature = (di: DiContainer, ...features: Feature[]) => { + features.forEach((feature) => { + registerFeatureRecursed(di, feature); + }); +}; diff --git a/packages/technical-features/feature-core/src/registration-of-feature.test.ts b/packages/technical-features/feature-core/src/registration-of-feature.test.ts index ee7d6d7c86..41b377bb25 100644 --- a/packages/technical-features/feature-core/src/registration-of-feature.test.ts +++ b/packages/technical-features/feature-core/src/registration-of-feature.test.ts @@ -1,10 +1,5 @@ import { registerFeature } from "./register-feature"; -import { - createContainer, - DiContainer, - getInjectable, - Injectable, -} from "@ogre-tools/injectable"; +import { createContainer, DiContainer, getInjectable, Injectable } from "@ogre-tools/injectable"; import type { Feature } from "./feature"; import { getFeature } from "./feature"; import { deregisterFeature } from "./deregister-feature"; @@ -90,9 +85,7 @@ describe("register-feature", () => { it("when a Feature is registered again, throws", () => { expect(() => { registerFeature(di, someFeature); - }).toThrow( - 'Tried to register feature "some-feature-1", but it was already registered.' - ); + }).toThrow('Tried to register feature "some-feature-1", but it was already registered.'); }); it("given a Feature deregistered, when deregistered again, throws", () => { @@ -100,15 +93,14 @@ describe("register-feature", () => { expect(() => { deregisterFeature(di, someFeature); - }).toThrow( - 'Tried to deregister feature "some-feature-1", but it was not registered.' - ); + }).toThrow('Tried to deregister feature "some-feature-1", but it was not registered.'); }); }); it("given di-container and registered Features with injectables forming a cycle, when an injectable is injected, throws with namespaced error about cycle", () => { const someInjectable: Injectable = getInjectable({ id: "some-injectable-1", + // eslint-disable-next-line @typescript-eslint/no-use-before-define instantiate: (di) => di.inject(someInjectable2), }); @@ -140,8 +132,9 @@ describe("register-feature", () => { expect(() => { di.inject(someInjectable); }).toThrow( - // 'Cycle of injectables encountered: "some-container" -> "some-feature-1:some-injectable-1" -> "some-feature-2:some-injectable-2" -> "some-feature-1:some-injectable-1"' - 'Maximum call stack size exceeded' + // 'Cycle of injectables encountered: "some-container" -> "some-feature-1:some-injectable-1" + // -> "some-feature-2:some-injectable-2" -> "some-feature-1:some-injectable-1"' + "Maximum call stack size exceeded", ); }); }); diff --git a/packages/technical-features/feature-core/tsconfig.json b/packages/technical-features/feature-core/tsconfig.json index a4f6fa613e..1819203dc1 100644 --- a/packages/technical-features/feature-core/tsconfig.json +++ b/packages/technical-features/feature-core/tsconfig.json @@ -1,3 +1,4 @@ { - "extends": "@k8slens/typescript/config/base.json" + "extends": "@k8slens/typescript/config/base.json", + "include": ["**/*.ts"] } diff --git a/packages/utility-features/run-many/README.md b/packages/utility-features/run-many/README.md new file mode 100644 index 0000000000..b24cf0fccd --- /dev/null +++ b/packages/utility-features/run-many/README.md @@ -0,0 +1,3 @@ +# @k8slens/run-many + +This package contains the functions `runMany` and `runManySync` diff --git a/packages/utility-features/run-many/index.ts b/packages/utility-features/run-many/index.ts new file mode 100644 index 0000000000..30f67f43d9 --- /dev/null +++ b/packages/utility-features/run-many/index.ts @@ -0,0 +1,4 @@ +export * from "./src/run-many-for"; +export * from "./src/run-many-sync-for"; + +export type { Runnable, RunnableSync, Run, RunSync } from "./src/types"; diff --git a/packages/utility-features/run-many/jest.config.js b/packages/utility-features/run-many/jest.config.js new file mode 100644 index 0000000000..23be80353b --- /dev/null +++ b/packages/utility-features/run-many/jest.config.js @@ -0,0 +1,2 @@ +module.exports = + require("@k8slens/jest").monorepoPackageConfig(__dirname).configForReact; diff --git a/packages/utility-features/run-many/package.json b/packages/utility-features/run-many/package.json new file mode 100644 index 0000000000..e469c50730 --- /dev/null +++ b/packages/utility-features/run-many/package.json @@ -0,0 +1,33 @@ +{ + "name": "@k8slens/run-many", + "version": "1.0.0", + "type": "commonjs", + "description": "A package containing runMany and runManySync", + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + }, + "private": false, + "files": [ + "dist" + ], + "main": "dist/index.js", + "types": "dist/index.d.ts", + "author": { + "name": "OpenLens Authors", + "email": "info@k8slens.dev" + }, + "license": "MIT", + "homepage": "https://github.com/lensapp/lens", + "scripts": { + "build": "webpack", + "dev": "webpack --mode=development --watch", + "test": "jest --coverage --runInBand" + }, + "peerDependencies": { + "@k8slens/test-utils": "^1.0.0", + "@k8slens/utilities": "^1.0.0", + "@ogre-tools/fp": "^15.1.1", + "@ogre-tools/injectable": "^15.1.1" + } +} diff --git a/packages/utility-features/run-many/src/helpers.ts b/packages/utility-features/run-many/src/helpers.ts new file mode 100644 index 0000000000..adb0126cbf --- /dev/null +++ b/packages/utility-features/run-many/src/helpers.ts @@ -0,0 +1,94 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { DiContainerForInjection, InjectionInstanceWithMeta } from "@ogre-tools/injectable"; +import { getOrInsertSetFor, isDefined } from "@k8slens/utilities"; +import * as uuid from "uuid"; +import assert from "assert"; +import type { Runnable, RunnableSync, RunnableSyncWithId, RunnableWithId } from "./types"; + +const computedNextEdge = (traversed: string[], graph: Map>, currentId: string, seenIds: Set) => { + seenIds.add(currentId); + const currentNode = graph.get(currentId); + + assert(currentNode, `Runnable graph does not contain node with id="${currentId}"`); + + for (const nextId of currentNode.values()) { + if (traversed.includes(nextId)) { + throw new Error(`Cycle in runnable graph: "${traversed.join(`" -> "`)}" -> "${nextId}"`); + } + + computedNextEdge([...traversed, nextId], graph, nextId, seenIds); + } +}; + +/** + * Verifies that the graph produces by `runnables`'s `runAfter`'s is acyclic. Namely that it + * produces a Directed Acyclic Graph. + * @param tokenId The ID of the injectionToken that was `injectManyWithMeta()`-ed. Used for error messages + * @param runnables The list of runnables to check. + */ +export function verifyRunnablesAreDAG(tokenId: string, runnables: RunnableWithId[]): void; +export function verifyRunnablesAreDAG(tokenId: string, runnables: RunnableSyncWithId[]): void; + +export function verifyRunnablesAreDAG(tokenId: string, runnables: (RunnableWithId[]) | (RunnableSyncWithId[])): void { + const rootId = uuid.v4(); + const runnableGraph = new Map>(); + const seenIds = new Set(); + const addRunnableId = getOrInsertSetFor(runnableGraph); + + // Build the Directed graph + for (const runnable of runnables) { + addRunnableId(runnable.id); + + if (runnable.runAfter.length === 0) { + addRunnableId(rootId).add(runnable.id); + } else { + for (const parentRunnable of runnable.runAfter) { + addRunnableId(parentRunnable.id).add(runnable.id); + } + } + } + + addRunnableId(rootId); + + // Do a DFS to find any cycles + computedNextEdge([], runnableGraph, rootId, seenIds); + + for (const id of runnableGraph.keys()) { + if (!seenIds.has(id)) { + const runnable = runnables.find(runnable => runnable.id === id); + + if (!runnable) { + throw new Error(`Runnable "${id}" is not part of the injection token "${tokenId}"`); + } + + const runAfters = [runnable.runAfter] + .flat() + .filter(isDefined) + .map(runnable => runnable.id) + .join('", "'); + + throw new Error(`Runnable "${id}" is unreachable for injection token "${tokenId}": run afters "${runAfters}" are a part of different injection tokens.`); + } + } +} + +export interface ConvertToWithId { + (src: InjectionInstanceWithMeta>): RunnableWithId; + (src: InjectionInstanceWithMeta>): RunnableSyncWithId; +} + +export const convertToWithIdWith = (di: DiContainerForInjection) => { + const convert = (meta: { id: string }, instance: Runnable): RunnableWithId => ({ + id: meta.id, + run: instance.run, + runAfter: [instance.runAfter] + .flat() + .filter(isDefined) + .map((injectable) => convert(injectable, di.inject(injectable))), + }); + + return ((src) => convert(src.meta, src.instance)) as ConvertToWithId; +}; diff --git a/packages/core/src/common/runnable/run-many-for.test.ts b/packages/utility-features/run-many/src/run-many-for.test.ts similarity index 91% rename from packages/core/src/common/runnable/run-many-for.test.ts rename to packages/utility-features/run-many/src/run-many-for.test.ts index 6002a149db..8fe753378c 100644 --- a/packages/core/src/common/runnable/run-many-for.test.ts +++ b/packages/utility-features/run-many/src/run-many-for.test.ts @@ -5,11 +5,10 @@ import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; import { createContainer, getInjectable, getInjectionToken } from "@ogre-tools/injectable"; -import type { Runnable } from "./run-many-for"; +import type { Runnable } from "./types"; import { runManyFor } from "./run-many-for"; -import { getPromiseStatus } from "../test-utils/get-promise-status"; +import { getPromiseStatus, flushPromises } from "@k8slens/test-utils"; import { runInAction } from "mobx"; -import { flushPromises } from "../test-utils/flush-promises"; describe("runManyFor", () => { describe("given no hierarchy, when running many", () => { @@ -28,7 +27,6 @@ describe("runManyFor", () => { const someInjectable = getInjectable({ id: "some-injectable", instantiate: () => ({ - id: "some-injectable", run: () => runMock("some-call"), }), injectionToken: someInjectionTokenForRunnables, @@ -37,7 +35,6 @@ describe("runManyFor", () => { const someOtherInjectable = getInjectable({ id: "some-other-injectable", instantiate: () => ({ - id: "some-other-injectable", run: () => runMock("some-other-call"), }), injectionToken: someInjectionTokenForRunnables, @@ -85,32 +82,25 @@ describe("runManyFor", () => { const someInjectable1 = getInjectable({ id: "some-injectable-1", - - instantiate: (di) => ({ - id: "some-injectable-1", + instantiate: () => ({ run: () => runMock("third-level-run"), - runAfter: di.inject(someInjectable2), + runAfter: someInjectable2, }), - injectionToken: someInjectionTokenForRunnables, }); const someInjectable2 = getInjectable({ id: "some-injectable-2", - - instantiate: (di) => ({ - id: "some-injectable-2", + instantiate: () => ({ run: () => runMock("second-level-run"), - runAfter: di.inject(someInjectable3), + runAfter: someInjectable3, }), - injectionToken: someInjectionTokenForRunnables, }); const someInjectable3 = getInjectable({ id: "some-injectable-3", instantiate: () => ({ - id: "some-injectable-3", run: () => runMock("first-level-run"), }), injectionToken: someInjectionTokenForRunnables, @@ -197,24 +187,18 @@ describe("runManyFor", () => { const someInjectable = getInjectable({ id: "some-runnable-1", - - instantiate: (di) => ({ - id: "some-runnable-1", + instantiate: () => ({ run: () => runMock("some-runnable-1"), - runAfter: di.inject(someOtherInjectable), + runAfter: someOtherInjectable, }), - injectionToken: someInjectionToken, }); const someOtherInjectable = getInjectable({ id: "some-runnable-2", - instantiate: () => ({ - id: "some-runnable-2", run: () => runMock("some-runnable-2"), }), - injectionToken: someOtherInjectionToken, }); @@ -244,38 +228,29 @@ describe("runManyFor", () => { const someInjectable = getInjectable({ id: "some-runnable-1", - - instantiate: (di) => ({ - id: "some-runnable-1", + instantiate: () => ({ run: () => runMock("some-runnable-1"), runAfter: [ - di.inject(someOtherInjectable), - di.inject(someSecondInjectable), + someOtherInjectable, + someSecondInjectable, ], }), - injectionToken: someInjectionToken, }); const someSecondInjectable = getInjectable({ id: "some-runnable-2", - instantiate: () => ({ - id: "some-runnable-2", run: () => runMock("some-runnable-2"), }), - injectionToken: someInjectionToken, }); const someOtherInjectable = getInjectable({ id: "some-runnable-3", - instantiate: () => ({ - id: "some-runnable-3", run: () => runMock("some-runnable-3"), }), - injectionToken: someOtherInjectionToken, }); @@ -306,23 +281,17 @@ describe("runManyFor", () => { const someInjectable = getInjectable({ id: "some-runnable-1", - instantiate: () => ({ - id: "some-runnable-1", run: (parameter) => runMock("run-of-some-runnable-1", parameter), }), - injectionToken: someInjectionTokenForRunnablesWithParameter, }); const someOtherInjectable = getInjectable({ id: "some-runnable-2", - instantiate: () => ({ - id: "some-runnable-2", run: (parameter) => runMock("run-of-some-runnable-2", parameter), }), - injectionToken: someInjectionTokenForRunnablesWithParameter, }); @@ -359,7 +328,6 @@ describe("runManyFor", () => { const runnableOneInjectable = getInjectable({ id: "runnable-1", instantiate: () => ({ - id: "runnable-1", run: () => runMock("runnable-1"), }), injectionToken: someInjectionToken, @@ -368,7 +336,6 @@ describe("runManyFor", () => { const runnableTwoInjectable = getInjectable({ id: "runnable-2", instantiate: () => ({ - id: "runnable-2", run: () => runMock("runnable-2"), runAfter: [], // shouldn't block being called }), @@ -377,42 +344,38 @@ describe("runManyFor", () => { const runnableThreeInjectable = getInjectable({ id: "runnable-3", - instantiate: (di) => ({ - id: "runnable-3", + instantiate: () => ({ run: () => runMock("runnable-3"), - runAfter: di.inject(runnableOneInjectable), + runAfter: runnableOneInjectable, }), injectionToken: someInjectionToken, }); const runnableFourInjectable = getInjectable({ id: "runnable-4", - instantiate: (di) => ({ - id: "runnable-4", + instantiate: () => ({ run: () => runMock("runnable-4"), - runAfter: [di.inject(runnableThreeInjectable)], // should be the same as an single item + runAfter: [runnableThreeInjectable], // should be the same as an single item }), injectionToken: someInjectionToken, }); const runnableFiveInjectable = getInjectable({ id: "runnable-5", - instantiate: (di) => ({ - id: "runnable-5", + instantiate: () => ({ run: () => runMock("runnable-5"), - runAfter: di.inject(runnableThreeInjectable), + runAfter: runnableThreeInjectable, }), injectionToken: someInjectionToken, }); const runnableSixInjectable = getInjectable({ id: "runnable-6", - instantiate: (di) => ({ - id: "runnable-6", + instantiate: () => ({ run: () => runMock("runnable-6"), runAfter: [ - di.inject(runnableFourInjectable), - di.inject(runnableFiveInjectable), + runnableFourInjectable, + runnableFiveInjectable, ], }), injectionToken: someInjectionToken, @@ -420,12 +383,11 @@ describe("runManyFor", () => { const runnableSevenInjectable = getInjectable({ id: "runnable-7", - instantiate: (di) => ({ - id: "runnable-7", + instantiate: () => ({ run: () => runMock("runnable-7"), runAfter: [ - di.inject(runnableFiveInjectable), - di.inject(runnableSixInjectable), + runnableFiveInjectable, + runnableSixInjectable, ], }), injectionToken: someInjectionToken, diff --git a/packages/utility-features/run-many/src/run-many-for.ts b/packages/utility-features/run-many/src/run-many-for.ts new file mode 100644 index 0000000000..4d33c009e2 --- /dev/null +++ b/packages/utility-features/run-many/src/run-many-for.ts @@ -0,0 +1,71 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { DiContainerForInjection, InjectionToken } from "@ogre-tools/injectable"; +import { getOrInsert } from "@k8slens/utilities"; +import type TypedEventEmitter from "typed-emitter"; +import EventEmitter from "events"; +import { convertToWithIdWith, verifyRunnablesAreDAG } from "./helpers"; +import type { RunnableWithId, Runnable, Run } from "./types"; +import type { Asyncify } from "type-fest"; + +export type RunMany = (injectionToken: InjectionToken, void>) => Asyncify>; + +interface BarrierEvent { + finish: (id: string) => void; +} + +class DynamicBarrier { + private readonly finishedIds = new Map>(); + private readonly events: TypedEventEmitter = new EventEmitter(); + + private initFinishingPromise(id: string): Promise { + return getOrInsert(this.finishedIds, id, new Promise(resolve => { + const handler = (finishedId: string) => { + if (finishedId === id) { + resolve(); + this.events.removeListener("finish", handler); + } + }; + + this.events.addListener("finish", handler); + })); + } + + setFinished(id: string): void { + void this.initFinishingPromise(id); + + this.events.emit("finish", id); + } + + async blockOn(id: string): Promise { + await this.initFinishingPromise(id); + } +} + +const executeRunnableWith = (param: Param) => { + const barrier = new DynamicBarrier(); + + return async (runnable: RunnableWithId): Promise => { + for (const parentRunnable of runnable.runAfter) { + await barrier.blockOn(parentRunnable.id); + } + + await runnable.run(param); + barrier.setFinished(runnable.id); + }; +}; + +export function runManyFor(di: DiContainerForInjection): RunMany { + const convertToWithId = convertToWithIdWith(di); + + return (injectionToken: InjectionToken, void>) => async (param: Param) => { + const executeRunnable = executeRunnableWith(param); + const allRunnables = di.injectManyWithMeta(injectionToken).map(x => convertToWithId(x)); + + verifyRunnablesAreDAG(injectionToken.id, allRunnables); + + await Promise.all(allRunnables.map(executeRunnable)); + }; +} diff --git a/packages/core/src/common/runnable/run-many-sync-for.test.ts b/packages/utility-features/run-many/src/run-many-sync-for.test.ts similarity index 87% rename from packages/core/src/common/runnable/run-many-sync-for.test.ts rename to packages/utility-features/run-many/src/run-many-sync-for.test.ts index 3aadcad0bf..e66c51d0b1 100644 --- a/packages/core/src/common/runnable/run-many-sync-for.test.ts +++ b/packages/utility-features/run-many/src/run-many-sync-for.test.ts @@ -3,8 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { createContainer, getInjectable, getInjectionToken } from "@ogre-tools/injectable"; -import type { RunnableSync } from "./run-many-sync-for"; import { runManySyncFor } from "./run-many-sync-for"; +import type { RunnableSync } from "./types"; describe("runManySyncFor", () => { describe("given hierarchy, when running many", () => { @@ -22,7 +22,6 @@ describe("runManySyncFor", () => { const someInjectable = getInjectable({ id: "some-injectable", instantiate: () => ({ - id: "some-injectable", run: () => runMock("some-call"), }), injectionToken: someInjectionTokenForRunnables, @@ -31,7 +30,6 @@ describe("runManySyncFor", () => { const someOtherInjectable = getInjectable({ id: "some-other-injectable", instantiate: () => ({ - id: "some-other-injectable", run: () => runMock("some-other-call"), }), injectionToken: someInjectionTokenForRunnables, @@ -66,32 +64,25 @@ describe("runManySyncFor", () => { const someInjectable1 = getInjectable({ id: "some-injectable-1", - - instantiate: (di) => ({ - id: "some-injectable-1", + instantiate: () => ({ run: () => void runMock("third-level-run"), - runAfter: di.inject(someInjectable2), + runAfter: someInjectable2, }), - injectionToken: someInjectionTokenForRunnables, }); const someInjectable2 = getInjectable({ id: "some-injectable-2", - - instantiate: (di) => ({ - id: "some-injectable-2", + instantiate: () => ({ run: () => void runMock("second-level-run"), - runAfter: di.inject(someInjectable3), + runAfter: someInjectable3, }), - injectionToken: someInjectionTokenForRunnables, }); const someInjectable3 = getInjectable({ id: "some-injectable-3", instantiate: () => ({ - id: "some-injectable-3", run: () => void runMock("first-level-run"), }), injectionToken: someInjectionTokenForRunnables, @@ -124,24 +115,18 @@ describe("runManySyncFor", () => { const someInjectable = getInjectable({ id: "some-runnable-1", - - instantiate: (di) => ({ - id: "some-runnable-1", + instantiate: () => ({ run: () => runMock("some-runnable-1"), - runAfter: di.inject(someOtherInjectable), + runAfter: someOtherInjectable, }), - injectionToken: someInjectionToken, }); const someOtherInjectable = getInjectable({ id: "some-runnable-2", - instantiate: () => ({ - id: "some-runnable-2", run: () => runMock("some-runnable-2"), }), - injectionToken: someOtherInjectionToken, }); @@ -152,7 +137,7 @@ describe("runManySyncFor", () => { ); return expect(() => runMany()).toThrow( - /Tried to get a composite but encountered missing parent ids: "some-runnable-2".\n\nAvailable parent ids are:\n"[0-9a-z-]+",\n"some-runnable-1"/, + /Runnable "some-runnable-1" is unreachable for injection token "some-injection-token": run afters "some-runnable-2" are a part of different injection tokens./, ); }); @@ -172,23 +157,17 @@ describe("runManySyncFor", () => { const someInjectable = getInjectable({ id: "some-runnable-1", - instantiate: () => ({ - id: "some-runnable-1", run: (parameter) => void runMock("run-of-some-runnable-1", parameter), }), - injectionToken: someInjectionTokenForRunnablesWithParameter, }); const someOtherInjectable = getInjectable({ id: "some-runnable-2", - instantiate: () => ({ - id: "some-runnable-2", run: (parameter) => void runMock("run-of-some-runnable-2", parameter), }), - injectionToken: someInjectionTokenForRunnablesWithParameter, }); diff --git a/packages/utility-features/run-many/src/run-many-sync-for.ts b/packages/utility-features/run-many/src/run-many-sync-for.ts new file mode 100644 index 0000000000..f93b41470e --- /dev/null +++ b/packages/utility-features/run-many/src/run-many-sync-for.ts @@ -0,0 +1,77 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { DiContainerForInjection, InjectionToken } from "@ogre-tools/injectable"; +import type { Disposer } from "@k8slens/utilities"; +import type { RunnableSync, RunSync, RunnableSyncWithId } from "./types"; +import { convertToWithIdWith, verifyRunnablesAreDAG } from "./helpers"; +import type TypedEventEmitter from "typed-emitter"; +import EventEmitter from "events"; + +export type RunManySync = (injectionToken: InjectionToken, void>) => RunSync; + +class SyncBarrier { + private readonly finishedIds = new Set(); + private readonly events: TypedEventEmitter void>> = new EventEmitter(); + + setFinished(id: string): void { + this.finishedIds.add(id); + this.events.emit(id); + } + + onceParentsAreFinished(id: string, parentIds: string[], action: () => void) { + const finishers = new Map(); + + const checkAndRun = () => { + if (finishers.size === 0) { + action(); + this.setFinished(id); + } + }; + + for (const parentId of parentIds) { + if (this.finishedIds.has(parentId)) { + continue; + } + + const onParentFinished = () => { + this.events.removeListener(parentId, onParentFinished); + finishers.delete(parentId); + checkAndRun(); + }; + + finishers.set(parentId, onParentFinished); + this.events.once(parentId, onParentFinished); + } + + checkAndRun(); + } +} + +const executeRunnableWith = (param: Param) => { + const barrier = new SyncBarrier(); + + return (runnable: RunnableSyncWithId) => { + barrier.onceParentsAreFinished( + runnable.id, + runnable.runAfter.map(r => r.id), + () => runnable.run(param), + ); + }; +}; + +export function runManySyncFor(di: DiContainerForInjection): RunManySync { + const convertToWithId = convertToWithIdWith(di); + + return (injectionToken: InjectionToken, void>) => (param: Param): undefined => { + const executeRunnable = executeRunnableWith(param); + const allRunnables = di.injectManyWithMeta(injectionToken).map(convertToWithId); + + verifyRunnablesAreDAG(injectionToken.id, allRunnables); + + allRunnables.forEach(executeRunnable); + + return undefined; + }; +} diff --git a/packages/utility-features/run-many/src/types.ts b/packages/utility-features/run-many/src/types.ts new file mode 100644 index 0000000000..007d9bcef1 --- /dev/null +++ b/packages/utility-features/run-many/src/types.ts @@ -0,0 +1,40 @@ +/** + * 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 type { SingleOrMany } from "@k8slens/utilities"; + +export type Run = (parameter: Param) => Promise | void; + +export interface Runnable { + id?: never; + run: Run; + readonly runAfter?: SingleOrMany, Runnable, void>>; +} + +export interface RunnableWithId { + run: Run; + readonly id: string; + readonly runAfter: RunnableWithId[]; +} + +export interface RunnableSync { + id?: never; + run: RunSync; + runAfter?: SingleOrMany, RunnableSync, void>>; +} + +export interface RunnableSyncWithId { + run: RunSync; + readonly id: string; + readonly runAfter: RunnableSyncWithId[]; +} + +/** + * NOTE: this is the worse of two evils. This makes sure that `RunnableSync` always is sync. + * If the return type is `void` instead then async functions (those return `Promise`) can + * coerce to it. + */ +export type RunSync = (parameter: Param) => undefined; diff --git a/packages/utility-features/run-many/tsconfig.json b/packages/utility-features/run-many/tsconfig.json new file mode 100644 index 0000000000..a4f6fa613e --- /dev/null +++ b/packages/utility-features/run-many/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "@k8slens/typescript/config/base.json" +} diff --git a/packages/utility-features/run-many/webpack.config.js b/packages/utility-features/run-many/webpack.config.js new file mode 100644 index 0000000000..3183f30179 --- /dev/null +++ b/packages/utility-features/run-many/webpack.config.js @@ -0,0 +1 @@ +module.exports = require("@k8slens/webpack").configForNode; diff --git a/packages/utility-features/test-utils/README.md b/packages/utility-features/test-utils/README.md new file mode 100644 index 0000000000..657bc43995 --- /dev/null +++ b/packages/utility-features/test-utils/README.md @@ -0,0 +1,3 @@ +# @k8slens/test-utils + +This package contains many useful utilities for testing. diff --git a/packages/utility-features/test-utils/index.ts b/packages/utility-features/test-utils/index.ts new file mode 100644 index 0000000000..ed5afc6535 --- /dev/null +++ b/packages/utility-features/test-utils/index.ts @@ -0,0 +1,4 @@ +export * from "./src/flush-promises"; +export * from "./src/get-global-override-for-function"; +export * from "./src/get-global-override"; +export * from "./src/get-promise-status"; diff --git a/packages/utility-features/test-utils/jest.config.js b/packages/utility-features/test-utils/jest.config.js new file mode 100644 index 0000000000..23be80353b --- /dev/null +++ b/packages/utility-features/test-utils/jest.config.js @@ -0,0 +1,2 @@ +module.exports = + require("@k8slens/jest").monorepoPackageConfig(__dirname).configForReact; diff --git a/packages/utility-features/test-utils/package.json b/packages/utility-features/test-utils/package.json new file mode 100644 index 0000000000..9074957a69 --- /dev/null +++ b/packages/utility-features/test-utils/package.json @@ -0,0 +1,27 @@ +{ + "name": "@k8slens/test-utils", + "version": "1.0.0", + "description": "A collection of utilities for testing", + "type": "commonjs", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + }, + "private": false, + "files": [ + "dist" + ], + "author": { + "name": "OpenLens Authors", + "email": "info@k8slens.dev" + }, + "license": "MIT", + "homepage": "https://github.com/lensapp/lens", + "scripts": { + "build": "webpack", + "dev": "webpack --mode=development --watch", + "test": "jest --coverage --runInBand" + } +} diff --git a/packages/core/src/common/test-utils/flush-promises.ts b/packages/utility-features/test-utils/src/flush-promises.ts similarity index 100% rename from packages/core/src/common/test-utils/flush-promises.ts rename to packages/utility-features/test-utils/src/flush-promises.ts diff --git a/packages/core/src/common/test-utils/get-global-override-for-function.ts b/packages/utility-features/test-utils/src/get-global-override-for-function.ts similarity index 63% rename from packages/core/src/common/test-utils/get-global-override-for-function.ts rename to packages/utility-features/test-utils/src/get-global-override-for-function.ts index 238ee5621a..1b718c7554 100644 --- a/packages/core/src/common/test-utils/get-global-override-for-function.ts +++ b/packages/utility-features/test-utils/src/get-global-override-for-function.ts @@ -6,9 +6,7 @@ import type { Injectable } from "@ogre-tools/injectable"; import { getGlobalOverride } from "./get-global-override"; import { camelCase } from "lodash/fp"; -export const getGlobalOverrideForFunction = ( - injectable: Injectable, -) => +export const getGlobalOverrideForFunction = (injectable: Injectable) => ( getGlobalOverride(injectable, () => (...args: any[]) => { console.warn( `Tried to invoke a function "${injectable.id}" without override. The args were:`, @@ -16,10 +14,7 @@ export const getGlobalOverrideForFunction = ( ); throw new Error( - `Tried to invoke a function "${ - injectable.id - }" without override. Add eg. "di.override(${camelCase( - injectable.id, - )}Mock)" to the unit test interested in this.`, + `Tried to invoke a function "${injectable.id}" without override. Add eg. "di.override(${camelCase(injectable.id)}Mock)" to the unit test interested in this.`, ); - }); + }) +); diff --git a/packages/utility-features/test-utils/src/get-global-override.ts b/packages/utility-features/test-utils/src/get-global-override.ts new file mode 100644 index 0000000000..c1902d60d7 --- /dev/null +++ b/packages/utility-features/test-utils/src/get-global-override.ts @@ -0,0 +1,18 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { Injectable, Instantiate } from "@ogre-tools/injectable"; + +export interface GlobalOverride { + injectable: Injectable; + overridingInstantiate: Instantiate; +} + +export const getGlobalOverride = ( + injectable: Injectable, + overridingInstantiate: (typeof injectable)["instantiate"], +) => ({ + injectable, + overridingInstantiate, +}); diff --git a/packages/core/src/common/test-utils/get-promise-status.ts b/packages/utility-features/test-utils/src/get-promise-status.ts similarity index 100% rename from packages/core/src/common/test-utils/get-promise-status.ts rename to packages/utility-features/test-utils/src/get-promise-status.ts diff --git a/packages/utility-features/test-utils/tsconfig.json b/packages/utility-features/test-utils/tsconfig.json new file mode 100644 index 0000000000..a4f6fa613e --- /dev/null +++ b/packages/utility-features/test-utils/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "@k8slens/typescript/config/base.json" +} diff --git a/packages/utility-features/test-utils/webpack.config.js b/packages/utility-features/test-utils/webpack.config.js new file mode 100644 index 0000000000..3183f30179 --- /dev/null +++ b/packages/utility-features/test-utils/webpack.config.js @@ -0,0 +1 @@ +module.exports = require("@k8slens/webpack").configForNode; diff --git a/packages/utility-features/utilities/README.md b/packages/utility-features/utilities/README.md new file mode 100644 index 0000000000..336b802f84 --- /dev/null +++ b/packages/utility-features/utilities/README.md @@ -0,0 +1,3 @@ +# @k8slens/utilities + +This package contains many useful types. diff --git a/packages/utility-features/utilities/index.ts b/packages/utility-features/utilities/index.ts new file mode 100644 index 0000000000..dc8eacdfdd --- /dev/null +++ b/packages/utility-features/utilities/index.ts @@ -0,0 +1,45 @@ +export * from "./src/abort-controller"; +export * from "./src/array"; +export * from "./src/backoff-caller"; +export * from "./src/base64"; +export * from "./src/buildUrl"; +export * from "./src/camelCase"; +export * from "./src/collection-functions"; +export * from "./src/computed-or"; +export * from "./src/convertCpu"; +export * from "./src/convertMemory"; +export * from "./src/cssNames"; +export * from "./src/cssVar"; +export * from "./src/debouncePromise"; +export * from "./src/delay"; +export * from "./src/display-mode"; +export * from "./src/disposer"; +export * from "./src/formatDuration"; +export * from "./src/hash-set"; +export * from "./src/interval"; +export * from "./src/is-node-falsy"; +export * from "./src/isMiddleClick"; +export * from "./src/isReactNode"; +export * from "./src/iter"; +export * from "./src/json"; +export * from "./src/jsonPath"; +export * from "./src/metricUnitsToNumber"; +export * from "./src/name-parts"; +export * from "./src/noop"; +export * from "./src/object"; +export * from "./src/observable-crate"; +export * from "./src/on-keyboard-shortcut"; +export * from "./src/prevDefault"; +export * from "./src/readableStream"; +export * from "./src/readonly"; +export * from "./src/reject-promise"; +export * from "./src/result"; +export * from "./src/sort-compare"; +export * from "./src/sort-function"; +export * from "./src/tar"; +export * from "./src/tuple"; +export * from "./src/type-narrowing"; +export * from "./src/types"; +export * from "./src/union-env-path"; +export * from "./src/wait"; +export * from "./src/with-concurrency-limit"; diff --git a/packages/utility-features/utilities/jest.config.js b/packages/utility-features/utilities/jest.config.js new file mode 100644 index 0000000000..23be80353b --- /dev/null +++ b/packages/utility-features/utilities/jest.config.js @@ -0,0 +1,2 @@ +module.exports = + require("@k8slens/jest").monorepoPackageConfig(__dirname).configForReact; diff --git a/packages/utility-features/utilities/package.json b/packages/utility-features/utilities/package.json new file mode 100644 index 0000000000..78ac7085e9 --- /dev/null +++ b/packages/utility-features/utilities/package.json @@ -0,0 +1,31 @@ +{ + "name": "@k8slens/utilities", + "description": "A collection of useful types", + "version": "1.0.0", + "type": "commonjs", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + }, + "private": false, + "files": [ + "dist" + ], + "author": { + "name": "OpenLens Authors", + "email": "info@k8slens.dev" + }, + "license": "MIT", + "homepage": "https://github.com/lensapp/lens", + "scripts": { + "build": "webpack", + "dev": "webpack --mode=development --watch", + "test": "jest --coverage --runInBand" + }, + "peerDependencies": { + "mobx": "^6.8.0", + "type-fest": "^2.19.0" + } +} diff --git a/packages/core/src/common/utils/abort-controller.ts b/packages/utility-features/utilities/src/abort-controller.ts similarity index 100% rename from packages/core/src/common/utils/abort-controller.ts rename to packages/utility-features/utilities/src/abort-controller.ts diff --git a/packages/core/src/common/utils/splitArray.ts b/packages/utility-features/utilities/src/array.ts similarity index 52% rename from packages/core/src/common/utils/splitArray.ts rename to packages/utility-features/utilities/src/array.ts index 142d4a33ff..0f7a554318 100644 --- a/packages/core/src/common/utils/splitArray.ts +++ b/packages/utility-features/utilities/src/array.ts @@ -3,6 +3,15 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ +/** + * A inference typed version of `Array(length).fill(value)` + * @param length The number of entries + * @param value The value of each of the indices + */ +function filled(length: number, value: T): T[] { + return Array(length).fill(value); +} + /** * This function splits an array into two sub arrays on the first instance of * element (from the left). If the array does not contain the element. The @@ -14,29 +23,33 @@ * @returns the left and right sub-arrays which when conjoined with `element` * is the same as `array`, and `true` */ -export function splitArray(array: T[], element: T): [T[], T[], boolean] { - const index = array.indexOf(element); +function split(src: T[], element: T): [T[], T[], boolean] { + const index = src.indexOf(element); if (index < 0) { - return [array, [], false]; + return [src, [], false]; } - return [array.slice(0, index), array.slice(index + 1, array.length), true]; + return [src.slice(0, index), src.slice(index + 1, src.length), true]; } -/** - * Splits an array into two parts based on the outcome of `condition`. If `true` - * the value will be returned as part of the right array. If `false` then part of - * the left array. - * @param src the full array to bifurcate - * @param condition the function to determine which set each is in - */ -export function bifurcateArray(src: T[], condition: (item: T) => boolean): [falses: T[], trues: T[]] { - const res: [T[], T[]] = [[], []]; +function bifurcate(src: T[], condition: (item: T) => any): [falses: T[], trues: T[]] { + const trues: T[] = []; + const falses: T[] = []; for (const item of src) { - res[+condition(item)].push(item); + if (condition(item)) { + trues.push(item); + } else { + falses.push(item); + } } - return res; + return [falses, trues]; } + +export const array = { + bifurcate, + filled, + split, +}; diff --git a/packages/core/src/common/utils/backoff-caller.ts b/packages/utility-features/utilities/src/backoff-caller.ts similarity index 85% rename from packages/core/src/common/utils/backoff-caller.ts rename to packages/utility-features/utilities/src/backoff-caller.ts index 131565bb09..a76e666c7e 100644 --- a/packages/core/src/common/utils/backoff-caller.ts +++ b/packages/utility-features/utilities/src/backoff-caller.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { AsyncResult } from "./async-result"; +import type { AsyncResult, Result } from "./result"; import { delay } from "./delay"; import { noop } from "./noop"; @@ -25,7 +25,7 @@ export interface BackoffCallerOptions { maxAttempts?: number; /** - * In miliseconds + * In milliseconds * @default 1000 */ initialTimeout?: number; @@ -41,7 +41,7 @@ export interface BackoffCallerOptions { * @param fn The function to repeatedly attempt * @returns The first success or the last failure */ -export const backoffCaller = async >(fn: () => Promise, options?: BackoffCallerOptions): Promise => { +export const backoffCaller = async (fn: () => AsyncResult, options?: BackoffCallerOptions): AsyncResult => { const { initialTimeout = 1000, maxAttempts = 5, @@ -51,7 +51,7 @@ export const backoffCaller = async >(fn: () => let timeout = initialTimeout; let attempt = 0; - let result: R; + let result: Result; do { result = await fn(); diff --git a/packages/core/src/common/utils/base64.ts b/packages/utility-features/utilities/src/base64.ts similarity index 82% rename from packages/core/src/common/utils/base64.ts rename to packages/utility-features/utilities/src/base64.ts index c55a5de6a7..1f2aa0810f 100755 --- a/packages/core/src/common/utils/base64.ts +++ b/packages/utility-features/utilities/src/base64.ts @@ -12,7 +12,7 @@ import * as Utf8 from "crypto-js/enc-utf8"; * @param data A Base64 encoded string * @returns The original utf-8 string */ -export function decode(data: string): string { +function decode(data: string): string { return Base64.parse(data).toString(Utf8); } @@ -21,6 +21,11 @@ export function decode(data: string): string { * @param data A normal string * @returns A base64 encoded version */ -export function encode(data: string): string { +function encode(data: string): string { return Utf8.parse(data).toString(Base64); } + +export const base64 = { + encode, + decode, +}; diff --git a/packages/core/src/common/utils/buildUrl.ts b/packages/utility-features/utilities/src/buildUrl.ts similarity index 100% rename from packages/core/src/common/utils/buildUrl.ts rename to packages/utility-features/utilities/src/buildUrl.ts diff --git a/packages/core/src/common/utils/camelCase.ts b/packages/utility-features/utilities/src/camelCase.ts similarity index 96% rename from packages/core/src/common/utils/camelCase.ts rename to packages/utility-features/utilities/src/camelCase.ts index a37e4c7f5c..056b427656 100644 --- a/packages/core/src/common/utils/camelCase.ts +++ b/packages/utility-features/utilities/src/camelCase.ts @@ -7,7 +7,7 @@ import { camelCase } from "lodash"; import type { SingleOrMany } from "./types"; import { isObject, isString } from "./type-narrowing"; -import * as object from "./objects"; +import { object } from "./object"; export function toCamelCase[]>(obj: T): T; export function toCamelCase>(obj: T): T; diff --git a/packages/core/src/common/utils/collection-functions.ts b/packages/utility-features/utilities/src/collection-functions.ts similarity index 94% rename from packages/core/src/common/utils/collection-functions.ts rename to packages/utility-features/utilities/src/collection-functions.ts index 5d6dc80548..e78e215e8b 100644 --- a/packages/core/src/common/utils/collection-functions.ts +++ b/packages/utility-features/utilities/src/collection-functions.ts @@ -19,7 +19,6 @@ export function getOrInsert(map: Map, key: K, value: V): V { map.set(key, value); } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return map.get(key)!; } @@ -67,7 +66,6 @@ export function getOrInsertWith(map: Map | WeakMap(map: Map, key: K): V { throw new TypeError(`Map does not contains key: ${inspect(key)}`); } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return map.get(key)!; } diff --git a/packages/core/src/common/utils/computed-or.ts b/packages/utility-features/utilities/src/computed-or.ts similarity index 100% rename from packages/core/src/common/utils/computed-or.ts rename to packages/utility-features/utilities/src/computed-or.ts diff --git a/packages/core/src/common/utils/__tests__/convert-memory.test.ts b/packages/utility-features/utilities/src/convert-memory.test.ts similarity index 98% rename from packages/core/src/common/utils/__tests__/convert-memory.test.ts rename to packages/utility-features/utilities/src/convert-memory.test.ts index c69f43a061..ccbb26c4ba 100644 --- a/packages/core/src/common/utils/__tests__/convert-memory.test.ts +++ b/packages/utility-features/utilities/src/convert-memory.test.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { bytesToUnits, unitsToBytes } from "../convertMemory"; +import { bytesToUnits, unitsToBytes } from "./convertMemory"; describe("unitsToBytes", () => { it("without any units, just parse as float", () => { diff --git a/packages/core/src/common/utils/convertCpu.ts b/packages/utility-features/utilities/src/convertCpu.ts similarity index 100% rename from packages/core/src/common/utils/convertCpu.ts rename to packages/utility-features/utilities/src/convertCpu.ts diff --git a/packages/core/src/common/utils/convertMemory.ts b/packages/utility-features/utilities/src/convertMemory.ts similarity index 98% rename from packages/core/src/common/utils/convertMemory.ts rename to packages/utility-features/utilities/src/convertMemory.ts index 7cae1cf0c1..3a9aea6d5f 100644 --- a/packages/core/src/common/utils/convertMemory.ts +++ b/packages/utility-features/utilities/src/convertMemory.ts @@ -4,7 +4,7 @@ */ import assert from "assert"; -import * as iter from "./iter"; +import { iter } from "./iter"; // Helper to convert memory from units Ki, Mi, Gi, Ti, Pi to bytes and vise versa diff --git a/packages/core/src/renderer/utils/__tests__/converted-name.test.ts b/packages/utility-features/utilities/src/converted-name.test.ts similarity index 92% rename from packages/core/src/renderer/utils/__tests__/converted-name.test.ts rename to packages/utility-features/utilities/src/converted-name.test.ts index ab1f040b95..24c89185f5 100644 --- a/packages/core/src/renderer/utils/__tests__/converted-name.test.ts +++ b/packages/utility-features/utilities/src/converted-name.test.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getConvertedParts } from "../name-parts"; +import { getConvertedParts } from "./name-parts"; describe("getConvertedParts", () => { it.each([ diff --git a/packages/core/src/renderer/utils/cssNames.ts b/packages/utility-features/utilities/src/cssNames.ts similarity index 77% rename from packages/core/src/renderer/utils/cssNames.ts rename to packages/utility-features/utilities/src/cssNames.ts index aebf5cdf72..a8db957fcc 100755 --- a/packages/core/src/renderer/utils/cssNames.ts +++ b/packages/utility-features/utilities/src/cssNames.ts @@ -3,7 +3,9 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { iter } from "../../common/utils"; +import { iter } from "./iter"; +import { object } from "./object"; +import { isObject } from "./type-narrowing"; export type IgnoredClassNames = number | symbol | Function; export type IClassName = string | string[] | Record | undefined | null | false | IgnoredClassNames; @@ -18,15 +20,15 @@ export function cssNames(...classNames: IClassName[]): string { for (const name of className) { classNamesEnabled.set(name, true); } - } else if (className && typeof className === "object") { - for (const [name, value] of Object.entries(className)) { + } else if (isObject(className)) { + for (const [name, value] of object.entries(className)) { classNamesEnabled.set(name, Boolean(value)); } } } return iter.chain(classNamesEnabled.entries()) - .filter(([, isActive]) => !!isActive) + .filter(([, isActive]) => isActive) .filterMap(([className]) => className.trim()) .join(" "); } diff --git a/packages/core/src/renderer/utils/cssVar.ts b/packages/utility-features/utilities/src/cssVar.ts similarity index 100% rename from packages/core/src/renderer/utils/cssVar.ts rename to packages/utility-features/utilities/src/cssVar.ts diff --git a/packages/core/src/common/utils/debouncePromise.ts b/packages/utility-features/utilities/src/debouncePromise.ts similarity index 85% rename from packages/core/src/common/utils/debouncePromise.ts rename to packages/utility-features/utilities/src/debouncePromise.ts index c15b206a76..1610b977b2 100755 --- a/packages/core/src/common/utils/debouncePromise.ts +++ b/packages/utility-features/utilities/src/debouncePromise.ts @@ -10,6 +10,6 @@ export function debouncePromise(func: (...args: F) => T | Pr return (...params: F) => new Promise(resolve => { clearTimeout(timer); - timer = global.setTimeout(() => resolve(func(...params)), timeout); + timer = setTimeout(() => resolve(func(...params)), timeout); }); } diff --git a/packages/core/src/common/utils/delay.ts b/packages/utility-features/utilities/src/delay.ts similarity index 100% rename from packages/core/src/common/utils/delay.ts rename to packages/utility-features/utilities/src/delay.ts diff --git a/packages/core/src/renderer/utils/display-mode.ts b/packages/utility-features/utilities/src/display-mode.ts similarity index 100% rename from packages/core/src/renderer/utils/display-mode.ts rename to packages/utility-features/utilities/src/display-mode.ts diff --git a/packages/core/src/common/utils/disposer.ts b/packages/utility-features/utilities/src/disposer.ts similarity index 91% rename from packages/core/src/common/utils/disposer.ts rename to packages/utility-features/utilities/src/disposer.ts index 2949a7ae35..f7be4dc34d 100644 --- a/packages/core/src/common/utils/disposer.ts +++ b/packages/utility-features/utilities/src/disposer.ts @@ -5,8 +5,6 @@ import type { SingleOrMany } from "./types"; - - export interface Disposer { (): void; } @@ -16,7 +14,7 @@ export interface Disposable { } export interface ExtendableDisposer extends Disposer { - push(...vals: (Disposer | ExtendableDisposer | Disposable)[]): void; + push(...values: (Disposer | ExtendableDisposer | Disposable)[]): void; } export function disposer(...items: SingleOrMany[]): ExtendableDisposer { diff --git a/packages/core/src/common/utils/__tests__/formatDuration.test.ts b/packages/utility-features/utilities/src/formatDuration.test.ts similarity index 97% rename from packages/core/src/common/utils/__tests__/formatDuration.test.ts rename to packages/utility-features/utilities/src/formatDuration.test.ts index 3c42db9060..b72b7173f2 100644 --- a/packages/core/src/common/utils/__tests__/formatDuration.test.ts +++ b/packages/utility-features/utilities/src/formatDuration.test.ts @@ -4,7 +4,7 @@ */ import moment from "moment"; -import { formatDuration } from "../formatDuration"; +import { formatDuration } from "./formatDuration"; const second = 1000; const minute = 60 * second; diff --git a/packages/core/src/common/utils/formatDuration.ts b/packages/utility-features/utilities/src/formatDuration.ts similarity index 100% rename from packages/core/src/common/utils/formatDuration.ts rename to packages/utility-features/utilities/src/formatDuration.ts diff --git a/packages/core/src/common/utils/__tests__/hash-set.test.ts b/packages/utility-features/utilities/src/hash-set.test.ts similarity index 98% rename from packages/core/src/common/utils/__tests__/hash-set.test.ts rename to packages/utility-features/utilities/src/hash-set.test.ts index 4e78a1ca4c..2feaab4d9b 100644 --- a/packages/core/src/common/utils/__tests__/hash-set.test.ts +++ b/packages/utility-features/utilities/src/hash-set.test.ts @@ -3,14 +3,14 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { HashSet, ObservableHashSet } from "../hash-set"; +import { HashSet, ObservableHashSet } from "./hash-set"; describe("ObservableHashSet", () => { it("should not throw on creation", () => { expect(() => new ObservableHashSet<{ a: number }>([], item => item.a.toString())).not.toThrowError(); }); - it("should be initializable", () => { + it("should be initialized", () => { const res = new ObservableHashSet([ { a: 1 }, { a: 2 }, @@ -263,7 +263,7 @@ describe("HashSet", () => { expect(() => new HashSet<{ a: number }>([], item => item.a.toString())).not.toThrowError(); }); - it("should be initializable", () => { + it("should be initialized", () => { const res = new HashSet([ { a: 1 }, { a: 2 }, diff --git a/packages/core/src/common/utils/hash-set.ts b/packages/utility-features/utilities/src/hash-set.ts similarity index 88% rename from packages/core/src/common/utils/hash-set.ts rename to packages/utility-features/utilities/src/hash-set.ts index 23ce13b1b2..7369fa32d9 100644 --- a/packages/core/src/common/utils/hash-set.ts +++ b/packages/utility-features/utilities/src/hash-set.ts @@ -4,7 +4,7 @@ */ import type { IInterceptable, IInterceptor, IListenable, ISetWillChange, ObservableMap } from "mobx"; -import { action, observable, ObservableSet } from "mobx"; +import { observable, ObservableSet, runInAction } from "mobx"; export function makeIterableIterator(iterator: Iterator): IterableIterator { (iterator as IterableIterator)[Symbol.iterator] = () => iterator as IterableIterator; @@ -138,23 +138,24 @@ export class ObservableHashSet implements Set, IInterceptable(Array.from(initialValues, value => [this.hasher(value), value]), undefined); } - @action replace(other: ObservableHashSet | ObservableSet | Set | readonly T[]): this { - if (other === null || other === undefined) { + return runInAction(() => { + if (other === null || other === undefined) { + return this; + } + + if (!(Array.isArray(other) || other instanceof Set || other instanceof ObservableHashSet || other instanceof ObservableSet)) { + throw new Error(`ObservableHashSet: Cannot initialize set from ${other}`); + } + + this.clear(); + + for (const value of other) { + this.add(value); + } + return this; - } - - if (!(Array.isArray(other) || other instanceof Set || other instanceof ObservableHashSet || other instanceof ObservableSet)) { - throw new Error(`ObservableHashSet: Cannot initialize set from ${other}`); - } - - this.clear(); - - for (const value of other) { - this.add(value); - } - - return this; + }); } clear(): void { @@ -167,15 +168,16 @@ export class ObservableHashSet implements Set, IInterceptable { + const hash = this.hasher(value); - if (this.#hashmap.has(hash)) { - this.#hashmap.delete(hash); - } else { - this.#hashmap.set(hash, value); - } + if (this.#hashmap.has(hash)) { + this.#hashmap.delete(hash); + } else { + this.#hashmap.set(hash, value); + } + }); } delete(value: T): boolean { diff --git a/packages/core/src/renderer/utils/interval.ts b/packages/utility-features/utilities/src/interval.ts similarity index 100% rename from packages/core/src/renderer/utils/interval.ts rename to packages/utility-features/utilities/src/interval.ts diff --git a/packages/core/src/renderer/utils/is-node-falsy.ts b/packages/utility-features/utilities/src/is-node-falsy.ts similarity index 100% rename from packages/core/src/renderer/utils/is-node-falsy.ts rename to packages/utility-features/utilities/src/is-node-falsy.ts diff --git a/packages/core/src/renderer/utils/isMiddleClick.ts b/packages/utility-features/utilities/src/isMiddleClick.ts similarity index 100% rename from packages/core/src/renderer/utils/isMiddleClick.ts rename to packages/utility-features/utilities/src/isMiddleClick.ts diff --git a/packages/core/src/renderer/utils/isReactNode.ts b/packages/utility-features/utilities/src/isReactNode.ts similarity index 91% rename from packages/core/src/renderer/utils/isReactNode.ts rename to packages/utility-features/utilities/src/isReactNode.ts index 682ac0f93b..a2c97c707a 100755 --- a/packages/core/src/renderer/utils/isReactNode.ts +++ b/packages/utility-features/utilities/src/isReactNode.ts @@ -6,7 +6,7 @@ // Type guard for checking valid react node to use in render import type { ReactNode } from "react"; import React from "react"; -import { isObject } from "../../common/utils"; +import { isObject } from "./type-narrowing"; export function isReactNode(node: unknown): node is ReactNode { return (isObject(node) && React.isValidElement(node)) diff --git a/packages/utility-features/utilities/src/iter.test.ts b/packages/utility-features/utilities/src/iter.test.ts new file mode 100644 index 0000000000..c1a4837505 --- /dev/null +++ b/packages/utility-features/utilities/src/iter.test.ts @@ -0,0 +1,101 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { iter } from "./iter"; + +describe("iter", () => { + describe("reduce", () => { + it("can reduce a value", () => { + expect(iter.reduce([1, 2, 3], (acc: number[], current: number) => [current, ...acc], [0])).toEqual([3, 2, 1, 0]); + }); + + it("can reduce an empty iterable", () => { + expect(iter.reduce([], (acc: number[], current: number) => [acc[0] + current], [])).toEqual([]); + }); + }); + + describe("join", () => { + it("should not prefix the output by the separator", () => { + expect(iter.join(["a", "b", "c"].values(), " ")).toBe("a b c"); + }); + + it("should return empty string if iterator is empty", () => { + expect(iter.join([].values(), " ")).toBe(""); + }); + + it("should return just first entry if iterator is of size 1", () => { + expect(iter.join(["d"].values(), " ")).toBe("d"); + }); + }); + + describe("nth", () => { + it("should return undefined past the end of the iterator", () => { + expect(iter.nth(["a"], 123)).toBeUndefined(); + }); + + it("should by 0-indexing the index", () => { + expect(iter.nth(["a", "b"], 0)).toBe("a"); + }); + }); + + describe("concat", () => { + it("should yield undefined for empty args", () => { + const i = iter.concat(); + + expect(i.next()).toEqual({ done: true }); + }); + + it("should yield undefined for only empty args", () => { + const i = iter.concat([].values(), [].values(), [].values(), [].values()); + + expect(i.next()).toEqual({ done: true }); + }); + + it("should yield all of the first and then all of the second", () => { + const i = iter.concat([1, 2, 3].values(), [4, 5, 6].values()); + + expect(i.next()).toEqual({ done: false, value: 1 }); + expect(i.next()).toEqual({ done: false, value: 2 }); + expect(i.next()).toEqual({ done: false, value: 3 }); + expect(i.next()).toEqual({ done: false, value: 4 }); + expect(i.next()).toEqual({ done: false, value: 5 }); + expect(i.next()).toEqual({ done: false, value: 6 }); + expect(i.next()).toEqual({ done: true }); + }); + }); + + describe("nFircate", () => { + it("should produce an empty array if no parts are provided", () => { + expect(iter.nFircate([{ a: 1 }, { a: 2 }], "a", []).length).toBe(0); + }); + + it("should ignore non-matching parts", () => { + const res = iter.nFircate([{ a: 1 }, { a: 2 }], "a", [1]); + + expect(res.length).toBe(1); + expect(res[0].length).toBe(1); + }); + + it("should include all matching parts in each type", () => { + const res = iter.nFircate([{ a: 1, b: "a" }, { a: 2, b: "b" }, { a: 1, b: "c" }], "a", [1, 2]); + + expect(res.length).toBe(2); + expect(res[0].length).toBe(2); + expect(res[0][0].b).toBe("a"); + expect(res[0][1].b).toBe("c"); + expect(res[1].length).toBe(1); + expect(res[1][0].b).toBe("b"); + }); + + it("should throw a type error if the same part is provided more than once", () => { + try { + iter.nFircate([{ a: 1, b: "a" }, { a: 2, b: "b" }, { a: 1, b: "c" }], "a", [1, 2, 1]); + fail("Expected error"); + } catch (error) { + expect(error).toBeInstanceOf(TypeError); + } + }); + }); +}); diff --git a/packages/core/src/common/utils/iter.ts b/packages/utility-features/utilities/src/iter.ts similarity index 62% rename from packages/core/src/common/utils/iter.ts rename to packages/utility-features/utilities/src/iter.ts index dc1c4621fd..abbf4cc92d 100644 --- a/packages/core/src/common/utils/iter.ts +++ b/packages/utility-features/utilities/src/iter.ts @@ -3,11 +3,11 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -export type Falsey = false | 0 | "" | null | undefined; +export type Falsy = false | 0 | "" | null | undefined; interface Iterator extends Iterable { filter(fn: (val: T) => unknown): Iterator; - filterMap(fn: (val: T) => Falsey | U): Iterator; + filterMap(fn: (val: T) => Falsy | U): Iterator; find(fn: (val: T) => unknown): T | undefined; collect(fn: (values: Iterable) => U): U; map(fn: (val: T) => U): Iterator; @@ -16,7 +16,7 @@ interface Iterator extends Iterable { join(sep?: string): string; } -export function chain(src: IterableIterator): Iterator { +function chain(src: IterableIterator): Iterator { return { filter: (fn) => chain(filter(src, fn)), filterMap: (fn) => chain(filterMap(src, fn)), @@ -34,7 +34,7 @@ export function chain(src: IterableIterator): Iterator { * Create a new type safe empty Iterable * @returns An `Iterable` that yields 0 items */ -export function* newEmpty(): IterableIterator {} +function* newEmpty(): IterableIterator {} /** * Creates a new `Iterable` that yields at most n items from src. @@ -42,7 +42,7 @@ export function* newEmpty(): IterableIterator {} * @param src An initial iterator * @param n The maximum number of elements to take from src. Yields up to the floor of `n` and 0 items if n < 0 */ -export function* take(src: Iterable, n: number): IterableIterator { +function* take(src: Iterable, n: number): IterableIterator { outer: for (let i = 0; i < n; i += 1) { for (const item of src) { yield item; @@ -60,18 +60,18 @@ export function* take(src: Iterable, n: number): IterableIterator { * @param src A type that can be iterated over * @param fn The function that is called for each value */ -export function* map(src: Iterable, fn: (from: T) => U): IterableIterator { +function* map(src: Iterable, fn: (from: T) => U): IterableIterator { for (const from of src) { yield fn(from); } } /** - * The single layer flattening of an iterator, discarding `Falsey` values. + * The single layer flattening of an iterator, discarding `Falsy` values. * @param src A type that can be iterated over - * @param fn The function that returns either an iterable over items that should be filtered out or a `Falsey` value indicating that it should be ignored + * @param fn The function that returns either an iterable over items that should be filtered out or a `Falsy` value indicating that it should be ignored */ -export function* filterFlatMap(src: Iterable, fn: (from: T) => Iterable | Falsey): IterableIterator { +function* filterFlatMap(src: Iterable, fn: (from: T) => Iterable | Falsy): IterableIterator { for (const from of src) { if (!from) { continue; @@ -96,7 +96,7 @@ export function* filterFlatMap(src: Iterable, fn: (from: T) => Iterable * @param src A type that can be iterated over * @param fn A function that returns an iterator */ -export function* flatMap(src: Iterable, fn: (from: T) => Iterable): IterableIterator { +function* flatMap(src: Iterable, fn: (from: T) => Iterable): IterableIterator { for (const from of src) { yield* fn(from); } @@ -108,7 +108,7 @@ export function* flatMap(src: Iterable, fn: (from: T) => Iterable): * @param src A type that can be iterated over * @param fn The function that is called for each value */ -export function* filter(src: Iterable, fn: (from: T) => any): IterableIterator { +function* filter(src: Iterable, fn: (from: T) => any): IterableIterator { for (const from of src) { if (fn(from)) { yield from; @@ -122,7 +122,7 @@ export function* filter(src: Iterable, fn: (from: T) => any): IterableIter * @param src A type that can be iterated over * @param fn The function that is called for each value */ -export function* filterMap(src: Iterable, fn: (from: T) => U | Falsey): IterableIterator { +function* filterMap(src: Iterable, fn: (from: T) => U | Falsy): IterableIterator { for (const from of src) { const res = fn(from); @@ -138,7 +138,7 @@ export function* filterMap(src: Iterable, fn: (from: T) => U | Falsey): * @param src A type that can be iterated over * @param fn The function that is called for each value */ -export function* filterMapStrict(src: Iterable, fn: (from: T) => U | null | undefined): IterableIterator { +function* filterMapStrict(src: Iterable, fn: (from: T) => U | null | undefined): IterableIterator { for (const from of src) { const res = fn(from); @@ -154,7 +154,7 @@ export function* filterMapStrict(src: Iterable, fn: (from: T) => U | nu * @param match A function that should return a truthy value for the item that you want to find * @returns The first entry that `match` returns a truthy value for, or `undefined` */ -export function find(src: Iterable, match: (i: T) => any): T | undefined { +function find(src: Iterable, match: (i: T) => any): T | undefined { for (const from of src) { if (match(from)) { return from; @@ -166,14 +166,14 @@ export function find(src: Iterable, match: (i: T) => any): T | undefined { /** * Iterate over `src` calling `reducer` with the previous produced value and the current - * yielded value until `src` is exausted. Then return the final value. + * yielded value until `src` is exhausted. Then return the final value. * @param src The value to iterate over - * @param reducer A function for producing the next item from an accumilation and the current item + * @param reducer A function for producing the next item from an accumulation and the current item * @param initial The initial value for the iteration */ -export function reduce>(src: Iterable, reducer: (acc: R, cur: T) => R, initial: R): R; +function reduce>(src: Iterable, reducer: (acc: R, cur: T) => R, initial: R): R; -export function reduce(src: Iterable, reducer: (acc: R, cur: T) => R, initial: R): R { +function reduce(src: Iterable, reducer: (acc: R, cur: T) => R, initial: R): R { let acc = initial; for (const item of src) { @@ -189,7 +189,7 @@ export function reduce(src: Iterable, reducer: (acc: R, cur: T) => * @param connector The string value to intersperse between the yielded values * @returns The concatenated entries of `src` interspersed with copies of `connector` */ -export function join(src: IterableIterator, connector = ","): string { +function join(src: IterableIterator, connector = ","): string { const iterSrc = src[Symbol.iterator](); const first = iterSrc.next(); @@ -205,7 +205,7 @@ export function join(src: IterableIterator, connector = ","): string { * @param src The value to iterate over * @param n The zero-index value for the item to return to. */ -export function nth(src: Iterable, n: number): T | undefined { +function nth(src: Iterable, n: number): T | undefined { const iterator = src[Symbol.iterator](); while (n --> 0) { @@ -219,17 +219,17 @@ export function nth(src: Iterable, n: number): T | undefined { * A convenience function to get the first item of an iterator * @param src The value to iterate over */ -export function first(src: Iterable): T | undefined { +function first(src: Iterable): T | undefined { return nth(src, 0); } /** - * Iterate through `src` and return `true` if `fn` returns a thruthy value for every yielded value. + * Iterate through `src` and return `true` if `fn` returns a truthy value for every yielded value. * Otherwise, return `false`. This function short circuits. * @param src The type to be iterated over * @param fn A function to check each iteration */ -export function every(src: Iterable, fn: (val: T) => any): boolean { +function every(src: Iterable, fn: (val: T) => any): boolean { for (const val of src) { if (!fn(val)) { return false; @@ -239,10 +239,61 @@ export function every(src: Iterable, fn: (val: T) => any): boolean { return true; } -export function* concat(...sources: IterableIterator[]): IterableIterator { +function* concat(...sources: IterableIterator[]): IterableIterator { for (const source of sources) { for (const val of source) { yield val; } } } + +/** + * Split an iterable into several arrays with matching fields + * @param from The iterable of items to split up + * @param field The field of each item to split over + * @param parts What each array will be filtered to + * @returns A `parts.length` tuple of `T[]` where each array has matching `field` values + */ +function nFircate(from: Iterable, field: keyof T, parts: []): []; +function nFircate(from: Iterable, field: keyof T, parts: [T[typeof field]]): [T[]]; +function nFircate(from: Iterable, field: keyof T, parts: [T[typeof field], T[typeof field]]): [T[], T[]]; +function nFircate(from: Iterable, field: keyof T, parts: [T[typeof field], T[typeof field], T[typeof field]]): [T[], T[], T[]]; +function nFircate(from: Iterable, field: keyof T, parts: T[typeof field][]): T[][] { + if (new Set(parts).size !== parts.length) { + throw new TypeError("Duplicate parts entries"); + } + + const res = Array.from(parts, () => [] as T[]); + + for (const item of from) { + const index = parts.indexOf(item[field]); + + if (index < 0) { + continue; + } + + res[index].push(item); + } + + return res; +} + +export const iter = { + chain, + concat, + every, + filter, + filterFlatMap, + filterMap, + filterMapStrict, + find, + first, + flatMap, + join, + map, + nFircate, + newEmpty, + nth, + reduce, + take, +}; diff --git a/packages/utility-features/utilities/src/json.ts b/packages/utility-features/utilities/src/json.ts new file mode 100644 index 0000000000..1c8d051ac3 --- /dev/null +++ b/packages/utility-features/utilities/src/json.ts @@ -0,0 +1,22 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type { Result } from "./result"; + +export const json = { + parse: (input: string): Result => { + try { + return { + callWasSuccessful: true, + response: JSON.parse(input) as unknown, + } + } catch (error) { + return { + callWasSuccessful: false, + error: error as Error, + } + } + }, +}; diff --git a/packages/core/src/renderer/utils/__tests__/jsonPath.test.ts b/packages/utility-features/utilities/src/jsonPath.test.ts similarity index 99% rename from packages/core/src/renderer/utils/__tests__/jsonPath.test.ts rename to packages/utility-features/utilities/src/jsonPath.test.ts index 312522a63f..ecf0b385da 100644 --- a/packages/core/src/renderer/utils/__tests__/jsonPath.test.ts +++ b/packages/utility-features/utilities/src/jsonPath.test.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { convertKubectlJsonPathToNodeJsonPath, safeJSONPathValue } from "../jsonPath"; +import { convertKubectlJsonPathToNodeJsonPath, safeJSONPathValue } from "./jsonPath"; describe("convertKubectlJsonPathToNodeJsonPath", () => { it("should convert \\. to use indexed notation", () => { diff --git a/packages/core/src/renderer/utils/jsonPath.ts b/packages/utility-features/utilities/src/jsonPath.ts similarity index 100% rename from packages/core/src/renderer/utils/jsonPath.ts rename to packages/utility-features/utilities/src/jsonPath.ts diff --git a/packages/core/src/renderer/utils/__tests__/metricUnitsToNumber.test.ts b/packages/utility-features/utilities/src/metricUnitsToNumber.test.ts similarity index 89% rename from packages/core/src/renderer/utils/__tests__/metricUnitsToNumber.test.ts rename to packages/utility-features/utilities/src/metricUnitsToNumber.test.ts index e6c2795eb0..5ef7328930 100644 --- a/packages/core/src/renderer/utils/__tests__/metricUnitsToNumber.test.ts +++ b/packages/utility-features/utilities/src/metricUnitsToNumber.test.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { metricUnitsToNumber } from "../metricUnitsToNumber"; +import { metricUnitsToNumber } from "./metricUnitsToNumber"; describe("metricUnitsToNumber tests", () => { test("plain number", () => { diff --git a/packages/core/src/renderer/utils/metricUnitsToNumber.ts b/packages/utility-features/utilities/src/metricUnitsToNumber.ts similarity index 100% rename from packages/core/src/renderer/utils/metricUnitsToNumber.ts rename to packages/utility-features/utilities/src/metricUnitsToNumber.ts diff --git a/packages/core/src/renderer/utils/name-parts.ts b/packages/utility-features/utilities/src/name-parts.ts similarity index 100% rename from packages/core/src/renderer/utils/name-parts.ts rename to packages/utility-features/utilities/src/name-parts.ts diff --git a/packages/core/src/common/utils/noop.ts b/packages/utility-features/utilities/src/noop.ts similarity index 99% rename from packages/core/src/common/utils/noop.ts rename to packages/utility-features/utilities/src/noop.ts index a9171f2618..b985da1930 100644 --- a/packages/core/src/common/utils/noop.ts +++ b/packages/utility-features/utilities/src/noop.ts @@ -2,9 +2,11 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ + /** * A function that does nothing */ export function noop(...args: T): void { return void args; } + diff --git a/packages/utility-features/utilities/src/object.ts b/packages/utility-features/utilities/src/object.ts new file mode 100644 index 0000000000..51cdfd3904 --- /dev/null +++ b/packages/utility-features/utilities/src/object.ts @@ -0,0 +1,34 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +/** + * A better typed version of `Object.fromEntries` where the keys are known to + * be a specific subset + */ +function fromEntries(entries: Iterable): Record { + return Object.fromEntries(entries) as Record; +} + +function keys(obj: Partial>): K[]; +function keys(obj: Record): K[] { + return Object.keys(obj) as K[]; +} + +function entries(obj: Partial> | null | undefined): [K, V][]; +function entries(obj: Partial> | null | undefined): [K, V][]; +function entries(obj: Record | null | undefined): [K, V][]; +function entries(obj: Record | null | undefined): [K, V][] { + if (obj && typeof obj == "object") { + return Object.entries(obj) as never; + } + + return [] as never; +} + +export const object = { + entries, + fromEntries, + keys, +}; diff --git a/packages/core/src/common/utils/observable-crate/observable-crate.test.ts b/packages/utility-features/utilities/src/observable-crate.test.ts similarity index 96% rename from packages/core/src/common/utils/observable-crate/observable-crate.test.ts rename to packages/utility-features/utilities/src/observable-crate.test.ts index 03ee2e43f8..acadb804cc 100644 --- a/packages/core/src/common/utils/observable-crate/observable-crate.test.ts +++ b/packages/utility-features/utilities/src/observable-crate.test.ts @@ -3,8 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { ObservableCrate } from "./impl"; -import { observableCrate } from "./impl"; +import type { ObservableCrate } from "./observable-crate"; +import { observableCrate } from "./observable-crate"; describe("observable-crate", () => { it("can be constructed with initial value", () => { diff --git a/packages/core/src/common/utils/observable-crate/impl.ts b/packages/utility-features/utilities/src/observable-crate.ts similarity index 93% rename from packages/core/src/common/utils/observable-crate/impl.ts rename to packages/utility-features/utilities/src/observable-crate.ts index e9874c9b7d..d7cd1b75bb 100644 --- a/packages/core/src/common/utils/observable-crate/impl.ts +++ b/packages/utility-features/utilities/src/observable-crate.ts @@ -4,8 +4,8 @@ */ import { observable, runInAction } from "mobx"; -import { getOrInsertMap } from "../collection-functions"; -import { noop } from "../noop"; +import { getOrInsertMap } from "./collection-functions"; +import { noop } from "./noop"; export interface ObservableCrate { get(): T; diff --git a/packages/core/src/renderer/utils/on-keyboard-shortcut.ts b/packages/utility-features/utilities/src/on-keyboard-shortcut.ts similarity index 91% rename from packages/core/src/renderer/utils/on-keyboard-shortcut.ts rename to packages/utility-features/utilities/src/on-keyboard-shortcut.ts index 4504765ac7..443df8e5f0 100644 --- a/packages/core/src/renderer/utils/on-keyboard-shortcut.ts +++ b/packages/utility-features/utilities/src/on-keyboard-shortcut.ts @@ -3,8 +3,6 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { WindowEventListener } from "../window/event-listener.injectable"; - function parseKeyDownDescriptor(descriptor: string): (event: KeyboardEvent) => boolean { const parts = new Set(( descriptor @@ -43,7 +41,7 @@ function parseKeyDownDescriptor(descriptor: string): (event: KeyboardEvent) => b }; } -export function onKeyboardShortcut(descriptor: string, action: () => void): WindowEventListener<"keydown"> { +export function onKeyboardShortcut(descriptor: string, action: () => void): (this: Window, ev: WindowEventMap["keydown"]) => any { const isMatchingEvent = parseKeyDownDescriptor(descriptor); return (event) => { diff --git a/packages/core/src/renderer/utils/prevDefault.ts b/packages/utility-features/utilities/src/prevDefault.ts similarity index 100% rename from packages/core/src/renderer/utils/prevDefault.ts rename to packages/utility-features/utilities/src/prevDefault.ts diff --git a/packages/core/src/common/utils/readableStream.ts b/packages/utility-features/utilities/src/readableStream.ts similarity index 100% rename from packages/core/src/common/utils/readableStream.ts rename to packages/utility-features/utilities/src/readableStream.ts diff --git a/packages/core/src/common/utils/readonly.ts b/packages/utility-features/utilities/src/readonly.ts similarity index 100% rename from packages/core/src/common/utils/readonly.ts rename to packages/utility-features/utilities/src/readonly.ts diff --git a/packages/core/src/common/utils/reject-promise.ts b/packages/utility-features/utilities/src/reject-promise.ts similarity index 100% rename from packages/core/src/common/utils/reject-promise.ts rename to packages/utility-features/utilities/src/reject-promise.ts diff --git a/packages/core/src/common/utils/async-result.ts b/packages/utility-features/utilities/src/result.ts similarity index 51% rename from packages/core/src/common/utils/async-result.ts rename to packages/utility-features/utilities/src/result.ts index 69927f3275..b0153d46d4 100644 --- a/packages/core/src/common/utils/async-result.ts +++ b/packages/utility-features/utilities/src/result.ts @@ -2,7 +2,17 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -export type AsyncResult = + +/** + * A helper type for async functions that return a `Result` + */ +export type AsyncResult = Promise>; + +/** + * Result describes the "error is just more data" pattern instead of using exceptions for + * normal execution + */ +export type Result = | ( Response extends void ? { callWasSuccessful: true; response?: undefined } diff --git a/packages/core/src/common/utils/sort-compare.ts b/packages/utility-features/utilities/src/sort-compare.ts similarity index 92% rename from packages/core/src/common/utils/sort-compare.ts rename to packages/utility-features/utilities/src/sort-compare.ts index 35d88c01b9..69d77660e4 100644 --- a/packages/core/src/common/utils/sort-compare.ts +++ b/packages/utility-features/utilities/src/sort-compare.ts @@ -46,12 +46,12 @@ export function sortCompare(left: T, right: T): Ordering { } /** - * This function sorts of list of items that have what should be a semver version formated string - * as the field `version` but if it is not loosely coercable to semver falls back to sorting them + * This function sorts of list of items that have what should be a semver version formatted string + * as the field `version` but if it is not loosely coercible to semver falls back to sorting them * alphanumerically */ -export function sortBySemverVersion(versioneds: T[]): T[] { - return versioneds +export function sortBySemverVersion(versioned: T[]): T[] { + return versioned .map(versioned => ({ __version: coerce(versioned.version, { loose: true }), raw: versioned, diff --git a/packages/core/src/common/utils/sort-function.ts b/packages/utility-features/utilities/src/sort-function.ts similarity index 100% rename from packages/core/src/common/utils/sort-function.ts rename to packages/utility-features/utilities/src/sort-function.ts diff --git a/packages/core/src/common/utils/__tests__/splitArray.test.ts b/packages/utility-features/utilities/src/splitArray.test.ts similarity index 100% rename from packages/core/src/common/utils/__tests__/splitArray.test.ts rename to packages/utility-features/utilities/src/splitArray.test.ts diff --git a/packages/core/src/common/utils/tar.ts b/packages/utility-features/utilities/src/tar.ts similarity index 94% rename from packages/core/src/common/utils/tar.ts rename to packages/utility-features/utilities/src/tar.ts index 3102098976..701cd66fd8 100644 --- a/packages/core/src/common/utils/tar.ts +++ b/packages/utility-features/utilities/src/tar.ts @@ -7,7 +7,6 @@ // Docs: https://github.com/npm/node-tar import tar from "tar"; import path from "path"; -import { parse } from "./json"; import type { JsonValue } from "type-fest"; export type ReadFileFromTarOpts = { @@ -43,7 +42,7 @@ export function readFileFromTar({ tarPath, filePath, }); entry.once("end", () => { const data = Buffer.concat(fileChunks); - const result = parseJson ? parse(data.toString("utf8")) : data; + const result = parseJson ? JSON.parse(data.toString("utf8")) : data; resolve(result); }); diff --git a/packages/core/src/common/utils/__tests__/tuple.test.ts b/packages/utility-features/utilities/src/tuple.test.ts similarity index 96% rename from packages/core/src/common/utils/__tests__/tuple.test.ts rename to packages/utility-features/utilities/src/tuple.test.ts index 73a4ae1e25..e5cdfbea23 100644 --- a/packages/core/src/common/utils/__tests__/tuple.test.ts +++ b/packages/utility-features/utilities/src/tuple.test.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { tuple } from "../../utils"; +import { tuple } from "./tuple"; describe("tuple tests", () => { describe("zip()", () => { diff --git a/packages/core/src/common/utils/tuple.ts b/packages/utility-features/utilities/src/tuple.ts similarity index 71% rename from packages/core/src/common/utils/tuple.ts rename to packages/utility-features/utilities/src/tuple.ts index 1268678617..ca6284b681 100644 --- a/packages/core/src/common/utils/tuple.ts +++ b/packages/utility-features/utilities/src/tuple.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import * as array from "../utils/array"; +import { array } from "./array"; /** * A strict N-tuple of type T @@ -24,11 +24,10 @@ type TupleOfImpl = R["length"] extends * @yields A tuple of the next element from each of the sources * @returns The tuple of all the sources as soon as at least one of the sources is exausted */ -export function zip(...sources: Tuple): Iterator, Tuple>; -export function zip(...sources: Tuple): Iterator, Tuple>; -export function zip(...sources: Tuple): Iterator, Tuple>; - -export function* zip(...sources: Tuple): Iterator, Tuple> { +function zip(...sources: Tuple): Iterator, Tuple>; +function zip(...sources: Tuple): Iterator, Tuple>; +function zip(...sources: Tuple): Iterator, Tuple>; +function* zip(...sources: Tuple): Iterator, Tuple> { const maxSafeLength = Math.min(...sources.map(source => source.length)); for (let i = 0; i < maxSafeLength; i += 1) { @@ -43,13 +42,19 @@ export function* zip(...sources: Tuple): Iterator(length: L, value: T): Tuple { +function filled(length: L, value: T): Tuple { return array.filled(length, value) as Tuple; } /** * A function for converting an explicit array to a tuple but without the `readonly` typing */ -export function from(...args: T): [...T] { +function from(...args: T): [...T] { return args; } + +export const tuple = { + zip, + filled, + from, +}; diff --git a/packages/core/src/common/utils/type-narrowing.ts b/packages/utility-features/utilities/src/type-narrowing.ts similarity index 100% rename from packages/core/src/common/utils/type-narrowing.ts rename to packages/utility-features/utilities/src/type-narrowing.ts diff --git a/packages/core/src/common/utils/types.ts b/packages/utility-features/utilities/src/types.ts similarity index 93% rename from packages/core/src/common/utils/types.ts rename to packages/utility-features/utilities/src/types.ts index 32ebe14e33..25d665b811 100644 --- a/packages/core/src/common/utils/types.ts +++ b/packages/utility-features/utilities/src/types.ts @@ -14,7 +14,7 @@ export type RemoveUndefinedFromValues = { */ export type Defaulted = RemoveUndefinedFromValues>> & Omit; -export type OptionVarient = { +export type OptionVariant = { type: Key; } & Pick & { [OtherKey in Exclude]?: undefined; diff --git a/packages/core/src/common/utils/__tests__/union-env-path.test.ts b/packages/utility-features/utilities/src/union-env-path.test.ts similarity index 100% rename from packages/core/src/common/utils/__tests__/union-env-path.test.ts rename to packages/utility-features/utilities/src/union-env-path.test.ts diff --git a/packages/core/src/common/utils/union-env-path.ts b/packages/utility-features/utilities/src/union-env-path.ts similarity index 86% rename from packages/core/src/common/utils/union-env-path.ts rename to packages/utility-features/utilities/src/union-env-path.ts index 991e2c776c..ad41d049bc 100644 --- a/packages/core/src/common/utils/union-env-path.ts +++ b/packages/utility-features/utilities/src/union-env-path.ts @@ -4,10 +4,10 @@ */ import path from "path"; -import * as iter from "./iter"; +import { iter } from "./iter"; /** - * Join all entires with a PATH env var delimated string together + * Join all entires with a PATH env var delimited string together * @param PATHs Any number of PATH env variables * * NOTE: This function does not attempt to handle any sort of escape sequences since after testing diff --git a/packages/core/src/common/utils/wait.ts b/packages/utility-features/utilities/src/wait.ts similarity index 100% rename from packages/core/src/common/utils/wait.ts rename to packages/utility-features/utilities/src/wait.ts diff --git a/packages/core/src/common/utils/with-concurrency-limit.ts b/packages/utility-features/utilities/src/with-concurrency-limit.ts similarity index 86% rename from packages/core/src/common/utils/with-concurrency-limit.ts rename to packages/utility-features/utilities/src/with-concurrency-limit.ts index 284bb334e1..43c083c2dd 100644 --- a/packages/core/src/common/utils/with-concurrency-limit.ts +++ b/packages/utility-features/utilities/src/with-concurrency-limit.ts @@ -2,12 +2,12 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import plimit from "p-limit"; +import pLimit from "p-limit"; export type ConcurrencyLimiter = (fn: (...args: Args) => Res) => (...args: Args) => Promise; export function withConcurrencyLimit(limit: number): ConcurrencyLimiter { - const limiter = plimit(limit); + const limiter = pLimit(limit); return fn => (...args) => limiter(() => fn(...args)); } diff --git a/packages/utility-features/utilities/tsconfig.json b/packages/utility-features/utilities/tsconfig.json new file mode 100644 index 0000000000..a4f6fa613e --- /dev/null +++ b/packages/utility-features/utilities/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "@k8slens/typescript/config/base.json" +} diff --git a/packages/utility-features/utilities/webpack.config.js b/packages/utility-features/utilities/webpack.config.js new file mode 100644 index 0000000000..3183f30179 --- /dev/null +++ b/packages/utility-features/utilities/webpack.config.js @@ -0,0 +1 @@ +module.exports = require("@k8slens/webpack").configForNode;