From bd5aace104574486cea093e026168f61e49c6cef Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Fri, 16 Jul 2021 09:14:05 -0400 Subject: [PATCH] Ban circular dependencies Signed-off-by: Sebastian Malton --- .eslintrc.js | 18 +- Makefile | 2 +- extensions/.eslintrc.js | 36 ++ .../package-lock.json | 9 +- .../metrics-cluster-feature/package-lock.json | 9 +- extensions/node-menu/package-lock.json | 9 +- extensions/pod-menu/package-lock.json | 9 +- package.json | 8 +- src/common/__tests__/cluster-store.test.ts | 5 +- .../catalog-entities/kubernetes-cluster.ts | 3 +- src/common/hotbar-store.ts | 59 +-- src/common/hotbar-types.ts | 52 +++ src/common/rbac.ts | 18 - src/common/user-store/preferences-helpers.ts | 8 +- src/common/user-store/user-store.ts | 3 +- src/common/utils/allowed-resource.ts | 39 ++ src/common/utils/index.ts | 7 +- src/extensions/renderer-api/components.ts | 10 +- src/extensions/renderer-api/k8s-api.ts | 2 +- src/extensions/renderer-api/navigation.ts | 2 +- .../cluster-detectors/detector-registry.ts | 19 +- .../cluster-detectors/version-detector.ts | 2 +- src/main/cluster.ts | 8 +- src/main/helm/helm-release-manager.ts | 2 +- src/main/index.ts | 25 +- .../cluster-metadata-detectors.ts | 36 ++ src/main/initializers/index.ts | 1 + src/main/k8s-request.ts | 2 +- src/main/kubeconfig-manager.ts | 2 +- src/main/{proxy => }/lens-proxy.ts | 113 ++--- src/main/proxy-functions/index.ts | 24 ++ src/main/proxy-functions/kube-api-request.ts | 80 ++++ .../shell-api-request.ts} | 26 +- src/main/proxy-functions/types.ts | 29 ++ src/main/resource-applier.ts | 2 +- src/main/routes/metrics-route.ts | 2 +- src/main/window-manager.ts | 14 +- src/migrations/hotbar-store/5.0.0-alpha.0.ts | 13 +- src/migrations/hotbar-store/5.0.0-alpha.2.ts | 2 +- src/migrations/hotbar-store/5.0.0-beta.10.ts | 20 +- src/migrations/hotbar-store/5.0.0-beta.5.ts | 4 +- .../__tests__/catalog-entity-registry.test.ts | 1 - src/renderer/api/api-manager.ts | 42 +- .../api/endpoints/resource-applier.api.ts | 20 +- src/renderer/api/kube-api-parse.ts | 41 -- src/renderer/api/kube-api.ts | 5 - src/renderer/api/kube-object.ts | 4 +- .../components/+add-cluster/add-cluster.tsx | 5 +- .../+apps-releases/release-details.tsx | 2 +- .../components/+cluster/cluster-issues.tsx | 6 +- .../+config-autoscalers/hpa-details.tsx | 11 +- .../components/+config-autoscalers/hpa.tsx | 2 +- .../limit-range-details.tsx | 4 +- .../+config-limit-ranges/limit-ranges.tsx | 2 +- .../+config-maps/config-map-details.tsx | 4 +- .../components/+config-maps/config-maps.tsx | 2 +- .../pod-disruption-budgets-details.tsx | 4 +- .../pod-disruption-budgets.tsx | 3 +- .../resource-quota-details.tsx | 4 +- .../resource-quotas.tsx | 2 +- .../+config-secrets/add-secret-dialog.tsx | 2 +- .../+config-secrets/secret-details.tsx | 4 +- .../components/+config-secrets/secrets.tsx | 2 +- src/renderer/components/+config/config.tsx | 2 +- .../+custom-resources/crd-details.tsx | 4 +- .../components/+custom-resources/crd-list.tsx | 4 +- .../crd-resource-details.tsx | 4 +- .../+custom-resources/crd-resources.tsx | 2 +- .../components/+events/event-details.tsx | 9 +- src/renderer/components/+events/events.tsx | 9 +- .../+namespaces/namespace-details.tsx | 7 +- .../components/+namespaces/namespaces.tsx | 2 +- .../+network-endpoints/endpoint-details.tsx | 4 +- .../endpoint-subset-list.tsx | 6 +- .../+network-endpoints/endpoints.tsx | 2 +- .../+network-ingresses/ingress-details.tsx | 4 +- .../+network-ingresses/ingresses.tsx | 2 +- .../+network-policies/network-policies.tsx | 2 +- .../network-policy-details.tsx | 4 +- .../service-details-endpoint.tsx | 2 +- .../+network-services/service-details.tsx | 4 +- .../components/+network-services/services.tsx | 2 +- src/renderer/components/+network/network.tsx | 2 +- .../components/+nodes/node-details.tsx | 4 +- src/renderer/components/+nodes/nodes.tsx | 2 +- .../pod-security-policies.tsx | 2 +- .../pod-security-policy-details.tsx | 4 +- .../components/+preferences/preferences.tsx | 3 +- .../storage-class-details.tsx | 4 +- .../+storage-classes/storage-classes.tsx | 2 +- .../volume-claim-details.tsx | 4 +- .../+storage-volume-claims/volume-claims.tsx | 3 +- .../+storage-volumes/volume-details-list.tsx | 2 +- .../+storage-volumes/volume-details.tsx | 5 +- .../components/+storage-volumes/volumes.tsx | 3 +- src/renderer/components/+storage/storage.tsx | 2 +- .../+cluster-role-bindings/details.tsx | 4 +- .../+cluster-role-bindings/dialog.tsx | 6 +- .../+cluster-role-bindings/view.tsx | 2 +- .../+cluster-roles/add-dialog.tsx | 2 +- .../+cluster-roles/details.tsx | 4 +- .../+user-management/+cluster-roles/view.tsx | 2 +- .../+role-bindings/details.tsx | 4 +- .../+role-bindings/dialog.tsx | 2 +- .../+user-management/+role-bindings/view.tsx | 2 +- .../+user-management/+roles/add-dialog.tsx | 4 +- .../+user-management/+roles/details.tsx | 4 +- .../+user-management/+roles/view.tsx | 2 +- .../+service-accounts/create-dialog.tsx | 2 +- .../+service-accounts/details.tsx | 5 +- .../+service-accounts/view.tsx | 4 +- .../+user-management/user-management.tsx | 2 +- .../+workloads-cronjobs/cronjob-details.tsx | 5 +- .../+workloads-cronjobs/cronjobs.tsx | 4 +- .../daemonset-details.tsx | 6 +- .../+workloads-daemonsets/daemonsets.tsx | 2 +- .../deployment-details.tsx | 6 +- .../deployment-replicasets.tsx | 4 +- .../+workloads-deployments/deployments.tsx | 4 +- .../+workloads-jobs/job-details.tsx | 11 +- .../components/+workloads-jobs/jobs.tsx | 2 +- .../+workloads-overview/overview-statuses.tsx | 3 +- .../+workloads-pods/pod-details-list.tsx | 2 +- .../+workloads-pods/pod-details-secrets.tsx | 2 +- .../+workloads-pods/pod-details.tsx | 5 +- .../components/+workloads-pods/pods.tsx | 7 +- .../replicaset-details.tsx | 6 +- .../+workloads-replicasets/replicasets.tsx | 4 +- .../statefulset-details.tsx | 6 +- .../+workloads-statefulsets/statefulsets.tsx | 4 +- .../components/+workloads/workloads.tsx | 2 +- src/renderer/components/app.tsx | 4 +- .../components/cluster-node-shell-setting.tsx | 2 +- .../command-palette/command-container.tsx | 45 +- .../command-palette/command-dialog.tsx | 2 +- .../command-palette/command-overlay.ts | 44 ++ .../components/command-palette/index.ts | 1 + src/renderer/components/context.ts | 4 +- .../components/dock/create-resource.tsx | 13 +- src/renderer/components/dock/dock.store.ts | 1 + .../components/hotbar/hotbar-menu.tsx | 3 +- .../components/hotbar/hotbar-selector.tsx | 3 +- .../components/kube-details}/index.ts | 5 +- .../components/kube-details/params.ts | 67 +++ .../components/kube-object-details/index.ts | 22 + .../kube-object-details.scss | 0 .../kube-object-details.tsx | 53 +-- .../index.ts | 3 - .../kube-object-list-layout.tsx | 4 +- .../components/kube-object-menu/index.ts | 22 + .../kube-object-menu.tsx | 10 +- .../components/kube-object-meta/index.ts | 22 + .../kube-object-meta.tsx | 6 +- src/renderer/components/layout/sidebar.tsx | 2 +- src/renderer/components/menu/menu-actions.tsx | 2 +- src/renderer/components/table/react-table.tsx | 3 +- .../kube-object-detail-registry.tsx | 5 +- .../workloads-overview-detail-registry.tsx | 2 +- src/renderer/kube-object.store.ts | 3 +- src/renderer/utils/createStorage.ts | 11 - src/renderer/utils/storageHelper.ts | 2 +- yarn.lock | 392 +++++++++++++----- 162 files changed, 1188 insertions(+), 729 deletions(-) create mode 100644 extensions/.eslintrc.js create mode 100644 src/common/hotbar-types.ts create mode 100644 src/common/utils/allowed-resource.ts create mode 100644 src/main/initializers/cluster-metadata-detectors.ts rename src/main/{proxy => }/lens-proxy.ts (61%) create mode 100644 src/main/proxy-functions/index.ts create mode 100644 src/main/proxy-functions/kube-api-request.ts rename src/main/{proxy/ws-upgrade.ts => proxy-functions/shell-api-request.ts} (75%) create mode 100644 src/main/proxy-functions/types.ts create mode 100644 src/renderer/components/command-palette/command-overlay.ts rename src/{main/proxy => renderer/components/kube-details}/index.ts (92%) create mode 100644 src/renderer/components/kube-details/params.ts create mode 100644 src/renderer/components/kube-object-details/index.ts rename src/renderer/components/{kube-object => kube-object-details}/kube-object-details.scss (100%) rename src/renderer/components/{kube-object => kube-object-details}/kube-object-details.tsx (73%) rename src/renderer/components/{kube-object => kube-object-list-layout}/index.ts (91%) rename src/renderer/components/{kube-object => kube-object-list-layout}/kube-object-list-layout.tsx (96%) create mode 100644 src/renderer/components/kube-object-menu/index.ts rename src/renderer/components/{kube-object => kube-object-menu}/kube-object-menu.tsx (93%) create mode 100644 src/renderer/components/kube-object-meta/index.ts rename src/renderer/components/{kube-object => kube-object-meta}/kube-object-meta.tsx (95%) diff --git a/.eslintrc.js b/.eslintrc.js index 7ef30d22ff..59dfda2eee 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -20,12 +20,14 @@ */ const packageJson = require("./package.json"); +const isInVscode = Boolean(process.env.VSCODE_PID); module.exports = { ignorePatterns: [ "**/node_modules/**/*", "**/dist/**/*", "**/static/**/*", + "**/site/**/*", ], settings: { react: { @@ -94,6 +96,8 @@ module.exports = { parser: "@typescript-eslint/parser", extends: [ "plugin:@typescript-eslint/recommended", + "plugin:import/recommended", + "plugin:import/typescript", ], plugins: [ "header", @@ -114,6 +118,10 @@ module.exports = { "@typescript-eslint/ban-ts-comment": "off", "@typescript-eslint/no-empty-interface": "off", "@typescript-eslint/no-unused-vars": "off", + "import/no-cycle": [2, { + ignoreExternal: true, + maxDepth: isInVscode ? 10 : undefined, // This should speed up VScode locally + }], "unused-imports/no-unused-imports-ts": "error", "unused-imports/no-unused-vars-ts": [ "warn", { @@ -129,7 +137,6 @@ module.exports = { "avoidEscape": true, "allowTemplateLiterals": true, }], - "react/prop-types": "off", "semi": "off", "@typescript-eslint/semi": ["error"], "linebreak-style": ["error", "unix"], @@ -160,6 +167,8 @@ module.exports = { extends: [ "plugin:@typescript-eslint/recommended", "plugin:react/recommended", + "plugin:import/recommended", + "plugin:import/typescript", ], parserOptions: { ecmaVersion: 2018, @@ -168,6 +177,7 @@ module.exports = { }, rules: { "header/header": [2, "./license-header"], + "react/prop-types": "off", "no-invalid-this": "off", "@typescript-eslint/no-invalid-this": ["error"], "@typescript-eslint/explicit-function-return-type": "off", @@ -182,6 +192,11 @@ module.exports = { "@typescript-eslint/no-empty-function": "off", "react/display-name": "off", "@typescript-eslint/no-unused-vars": "off", + "import/no-cycle": [2, { + ignoreExternal: true, + // The following should speed up VScode but running `yarn lint` manually or in CI will still completely ban it + maxDepth: isInVscode ? 10 : undefined, + }], "unused-imports/no-unused-imports-ts": "error", "unused-imports/no-unused-vars-ts": [ "warn", { @@ -197,7 +212,6 @@ module.exports = { "avoidEscape": true, "allowTemplateLiterals": true, }], - "react/prop-types": "off", "semi": "off", "@typescript-eslint/semi": ["error"], "linebreak-style": ["error", "unix"], diff --git a/Makefile b/Makefile index 1a8baf0d37..aa5c761ad2 100644 --- a/Makefile +++ b/Makefile @@ -35,7 +35,7 @@ dev: binaries/client build-extensions static/build/LensDev.html yarn dev .PHONY: lint -lint: +lint: node_modules yarn lint .PHONY: release-version diff --git a/extensions/.eslintrc.js b/extensions/.eslintrc.js new file mode 100644 index 0000000000..40763866cc --- /dev/null +++ b/extensions/.eslintrc.js @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +module.exports = { + "overrides": [ + { + files: [ + "**/*.ts", + "**/*.tsx", + ], + rules: { + "import/no-unresolved": ["error", { + ignore: ["@k8slens/extensions"] + }], + } + } + ] +}; diff --git a/extensions/kube-object-event-status/package-lock.json b/extensions/kube-object-event-status/package-lock.json index f3b0fe6669..a2c8fd6490 100644 --- a/extensions/kube-object-event-status/package-lock.json +++ b/extensions/kube-object-event-status/package-lock.json @@ -11,7 +11,8 @@ "@material-ui/core": "*", "@types/node": "*", "@types/react-select": "*", - "conf": "^7.0.1" + "conf": "^7.0.1", + "typed-emitter": "^1.3.1" }, "dependencies": { "@babel/runtime": { @@ -675,6 +676,12 @@ "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", "dev": true }, + "typed-emitter": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-1.3.1.tgz", + "integrity": "sha512-2h7utWyXgd2R2u2IuL8B4yu1gqMxbgUj2VS/MGVbFhEVQNJKXoQQoS5CBMh+eW31zFeSmDfEQ3qQf4xy5SlPVQ==", + "dev": true + }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", diff --git a/extensions/metrics-cluster-feature/package-lock.json b/extensions/metrics-cluster-feature/package-lock.json index 15feb302b8..bb3d653b3d 100644 --- a/extensions/metrics-cluster-feature/package-lock.json +++ b/extensions/metrics-cluster-feature/package-lock.json @@ -665,7 +665,8 @@ "@material-ui/core": "*", "@types/node": "*", "@types/react-select": "*", - "conf": "^7.0.1" + "conf": "^7.0.1", + "typed-emitter": "^1.3.1" }, "dependencies": { "@babel/runtime": { @@ -1329,6 +1330,12 @@ "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", "dev": true }, + "typed-emitter": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-1.3.1.tgz", + "integrity": "sha512-2h7utWyXgd2R2u2IuL8B4yu1gqMxbgUj2VS/MGVbFhEVQNJKXoQQoS5CBMh+eW31zFeSmDfEQ3qQf4xy5SlPVQ==", + "dev": true + }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", diff --git a/extensions/node-menu/package-lock.json b/extensions/node-menu/package-lock.json index 3ca2677ed4..f49204c83c 100644 --- a/extensions/node-menu/package-lock.json +++ b/extensions/node-menu/package-lock.json @@ -631,7 +631,8 @@ "@material-ui/core": "*", "@types/node": "*", "@types/react-select": "*", - "conf": "^7.0.1" + "conf": "^7.0.1", + "typed-emitter": "^1.3.1" }, "dependencies": { "@babel/runtime": { @@ -1295,6 +1296,12 @@ "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", "dev": true }, + "typed-emitter": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-1.3.1.tgz", + "integrity": "sha512-2h7utWyXgd2R2u2IuL8B4yu1gqMxbgUj2VS/MGVbFhEVQNJKXoQQoS5CBMh+eW31zFeSmDfEQ3qQf4xy5SlPVQ==", + "dev": true + }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", diff --git a/extensions/pod-menu/package-lock.json b/extensions/pod-menu/package-lock.json index 70154d1055..745ae4e19b 100644 --- a/extensions/pod-menu/package-lock.json +++ b/extensions/pod-menu/package-lock.json @@ -631,7 +631,8 @@ "@material-ui/core": "*", "@types/node": "*", "@types/react-select": "*", - "conf": "^7.0.1" + "conf": "^7.0.1", + "typed-emitter": "^1.3.1" }, "dependencies": { "@babel/runtime": { @@ -1248,6 +1249,12 @@ "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", "dev": true }, + "typed-emitter": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-1.3.1.tgz", + "integrity": "sha512-2h7utWyXgd2R2u2IuL8B4yu1gqMxbgUj2VS/MGVbFhEVQNJKXoQQoS5CBMh+eW31zFeSmDfEQ3qQf4xy5SlPVQ==", + "dev": true + }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", diff --git a/package.json b/package.json index ee1bcfc09f..a89fdfa0d6 100644 --- a/package.json +++ b/package.json @@ -63,8 +63,7 @@ }, "moduleNameMapper": { "\\.(css|scss)$": "/__mocks__/styleMock.ts", - "\\.(svg)$": "/__mocks__/imageMock.ts", - "src/(.*)": "/__mocks__/windowMock.ts" + "\\.(svg)$": "/__mocks__/imageMock.ts" }, "modulePathIgnorePatterns": [ "/dist", @@ -309,8 +308,8 @@ "@types/webpack-dev-server": "^3.11.1", "@types/webpack-env": "^1.15.2", "@types/webpack-node-externals": "^1.7.1", - "@typescript-eslint/eslint-plugin": "^4.14.2", - "@typescript-eslint/parser": "^4.0.0", + "@typescript-eslint/eslint-plugin": "^4.28.3", + "@typescript-eslint/parser": "^4.28.3", "ace-builds": "^1.4.12", "ansi_up": "^5.0.0", "chart.js": "^2.9.3", @@ -327,6 +326,7 @@ "esbuild-loader": "^2.13.1", "eslint": "^7.7.0", "eslint-plugin-header": "^3.1.1", + "eslint-plugin-import": "^2.23.4", "eslint-plugin-react": "^7.24.0", "eslint-plugin-react-hooks": "^4.2.0", "eslint-plugin-unused-imports": "^1.0.1", diff --git a/src/common/__tests__/cluster-store.test.ts b/src/common/__tests__/cluster-store.test.ts index b90dbec8f1..5f2a958d52 100644 --- a/src/common/__tests__/cluster-store.test.ts +++ b/src/common/__tests__/cluster-store.test.ts @@ -25,10 +25,11 @@ import yaml from "js-yaml"; import path from "path"; import fse from "fs-extra"; import { Cluster } from "../../main/cluster"; -import { ClusterStore } from "../cluster-store"; import { Console } from "console"; import { stdout, stderr } from "process"; +import { ClusterStore } from "../cluster-store"; import type { ClusterId } from "../cluster-types"; +import { getCustomKubeConfigPath } from "../utils"; console = new Console(stdout, stderr); @@ -58,7 +59,7 @@ users: `; function embed(clusterId: ClusterId, contents: any): string { - const absPath = ClusterStore.getCustomKubeConfigPath(clusterId); + const absPath = getCustomKubeConfigPath(clusterId); fse.ensureDirSync(path.dirname(absPath)); fse.writeFileSync(absPath, contents, { encoding: "utf-8", mode: 0o600 }); diff --git a/src/common/catalog-entities/kubernetes-cluster.ts b/src/common/catalog-entities/kubernetes-cluster.ts index 2e8fdccf04..eca7821c62 100644 --- a/src/common/catalog-entities/kubernetes-cluster.ts +++ b/src/common/catalog-entities/kubernetes-cluster.ts @@ -20,11 +20,10 @@ */ import { catalogCategoryRegistry } from "../catalog/catalog-category-registry"; -import { CatalogEntity, CatalogEntityActionContext, CatalogEntityAddMenuContext, CatalogEntityContextMenuContext, CatalogEntityMetadata, CatalogEntityStatus } from "../catalog"; +import { CatalogEntity, CatalogEntityActionContext, CatalogEntityAddMenuContext, CatalogEntityContextMenuContext, CatalogEntityMetadata, CatalogEntityStatus, CatalogCategory, CatalogCategorySpec } from "../catalog"; import { clusterActivateHandler, clusterDeleteHandler, clusterDisconnectHandler } from "../cluster-ipc"; import { ClusterStore } from "../cluster-store"; import { requestMain } from "../ipc"; -import { CatalogCategory, CatalogCategorySpec } from "../catalog"; import { addClusterURL } from "../routes"; import { app } from "electron"; import type { CatalogEntitySpec } from "../catalog/catalog-entity"; diff --git a/src/common/hotbar-store.ts b/src/common/hotbar-store.ts index 0faa165bf7..1c6355139b 100644 --- a/src/common/hotbar-store.ts +++ b/src/common/hotbar-store.ts @@ -22,38 +22,17 @@ import { action, comparer, observable, makeObservable } from "mobx"; import { BaseStore } from "./base-store"; import migrations from "../migrations/hotbar-store"; -import * as uuid from "uuid"; import isNull from "lodash/isNull"; import { toJS } from "./utils"; import { CatalogEntity } from "./catalog"; import { catalogEntity } from "../main/catalog-sources/general"; - -export interface HotbarItem { - entity: { - uid: string; - name?: string; - source?: string; - }; - params?: { - [key: string]: string; - } -} - -export type Hotbar = Required; - -export interface HotbarCreateOptions { - id?: string; - name: string; - items?: (HotbarItem | null)[]; -} +import { Hotbar, HotbarCreateOptions, HotbarItem, getEmptyHotbar } from "./hotbar-types"; export interface HotbarStoreModel { hotbars: Hotbar[]; activeHotbarId: string; } -export const defaultHotbarCells = 12; // Number is chosen to easy hit any item with keyboard - export class HotbarStore extends BaseStore { @observable hotbars: Hotbar[] = []; @observable private _activeHotbarId: string; @@ -89,18 +68,16 @@ export class HotbarStore extends BaseStore { return this.hotbarIndex(this.activeHotbarId); } - static getInitialItems() { - return [...Array.from(Array(defaultHotbarCells).fill(null))]; - } - @action protected fromStore(data: Partial = {}) { if (!data.hotbars || !data.hotbars.length) { - this.hotbars = [{ - id: uuid.v4(), - name: "Default", - items: this.defaultHotbarInitialItems, - }]; + const hotbar = getEmptyHotbar("default"); + const { metadata: { uid, name, source } } = catalogEntity; + const initialItem = { entity: { uid, name, source } }; + + hotbar.items[0] = initialItem; + + this.hotbars = [hotbar]; } else { this.hotbars = data.hotbars; } @@ -116,16 +93,6 @@ export class HotbarStore extends BaseStore { } } - get defaultHotbarInitialItems() { - const { metadata: { uid, name, source } } = catalogEntity; - const initialItem = { entity: { uid, name, source }}; - - return [ - initialItem, - ...Array.from(Array(defaultHotbarCells - 1).fill(null)) - ]; - } - getActive() { return this.getById(this.activeHotbarId); } @@ -140,16 +107,12 @@ export class HotbarStore extends BaseStore { @action add(data: HotbarCreateOptions, { setActive = false } = {}) { - const { - id = uuid.v4(), - items = HotbarStore.getInitialItems(), - name, - } = data; + const hotbar = getEmptyHotbar(data.name, data.id); - this.hotbars.push({ id, name, items }); + this.hotbars.push(hotbar); if (setActive) { - this._activeHotbarId = id; + this._activeHotbarId = hotbar.id; } } diff --git a/src/common/hotbar-types.ts b/src/common/hotbar-types.ts new file mode 100644 index 0000000000..f8fc5a225b --- /dev/null +++ b/src/common/hotbar-types.ts @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +import * as uuid from "uuid"; +import type { Tuple } from "./utils"; + +export interface HotbarItem { + entity: { + uid: string; + name?: string; + source?: string; + }; + params?: { + [key: string]: string; + } +} + +export type Hotbar = Required; + +export interface HotbarCreateOptions { + id?: string; + name: string; + items?: Tuple; +} + +export const defaultHotbarCells = 12; // Number is chosen to easy hit any item with keyboard + +export function getEmptyHotbar(name: string, id: string = uuid.v4()): Hotbar { + return { + id, + items: Array(defaultHotbarCells).fill(null) as Tuple, + name, + }; +} diff --git a/src/common/rbac.ts b/src/common/rbac.ts index 1562d1915a..817d22b50a 100644 --- a/src/common/rbac.ts +++ b/src/common/rbac.ts @@ -19,9 +19,6 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import { ClusterStore } from "./cluster-store"; -import { getHostedClusterId } from "./utils"; - export type KubeResource = "namespaces" | "nodes" | "events" | "resourcequotas" | "services" | "limitranges" | "secrets" | "configmaps" | "ingresses" | "networkpolicies" | "persistentvolumeclaims" | "persistentvolumes" | "storageclasses" | @@ -74,18 +71,3 @@ export const apiResourceRecord: Record = { // TODO: auto-populate all resources dynamically (see: kubectl api-resources -o=wide -v=7) export const apiResources: KubeApiResource[] = Object.entries(apiResourceRecord) .map(([apiName, data]) => ({ apiName: apiName as KubeResource, ...data })); - -export function isAllowedResource(resources: KubeResource | KubeResource[]) { - if (!Array.isArray(resources)) { - resources = [resources]; - } - const { allowedResources = [] } = ClusterStore.getInstance().getById(getHostedClusterId()) || {}; - - for (const resource of resources) { - if (!allowedResources.includes(resource)) { - return false; - } - } - - return true; -} diff --git a/src/common/user-store/preferences-helpers.ts b/src/common/user-store/preferences-helpers.ts index 4363511120..9f6b775ef0 100644 --- a/src/common/user-store/preferences-helpers.ts +++ b/src/common/user-store/preferences-helpers.ts @@ -22,9 +22,11 @@ import moment from "moment-timezone"; import path from "path"; import os from "os"; -import { ThemeStore } from "../../renderer/theme.store"; +import type { ThemeId } from "../../renderer/theme.store"; import { ObservableToggleSet } from "../utils"; +export const defaultThemeName: ThemeId = "lens-dark"; + export interface KubeconfigSyncEntry extends KubeconfigSyncValue { filePath: string; } @@ -56,10 +58,10 @@ const shell: PreferenceDescription = { const colorTheme: PreferenceDescription = { fromStore(val) { - return val || ThemeStore.defaultTheme; + return val || defaultThemeName; }, toStore(val) { - if (!val || val === ThemeStore.defaultTheme) { + if (!val || val === defaultThemeName) { return undefined; } diff --git a/src/common/user-store/user-store.ts b/src/common/user-store/user-store.ts index 7121357671..216cece1bd 100644 --- a/src/common/user-store/user-store.ts +++ b/src/common/user-store/user-store.ts @@ -23,12 +23,11 @@ import { app, remote } from "electron"; import semver from "semver"; import { action, computed, observable, reaction, makeObservable } from "mobx"; import { BaseStore } from "../base-store"; -import migrations from "../../migrations/user-store"; +import migrations, { fileNameMigration } from "../../migrations/user-store"; import { getAppVersion } from "../utils/app-version"; import { kubeConfigDefaultPath } from "../kube-helpers"; import { appEventBus } from "../event-bus"; import path from "path"; -import { fileNameMigration } from "../../migrations/user-store"; import { ObservableToggleSet, toJS } from "../../renderer/utils"; import { DESCRIPTORS, KubeconfigSyncValue, UserPreferencesModel } from "./preferences-helpers"; import logger from "../../main/logger"; diff --git a/src/common/utils/allowed-resource.ts b/src/common/utils/allowed-resource.ts new file mode 100644 index 0000000000..83a3e8c03a --- /dev/null +++ b/src/common/utils/allowed-resource.ts @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +import { ClusterStore } from "../cluster-store"; +import type { KubeResource } from "../rbac"; +import { getHostedClusterId } from "./cluster-id-url-parsing"; + +export function isAllowedResource(resources: KubeResource | KubeResource[]) { + if (!Array.isArray(resources)) { + resources = [resources]; + } + const { allowedResources = [] } = ClusterStore.getInstance().getById(getHostedClusterId()) || {}; + + for (const resource of resources) { + if (!allowedResources.includes(resource)) { + return false; + } + } + + return true; +} diff --git a/src/common/utils/index.ts b/src/common/utils/index.ts index 140ceaea2c..1fa008f1c7 100644 --- a/src/common/utils/index.ts +++ b/src/common/utils/index.ts @@ -19,13 +19,13 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/** - * A function that does nothing - */ +// Common utils (main OR renderer) + export function noop(...args: T): void { return void args; } +export * from "./sort-compare"; export * from "./app-version"; export * from "./autobind"; export * from "./base64"; @@ -47,7 +47,6 @@ export * from "./openExternal"; export * from "./paths"; export * from "./reject-promise"; export * from "./singleton"; -export * from "./sort-compare"; export * from "./splitArray"; export * from "./tar"; export * from "./toggle-set"; diff --git a/src/extensions/renderer-api/components.ts b/src/extensions/renderer-api/components.ts index cb4cfd0377..b360951699 100644 --- a/src/extensions/renderer-api/components.ts +++ b/src/extensions/renderer-api/components.ts @@ -20,8 +20,6 @@ */ // layouts -export * from "../../renderer/components/layout/main-layout"; -export * from "../../renderer/components/layout/setting-layout"; export * from "../../renderer/components/layout/page-layout"; export * from "../../renderer/components/layout/wizard-layout"; export * from "../../renderer/components/layout/tab-layout"; @@ -62,10 +60,14 @@ export * from "../../renderer/components/chart/bar-chart"; export * from "../../renderer/components/chart/pie-chart"; // kube helpers -export * from "../../renderer/components/kube-object"; +export * from "../../renderer/components/kube-details"; +export * from "../../renderer/components/kube-object-details"; +export * from "../../renderer/components/kube-object-list-layout"; +export * from "../../renderer/components/kube-object-menu"; +export * from "../../renderer/components/kube-object-meta"; export * from "../../renderer/components/+events/kube-event-details"; // specific exports export * from "../../renderer/components/status-brick"; -export { terminalStore, createTerminalTab, TerminalStore } from "../../renderer/components/dock/terminal.store"; +export { terminalStore, TerminalStore, createTerminalTab } from "../../renderer/components/dock/terminal.store"; export { logTabStore } from "../../renderer/components/dock/log-tab.store"; diff --git a/src/extensions/renderer-api/k8s-api.ts b/src/extensions/renderer-api/k8s-api.ts index c579aafbb6..2c31a4036f 100644 --- a/src/extensions/renderer-api/k8s-api.ts +++ b/src/extensions/renderer-api/k8s-api.ts @@ -19,7 +19,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -export { isAllowedResource } from "../../common/rbac"; +export { isAllowedResource } from "../../common/utils/allowed-resource"; export { ResourceStack } from "../../common/k8s/resource-stack"; export { apiManager } from "../../renderer/api/api-manager"; export { KubeObjectStore } from "../../renderer/kube-object.store"; diff --git a/src/extensions/renderer-api/navigation.ts b/src/extensions/renderer-api/navigation.ts index ab4186d2da..eeb57f7c1b 100644 --- a/src/extensions/renderer-api/navigation.ts +++ b/src/extensions/renderer-api/navigation.ts @@ -23,7 +23,7 @@ import { navigation, PageParam, PageParamInit } from "../../renderer/navigation" export type { PageParamInit, PageParam } from "../../renderer/navigation/page-param"; export { navigate, isActiveRoute } from "../../renderer/navigation/helpers"; -export { hideDetails, showDetails, getDetailsUrl } from "../../renderer/components/kube-object/kube-object-details"; +export { hideDetails, showDetails, getDetailsUrl } from "../../renderer/components/kube-details"; export type { URLParams } from "../../common/utils/buildUrl"; export function createPageParam(init: PageParamInit) { diff --git a/src/main/cluster-detectors/detector-registry.ts b/src/main/cluster-detectors/detector-registry.ts index 40b4fa6949..5d3461b0bb 100644 --- a/src/main/cluster-detectors/detector-registry.ts +++ b/src/main/cluster-detectors/detector-registry.ts @@ -21,19 +21,17 @@ import { observable } from "mobx"; import type { ClusterMetadata } from "../../common/cluster-types"; +import { Singleton } from "../../common/utils"; import type { Cluster } from "../cluster"; import type { BaseClusterDetector, ClusterDetectionResult } from "./base-cluster-detector"; -import { ClusterIdDetector } from "./cluster-id-detector"; -import { DistributionDetector } from "./distribution-detector"; -import { LastSeenDetector } from "./last-seen-detector"; -import { NodesCountDetector } from "./nodes-count-detector"; -import { VersionDetector } from "./version-detector"; -export class DetectorRegistry { +export class DetectorRegistry extends Singleton { registry = observable.array([], { deep: false }); - add(detectorClass: typeof BaseClusterDetector) { + add(detectorClass: typeof BaseClusterDetector): this { this.registry.push(detectorClass); + + return this; } async detectForCluster(cluster: Cluster): Promise { @@ -63,10 +61,3 @@ export class DetectorRegistry { return metadata; } } - -export const detectorRegistry = new DetectorRegistry(); -detectorRegistry.add(ClusterIdDetector); -detectorRegistry.add(LastSeenDetector); -detectorRegistry.add(VersionDetector); -detectorRegistry.add(DistributionDetector); -detectorRegistry.add(NodesCountDetector); diff --git a/src/main/cluster-detectors/version-detector.ts b/src/main/cluster-detectors/version-detector.ts index 36d7e06dd1..2b7b76786f 100644 --- a/src/main/cluster-detectors/version-detector.ts +++ b/src/main/cluster-detectors/version-detector.ts @@ -19,8 +19,8 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import { BaseClusterDetector } from "./base-cluster-detector"; import { ClusterMetadataKey } from "../../common/cluster-types"; +import { BaseClusterDetector } from "./base-cluster-detector"; export class VersionDetector extends BaseClusterDetector { key = ClusterMetadataKey.VERSION; diff --git a/src/main/cluster.ts b/src/main/cluster.ts index ef76077a3c..ab920d762d 100644 --- a/src/main/cluster.ts +++ b/src/main/cluster.ts @@ -20,6 +20,8 @@ */ import { ipcMain } from "electron"; +import type { ClusterId, ClusterMetadata, ClusterMetricsResourceType, ClusterModel, ClusterPreferences, ClusterPrometheusPreferences, ClusterRefreshOptions, ClusterState, UpdateClusterModel } from "../common/cluster-types"; +import { ClusterStatus, ClusterMetadataKey, initialNodeShellImage } from "../common/cluster-types"; import { action, comparer, computed, makeObservable, observable, reaction, when } from "mobx"; import { broadcastMessage, ClusterListNamespaceForbiddenChannel } from "../common/ipc"; import { ContextHandler } from "./context-handler"; @@ -30,11 +32,9 @@ import { loadConfigFromFile, loadConfigFromFileSync, validateKubeConfig } from " import { apiResourceRecord, apiResources, KubeApiResource, KubeResource } from "../common/rbac"; import logger from "./logger"; import { VersionDetector } from "./cluster-detectors/version-detector"; -import { detectorRegistry } from "./cluster-detectors/detector-registry"; +import { DetectorRegistry } from "./cluster-detectors/detector-registry"; import plimit from "p-limit"; import { toJS } from "../common/utils"; -import { initialNodeShellImage } from "../common/cluster-store"; -import { ClusterState, ClusterMetadataKey, ClusterRefreshOptions, ClusterStatus, ClusterMetricsResourceType, ClusterId, ClusterMetadata, ClusterModel, ClusterPreferences, ClusterPrometheusPreferences, UpdateClusterModel } from "../common/cluster-types"; /** * Cluster @@ -405,7 +405,7 @@ export class Cluster implements ClusterModel, ClusterState { @action async refreshMetadata() { logger.info(`[CLUSTER]: refreshMetadata`, this.getMeta()); - const metadata = await detectorRegistry.detectForCluster(this); + const metadata = await DetectorRegistry.getInstance().detectForCluster(this); const existingMetadata = this.metadata; this.metadata = Object.assign(existingMetadata, metadata); diff --git a/src/main/helm/helm-release-manager.ts b/src/main/helm/helm-release-manager.ts index b8a18a1021..d629bbb328 100644 --- a/src/main/helm/helm-release-manager.ts +++ b/src/main/helm/helm-release-manager.ts @@ -19,7 +19,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import * as tempy from "tempy"; +import tempy from "tempy"; import fse from "fs-extra"; import * as yaml from "js-yaml"; import { promiseExec } from "../promise-exec"; diff --git a/src/main/index.ts b/src/main/index.ts index a5116cfdb0..b5f9e03172 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -28,7 +28,7 @@ import * as LensExtensionsMainApi from "../extensions/main-api"; import { app, autoUpdater, dialog, powerMonitor } from "electron"; import { appName, isMac, productName } from "../common/vars"; import path from "path"; -import { LensProxy } from "./proxy/lens-proxy"; +import { LensProxy } from "./lens-proxy"; import { WindowManager } from "./window-manager"; import { ClusterManager } from "./cluster-manager"; import { shellSync } from "./shell-sync"; @@ -49,7 +49,6 @@ import { pushCatalogToRenderer } from "./catalog-pusher"; import { catalogEntityRegistry } from "./catalog"; import { HelmRepoManager } from "./helm/helm-repo-manager"; import { syncGeneralEntities, syncWeblinks, KubeconfigSyncManager } from "./catalog-sources"; -import { handleWsUpgrade } from "./proxy/ws-upgrade"; import configurePackages from "../common/configure-packages"; import { PrometheusProviderRegistry } from "./prometheus"; import * as initializers from "./initializers"; @@ -60,6 +59,11 @@ import { WeblinkStore } from "../common/weblink-store"; import { ExtensionsStore } from "../extensions/extensions-store"; import { FilesystemProvisionerStore } from "./extension-filesystem"; import { SentryInit } from "../common/sentry"; +import { Router } from "./router"; +import { initMenu } from "./menu"; +import { initTray } from "./tray"; +import { DetectorRegistry } from "./cluster-detectors/detector-registry"; +import { kubeApiRequest, shellApiRequest } from "./proxy-functions"; // This has to be called before start using winton-based logger // For example, before any logger.log @@ -159,14 +163,18 @@ app.on("ready", async () => { HelmRepoManager.createInstance(); // create the instance - const lensProxy = LensProxy.createInstance( - handleWsUpgrade, - req => ClusterManager.getInstance().getClusterForRequest(req), - ); + const lensProxy = LensProxy.createInstance(new Router(), { + getClusterForRequest: req => ClusterManager.getInstance().getClusterForRequest(req), + kubeApiRequest, + shellApiRequest, + }); ClusterManager.createInstance().init(); KubeconfigSyncManager.createInstance(); + DetectorRegistry.createInstance(); + initializers.initClusterMetadataDetectors(); + try { logger.info("🔌 Starting LensProxy"); await lensProxy.listen(); @@ -204,6 +212,11 @@ app.on("ready", async () => { logger.info("🖥️ Starting WindowManager"); const windowManager = WindowManager.createInstance(); + cleanup.push( + initMenu(windowManager), + initTray(windowManager), + ); + installDeveloperTools(); if (!startHidden) { diff --git a/src/main/initializers/cluster-metadata-detectors.ts b/src/main/initializers/cluster-metadata-detectors.ts new file mode 100644 index 0000000000..e01a207cd6 --- /dev/null +++ b/src/main/initializers/cluster-metadata-detectors.ts @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +import { ClusterIdDetector } from "../cluster-detectors/cluster-id-detector"; +import { DetectorRegistry } from "../cluster-detectors/detector-registry"; +import { DistributionDetector } from "../cluster-detectors/distribution-detector"; +import { LastSeenDetector } from "../cluster-detectors/last-seen-detector"; +import { NodesCountDetector } from "../cluster-detectors/nodes-count-detector"; +import { VersionDetector } from "../cluster-detectors/version-detector"; + +export function initClusterMetadataDetectors() { + DetectorRegistry.getInstance() + .add(ClusterIdDetector) + .add(LastSeenDetector) + .add(VersionDetector) + .add(DistributionDetector) + .add(NodesCountDetector); +} diff --git a/src/main/initializers/index.ts b/src/main/initializers/index.ts index 526b61d4ed..34a5c32e34 100644 --- a/src/main/initializers/index.ts +++ b/src/main/initializers/index.ts @@ -22,3 +22,4 @@ export * from "./registries"; export * from "./metrics-providers"; export * from "./ipc"; +export * from "./cluster-metadata-detectors"; diff --git a/src/main/k8s-request.ts b/src/main/k8s-request.ts index b501bd5ce1..513860fbd9 100644 --- a/src/main/k8s-request.ts +++ b/src/main/k8s-request.ts @@ -22,7 +22,7 @@ import request, { RequestPromiseOptions } from "request-promise-native"; import { apiKubePrefix } from "../common/vars"; import type { IMetricsReqParams } from "../renderer/api/endpoints/metrics.api"; -import { LensProxy } from "./proxy/lens-proxy"; +import { LensProxy } from "./lens-proxy"; import type { Cluster } from "./cluster"; export async function k8sRequest(cluster: Cluster, path: string, options: RequestPromiseOptions = {}): Promise { diff --git a/src/main/kubeconfig-manager.ts b/src/main/kubeconfig-manager.ts index fc2e14a3cb..ab53118f60 100644 --- a/src/main/kubeconfig-manager.ts +++ b/src/main/kubeconfig-manager.ts @@ -27,7 +27,7 @@ import path from "path"; import fs from "fs-extra"; import { dumpConfigYaml } from "../common/kube-helpers"; import logger from "./logger"; -import { LensProxy } from "./proxy/lens-proxy"; +import { LensProxy } from "./lens-proxy"; export class KubeconfigManager { protected configDir = app.getPath("temp"); diff --git a/src/main/proxy/lens-proxy.ts b/src/main/lens-proxy.ts similarity index 61% rename from src/main/proxy/lens-proxy.ts rename to src/main/lens-proxy.ts index 9ffff0fd6a..6a89bbcfcd 100644 --- a/src/main/proxy/lens-proxy.ts +++ b/src/main/lens-proxy.ts @@ -19,33 +19,42 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import net from "net"; +import type net from "net"; import type http from "http"; import spdy from "spdy"; import httpProxy from "http-proxy"; -import url from "url"; -import { apiPrefix, apiKubePrefix } from "../../common/vars"; -import { Router } from "../router"; -import type { ContextHandler } from "../context-handler"; -import logger from "../logger"; -import { Singleton } from "../../common/utils"; -import type { Cluster } from "../cluster"; +import { apiPrefix, apiKubePrefix } from "../common/vars"; +import type { Router } from "./router"; +import type { ContextHandler } from "./context-handler"; +import logger from "./logger"; +import { Singleton } from "../common/utils"; +import type { Cluster } from "./cluster"; +import type { ProxyApiRequestArgs } from "./proxy-functions"; -type WSUpgradeHandler = (req: http.IncomingMessage, socket: net.Socket, head: Buffer) => void; +type GetClusterForRequest = (req: http.IncomingMessage) => Cluster | null; + +export interface LensProxyFunctions { + getClusterForRequest: GetClusterForRequest, + shellApiRequest: (args: ProxyApiRequestArgs) => void | Promise; + kubeApiRequest: (args: ProxyApiRequestArgs) => void | Promise; +} export class LensProxy extends Singleton { protected origin: string; protected proxyServer: http.Server; - protected router = new Router(); protected closed = false; protected retryCounters = new Map(); + protected proxy = this.createProxy(); + protected getClusterForRequest: GetClusterForRequest; public port: number; - constructor(handleWsUpgrade: WSUpgradeHandler, protected getClusterForRequest: (req: http.IncomingMessage) => Cluster | undefined) { + constructor(protected router: Router, functions: LensProxyFunctions) { super(); - const proxy = this.createProxy(); + const { shellApiRequest, kubeApiRequest } = functions; + + this.getClusterForRequest = functions.getClusterForRequest; this.proxyServer = spdy.createServer({ spdy: { @@ -53,17 +62,16 @@ export class LensProxy extends Singleton { protocols: ["http/1.1", "spdy/3.1"] } }, (req: http.IncomingMessage, res: http.ServerResponse) => { - this.handleRequest(proxy, req, res); + this.handleRequest(req, res); }); this.proxyServer .on("upgrade", (req: http.IncomingMessage, socket: net.Socket, head: Buffer) => { - if (req.url.startsWith(`${apiPrefix}?`)) { - handleWsUpgrade(req, socket, head); - } else { - this.handleProxyUpgrade(proxy, req, socket, head) - .catch(error => logger.error(`[LENS-PROXY]: failed to handle proxy upgrade: ${error}`)); - } + const isInternal = req.url.startsWith(`${apiPrefix}?`); + const reqHandler = isInternal ? shellApiRequest : kubeApiRequest; + + (async () => reqHandler({ req, socket, head }))() + .catch(error => logger.error(logger.error(`[LENS-PROXY]: failed to handle proxy upgrade: ${error}`))); }); } @@ -104,58 +112,6 @@ export class LensProxy extends Singleton { this.closed = true; } - protected async handleProxyUpgrade(proxy: httpProxy, req: http.IncomingMessage, socket: net.Socket, head: Buffer) { - const cluster = this.getClusterForRequest(req); - - if (cluster) { - const proxyUrl = await cluster.contextHandler.resolveAuthProxyUrl() + req.url.replace(apiKubePrefix, ""); - const apiUrl = url.parse(cluster.apiUrl); - const pUrl = url.parse(proxyUrl); - const connectOpts = { port: parseInt(pUrl.port), host: pUrl.hostname }; - const proxySocket = new net.Socket(); - - proxySocket.connect(connectOpts, () => { - proxySocket.write(`${req.method} ${pUrl.path} HTTP/1.1\r\n`); - proxySocket.write(`Host: ${apiUrl.host}\r\n`); - - for (let i = 0; i < req.rawHeaders.length; i += 2) { - const key = req.rawHeaders[i]; - - if (key !== "Host" && key !== "Authorization") { - proxySocket.write(`${req.rawHeaders[i]}: ${req.rawHeaders[i+1]}\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(); - }); - } - } - protected createProxy(): httpProxy { const proxy = httpProxy.createProxyServer(); @@ -169,10 +125,7 @@ export class LensProxy extends Singleton { if (!res.headersSent && req.url) { const url = new URL(req.url, "http://localhost"); - if (url.searchParams.has("watch")) { - res.statusCode = proxyRes.statusCode; - res.flushHeaders(); - } + if (url.searchParams.has("watch")) res.flushHeaders(); } }); @@ -181,8 +134,6 @@ export class LensProxy extends Singleton { return; } - logger.error(`[LENS-PROXY]: http proxy errored for cluster: ${error}`, { url: req.url }); - if (target) { logger.debug(`Failed proxy to target: ${JSON.stringify(target, null, 2)}`); @@ -195,7 +146,7 @@ export class LensProxy extends Singleton { logger.debug(`Retrying proxy request to url: ${reqId}`); setTimeout(() => { this.retryCounters.set(reqId, retryCount + 1); - this.handleRequest(proxy, req, res) + this.handleRequest(req, res) .catch(error => logger.error(`[LENS-PROXY]: failed to handle request on proxy error: ${error}`)); }, timeoutMs); } @@ -203,7 +154,7 @@ export class LensProxy extends Singleton { } try { - res.writeHead(500).end(`Oops, something went wrong.\n${error}`); + res.writeHead(500).end("Oops, something went wrong."); } catch (e) { logger.error(`[LENS-PROXY]: Failed to write headers: `, e); } @@ -226,7 +177,7 @@ export class LensProxy extends Singleton { return req.headers.host + req.url; } - protected async handleRequest(proxy: httpProxy, req: http.IncomingMessage, res: http.ServerResponse) { + protected async handleRequest(req: http.IncomingMessage, res: http.ServerResponse) { const cluster = this.getClusterForRequest(req); if (cluster) { @@ -237,7 +188,7 @@ export class LensProxy extends Singleton { // this should be safe because we have already validated cluster uuid res.setHeader("Access-Control-Allow-Origin", "*"); - return proxy.web(req, res, proxyTarget); + return this.proxy.web(req, res, proxyTarget); } } this.router.route(cluster, req, res); diff --git a/src/main/proxy-functions/index.ts b/src/main/proxy-functions/index.ts new file mode 100644 index 0000000000..2154d81014 --- /dev/null +++ b/src/main/proxy-functions/index.ts @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +export * from "./shell-api-request"; +export * from "./kube-api-request"; +export * from "./types"; diff --git a/src/main/proxy-functions/kube-api-request.ts b/src/main/proxy-functions/kube-api-request.ts new file mode 100644 index 0000000000..db21651899 --- /dev/null +++ b/src/main/proxy-functions/kube-api-request.ts @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +import net from "net"; +import url from "url"; +import { apiKubePrefix } from "../../common/vars"; +import { ClusterManager } from "../cluster-manager"; +import type { ProxyApiRequestArgs } from "./types"; + +export async function kubeApiRequest({ req, socket, head }: ProxyApiRequestArgs) { + const cluster = ClusterManager.getInstance().getClusterForRequest(req); + + if (!cluster) { + return; + } + + const proxyUrl = await cluster.contextHandler.resolveAuthProxyUrl() + req.url.replace(apiKubePrefix, ""); + const apiUrl = url.parse(cluster.apiUrl); + const pUrl = url.parse(proxyUrl); + const connectOpts = { port: parseInt(pUrl.port), host: pUrl.hostname }; + const proxySocket = new net.Socket(); + + proxySocket.connect(connectOpts, () => { + proxySocket.write(`${req.method} ${pUrl.path} HTTP/1.1\r\n`); + proxySocket.write(`Host: ${apiUrl.host}\r\n`); + + for (let i = 0; i < req.rawHeaders.length; i += 2) { + const key = req.rawHeaders[i]; + + if (key !== "Host" && key !== "Authorization") { + proxySocket.write(`${req.rawHeaders[i]}: ${req.rawHeaders[i + 1]}\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/src/main/proxy/ws-upgrade.ts b/src/main/proxy-functions/shell-api-request.ts similarity index 75% rename from src/main/proxy/ws-upgrade.ts rename to src/main/proxy-functions/shell-api-request.ts index 595b05430d..3edaecff81 100644 --- a/src/main/proxy/ws-upgrade.ts +++ b/src/main/proxy-functions/shell-api-request.ts @@ -19,24 +19,18 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/** - * This file is here so that the "../shell-session" import can be injected into - * LensProxy at creation time. So that the `pty.node` extension isn't loaded - * into Lens Extension webpack bundle. - */ - -import * as WebSocket from "ws"; import type http from "http"; -import type net from "net"; import url from "url"; -import { NodeShellSession, LocalShellSession } from "../shell-session"; -import { ClusterManager } from "../cluster-manager"; import logger from "../logger"; +import * as WebSocket from "ws"; +import { NodeShellSession, LocalShellSession } from "../shell-session"; +import type { ProxyApiRequestArgs } from "./types"; +import { ClusterManager } from "../cluster-manager"; -function createWsListener(): WebSocket.Server { +export function shellApiRequest({ req, socket, head }: ProxyApiRequestArgs) { const ws = new WebSocket.Server({ noServer: true }); - return ws.on("connection", ((socket: WebSocket, req: http.IncomingMessage) => { + ws.on("connection", ((socket: WebSocket, req: http.IncomingMessage) => { const cluster = ClusterManager.getInstance().getClusterForRequest(req); const nodeParam = url.parse(req.url, true).query["node"]?.toString(); const shell = nodeParam @@ -46,12 +40,8 @@ function createWsListener(): WebSocket.Server { shell.open() .catch(error => logger.error(`[SHELL-SESSION]: failed to open: ${error}`, { error })); })); -} -export async function handleWsUpgrade(req: http.IncomingMessage, socket: net.Socket, head: Buffer) { - const wsServer = createWsListener(); - - wsServer.handleUpgrade(req, socket, head, (con) => { - wsServer.emit("connection", con, req); + ws.handleUpgrade(req, socket, head, (con) => { + ws.emit("connection", con, req); }); } diff --git a/src/main/proxy-functions/types.ts b/src/main/proxy-functions/types.ts new file mode 100644 index 0000000000..57d3db1b7c --- /dev/null +++ b/src/main/proxy-functions/types.ts @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +import type http from "http"; +import type net from "net"; + +export interface ProxyApiRequestArgs { + req: http.IncomingMessage, + socket: net.Socket, + head: Buffer, +} diff --git a/src/main/resource-applier.ts b/src/main/resource-applier.ts index f4772c5275..cfd651accc 100644 --- a/src/main/resource-applier.ts +++ b/src/main/resource-applier.ts @@ -25,7 +25,7 @@ import { exec } from "child_process"; import fs from "fs"; import * as yaml from "js-yaml"; import path from "path"; -import * as tempy from "tempy"; +import tempy from "tempy"; import logger from "./logger"; import { appEventBus } from "../common/event-bus"; import { cloneJsonObject } from "../common/utils"; diff --git a/src/main/routes/metrics-route.ts b/src/main/routes/metrics-route.ts index 2b8aa0f921..e33a09b1d8 100644 --- a/src/main/routes/metrics-route.ts +++ b/src/main/routes/metrics-route.ts @@ -23,10 +23,10 @@ import _ from "lodash"; import type { LensApiRequest } from "../router"; import { respondJson } from "../utils/http-responses"; import type { Cluster } from "../cluster"; -import { ClusterMetadataKey, ClusterPrometheusMetadata } from "../../common/cluster-types"; import logger from "../logger"; import { getMetrics } from "../k8s-request"; import { PrometheusProviderRegistry } from "../prometheus"; +import { ClusterPrometheusMetadata, ClusterMetadataKey } from "../../common/cluster-types"; export type IMetricsQuery = string | string[] | { [metricName: string]: string; diff --git a/src/main/window-manager.ts b/src/main/window-manager.ts index d1b0f5da2a..13045bc496 100644 --- a/src/main/window-manager.ts +++ b/src/main/window-manager.ts @@ -25,14 +25,12 @@ import { app, BrowserWindow, dialog, ipcMain, shell, webContents } from "electro import windowStateKeeper from "electron-window-state"; import { appEventBus } from "../common/event-bus"; import { ipcMainOn } from "../common/ipc"; -import { initMenu } from "./menu"; -import { initTray } from "./tray"; import { delay, iter, Singleton } from "../common/utils"; import { ClusterFrameInfo, clusterFrameMap } from "../common/cluster-frames"; import { IpcRendererNavigationEvents } from "../renderer/navigation/events"; import logger from "./logger"; import { productName } from "../common/vars"; -import { LensProxy } from "./proxy/lens-proxy"; +import { LensProxy } from "./lens-proxy"; function isHideable(window: BrowserWindow | null): boolean { return Boolean(window && !window.isDestroyed()); @@ -56,8 +54,6 @@ export class WindowManager extends Singleton { super(); makeObservable(this); this.bindEvents(); - this.initMenu(); - this.initTray(); } get mainUrl() { @@ -136,14 +132,6 @@ export class WindowManager extends Singleton { } } - protected async initMenu() { - this.disposers.menuAutoUpdater = initMenu(this); - } - - protected initTray() { - this.disposers.trayAutoUpdater = initTray(this); - } - protected bindEvents() { // track visible cluster from ui ipcMainOn(IpcRendererNavigationEvents.CLUSTER_VIEW_CURRENT_ID, (event, clusterId: ClusterId) => { diff --git a/src/migrations/hotbar-store/5.0.0-alpha.0.ts b/src/migrations/hotbar-store/5.0.0-alpha.0.ts index 1a61ce8ef3..1152a917b1 100644 --- a/src/migrations/hotbar-store/5.0.0-alpha.0.ts +++ b/src/migrations/hotbar-store/5.0.0-alpha.0.ts @@ -20,23 +20,18 @@ */ // Cleans up a store that had the state related data stored -import { Hotbar, HotbarStore } from "../../common/hotbar-store"; -import * as uuid from "uuid"; import type { MigrationDeclaration } from "../helpers"; import { catalogEntity } from "../../main/catalog-sources/general"; +import { getEmptyHotbar } from "../../common/hotbar-types"; export default { version: "5.0.0-alpha.0", run(store) { - const hotbar: Hotbar = { - id: uuid.v4(), - name: "default", - items: HotbarStore.getInitialItems(), - }; - + const hotbar = getEmptyHotbar("default"); const { metadata: { uid, name, source } } = catalogEntity; + const initialItem = { entity: { uid, name, source } }; - hotbar.items[0] = { entity: { uid, name, source } }; + hotbar.items[0] = initialItem; store.set("hotbars", [hotbar]); } diff --git a/src/migrations/hotbar-store/5.0.0-alpha.2.ts b/src/migrations/hotbar-store/5.0.0-alpha.2.ts index e049a6d731..0a662b466a 100644 --- a/src/migrations/hotbar-store/5.0.0-alpha.2.ts +++ b/src/migrations/hotbar-store/5.0.0-alpha.2.ts @@ -20,7 +20,7 @@ */ // Cleans up a store that had the state related data stored -import type { Hotbar } from "../../common/hotbar-store"; +import type { Hotbar } from "../../common/hotbar-types"; import * as uuid from "uuid"; import type { MigrationDeclaration } from "../helpers"; diff --git a/src/migrations/hotbar-store/5.0.0-beta.10.ts b/src/migrations/hotbar-store/5.0.0-beta.10.ts index 3dd635effc..0ba52dc84c 100644 --- a/src/migrations/hotbar-store/5.0.0-beta.10.ts +++ b/src/migrations/hotbar-store/5.0.0-beta.10.ts @@ -25,7 +25,7 @@ import { isNull } from "lodash"; import path from "path"; import * as uuid from "uuid"; import type { ClusterStoreModel } from "../../common/cluster-store"; -import { defaultHotbarCells, Hotbar, HotbarStore } from "../../common/hotbar-store"; +import { Hotbar, defaultHotbarCells, getEmptyHotbar } from "../../common/hotbar-types"; import { catalogEntity } from "../../main/catalog-sources/general"; import { MigrationDeclaration, migrationLog } from "../helpers"; import { generateNewIdFor } from "../utils"; @@ -52,7 +52,7 @@ export default { migrationLog(`Creating new hotbar for ${name}`); workspaceHotbars.set(id, { id: uuid.v4(), // don't use the old IDs as they aren't necessarily UUIDs - items: [], + items: [] as any, name: `Workspace: ${name}`, }); } @@ -65,7 +65,7 @@ export default { workspaceHotbars.set("default", { name, id, - items: items.filter(Boolean), + items: items.filter(Boolean) as any, }); } @@ -94,7 +94,7 @@ export default { } for (const hotbar of workspaceHotbars.values()) { - if (hotbar.items.length === 0) { + if ((hotbar.items as any).length === 0) { migrationLog(`Skipping ${hotbar.name} due to it being empty`); continue; } @@ -123,11 +123,7 @@ export default { if (freeIndex === -1) { // making a new hotbar is less destructive if the first hotbar // called "default" is full than overriding a hotbar item - const hotbar = { - id: uuid.v4(), - name: "initial", - items: HotbarStore.getInitialItems(), - }; + const hotbar = getEmptyHotbar("initial"); hotbar.items[0] = { entity: { uid, name, source } }; hotbars.unshift(hotbar); @@ -135,11 +131,7 @@ export default { defaultHotbar.items[freeIndex] = { entity: { uid, name, source } }; } } else { - const hotbar = { - id: uuid.v4(), - name: "default", - items: HotbarStore.getInitialItems(), - }; + const hotbar = getEmptyHotbar("default"); hotbar.items[0] = { entity: { uid, name, source } }; hotbars.unshift(hotbar); diff --git a/src/migrations/hotbar-store/5.0.0-beta.5.ts b/src/migrations/hotbar-store/5.0.0-beta.5.ts index 8d589e9543..a02466a103 100644 --- a/src/migrations/hotbar-store/5.0.0-beta.5.ts +++ b/src/migrations/hotbar-store/5.0.0-beta.5.ts @@ -19,14 +19,14 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import type { Hotbar } from "../../common/hotbar-store"; +import type { Hotbar } from "../../common/hotbar-types"; import { catalogEntityRegistry } from "../../main/catalog"; import type { MigrationDeclaration } from "../helpers"; export default { version: "5.0.0-beta.5", run(store) { - const hotbars: Hotbar[] = store.get("hotbars"); + const hotbars: Hotbar[] = store.get("hotbars") ?? []; hotbars.forEach((hotbar, hotbarIndex) => { hotbar.items.forEach((item, itemIndex) => { diff --git a/src/renderer/api/__tests__/catalog-entity-registry.test.ts b/src/renderer/api/__tests__/catalog-entity-registry.test.ts index 4c3bcb48c3..c44d91f728 100644 --- a/src/renderer/api/__tests__/catalog-entity-registry.test.ts +++ b/src/renderer/api/__tests__/catalog-entity-registry.test.ts @@ -20,7 +20,6 @@ */ import { CatalogEntityRegistry } from "../catalog-entity-registry"; -import "../../../common/catalog-entities"; import { catalogCategoryRegistry } from "../../../common/catalog/catalog-category-registry"; import { CatalogCategory, CatalogEntityData, CatalogEntityKindData } from "../catalog-entity"; import { WebLink } from "../../../common/catalog-entities"; diff --git a/src/renderer/api/api-manager.ts b/src/renderer/api/api-manager.ts index 1e01bd4cfb..e11fd9a07b 100644 --- a/src/renderer/api/api-manager.ts +++ b/src/renderer/api/api-manager.ts @@ -23,8 +23,9 @@ import type { KubeObjectStore } from "../kube-object.store"; import { action, observable, makeObservable } from "mobx"; import { autoBind, iter } from "../utils"; -import { KubeApi, parseKubeApi } from "./kube-api"; +import type { KubeApi } from "./kube-api"; import type { KubeObject } from "./kube-object"; +import { IKubeObjectRef, parseKubeApi, createKubeApiURL } from "./kube-api-parse"; export class ApiManager { private apis = observable.map>(); @@ -91,6 +92,45 @@ export class ApiManager { getStore>(api: string | KubeApi): S | undefined { return this.stores.get(this.resolveApi(api)?.apiBase) as S; } + + lookupApiLink(ref: IKubeObjectRef, parentObject: KubeObject): string { + const { + kind, apiVersion, name, + namespace = parentObject.getNs() + } = ref; + + if (!kind) return ""; + + // search in registered apis by 'kind' & 'apiVersion' + const api = this.getApi(api => api.kind === kind && api.apiVersionWithGroup == apiVersion); + + if (api) { + return api.getUrl({ namespace, name }); + } + + // lookup api by generated resource link + const apiPrefixes = ["/apis", "/api"]; + const resource = kind.endsWith("s") ? `${kind.toLowerCase()}es` : `${kind.toLowerCase()}s`; + + for (const apiPrefix of apiPrefixes) { + const apiLink = createKubeApiURL({ apiPrefix, apiVersion, name, namespace, resource }); + + if (this.getApi(apiLink)) { + return apiLink; + } + } + + // resolve by kind only (hpa's might use refs to older versions of resources for example) + const apiByKind = this.getApi(api => api.kind === kind); + + if (apiByKind) { + return apiByKind.getUrl({ name, namespace }); + } + + // otherwise generate link with default prefix + // resource still might exists in k8s, but api is not registered in the app + return createKubeApiURL({ apiVersion, name, namespace, resource }); + } } export const apiManager = new ApiManager(); diff --git a/src/renderer/api/endpoints/resource-applier.api.ts b/src/renderer/api/endpoints/resource-applier.api.ts index b10c10f7db..b6a35d3a60 100644 --- a/src/renderer/api/endpoints/resource-applier.api.ts +++ b/src/renderer/api/endpoints/resource-applier.api.ts @@ -20,35 +20,21 @@ */ import jsYaml from "js-yaml"; -import { KubeObject } from "../kube-object"; import type { KubeJsonApiData } from "../kube-json-api"; import { apiBase } from "../index"; -import { apiManager } from "../api-manager"; export const resourceApplierApi = { annotations: [ "kubectl.kubernetes.io/last-applied-configuration" ], - async update(resource: object | string): Promise { + async update(resource: object | string): Promise { if (typeof resource === "string") { resource = jsYaml.safeLoad(resource); } - return apiBase - .post("/stack", { data: resource }) - .then(data => { - const items = data.map(obj => { - const api = apiManager.getApiByKind(obj.kind, obj.apiVersion); + const [data = null] = await apiBase.post("/stack", { data: resource }); - if (api) { - return new api.objectConstructor(obj); - } else { - return new KubeObject(obj); - } - }); - - return items[0] as K ?? null; - }); + return data; } }; diff --git a/src/renderer/api/kube-api-parse.ts b/src/renderer/api/kube-api-parse.ts index 689a6b9858..53d731203d 100644 --- a/src/renderer/api/kube-api-parse.ts +++ b/src/renderer/api/kube-api-parse.ts @@ -21,9 +21,7 @@ // Parse kube-api path and get api-version, group, etc. -import type { KubeObject } from "./kube-object"; import { splitArray } from "../../common/utils"; -import { apiManager } from "./api-manager"; import { isDebugging } from "../../common/vars"; import logger from "../../main/logger"; import { inspect } from "util"; @@ -159,42 +157,3 @@ export function createKubeApiURL(ref: IKubeApiLinkRef): string { .filter(v => v) .join("/"); } - -export function lookupApiLink(ref: IKubeObjectRef, parentObject: KubeObject): string { - const { - kind, apiVersion, name, - namespace = parentObject.getNs() - } = ref; - - if (!kind) return ""; - - // search in registered apis by 'kind' & 'apiVersion' - const api = apiManager.getApi(api => api.kind === kind && api.apiVersionWithGroup == apiVersion); - - if (api) { - return api.getUrl({ namespace, name }); - } - - // lookup api by generated resource link - const apiPrefixes = ["/apis", "/api"]; - const resource = kind.endsWith("s") ? `${kind.toLowerCase()}es` : `${kind.toLowerCase()}s`; - - for (const apiPrefix of apiPrefixes) { - const apiLink = createKubeApiURL({ apiPrefix, apiVersion, name, namespace, resource }); - - if (apiManager.getApi(apiLink)) { - return apiLink; - } - } - - // resolve by kind only (hpa's might use refs to older versions of resources for example) - const apiByKind = apiManager.getApi(api => api.kind === kind); - - if (apiByKind) { - return apiByKind.getUrl({ name, namespace }); - } - - // otherwise generate link with default prefix - // resource still might exists in k8s, but api is not registered in the app - return createKubeApiURL({ apiVersion, name, namespace, resource }); -} diff --git a/src/renderer/api/kube-api.ts b/src/renderer/api/kube-api.ts index 20c4672727..c7d088d0d5 100644 --- a/src/renderer/api/kube-api.ts +++ b/src/renderer/api/kube-api.ts @@ -56,11 +56,6 @@ export interface IKubeApiOptions { checkPreferredVersion?: boolean; } -export interface KubeApiListOptions { - namespace?: string; - reqInit?: RequestInit; -} - export interface IKubeApiQueryParams { watch?: boolean | number; resourceVersion?: string; diff --git a/src/renderer/api/kube-object.ts b/src/renderer/api/kube-object.ts index 2548cac3aa..ee4098a5ae 100644 --- a/src/renderer/api/kube-object.ts +++ b/src/renderer/api/kube-object.ts @@ -277,14 +277,14 @@ export class KubeObject(data: Partial): Promise { + async update(data: Partial): Promise { for (const field of KubeObject.nonEditableFields) { if (!_.isEqual(_.get(this, field), _.get(data, field))) { throw new Error(`Failed to update Kube Object: ${field} has been modified`); } } - return resourceApplierApi.update({ + return resourceApplierApi.update({ ...this.toPlainObject(), ...data, }); diff --git a/src/renderer/components/+add-cluster/add-cluster.tsx b/src/renderer/components/+add-cluster/add-cluster.tsx index 7ee8529492..5e59767081 100644 --- a/src/renderer/components/+add-cluster/add-cluster.tsx +++ b/src/renderer/components/+add-cluster/add-cluster.tsx @@ -30,12 +30,11 @@ import path from "path"; import React from "react"; import { catalogURL } from "../../../common/routes"; -import { ClusterStore } from "../../../common/cluster-store"; import { appEventBus } from "../../../common/event-bus"; import { loadConfigFromString, splitConfig } from "../../../common/kube-helpers"; import { docsUrl } from "../../../common/vars"; import { navigate } from "../../navigation"; -import { iter } from "../../utils"; +import { getCustomKubeConfigPath, iter } from "../../utils"; import { AceEditor } from "../ace-editor"; import { Button } from "../button"; import { Notifications } from "../notifications"; @@ -93,7 +92,7 @@ export class AddCluster extends React.Component { appEventBus.emit({ name: "cluster-add", action: "click" }); try { - const absPath = ClusterStore.getCustomKubeConfigPath(); + const absPath = getCustomKubeConfigPath(); await fse.ensureDir(path.dirname(absPath)); await fse.writeFile(absPath, this.customConfig.trim(), { encoding: "utf-8", mode: 0o600 }); diff --git a/src/renderer/components/+apps-releases/release-details.tsx b/src/renderer/components/+apps-releases/release-details.tsx index fae2e3ba71..04135e593c 100644 --- a/src/renderer/components/+apps-releases/release-details.tsx +++ b/src/renderer/components/+apps-releases/release-details.tsx @@ -45,7 +45,7 @@ import { apiManager } from "../../api/api-manager"; import { SubTitle } from "../layout/sub-title"; import { secretsStore } from "../+config-secrets/secrets.store"; import { Secret } from "../../api/endpoints"; -import { getDetailsUrl } from "../kube-object"; +import { getDetailsUrl } from "../kube-details"; import { Checkbox } from "../checkbox"; interface Props { diff --git a/src/renderer/components/+cluster/cluster-issues.tsx b/src/renderer/components/+cluster/cluster-issues.tsx index f35f8bea61..6135352e2b 100644 --- a/src/renderer/components/+cluster/cluster-issues.tsx +++ b/src/renderer/components/+cluster/cluster-issues.tsx @@ -33,9 +33,9 @@ import { boundMethod, cssNames, prevDefault } from "../../utils"; import type { ItemObject } from "../../item.store"; import { Spinner } from "../spinner"; import { ThemeStore } from "../../theme.store"; -import { lookupApiLink } from "../../api/kube-api"; -import { kubeSelectedUrlParam, showDetails } from "../kube-object"; +import { kubeSelectedUrlParam, showDetails } from "../kube-details"; import { kubeWatchApi } from "../../api/kube-watch-api"; +import { apiManager } from "../../api/api-manager"; interface Props { className?: string; @@ -106,7 +106,7 @@ export class ClusterIssues extends React.Component { age: getAge(), message, kind, - selfLink: lookupApiLink(involvedObject, error), + selfLink: apiManager.lookupApiLink(involvedObject, error), }); }); diff --git a/src/renderer/components/+config-autoscalers/hpa-details.tsx b/src/renderer/components/+config-autoscalers/hpa-details.tsx index cf56b2c35c..aef28e9241 100644 --- a/src/renderer/components/+config-autoscalers/hpa-details.tsx +++ b/src/renderer/components/+config-autoscalers/hpa-details.tsx @@ -26,12 +26,13 @@ import { observer } from "mobx-react"; import { Link } from "react-router-dom"; import { DrawerItem, DrawerTitle } from "../drawer"; import { Badge } from "../badge"; -import { KubeObjectDetailsProps, getDetailsUrl } from "../kube-object"; +import { getDetailsUrl } from "../kube-details"; import { cssNames } from "../../utils"; import { HorizontalPodAutoscaler, HpaMetricType, IHpaMetric } from "../../api/endpoints/hpa.api"; import { Table, TableCell, TableHead, TableRow } from "../table"; -import { lookupApiLink } from "../../api/kube-api"; -import { KubeObjectMeta } from "../kube-object/kube-object-meta"; +import { KubeObjectMeta } from "../kube-object-meta"; +import { apiManager } from "../../api/api-manager"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; interface Props extends KubeObjectDetailsProps { } @@ -54,7 +55,7 @@ export class HpaDetails extends React.Component { case HpaMetricType.Object: const { target } = metric.object; const { kind, name } = target; - const objectUrl = getDetailsUrl(lookupApiLink(target, hpa)); + const objectUrl = getDetailsUrl(apiManager.lookupApiLink(target, hpa)); return ( <> @@ -107,7 +108,7 @@ export class HpaDetails extends React.Component { {scaleTargetRef && ( - + {scaleTargetRef.kind}/{scaleTargetRef.name} )} diff --git a/src/renderer/components/+config-autoscalers/hpa.tsx b/src/renderer/components/+config-autoscalers/hpa.tsx index 35bf3d6375..855b5c3cec 100644 --- a/src/renderer/components/+config-autoscalers/hpa.tsx +++ b/src/renderer/components/+config-autoscalers/hpa.tsx @@ -24,7 +24,7 @@ import "./hpa.scss"; import React from "react"; import { observer } from "mobx-react"; import type { RouteComponentProps } from "react-router"; -import { KubeObjectListLayout } from "../kube-object"; +import { KubeObjectListLayout } from "../kube-object-list-layout"; import type { HorizontalPodAutoscaler } from "../../api/endpoints/hpa.api"; import { hpaStore } from "./hpa.store"; import { Badge } from "../badge"; diff --git a/src/renderer/components/+config-limit-ranges/limit-range-details.tsx b/src/renderer/components/+config-limit-ranges/limit-range-details.tsx index 8531029313..0d235252f2 100644 --- a/src/renderer/components/+config-limit-ranges/limit-range-details.tsx +++ b/src/renderer/components/+config-limit-ranges/limit-range-details.tsx @@ -23,9 +23,9 @@ import "./limit-range-details.scss"; import React from "react"; import { observer } from "mobx-react"; -import type { KubeObjectDetailsProps } from "../kube-object"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; import { LimitPart, LimitRange, LimitRangeItem, Resource } from "../../api/endpoints/limit-range.api"; -import { KubeObjectMeta } from "../kube-object/kube-object-meta"; +import { KubeObjectMeta } from "../kube-object-meta"; import { DrawerItem } from "../drawer/drawer-item"; import { Badge } from "../badge"; diff --git a/src/renderer/components/+config-limit-ranges/limit-ranges.tsx b/src/renderer/components/+config-limit-ranges/limit-ranges.tsx index e0bec106aa..dfc132b20f 100644 --- a/src/renderer/components/+config-limit-ranges/limit-ranges.tsx +++ b/src/renderer/components/+config-limit-ranges/limit-ranges.tsx @@ -23,7 +23,7 @@ import "./limit-ranges.scss"; import type { RouteComponentProps } from "react-router"; import { observer } from "mobx-react"; -import { KubeObjectListLayout } from "../kube-object/kube-object-list-layout"; +import { KubeObjectListLayout } from "../kube-object-list-layout"; import { limitRangeStore } from "./limit-ranges.store"; import React from "react"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; diff --git a/src/renderer/components/+config-maps/config-map-details.tsx b/src/renderer/components/+config-maps/config-map-details.tsx index 4858868186..b34ca83ab2 100644 --- a/src/renderer/components/+config-maps/config-map-details.tsx +++ b/src/renderer/components/+config-maps/config-map-details.tsx @@ -29,9 +29,9 @@ import { Notifications } from "../notifications"; import { Input } from "../input"; import { Button } from "../button"; import { configMapsStore } from "./config-maps.store"; -import type { KubeObjectDetailsProps } from "../kube-object"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; import type { ConfigMap } from "../../api/endpoints"; -import { KubeObjectMeta } from "../kube-object/kube-object-meta"; +import { KubeObjectMeta } from "../kube-object-meta"; interface Props extends KubeObjectDetailsProps { } diff --git a/src/renderer/components/+config-maps/config-maps.tsx b/src/renderer/components/+config-maps/config-maps.tsx index b9fecc9fc9..9733846994 100644 --- a/src/renderer/components/+config-maps/config-maps.tsx +++ b/src/renderer/components/+config-maps/config-maps.tsx @@ -25,7 +25,7 @@ import React from "react"; import { observer } from "mobx-react"; import type { RouteComponentProps } from "react-router"; import { configMapsStore } from "./config-maps.store"; -import { KubeObjectListLayout } from "../kube-object"; +import { KubeObjectListLayout } from "../kube-object-list-layout"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; import type { ConfigMapsRouteParams } from "../../../common/routes"; diff --git a/src/renderer/components/+config-pod-disruption-budgets/pod-disruption-budgets-details.tsx b/src/renderer/components/+config-pod-disruption-budgets/pod-disruption-budgets-details.tsx index ad4bc41dc1..4f8aaab465 100644 --- a/src/renderer/components/+config-pod-disruption-budgets/pod-disruption-budgets-details.tsx +++ b/src/renderer/components/+config-pod-disruption-budgets/pod-disruption-budgets-details.tsx @@ -25,9 +25,9 @@ import React from "react"; import { observer } from "mobx-react"; import { DrawerItem } from "../drawer"; import { Badge } from "../badge"; -import type { KubeObjectDetailsProps } from "../kube-object"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; import type { PodDisruptionBudget } from "../../api/endpoints"; -import { KubeObjectMeta } from "../kube-object/kube-object-meta"; +import { KubeObjectMeta } from "../kube-object-meta"; interface Props extends KubeObjectDetailsProps { } diff --git a/src/renderer/components/+config-pod-disruption-budgets/pod-disruption-budgets.tsx b/src/renderer/components/+config-pod-disruption-budgets/pod-disruption-budgets.tsx index f662c96ab3..ed908e8f66 100644 --- a/src/renderer/components/+config-pod-disruption-budgets/pod-disruption-budgets.tsx +++ b/src/renderer/components/+config-pod-disruption-budgets/pod-disruption-budgets.tsx @@ -25,8 +25,9 @@ import * as React from "react"; import { observer } from "mobx-react"; import { podDisruptionBudgetsStore } from "./pod-disruption-budgets.store"; import type { PodDisruptionBudget } from "../../api/endpoints/poddisruptionbudget.api"; -import { KubeObjectDetailsProps, KubeObjectListLayout } from "../kube-object"; +import { KubeObjectListLayout } from "../kube-object-list-layout"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; enum columnId { name = "name", diff --git a/src/renderer/components/+config-resource-quotas/resource-quota-details.tsx b/src/renderer/components/+config-resource-quotas/resource-quota-details.tsx index cf7c505dcf..06a154db61 100644 --- a/src/renderer/components/+config-resource-quotas/resource-quota-details.tsx +++ b/src/renderer/components/+config-resource-quotas/resource-quota-details.tsx @@ -25,11 +25,11 @@ import kebabCase from "lodash/kebabCase"; import { observer } from "mobx-react"; import { DrawerItem, DrawerTitle } from "../drawer"; import { cpuUnitsToNumber, cssNames, unitsToBytes, metricUnitsToNumber } from "../../utils"; -import type { KubeObjectDetailsProps } from "../kube-object"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; import type { ResourceQuota } from "../../api/endpoints/resource-quota.api"; import { LineProgress } from "../line-progress"; import { Table, TableCell, TableHead, TableRow } from "../table"; -import { KubeObjectMeta } from "../kube-object/kube-object-meta"; +import { KubeObjectMeta } from "../kube-object-meta"; interface Props extends KubeObjectDetailsProps { } diff --git a/src/renderer/components/+config-resource-quotas/resource-quotas.tsx b/src/renderer/components/+config-resource-quotas/resource-quotas.tsx index e1f54f2499..060b1e29fa 100644 --- a/src/renderer/components/+config-resource-quotas/resource-quotas.tsx +++ b/src/renderer/components/+config-resource-quotas/resource-quotas.tsx @@ -24,7 +24,7 @@ import "./resource-quotas.scss"; import React from "react"; import { observer } from "mobx-react"; import type { RouteComponentProps } from "react-router"; -import { KubeObjectListLayout } from "../kube-object"; +import { KubeObjectListLayout } from "../kube-object-list-layout"; import { AddQuotaDialog } from "./add-quota-dialog"; import { resourceQuotaStore } from "./resource-quotas.store"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; diff --git a/src/renderer/components/+config-secrets/add-secret-dialog.tsx b/src/renderer/components/+config-secrets/add-secret-dialog.tsx index 5c417023e2..f30ddef57c 100644 --- a/src/renderer/components/+config-secrets/add-secret-dialog.tsx +++ b/src/renderer/components/+config-secrets/add-secret-dialog.tsx @@ -37,7 +37,7 @@ import type { KubeObjectMetadata } from "../../api/kube-object"; import { base64 } from "../../utils"; import { Notifications } from "../notifications"; import upperFirst from "lodash/upperFirst"; -import { showDetails } from "../kube-object"; +import { showDetails } from "../kube-details"; interface Props extends Partial { } diff --git a/src/renderer/components/+config-secrets/secret-details.tsx b/src/renderer/components/+config-secrets/secret-details.tsx index 672ba86203..370c28b9d2 100644 --- a/src/renderer/components/+config-secrets/secret-details.tsx +++ b/src/renderer/components/+config-secrets/secret-details.tsx @@ -32,9 +32,9 @@ import { Notifications } from "../notifications"; import { base64 } from "../../utils"; import { Icon } from "../icon"; import { secretsStore } from "./secrets.store"; -import type { KubeObjectDetailsProps } from "../kube-object"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; import type { Secret } from "../../api/endpoints"; -import { KubeObjectMeta } from "../kube-object/kube-object-meta"; +import { KubeObjectMeta } from "../kube-object-meta"; interface Props extends KubeObjectDetailsProps { } diff --git a/src/renderer/components/+config-secrets/secrets.tsx b/src/renderer/components/+config-secrets/secrets.tsx index f00c20d67e..7e75b04d0e 100644 --- a/src/renderer/components/+config-secrets/secrets.tsx +++ b/src/renderer/components/+config-secrets/secrets.tsx @@ -25,7 +25,7 @@ import React from "react"; import { observer } from "mobx-react"; import type { RouteComponentProps } from "react-router"; import { AddSecretDialog } from "./add-secret-dialog"; -import { KubeObjectListLayout } from "../kube-object"; +import { KubeObjectListLayout } from "../kube-object-list-layout"; import { Badge } from "../badge"; import { secretsStore } from "./secrets.store"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; diff --git a/src/renderer/components/+config/config.tsx b/src/renderer/components/+config/config.tsx index c04f5eeb37..24d84cff34 100644 --- a/src/renderer/components/+config/config.tsx +++ b/src/renderer/components/+config/config.tsx @@ -27,7 +27,7 @@ import { Secrets } from "../+config-secrets"; import { ResourceQuotas } from "../+config-resource-quotas"; import { PodDisruptionBudgets } from "../+config-pod-disruption-budgets"; import { HorizontalPodAutoscalers } from "../+config-autoscalers"; -import { isAllowedResource } from "../../../common/rbac"; +import { isAllowedResource } from "../../../common/utils/allowed-resource"; import { LimitRanges } from "../+config-limit-ranges"; import * as routes from "../../../common/routes"; diff --git a/src/renderer/components/+custom-resources/crd-details.tsx b/src/renderer/components/+custom-resources/crd-details.tsx index bef1dc6f67..79d5a31e65 100644 --- a/src/renderer/components/+custom-resources/crd-details.tsx +++ b/src/renderer/components/+custom-resources/crd-details.tsx @@ -28,10 +28,10 @@ import type { CustomResourceDefinition } from "../../api/endpoints/crd.api"; import { AceEditor } from "../ace-editor"; import { Badge } from "../badge"; import { DrawerItem, DrawerTitle } from "../drawer"; -import type { KubeObjectDetailsProps } from "../kube-object"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; import { Table, TableCell, TableHead, TableRow } from "../table"; import { Input } from "../input"; -import { KubeObjectMeta } from "../kube-object/kube-object-meta"; +import { KubeObjectMeta } from "../kube-object-meta"; interface Props extends KubeObjectDetailsProps { } diff --git a/src/renderer/components/+custom-resources/crd-list.tsx b/src/renderer/components/+custom-resources/crd-list.tsx index 70ae2c96fb..fb0735d223 100644 --- a/src/renderer/components/+custom-resources/crd-list.tsx +++ b/src/renderer/components/+custom-resources/crd-list.tsx @@ -26,7 +26,7 @@ import { computed, makeObservable } from "mobx"; import { observer } from "mobx-react"; import { Link } from "react-router-dom"; import { stopPropagation } from "../../utils"; -import { KubeObjectListLayout } from "../kube-object"; +import { KubeObjectListLayout } from "../kube-object-list-layout"; import { crdStore } from "./crd.store"; import type { CustomResourceDefinition } from "../../api/endpoints/crd.api"; import { Select, SelectOption } from "../select"; @@ -116,7 +116,7 @@ export class CrdList extends React.Component { controlShouldRenderValue={false} formatOptionLabel={({ value: group }: SelectOption) => { const isSelected = selectedGroups.includes(group); - + return (
diff --git a/src/renderer/components/+custom-resources/crd-resource-details.tsx b/src/renderer/components/+custom-resources/crd-resource-details.tsx index dc6181c63c..027a27618d 100644 --- a/src/renderer/components/+custom-resources/crd-resource-details.tsx +++ b/src/renderer/components/+custom-resources/crd-resource-details.tsx @@ -28,9 +28,9 @@ import { computed, makeObservable } from "mobx"; import { cssNames } from "../../utils"; import { Badge } from "../badge"; import { DrawerItem } from "../drawer"; -import type { KubeObjectDetailsProps } from "../kube-object"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; import { crdStore } from "./crd.store"; -import { KubeObjectMeta } from "../kube-object/kube-object-meta"; +import { KubeObjectMeta } from "../kube-object-meta"; import { Input } from "../input"; import type { AdditionalPrinterColumnsV1, CustomResourceDefinition } from "../../api/endpoints/crd.api"; import { parseJsonPath } from "../../utils/jsonPath"; diff --git a/src/renderer/components/+custom-resources/crd-resources.tsx b/src/renderer/components/+custom-resources/crd-resources.tsx index be12f910c1..d64dd4e5f0 100644 --- a/src/renderer/components/+custom-resources/crd-resources.tsx +++ b/src/renderer/components/+custom-resources/crd-resources.tsx @@ -25,7 +25,7 @@ import React from "react"; import jsonPath from "jsonpath"; import { observer } from "mobx-react"; import type { RouteComponentProps } from "react-router"; -import { KubeObjectListLayout } from "../kube-object"; +import { KubeObjectListLayout } from "../kube-object-list-layout"; import type { KubeObject } from "../../api/kube-object"; import { computed, makeObservable } from "mobx"; import { crdStore } from "./crd.store"; diff --git a/src/renderer/components/+events/event-details.tsx b/src/renderer/components/+events/event-details.tsx index 639c4b9dcf..27e1affbb3 100644 --- a/src/renderer/components/+events/event-details.tsx +++ b/src/renderer/components/+events/event-details.tsx @@ -26,12 +26,13 @@ import kebabCase from "lodash/kebabCase"; import { DrawerItem, DrawerTitle } from "../drawer"; import { Link } from "react-router-dom"; import { observer } from "mobx-react"; -import { KubeObjectDetailsProps, getDetailsUrl } from "../kube-object"; +import type { KubeObjectDetailsProps} from "../kube-object-details"; +import { getDetailsUrl } from "../kube-details"; import type { KubeEvent } from "../../api/endpoints/events.api"; -import { KubeObjectMeta } from "../kube-object/kube-object-meta"; +import { KubeObjectMeta } from "../kube-object-meta"; import { Table, TableCell, TableHead, TableRow } from "../table"; -import { lookupApiLink } from "../../api/kube-api"; import { LocaleDate } from "../locale-date"; +import { apiManager } from "../../api/api-manager"; interface Props extends KubeObjectDetailsProps { } @@ -81,7 +82,7 @@ export class EventDetails extends React.Component { - + {name} diff --git a/src/renderer/components/+events/events.tsx b/src/renderer/components/+events/events.tsx index 23aa985ab8..56ed0d8ea1 100644 --- a/src/renderer/components/+events/events.tsx +++ b/src/renderer/components/+events/events.tsx @@ -27,7 +27,6 @@ import { observer } from "mobx-react"; import { orderBy } from "lodash"; import { TabLayout } from "../layout/tab-layout"; import { EventStore, eventStore } from "./event.store"; -import { getDetailsUrl, KubeObjectListLayout, KubeObjectListLayoutProps } from "../kube-object"; import type { KubeEvent } from "../../api/endpoints/events.api"; import type { TableSortCallbacks, TableSortParams } from "../table"; import type { HeaderCustomizer } from "../item-object-list"; @@ -35,8 +34,10 @@ import { Tooltip } from "../tooltip"; import { Link } from "react-router-dom"; import { cssNames, IClassName, stopPropagation } from "../../utils"; import { Icon } from "../icon"; -import { lookupApiLink } from "../../api/kube-api"; import { eventsURL } from "../../../common/routes"; +import { apiManager } from "../../api/api-manager"; +import { getDetailsUrl } from "../kube-details"; +import { KubeObjectListLayoutProps, KubeObjectListLayout } from "../kube-object-list-layout"; enum columnId { message = "message", @@ -133,7 +134,7 @@ export class Events extends React.Component { tooltip={`Limited to ${store.limit}`} /> , - title, + title, ...headerPlaceholders }; }; @@ -195,7 +196,7 @@ export class Events extends React.Component { ) }, event.getNs(), - + {involvedObject.kind}: {involvedObject.name} , event.getSource(), diff --git a/src/renderer/components/+namespaces/namespace-details.tsx b/src/renderer/components/+namespaces/namespace-details.tsx index ff997fe335..9793371465 100644 --- a/src/renderer/components/+namespaces/namespace-details.tsx +++ b/src/renderer/components/+namespaces/namespace-details.tsx @@ -27,16 +27,17 @@ import { disposeOnUnmount, observer } from "mobx-react"; import { DrawerItem } from "../drawer"; import { boundMethod, cssNames } from "../../utils"; import { getMetricsForNamespace, IPodMetrics, Namespace } from "../../api/endpoints"; -import { getDetailsUrl, KubeObjectDetailsProps } from "../kube-object"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; import { Link } from "react-router-dom"; import { Spinner } from "../spinner"; import { resourceQuotaStore } from "../+config-resource-quotas/resource-quotas.store"; -import { KubeObjectMeta } from "../kube-object/kube-object-meta"; +import { KubeObjectMeta } from "../kube-object-meta"; import { limitRangeStore } from "../+config-limit-ranges/limit-ranges.store"; -import { ResourceMetrics } from "../resource-metrics"; import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts"; +import { getDetailsUrl } from "../kube-details"; import { ClusterMetricsResourceType } from "../../../common/cluster-types"; import { getActiveClusterEntity } from "../../api/catalog-entity-registry"; +import { ResourceMetrics } from "../resource-metrics"; interface Props extends KubeObjectDetailsProps { } diff --git a/src/renderer/components/+namespaces/namespaces.tsx b/src/renderer/components/+namespaces/namespaces.tsx index cc29fa05ea..cd90d44f9d 100644 --- a/src/renderer/components/+namespaces/namespaces.tsx +++ b/src/renderer/components/+namespaces/namespaces.tsx @@ -27,7 +27,7 @@ import { AddNamespaceDialog } from "./add-namespace-dialog"; import { TabLayout } from "../layout/tab-layout"; import { Badge } from "../badge"; import type { RouteComponentProps } from "react-router"; -import { KubeObjectListLayout } from "../kube-object"; +import { KubeObjectListLayout } from "../kube-object-list-layout"; import { namespaceStore } from "./namespace.store"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; import type { NamespacesRouteParams } from "../../../common/routes"; diff --git a/src/renderer/components/+network-endpoints/endpoint-details.tsx b/src/renderer/components/+network-endpoints/endpoint-details.tsx index 8554a4b2f7..70677cc51e 100644 --- a/src/renderer/components/+network-endpoints/endpoint-details.tsx +++ b/src/renderer/components/+network-endpoints/endpoint-details.tsx @@ -24,9 +24,9 @@ import "./endpoint-details.scss"; import React from "react"; import { observer } from "mobx-react"; import { DrawerTitle } from "../drawer"; -import type { KubeObjectDetailsProps } from "../kube-object"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; import type { Endpoint } from "../../api/endpoints"; -import { KubeObjectMeta } from "../kube-object/kube-object-meta"; +import { KubeObjectMeta } from "../kube-object-meta"; import { EndpointSubsetList } from "./endpoint-subset-list"; interface Props extends KubeObjectDetailsProps { diff --git a/src/renderer/components/+network-endpoints/endpoint-subset-list.tsx b/src/renderer/components/+network-endpoints/endpoint-subset-list.tsx index 1556394a9c..36bc511cbf 100644 --- a/src/renderer/components/+network-endpoints/endpoint-subset-list.tsx +++ b/src/renderer/components/+network-endpoints/endpoint-subset-list.tsx @@ -26,9 +26,9 @@ import { observer } from "mobx-react"; import { EndpointSubset, Endpoint, EndpointAddress} from "../../api/endpoints"; import { Table, TableCell, TableHead, TableRow } from "../table"; import { boundMethod } from "../../utils"; -import { lookupApiLink } from "../../api/kube-api"; import { Link } from "react-router-dom"; -import { getDetailsUrl } from "../kube-object"; +import { getDetailsUrl } from "../kube-details"; +import { apiManager } from "../../api/api-manager"; interface Props { subset: EndpointSubset; @@ -92,7 +92,7 @@ export class EndpointSubsetList extends React.Component { {address.hostname} { address.targetRef && ( - + {address.targetRef.name} )} diff --git a/src/renderer/components/+network-endpoints/endpoints.tsx b/src/renderer/components/+network-endpoints/endpoints.tsx index 940ab89783..38c99fc19c 100644 --- a/src/renderer/components/+network-endpoints/endpoints.tsx +++ b/src/renderer/components/+network-endpoints/endpoints.tsx @@ -25,7 +25,7 @@ import React from "react"; import { observer } from "mobx-react"; import type { RouteComponentProps } from "react-router-dom"; import { endpointStore } from "./endpoints.store"; -import { KubeObjectListLayout } from "../kube-object"; +import { KubeObjectListLayout } from "../kube-object-list-layout"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; import type { EndpointRouteParams } from "../../../common/routes"; diff --git a/src/renderer/components/+network-ingresses/ingress-details.tsx b/src/renderer/components/+network-ingresses/ingress-details.tsx index 97303ad679..bad75d717b 100644 --- a/src/renderer/components/+network-ingresses/ingress-details.tsx +++ b/src/renderer/components/+network-ingresses/ingress-details.tsx @@ -28,9 +28,9 @@ import { DrawerItem, DrawerTitle } from "../drawer"; import type { ILoadBalancerIngress, Ingress } from "../../api/endpoints"; import { Table, TableCell, TableHead, TableRow } from "../table"; import { ResourceMetrics } from "../resource-metrics"; -import type { KubeObjectDetailsProps } from "../kube-object"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; import { IngressCharts } from "./ingress-charts"; -import { KubeObjectMeta } from "../kube-object/kube-object-meta"; +import { KubeObjectMeta } from "../kube-object-meta"; import { getBackendServiceNamePort, getMetricsForIngress, IIngressMetrics } from "../../api/endpoints/ingress.api"; import { getActiveClusterEntity } from "../../api/catalog-entity-registry"; import { ClusterMetricsResourceType } from "../../../common/cluster-types"; diff --git a/src/renderer/components/+network-ingresses/ingresses.tsx b/src/renderer/components/+network-ingresses/ingresses.tsx index 153a4eb62f..cfe71e7c8c 100644 --- a/src/renderer/components/+network-ingresses/ingresses.tsx +++ b/src/renderer/components/+network-ingresses/ingresses.tsx @@ -25,7 +25,7 @@ import React from "react"; import { observer } from "mobx-react"; import type { RouteComponentProps } from "react-router-dom"; import { ingressStore } from "./ingress.store"; -import { KubeObjectListLayout } from "../kube-object"; +import { KubeObjectListLayout } from "../kube-object-list-layout"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; import type { IngressRouteParams } from "../../../common/routes"; diff --git a/src/renderer/components/+network-policies/network-policies.tsx b/src/renderer/components/+network-policies/network-policies.tsx index 65579eaa56..f6ba704de4 100644 --- a/src/renderer/components/+network-policies/network-policies.tsx +++ b/src/renderer/components/+network-policies/network-policies.tsx @@ -24,7 +24,7 @@ import "./network-policies.scss"; import React from "react"; import { observer } from "mobx-react"; import type { RouteComponentProps } from "react-router-dom"; -import { KubeObjectListLayout } from "../kube-object"; +import { KubeObjectListLayout } from "../kube-object-list-layout"; import { networkPolicyStore } from "./network-policy.store"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; import type { NetworkPoliciesRouteParams } from "../../../common/routes"; diff --git a/src/renderer/components/+network-policies/network-policy-details.tsx b/src/renderer/components/+network-policies/network-policy-details.tsx index 7ac8f2f7bf..a81afc211b 100644 --- a/src/renderer/components/+network-policies/network-policy-details.tsx +++ b/src/renderer/components/+network-policies/network-policy-details.tsx @@ -28,8 +28,8 @@ import type { IPolicyEgress, IPolicyIngress, IPolicyIpBlock, IPolicySelector, Ne import { Badge } from "../badge"; import { SubTitle } from "../layout/sub-title"; import { observer } from "mobx-react"; -import type { KubeObjectDetailsProps } from "../kube-object"; -import { KubeObjectMeta } from "../kube-object/kube-object-meta"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; +import { KubeObjectMeta } from "../kube-object-meta"; interface Props extends KubeObjectDetailsProps { } diff --git a/src/renderer/components/+network-services/service-details-endpoint.tsx b/src/renderer/components/+network-services/service-details-endpoint.tsx index 2e04c78f1a..427a908cea 100644 --- a/src/renderer/components/+network-services/service-details-endpoint.tsx +++ b/src/renderer/components/+network-services/service-details-endpoint.tsx @@ -26,7 +26,7 @@ import { Table, TableHead, TableCell, TableRow } from "../table"; import { prevDefault } from "../../utils"; import { endpointStore } from "../+network-endpoints/endpoints.store"; import { Spinner } from "../spinner"; -import { showDetails } from "../kube-object"; +import { showDetails } from "../kube-details"; interface Props { endpoint: KubeObject; diff --git a/src/renderer/components/+network-services/service-details.tsx b/src/renderer/components/+network-services/service-details.tsx index ec10cd5f94..6b6067f077 100644 --- a/src/renderer/components/+network-services/service-details.tsx +++ b/src/renderer/components/+network-services/service-details.tsx @@ -25,9 +25,9 @@ import React from "react"; import { disposeOnUnmount, observer } from "mobx-react"; import { DrawerItem, DrawerTitle } from "../drawer"; import { Badge } from "../badge"; -import type { KubeObjectDetailsProps } from "../kube-object"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; import type { Service } from "../../api/endpoints"; -import { KubeObjectMeta } from "../kube-object/kube-object-meta"; +import { KubeObjectMeta } from "../kube-object-meta"; import { ServicePortComponent } from "./service-port-component"; import { endpointStore } from "../+network-endpoints/endpoints.store"; import { ServiceDetailsEndpoint } from "./service-details-endpoint"; diff --git a/src/renderer/components/+network-services/services.tsx b/src/renderer/components/+network-services/services.tsx index 745236be61..fe3b2b40ab 100644 --- a/src/renderer/components/+network-services/services.tsx +++ b/src/renderer/components/+network-services/services.tsx @@ -24,7 +24,7 @@ import "./services.scss"; import React from "react"; import { observer } from "mobx-react"; import type { RouteComponentProps } from "react-router"; -import { KubeObjectListLayout } from "../kube-object"; +import { KubeObjectListLayout } from "../kube-object-list-layout"; import { Badge } from "../badge"; import { serviceStore } from "./services.store"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; diff --git a/src/renderer/components/+network/network.tsx b/src/renderer/components/+network/network.tsx index ae4a7596fa..7c177ee2a3 100644 --- a/src/renderer/components/+network/network.tsx +++ b/src/renderer/components/+network/network.tsx @@ -28,7 +28,7 @@ import { Services } from "../+network-services"; import { Endpoints } from "../+network-endpoints"; import { Ingresses } from "../+network-ingresses"; import { NetworkPolicies } from "../+network-policies"; -import { isAllowedResource } from "../../../common/rbac"; +import { isAllowedResource } from "../../../common/utils/allowed-resource"; import * as routes from "../../../common/routes"; @observer diff --git a/src/renderer/components/+nodes/node-details.tsx b/src/renderer/components/+nodes/node-details.tsx index 96e4eea4ca..db97754eda 100644 --- a/src/renderer/components/+nodes/node-details.tsx +++ b/src/renderer/components/+nodes/node-details.tsx @@ -29,12 +29,12 @@ import { DrawerItem, DrawerItemLabels } from "../drawer"; import { Badge } from "../badge"; import { ResourceMetrics } from "../resource-metrics"; import { podsStore } from "../+workloads-pods/pods.store"; -import type { KubeObjectDetailsProps } from "../kube-object"; import { getMetricsByNodeNames, IClusterMetrics, Node } from "../../api/endpoints"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; import { NodeCharts } from "./node-charts"; import { makeObservable, observable, reaction } from "mobx"; import { PodDetailsList } from "../+workloads-pods/pod-details-list"; -import { KubeObjectMeta } from "../kube-object/kube-object-meta"; +import { KubeObjectMeta } from "../kube-object-meta"; import { getActiveClusterEntity } from "../../api/catalog-entity-registry"; import { ClusterMetricsResourceType } from "../../../common/cluster-types"; import { NodeDetailsResources } from "./node-details-resources"; diff --git a/src/renderer/components/+nodes/nodes.tsx b/src/renderer/components/+nodes/nodes.tsx index 1225ea8c15..455ca5959d 100644 --- a/src/renderer/components/+nodes/nodes.tsx +++ b/src/renderer/components/+nodes/nodes.tsx @@ -27,8 +27,8 @@ import { cssNames, interval } from "../../utils"; import { TabLayout } from "../layout/tab-layout"; import { nodesStore } from "./nodes.store"; import { podsStore } from "../+workloads-pods/pods.store"; -import { KubeObjectListLayout } from "../kube-object"; import { getMetricsForAllNodes, INodeMetrics, Node } from "../../api/endpoints/nodes.api"; +import { KubeObjectListLayout } from "../kube-object-list-layout"; import { LineProgress } from "../line-progress"; import { bytesToUnits } from "../../utils/convertMemory"; import { Tooltip, TooltipPosition } from "../tooltip"; diff --git a/src/renderer/components/+pod-security-policies/pod-security-policies.tsx b/src/renderer/components/+pod-security-policies/pod-security-policies.tsx index c578bf8e34..232f7a5fba 100644 --- a/src/renderer/components/+pod-security-policies/pod-security-policies.tsx +++ b/src/renderer/components/+pod-security-policies/pod-security-policies.tsx @@ -23,7 +23,7 @@ import "./pod-security-policies.scss"; import React from "react"; import { observer } from "mobx-react"; -import { KubeObjectListLayout } from "../kube-object"; +import { KubeObjectListLayout } from "../kube-object-list-layout"; import { podSecurityPoliciesStore } from "./pod-security-policies.store"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; diff --git a/src/renderer/components/+pod-security-policies/pod-security-policy-details.tsx b/src/renderer/components/+pod-security-policies/pod-security-policy-details.tsx index abdefe9228..7da0218a7a 100644 --- a/src/renderer/components/+pod-security-policies/pod-security-policy-details.tsx +++ b/src/renderer/components/+pod-security-policies/pod-security-policy-details.tsx @@ -24,11 +24,11 @@ import "./pod-security-policy-details.scss"; import React from "react"; import { observer } from "mobx-react"; import { DrawerItem, DrawerTitle } from "../drawer"; -import type { KubeObjectDetailsProps } from "../kube-object"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; import type { PodSecurityPolicy } from "../../api/endpoints"; import { Badge } from "../badge"; import { Table, TableCell, TableHead, TableRow } from "../table"; -import { KubeObjectMeta } from "../kube-object/kube-object-meta"; +import { KubeObjectMeta } from "../kube-object-meta"; interface Props extends KubeObjectDetailsProps { } diff --git a/src/renderer/components/+preferences/preferences.tsx b/src/renderer/components/+preferences/preferences.tsx index f384d049db..82f363ee23 100644 --- a/src/renderer/components/+preferences/preferences.tsx +++ b/src/renderer/components/+preferences/preferences.tsx @@ -26,7 +26,7 @@ import moment from "moment-timezone"; import { computed, observable, reaction, makeObservable } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; -import { isWindows } from "../../../common/vars"; +import { isWindows, sentryDsn } from "../../../common/vars"; import { AppPreferenceRegistry, RegisteredAppPreference } from "../../../extensions/registries/app-preference-registry"; import { UserStore } from "../../../common/user-store"; import { ThemeStore } from "../../theme.store"; @@ -41,7 +41,6 @@ import { FormSwitch, Switcher } from "../switch"; import { KubeconfigSyncs } from "./kubeconfig-syncs"; import { SettingLayout } from "../layout/setting-layout"; import { Checkbox } from "../checkbox"; -import { sentryDsn } from "../../../common/vars"; enum Pages { Application = "application", diff --git a/src/renderer/components/+storage-classes/storage-class-details.tsx b/src/renderer/components/+storage-classes/storage-class-details.tsx index 0d2b9e0600..302a94b3f4 100644 --- a/src/renderer/components/+storage-classes/storage-class-details.tsx +++ b/src/renderer/components/+storage-classes/storage-class-details.tsx @@ -26,9 +26,9 @@ import startCase from "lodash/startCase"; import { DrawerItem, DrawerTitle } from "../drawer"; import { Badge } from "../badge"; import { observer } from "mobx-react"; -import type { KubeObjectDetailsProps } from "../kube-object"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; import type { StorageClass } from "../../api/endpoints"; -import { KubeObjectMeta } from "../kube-object/kube-object-meta"; +import { KubeObjectMeta } from "../kube-object-meta"; import { storageClassStore } from "./storage-class.store"; import { VolumeDetailsList } from "../+storage-volumes/volume-details-list"; import { volumesStore } from "../+storage-volumes/volumes.store"; diff --git a/src/renderer/components/+storage-classes/storage-classes.tsx b/src/renderer/components/+storage-classes/storage-classes.tsx index d81d32041e..64edc494e1 100644 --- a/src/renderer/components/+storage-classes/storage-classes.tsx +++ b/src/renderer/components/+storage-classes/storage-classes.tsx @@ -24,7 +24,7 @@ import "./storage-classes.scss"; import React from "react"; import type { RouteComponentProps } from "react-router-dom"; import { observer } from "mobx-react"; -import { KubeObjectListLayout } from "../kube-object"; +import { KubeObjectListLayout } from "../kube-object-list-layout"; import { storageClassStore } from "./storage-class.store"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; import type { StorageClassesRouteParams } from "../../../common/routes"; diff --git a/src/renderer/components/+storage-volume-claims/volume-claim-details.tsx b/src/renderer/components/+storage-volume-claims/volume-claim-details.tsx index 36d85b0488..3a7c373db5 100644 --- a/src/renderer/components/+storage-volume-claims/volume-claim-details.tsx +++ b/src/renderer/components/+storage-volume-claims/volume-claim-details.tsx @@ -30,10 +30,12 @@ import { podsStore } from "../+workloads-pods/pods.store"; import { Link } from "react-router-dom"; import { ResourceMetrics } from "../resource-metrics"; import { VolumeClaimDiskChart } from "./volume-claim-disk-chart"; -import { getDetailsUrl, KubeObjectDetailsProps, KubeObjectMeta } from "../kube-object"; import { getMetricsForPvc, IPvcMetrics, PersistentVolumeClaim } from "../../api/endpoints"; import { getActiveClusterEntity } from "../../api/catalog-entity-registry"; import { ClusterMetricsResourceType } from "../../../common/cluster-types"; +import { getDetailsUrl } from "../kube-details"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; +import { KubeObjectMeta } from "../kube-object-meta"; interface Props extends KubeObjectDetailsProps { } diff --git a/src/renderer/components/+storage-volume-claims/volume-claims.tsx b/src/renderer/components/+storage-volume-claims/volume-claims.tsx index 60230033f9..4e8d7dd9fe 100644 --- a/src/renderer/components/+storage-volume-claims/volume-claims.tsx +++ b/src/renderer/components/+storage-volume-claims/volume-claims.tsx @@ -26,12 +26,13 @@ import { observer } from "mobx-react"; import { Link, RouteComponentProps } from "react-router-dom"; import { volumeClaimStore } from "./volume-claim.store"; import { podsStore } from "../+workloads-pods/pods.store"; -import { getDetailsUrl, KubeObjectListLayout } from "../kube-object"; +import { KubeObjectListLayout } from "../kube-object-list-layout"; import { unitsToBytes } from "../../utils/convertMemory"; import { stopPropagation } from "../../utils"; import { storageClassApi } from "../../api/endpoints"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; import type { VolumeClaimsRouteParams } from "../../../common/routes"; +import { getDetailsUrl } from "../kube-details"; enum columnId { name = "name", diff --git a/src/renderer/components/+storage-volumes/volume-details-list.tsx b/src/renderer/components/+storage-volumes/volume-details-list.tsx index e38af1d3f8..50894e73ef 100644 --- a/src/renderer/components/+storage-volumes/volume-details-list.tsx +++ b/src/renderer/components/+storage-volumes/volume-details-list.tsx @@ -27,7 +27,7 @@ import type { PersistentVolume } from "../../api/endpoints/persistent-volume.api import { boundMethod } from "../../../common/utils/autobind"; import { TableRow } from "../table/table-row"; import { cssNames, prevDefault } from "../../utils"; -import { showDetails } from "../kube-object/kube-object-details"; +import { showDetails } from "../kube-details"; import { TableCell } from "../table/table-cell"; import { Spinner } from "../spinner/spinner"; import { DrawerTitle } from "../drawer/drawer-title"; diff --git a/src/renderer/components/+storage-volumes/volume-details.tsx b/src/renderer/components/+storage-volumes/volume-details.tsx index 66354db988..7d486fd5f9 100644 --- a/src/renderer/components/+storage-volumes/volume-details.tsx +++ b/src/renderer/components/+storage-volumes/volume-details.tsx @@ -28,8 +28,9 @@ import { observer } from "mobx-react"; import { DrawerItem, DrawerTitle } from "../drawer"; import { Badge } from "../badge"; import { PersistentVolume, pvcApi } from "../../api/endpoints"; -import { getDetailsUrl, KubeObjectDetailsProps } from "../kube-object"; -import { KubeObjectMeta } from "../kube-object/kube-object-meta"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; +import { getDetailsUrl} from "../kube-details"; +import { KubeObjectMeta } from "../kube-object-meta"; interface Props extends KubeObjectDetailsProps { } diff --git a/src/renderer/components/+storage-volumes/volumes.tsx b/src/renderer/components/+storage-volumes/volumes.tsx index ce1e313e9b..89b215946b 100644 --- a/src/renderer/components/+storage-volumes/volumes.tsx +++ b/src/renderer/components/+storage-volumes/volumes.tsx @@ -24,12 +24,13 @@ import "./volumes.scss"; import React from "react"; import { observer } from "mobx-react"; import { Link, RouteComponentProps } from "react-router-dom"; -import { getDetailsUrl, KubeObjectListLayout } from "../kube-object"; import { stopPropagation } from "../../utils"; import { volumesStore } from "./volumes.store"; import { pvcApi, storageClassApi } from "../../api/endpoints"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; import type { VolumesRouteParams } from "../../../common/routes"; +import { getDetailsUrl } from "../kube-details"; +import { KubeObjectListLayout } from "../kube-object-list-layout"; enum columnId { name = "name", diff --git a/src/renderer/components/+storage/storage.tsx b/src/renderer/components/+storage/storage.tsx index 3d4dd55ce3..cdc06a1e3c 100644 --- a/src/renderer/components/+storage/storage.tsx +++ b/src/renderer/components/+storage/storage.tsx @@ -27,7 +27,7 @@ import { TabLayout, TabLayoutRoute } from "../layout/tab-layout"; import { PersistentVolumes } from "../+storage-volumes"; import { StorageClasses } from "../+storage-classes"; import { PersistentVolumeClaims } from "../+storage-volume-claims"; -import { isAllowedResource } from "../../../common/rbac"; +import { isAllowedResource } from "../../../common/utils/allowed-resource"; import * as routes from "../../../common/routes"; @observer diff --git a/src/renderer/components/+user-management/+cluster-role-bindings/details.tsx b/src/renderer/components/+user-management/+cluster-role-bindings/details.tsx index 7dea8c083e..b6a6afba83 100644 --- a/src/renderer/components/+user-management/+cluster-role-bindings/details.tsx +++ b/src/renderer/components/+user-management/+cluster-role-bindings/details.tsx @@ -30,8 +30,8 @@ import { autoBind, ObservableHashSet, prevDefault } from "../../../utils"; import { AddRemoveButtons } from "../../add-remove-buttons"; import { ConfirmDialog } from "../../confirm-dialog"; import { DrawerTitle } from "../../drawer"; -import type { KubeObjectDetailsProps } from "../../kube-object"; -import { KubeObjectMeta } from "../../kube-object/kube-object-meta"; +import type { KubeObjectDetailsProps } from "../../kube-object-details"; +import { KubeObjectMeta } from "../../kube-object-meta"; import { Table, TableCell, TableHead, TableRow } from "../../table"; import { ClusterRoleBindingDialog } from "./dialog"; import { clusterRoleBindingsStore } from "./store"; diff --git a/src/renderer/components/+user-management/+cluster-role-bindings/dialog.tsx b/src/renderer/components/+user-management/+cluster-role-bindings/dialog.tsx index 0d810f6c48..671c0a9d2a 100644 --- a/src/renderer/components/+user-management/+cluster-role-bindings/dialog.tsx +++ b/src/renderer/components/+user-management/+cluster-role-bindings/dialog.tsx @@ -30,7 +30,7 @@ import { ClusterRole, ClusterRoleBinding, ClusterRoleBindingSubject, ServiceAcco import { Dialog, DialogProps } from "../../dialog"; import { EditableList } from "../../editable-list"; import { Icon } from "../../icon"; -import { showDetails } from "../../kube-object"; +import { showDetails } from "../../kube-details"; import { SubTitle } from "../../layout/sub-title"; import { Notifications } from "../../notifications"; import { Select, SelectOption } from "../../select"; @@ -202,13 +202,13 @@ export class ClusterRoleBindingDialog extends React.Component { if (!this.selectedRoleRef || this.bindingName === this.selectedRoleRef.getName()) { this.bindingName = value.getName(); } - + this.selectedRoleRef = value; }} /> - { diff --git a/src/renderer/components/+user-management/+cluster-roles/view.tsx b/src/renderer/components/+user-management/+cluster-roles/view.tsx index 271802c10b..aa36fbd82a 100644 --- a/src/renderer/components/+user-management/+cluster-roles/view.tsx +++ b/src/renderer/components/+user-management/+cluster-roles/view.tsx @@ -24,7 +24,7 @@ import "./view.scss"; import { observer } from "mobx-react"; import React from "react"; import type { RouteComponentProps } from "react-router"; -import { KubeObjectListLayout } from "../../kube-object"; +import { KubeObjectListLayout } from "../../kube-object-list-layout"; import { KubeObjectStatusIcon } from "../../kube-object-status-icon"; import { AddClusterRoleDialog } from "./add-dialog"; import { clusterRolesStore } from "./store"; diff --git a/src/renderer/components/+user-management/+role-bindings/details.tsx b/src/renderer/components/+user-management/+role-bindings/details.tsx index aee0f6c2af..71f062aa22 100644 --- a/src/renderer/components/+user-management/+role-bindings/details.tsx +++ b/src/renderer/components/+user-management/+role-bindings/details.tsx @@ -29,8 +29,8 @@ import { prevDefault, boundMethod } from "../../../utils"; import { AddRemoveButtons } from "../../add-remove-buttons"; import { ConfirmDialog } from "../../confirm-dialog"; import { DrawerTitle } from "../../drawer"; -import type { KubeObjectDetailsProps } from "../../kube-object"; -import { KubeObjectMeta } from "../../kube-object/kube-object-meta"; +import type { KubeObjectDetailsProps } from "../../kube-object-details"; +import { KubeObjectMeta } from "../../kube-object-meta"; import { Table, TableCell, TableHead, TableRow } from "../../table"; import { RoleBindingDialog } from "./dialog"; import { roleBindingsStore } from "./store"; diff --git a/src/renderer/components/+user-management/+role-bindings/dialog.tsx b/src/renderer/components/+user-management/+role-bindings/dialog.tsx index c163a01b83..cbd02c160a 100644 --- a/src/renderer/components/+user-management/+role-bindings/dialog.tsx +++ b/src/renderer/components/+user-management/+role-bindings/dialog.tsx @@ -32,7 +32,7 @@ import { ClusterRole, Role, roleApi, RoleBinding, RoleBindingSubject, ServiceAcc import { Dialog, DialogProps } from "../../dialog"; import { EditableList } from "../../editable-list"; import { Icon } from "../../icon"; -import { showDetails } from "../../kube-object"; +import { showDetails } from "../../kube-details"; import { SubTitle } from "../../layout/sub-title"; import { Notifications } from "../../notifications"; import { Select, SelectOption } from "../../select"; diff --git a/src/renderer/components/+user-management/+role-bindings/view.tsx b/src/renderer/components/+user-management/+role-bindings/view.tsx index 247e72482c..3eb60ad9ba 100644 --- a/src/renderer/components/+user-management/+role-bindings/view.tsx +++ b/src/renderer/components/+user-management/+role-bindings/view.tsx @@ -23,7 +23,7 @@ import "./view.scss"; import { observer } from "mobx-react"; import React from "react"; import type { RouteComponentProps } from "react-router"; -import { KubeObjectListLayout } from "../../kube-object"; +import { KubeObjectListLayout } from "../../kube-object-list-layout"; import { KubeObjectStatusIcon } from "../../kube-object-status-icon"; import { RoleBindingDialog } from "./dialog"; import { roleBindingsStore } from "./store"; diff --git a/src/renderer/components/+user-management/+roles/add-dialog.tsx b/src/renderer/components/+user-management/+roles/add-dialog.tsx index 361c14dc61..b74df3d673 100644 --- a/src/renderer/components/+user-management/+roles/add-dialog.tsx +++ b/src/renderer/components/+user-management/+roles/add-dialog.tsx @@ -28,7 +28,7 @@ import { observer } from "mobx-react"; import { NamespaceSelect } from "../../+namespaces/namespace-select"; import { Dialog, DialogProps } from "../../dialog"; import { Input } from "../../input"; -import { showDetails } from "../../kube-object"; +import { showDetails } from "../../kube-details"; import { SubTitle } from "../../layout/sub-title"; import { Notifications } from "../../notifications"; import { Wizard, WizardStep } from "../../wizard"; @@ -40,7 +40,7 @@ interface Props extends Partial { @observer export class AddRoleDialog extends React.Component { static isOpen = observable.box(false); - + @observable roleName = ""; @observable namespace = ""; diff --git a/src/renderer/components/+user-management/+roles/details.tsx b/src/renderer/components/+user-management/+roles/details.tsx index 2b6f822ed0..e90ac46e6b 100644 --- a/src/renderer/components/+user-management/+roles/details.tsx +++ b/src/renderer/components/+user-management/+roles/details.tsx @@ -26,8 +26,8 @@ import React from "react"; import type { Role } from "../../../api/endpoints"; import { DrawerTitle } from "../../drawer"; -import type { KubeObjectDetailsProps } from "../../kube-object"; -import { KubeObjectMeta } from "../../kube-object/kube-object-meta"; +import type { KubeObjectDetailsProps } from "../../kube-object-details"; +import { KubeObjectMeta } from "../../kube-object-meta"; interface Props extends KubeObjectDetailsProps { } diff --git a/src/renderer/components/+user-management/+roles/view.tsx b/src/renderer/components/+user-management/+roles/view.tsx index dd71c83b93..30e58e787d 100644 --- a/src/renderer/components/+user-management/+roles/view.tsx +++ b/src/renderer/components/+user-management/+roles/view.tsx @@ -24,7 +24,7 @@ import "./view.scss"; import { observer } from "mobx-react"; import React from "react"; import type { RouteComponentProps } from "react-router"; -import { KubeObjectListLayout } from "../../kube-object"; +import { KubeObjectListLayout } from "../../kube-object-list-layout"; import { KubeObjectStatusIcon } from "../../kube-object-status-icon"; import { AddRoleDialog } from "./add-dialog"; import { rolesStore } from "./store"; diff --git a/src/renderer/components/+user-management/+service-accounts/create-dialog.tsx b/src/renderer/components/+user-management/+service-accounts/create-dialog.tsx index 1f50e717c6..0fbebbd77a 100644 --- a/src/renderer/components/+user-management/+service-accounts/create-dialog.tsx +++ b/src/renderer/components/+user-management/+service-accounts/create-dialog.tsx @@ -29,7 +29,7 @@ import { NamespaceSelect } from "../../+namespaces/namespace-select"; import { Dialog, DialogProps } from "../../dialog"; import { Input } from "../../input"; import { systemName } from "../../input/input_validators"; -import { showDetails } from "../../kube-object"; +import { showDetails } from "../../kube-details"; import { SubTitle } from "../../layout/sub-title"; import { Notifications } from "../../notifications"; import { Wizard, WizardStep } from "../../wizard"; diff --git a/src/renderer/components/+user-management/+service-accounts/details.tsx b/src/renderer/components/+user-management/+service-accounts/details.tsx index 578cde2ab4..9b6bab1ff1 100644 --- a/src/renderer/components/+user-management/+service-accounts/details.tsx +++ b/src/renderer/components/+user-management/+service-accounts/details.tsx @@ -30,10 +30,11 @@ import { secretsStore } from "../../+config-secrets/secrets.store"; import { Secret, ServiceAccount } from "../../../api/endpoints"; import { DrawerItem, DrawerTitle } from "../../drawer"; import { Icon } from "../../icon"; -import { getDetailsUrl, KubeObjectDetailsProps } from "../../kube-object"; -import { KubeObjectMeta } from "../../kube-object/kube-object-meta"; +import { KubeObjectMeta } from "../../kube-object-meta"; import { Spinner } from "../../spinner"; import { ServiceAccountsSecret } from "./secret"; +import { getDetailsUrl } from "../../kube-details"; +import type { KubeObjectDetailsProps } from "../../kube-object-details"; interface Props extends KubeObjectDetailsProps { } diff --git a/src/renderer/components/+user-management/+service-accounts/view.tsx b/src/renderer/components/+user-management/+service-accounts/view.tsx index c8bdaaa656..af2090018c 100644 --- a/src/renderer/components/+user-management/+service-accounts/view.tsx +++ b/src/renderer/components/+user-management/+service-accounts/view.tsx @@ -26,9 +26,9 @@ import React from "react"; import type { RouteComponentProps } from "react-router"; import type { ServiceAccount } from "../../../api/endpoints/service-accounts.api"; import { Icon } from "../../icon"; -import { KubeObjectListLayout } from "../../kube-object"; +import { KubeObjectListLayout } from "../../kube-object-list-layout"; import { KubeObjectStatusIcon } from "../../kube-object-status-icon"; -import type { KubeObjectMenuProps } from "../../kube-object/kube-object-menu"; +import type { KubeObjectMenuProps } from "../../kube-object-menu"; import { openServiceAccountKubeConfig } from "../../kubeconfig-dialog"; import { MenuItem } from "../../menu"; import { CreateServiceAccountDialog } from "./create-dialog"; diff --git a/src/renderer/components/+user-management/user-management.tsx b/src/renderer/components/+user-management/user-management.tsx index 3c7e042cd5..2b6191a13e 100644 --- a/src/renderer/components/+user-management/user-management.tsx +++ b/src/renderer/components/+user-management/user-management.tsx @@ -25,7 +25,7 @@ import React from "react"; import { observer } from "mobx-react"; import { TabLayout, TabLayoutRoute } from "../layout/tab-layout"; import { PodSecurityPolicies } from "../+pod-security-policies"; -import { isAllowedResource } from "../../../common/rbac"; +import { isAllowedResource } from "../../../common/utils/allowed-resource"; import * as routes from "../../../common/routes"; import { ClusterRoleBindings } from "./+cluster-role-bindings"; import { ServiceAccounts } from "./+service-accounts"; diff --git a/src/renderer/components/+workloads-cronjobs/cronjob-details.tsx b/src/renderer/components/+workloads-cronjobs/cronjob-details.tsx index 12f919b4e6..8d0c50b5e0 100644 --- a/src/renderer/components/+workloads-cronjobs/cronjob-details.tsx +++ b/src/renderer/components/+workloads-cronjobs/cronjob-details.tsx @@ -29,9 +29,10 @@ import { Badge } from "../badge/badge"; import { jobStore } from "../+workloads-jobs/job.store"; import { Link } from "react-router-dom"; import { cronJobStore } from "./cronjob.store"; -import { getDetailsUrl, KubeObjectDetailsProps } from "../kube-object"; import type { CronJob, Job } from "../../api/endpoints"; -import { KubeObjectMeta } from "../kube-object/kube-object-meta"; +import { KubeObjectMeta } from "../kube-object-meta"; +import { getDetailsUrl } from "../kube-details"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; interface Props extends KubeObjectDetailsProps { } diff --git a/src/renderer/components/+workloads-cronjobs/cronjobs.tsx b/src/renderer/components/+workloads-cronjobs/cronjobs.tsx index 8dca609361..f17d8ed5f1 100644 --- a/src/renderer/components/+workloads-cronjobs/cronjobs.tsx +++ b/src/renderer/components/+workloads-cronjobs/cronjobs.tsx @@ -30,8 +30,8 @@ import { Icon } from "../icon"; import { cronJobStore } from "./cronjob.store"; import { jobStore } from "../+workloads-jobs/job.store"; import { eventStore } from "../+events/event.store"; -import type { KubeObjectMenuProps } from "../kube-object/kube-object-menu"; -import { KubeObjectListLayout } from "../kube-object"; +import type { KubeObjectMenuProps } from "../kube-object-menu"; +import { KubeObjectListLayout } from "../kube-object-list-layout"; import { CronJobTriggerDialog } from "./cronjob-trigger-dialog"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; import { ConfirmDialog } from "../confirm-dialog/confirm-dialog"; diff --git a/src/renderer/components/+workloads-daemonsets/daemonset-details.tsx b/src/renderer/components/+workloads-daemonsets/daemonset-details.tsx index e572ca5ab2..b9931bc82b 100644 --- a/src/renderer/components/+workloads-daemonsets/daemonset-details.tsx +++ b/src/renderer/components/+workloads-daemonsets/daemonset-details.tsx @@ -30,16 +30,16 @@ import { PodDetailsTolerations } from "../+workloads-pods/pod-details-toleration import { PodDetailsAffinities } from "../+workloads-pods/pod-details-affinities"; import { daemonSetStore } from "./daemonsets.store"; import { podsStore } from "../+workloads-pods/pods.store"; -import type { KubeObjectDetailsProps } from "../kube-object"; import { DaemonSet, getMetricsForDaemonSets, IPodMetrics } from "../../api/endpoints"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; import { ResourceMetrics, ResourceMetricsText } from "../resource-metrics"; import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts"; import { makeObservable, observable, reaction } from "mobx"; import { PodDetailsList } from "../+workloads-pods/pod-details-list"; -import { KubeObjectMeta } from "../kube-object/kube-object-meta"; +import { KubeObjectMeta } from "../kube-object-meta"; import { getActiveClusterEntity } from "../../api/catalog-entity-registry"; -import { ClusterMetricsResourceType } from "../../../common/cluster-types"; import { boundMethod } from "../../utils"; +import { ClusterMetricsResourceType } from "../../../common/cluster-types"; interface Props extends KubeObjectDetailsProps { } diff --git a/src/renderer/components/+workloads-daemonsets/daemonsets.tsx b/src/renderer/components/+workloads-daemonsets/daemonsets.tsx index 63f04a8049..b8dcb51568 100644 --- a/src/renderer/components/+workloads-daemonsets/daemonsets.tsx +++ b/src/renderer/components/+workloads-daemonsets/daemonsets.tsx @@ -29,7 +29,7 @@ import { eventStore } from "../+events/event.store"; import { daemonSetStore } from "./daemonsets.store"; import { podsStore } from "../+workloads-pods/pods.store"; import { nodesStore } from "../+nodes/nodes.store"; -import { KubeObjectListLayout } from "../kube-object"; +import { KubeObjectListLayout } from "../kube-object-list-layout"; import { Badge } from "../badge"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; import type { DaemonSetsRouteParams } from "../../../common/routes"; diff --git a/src/renderer/components/+workloads-deployments/deployment-details.tsx b/src/renderer/components/+workloads-deployments/deployment-details.tsx index 6797df5ce1..ac3807fae6 100644 --- a/src/renderer/components/+workloads-deployments/deployment-details.tsx +++ b/src/renderer/components/+workloads-deployments/deployment-details.tsx @@ -30,18 +30,18 @@ import { Deployment, getMetricsForDeployments, IPodMetrics } from "../../api/end import { PodDetailsTolerations } from "../+workloads-pods/pod-details-tolerations"; import { PodDetailsAffinities } from "../+workloads-pods/pod-details-affinities"; import { podsStore } from "../+workloads-pods/pods.store"; -import type { KubeObjectDetailsProps } from "../kube-object"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; import { ResourceMetrics, ResourceMetricsText } from "../resource-metrics"; import { deploymentStore } from "./deployments.store"; import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts"; import { makeObservable, observable, reaction } from "mobx"; import { PodDetailsList } from "../+workloads-pods/pod-details-list"; -import { KubeObjectMeta } from "../kube-object/kube-object-meta"; +import { KubeObjectMeta } from "../kube-object-meta"; import { replicaSetStore } from "../+workloads-replicasets/replicasets.store"; import { DeploymentReplicaSets } from "./deployment-replicasets"; import { getActiveClusterEntity } from "../../api/catalog-entity-registry"; -import { ClusterMetricsResourceType } from "../../../common/cluster-types"; import { boundMethod } from "../../utils"; +import { ClusterMetricsResourceType } from "../../../common/cluster-types"; interface Props extends KubeObjectDetailsProps { } diff --git a/src/renderer/components/+workloads-deployments/deployment-replicasets.tsx b/src/renderer/components/+workloads-deployments/deployment-replicasets.tsx index 0a556ddcfc..8b8e65e7f7 100644 --- a/src/renderer/components/+workloads-deployments/deployment-replicasets.tsx +++ b/src/renderer/components/+workloads-deployments/deployment-replicasets.tsx @@ -24,14 +24,14 @@ import "./deployment-replicasets.scss"; import React from "react"; import { observer } from "mobx-react"; import type { ReplicaSet } from "../../api/endpoints"; -import { KubeObjectMenu, KubeObjectMenuProps } from "../kube-object/kube-object-menu"; +import { KubeObjectMenu, KubeObjectMenuProps } from "../kube-object-menu"; import { Spinner } from "../spinner"; import { prevDefault, stopPropagation } from "../../utils"; import { DrawerTitle } from "../drawer"; import { Table, TableCell, TableHead, TableRow } from "../table"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; import { replicaSetStore } from "../+workloads-replicasets/replicasets.store"; -import { showDetails } from "../kube-object"; +import { showDetails } from "../kube-details"; enum sortBy { diff --git a/src/renderer/components/+workloads-deployments/deployments.tsx b/src/renderer/components/+workloads-deployments/deployments.tsx index d43670f6e7..6531114fa9 100644 --- a/src/renderer/components/+workloads-deployments/deployments.tsx +++ b/src/renderer/components/+workloads-deployments/deployments.tsx @@ -25,7 +25,7 @@ import React from "react"; import { observer } from "mobx-react"; import type { RouteComponentProps } from "react-router"; import { Deployment, deploymentApi } from "../../api/endpoints"; -import type { KubeObjectMenuProps } from "../kube-object/kube-object-menu"; +import type { KubeObjectMenuProps } from "../kube-object-menu"; import { MenuItem } from "../menu"; import { Icon } from "../icon"; import { DeploymentScaleDialog } from "./deployment-scale-dialog"; @@ -35,7 +35,7 @@ import { replicaSetStore } from "../+workloads-replicasets/replicasets.store"; import { podsStore } from "../+workloads-pods/pods.store"; import { nodesStore } from "../+nodes/nodes.store"; import { eventStore } from "../+events/event.store"; -import { KubeObjectListLayout } from "../kube-object"; +import { KubeObjectListLayout } from "../kube-object-list-layout"; import { cssNames } from "../../utils"; import kebabCase from "lodash/kebabCase"; import orderBy from "lodash/orderBy"; diff --git a/src/renderer/components/+workloads-jobs/job-details.tsx b/src/renderer/components/+workloads-jobs/job-details.tsx index bdaa4650de..fe2f9b9798 100644 --- a/src/renderer/components/+workloads-jobs/job-details.tsx +++ b/src/renderer/components/+workloads-jobs/job-details.tsx @@ -32,17 +32,18 @@ import { PodDetailsTolerations } from "../+workloads-pods/pod-details-toleration import { PodDetailsAffinities } from "../+workloads-pods/pod-details-affinities"; import { podsStore } from "../+workloads-pods/pods.store"; import { jobStore } from "./job.store"; -import { getDetailsUrl, KubeObjectDetailsProps } from "../kube-object"; import { getMetricsForJobs, IPodMetrics, Job } from "../../api/endpoints"; import { PodDetailsList } from "../+workloads-pods/pod-details-list"; -import { lookupApiLink } from "../../api/kube-api"; -import { KubeObjectMeta } from "../kube-object/kube-object-meta"; import { makeObservable, observable } from "mobx"; import { podMetricTabs, PodCharts } from "../+workloads-pods/pod-charts"; -import { ClusterMetricsResourceType } from "../../../common/cluster-types"; import { getActiveClusterEntity } from "../../api/catalog-entity-registry"; import { ResourceMetrics } from "../resource-metrics"; import { boundMethod } from "autobind-decorator"; +import { KubeObjectMeta } from "../kube-object-meta"; +import { apiManager } from "../../api/api-manager"; +import { getDetailsUrl } from "../kube-details"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; +import { ClusterMetricsResourceType } from "../../../common/cluster-types"; interface Props extends KubeObjectDetailsProps { } @@ -116,7 +117,7 @@ export class JobDetails extends React.Component { { ownerRefs.map(ref => { const { name, kind } = ref; - const detailsUrl = getDetailsUrl(lookupApiLink(ref, job)); + const detailsUrl = getDetailsUrl(apiManager.lookupApiLink(ref, job)); return (

diff --git a/src/renderer/components/+workloads-jobs/jobs.tsx b/src/renderer/components/+workloads-jobs/jobs.tsx index e2640db6f6..6dc2362604 100644 --- a/src/renderer/components/+workloads-jobs/jobs.tsx +++ b/src/renderer/components/+workloads-jobs/jobs.tsx @@ -27,7 +27,7 @@ import type { RouteComponentProps } from "react-router"; import { podsStore } from "../+workloads-pods/pods.store"; import { jobStore } from "./job.store"; import { eventStore } from "../+events/event.store"; -import { KubeObjectListLayout } from "../kube-object"; +import { KubeObjectListLayout } from "../kube-object-list-layout"; import kebabCase from "lodash/kebabCase"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; import type { JobsRouteParams } from "../../../common/routes"; diff --git a/src/renderer/components/+workloads-overview/overview-statuses.tsx b/src/renderer/components/+workloads-overview/overview-statuses.tsx index ebf62c1d98..f20b9d25ff 100644 --- a/src/renderer/components/+workloads-overview/overview-statuses.tsx +++ b/src/renderer/components/+workloads-overview/overview-statuses.tsx @@ -28,10 +28,11 @@ import { Link } from "react-router-dom"; import { workloadStores } from "../+workloads"; import { namespaceStore } from "../+namespaces/namespace.store"; import { NamespaceSelectFilter } from "../+namespaces/namespace-select-filter"; -import { isAllowedResource, KubeResource } from "../../../common/rbac"; +import type { KubeResource } from "../../../common/rbac"; import { ResourceNames } from "../../utils/rbac"; import { boundMethod } from "../../utils"; import { workloadURL } from "../../../common/routes"; +import { isAllowedResource } from "../../../common/utils/allowed-resource"; const resources: KubeResource[] = [ "pods", diff --git a/src/renderer/components/+workloads-pods/pod-details-list.tsx b/src/renderer/components/+workloads-pods/pod-details-list.tsx index 8ea49c366d..558d2c2275 100644 --- a/src/renderer/components/+workloads-pods/pod-details-list.tsx +++ b/src/renderer/components/+workloads-pods/pod-details-list.tsx @@ -34,7 +34,7 @@ import { Table, TableCell, TableHead, TableRow } from "../table"; import { Spinner } from "../spinner"; import { DrawerTitle } from "../drawer"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; -import { showDetails } from "../kube-object"; +import { showDetails } from "../kube-details"; enum sortBy { name = "name", diff --git a/src/renderer/components/+workloads-pods/pod-details-secrets.tsx b/src/renderer/components/+workloads-pods/pod-details-secrets.tsx index 9ca49c3668..d1fc655b2b 100644 --- a/src/renderer/components/+workloads-pods/pod-details-secrets.tsx +++ b/src/renderer/components/+workloads-pods/pod-details-secrets.tsx @@ -26,7 +26,7 @@ import { Link } from "react-router-dom"; import { autorun, observable, makeObservable } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; import { Pod, Secret, secretsApi } from "../../api/endpoints"; -import { getDetailsUrl } from "../kube-object"; +import { getDetailsUrl } from "../kube-details"; interface Props { pod: Pod; diff --git a/src/renderer/components/+workloads-pods/pod-details.tsx b/src/renderer/components/+workloads-pods/pod-details.tsx index 3087cc8257..e79a37275e 100644 --- a/src/renderer/components/+workloads-pods/pod-details.tsx +++ b/src/renderer/components/+workloads-pods/pod-details.tsx @@ -36,12 +36,13 @@ import { PodDetailsTolerations } from "./pod-details-tolerations"; import { Icon } from "../icon"; import { PodDetailsSecrets } from "./pod-details-secrets"; import { ResourceMetrics } from "../resource-metrics"; -import { getDetailsUrl, KubeObjectDetailsProps } from "../kube-object"; import { getItemMetrics } from "../../api/endpoints/metrics.api"; import { PodCharts, podMetricTabs } from "./pod-charts"; -import { KubeObjectMeta } from "../kube-object/kube-object-meta"; +import { KubeObjectMeta } from "../kube-object-meta"; import { getActiveClusterEntity } from "../../api/catalog-entity-registry"; import { ClusterMetricsResourceType } from "../../../common/cluster-types"; +import { getDetailsUrl } from "../kube-details"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; interface Props extends KubeObjectDetailsProps { } diff --git a/src/renderer/components/+workloads-pods/pods.tsx b/src/renderer/components/+workloads-pods/pods.tsx index b91a8a98e8..a11d8c0fd6 100644 --- a/src/renderer/components/+workloads-pods/pods.tsx +++ b/src/renderer/components/+workloads-pods/pods.tsx @@ -28,17 +28,18 @@ import { podsStore } from "./pods.store"; import type { RouteComponentProps } from "react-router"; import { volumeClaimStore } from "../+storage-volume-claims/volume-claim.store"; import { eventStore } from "../+events/event.store"; -import { getDetailsUrl, KubeObjectListLayout } from "../kube-object"; import { nodesApi, Pod } from "../../api/endpoints"; import { StatusBrick } from "../status-brick"; import { cssNames, stopPropagation } from "../../utils"; import toPairs from "lodash/toPairs"; import startCase from "lodash/startCase"; import kebabCase from "lodash/kebabCase"; -import { lookupApiLink } from "../../api/kube-api"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; import { Badge } from "../badge"; import type { PodsRouteParams } from "../../../common/routes"; +import { apiManager } from "../../api/api-manager"; +import { getDetailsUrl } from "../kube-details"; +import { KubeObjectListLayout } from "../kube-object-list-layout"; enum columnId { name = "name", @@ -134,7 +135,7 @@ export class Pods extends React.Component { pod.getRestartsCount(), pod.getOwnerRefs().map(ref => { const { kind, name } = ref; - const detailsLink = getDetailsUrl(lookupApiLink(ref, pod)); + const detailsLink = getDetailsUrl(apiManager.lookupApiLink(ref, pod)); return ( diff --git a/src/renderer/components/+workloads-replicasets/replicaset-details.tsx b/src/renderer/components/+workloads-replicasets/replicaset-details.tsx index 2f84976db5..6eaffed60b 100644 --- a/src/renderer/components/+workloads-replicasets/replicaset-details.tsx +++ b/src/renderer/components/+workloads-replicasets/replicaset-details.tsx @@ -30,15 +30,15 @@ import { PodDetailsTolerations } from "../+workloads-pods/pod-details-toleration import { PodDetailsAffinities } from "../+workloads-pods/pod-details-affinities"; import { disposeOnUnmount, observer } from "mobx-react"; import { podsStore } from "../+workloads-pods/pods.store"; -import type { KubeObjectDetailsProps } from "../kube-object"; import { getMetricsForReplicaSets, IPodMetrics, ReplicaSet } from "../../api/endpoints"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; import { ResourceMetrics, ResourceMetricsText } from "../resource-metrics"; import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts"; import { PodDetailsList } from "../+workloads-pods/pod-details-list"; -import { KubeObjectMeta } from "../kube-object/kube-object-meta"; +import { KubeObjectMeta } from "../kube-object-meta"; import { getActiveClusterEntity } from "../../api/catalog-entity-registry"; -import { ClusterMetricsResourceType } from "../../../common/cluster-types"; import { boundMethod } from "../../utils"; +import { ClusterMetricsResourceType } from "../../../common/cluster-types"; interface Props extends KubeObjectDetailsProps { } diff --git a/src/renderer/components/+workloads-replicasets/replicasets.tsx b/src/renderer/components/+workloads-replicasets/replicasets.tsx index 447280899f..156d3e0a13 100644 --- a/src/renderer/components/+workloads-replicasets/replicasets.tsx +++ b/src/renderer/components/+workloads-replicasets/replicasets.tsx @@ -24,11 +24,11 @@ import "./replicasets.scss"; import React from "react"; import { observer } from "mobx-react"; import type { ReplicaSet } from "../../api/endpoints"; -import type { KubeObjectMenuProps } from "../kube-object/kube-object-menu"; +import type { KubeObjectMenuProps } from "../kube-object-menu"; import { replicaSetStore } from "./replicasets.store"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; import type { RouteComponentProps } from "react-router"; -import { KubeObjectListLayout } from "../kube-object/kube-object-list-layout"; +import { KubeObjectListLayout } from "../kube-object-list-layout"; import { MenuItem } from "../menu/menu"; import { Icon } from "../icon/icon"; import { ReplicaSetScaleDialog } from "./replicaset-scale-dialog"; diff --git a/src/renderer/components/+workloads-statefulsets/statefulset-details.tsx b/src/renderer/components/+workloads-statefulsets/statefulset-details.tsx index 0dac7c8a08..c9539f8a2f 100644 --- a/src/renderer/components/+workloads-statefulsets/statefulset-details.tsx +++ b/src/renderer/components/+workloads-statefulsets/statefulset-details.tsx @@ -31,15 +31,15 @@ import { PodDetailsTolerations } from "../+workloads-pods/pod-details-toleration import { PodDetailsAffinities } from "../+workloads-pods/pod-details-affinities"; import { podsStore } from "../+workloads-pods/pods.store"; import { statefulSetStore } from "./statefulset.store"; -import type { KubeObjectDetailsProps } from "../kube-object"; import { getMetricsForStatefulSets, IPodMetrics, StatefulSet } from "../../api/endpoints"; +import type { KubeObjectDetailsProps } from "../kube-object-details"; import { ResourceMetrics, ResourceMetricsText } from "../resource-metrics"; import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts"; import { PodDetailsList } from "../+workloads-pods/pod-details-list"; -import { KubeObjectMeta } from "../kube-object/kube-object-meta"; +import { KubeObjectMeta } from "../kube-object-meta"; import { getActiveClusterEntity } from "../../api/catalog-entity-registry"; -import { ClusterMetricsResourceType } from "../../../common/cluster-types"; import { boundMethod } from "../../utils"; +import { ClusterMetricsResourceType } from "../../../common/cluster-types"; interface Props extends KubeObjectDetailsProps { } diff --git a/src/renderer/components/+workloads-statefulsets/statefulsets.tsx b/src/renderer/components/+workloads-statefulsets/statefulsets.tsx index ff6441f33a..88997e19c7 100644 --- a/src/renderer/components/+workloads-statefulsets/statefulsets.tsx +++ b/src/renderer/components/+workloads-statefulsets/statefulsets.tsx @@ -29,8 +29,8 @@ import { podsStore } from "../+workloads-pods/pods.store"; import { statefulSetStore } from "./statefulset.store"; import { nodesStore } from "../+nodes/nodes.store"; import { eventStore } from "../+events/event.store"; -import type { KubeObjectMenuProps } from "../kube-object/kube-object-menu"; -import { KubeObjectListLayout } from "../kube-object"; +import type { KubeObjectMenuProps } from "../kube-object-menu"; +import { KubeObjectListLayout } from "../kube-object-list-layout"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; import { StatefulSetScaleDialog } from "./statefulset-scale-dialog"; import { MenuItem } from "../menu/menu"; diff --git a/src/renderer/components/+workloads/workloads.tsx b/src/renderer/components/+workloads/workloads.tsx index 5f8724b928..71007b1195 100644 --- a/src/renderer/components/+workloads/workloads.tsx +++ b/src/renderer/components/+workloads/workloads.tsx @@ -31,7 +31,7 @@ import { DaemonSets } from "../+workloads-daemonsets"; import { StatefulSets } from "../+workloads-statefulsets"; import { Jobs } from "../+workloads-jobs"; import { CronJobs } from "../+workloads-cronjobs"; -import { isAllowedResource } from "../../../common/rbac"; +import { isAllowedResource } from "../../../common/utils/allowed-resource"; import { ReplicaSets } from "../+workloads-replicasets"; import * as routes from "../../../common/routes"; diff --git a/src/renderer/components/app.tsx b/src/renderer/components/app.tsx index b9c56f475e..7a11da995d 100755 --- a/src/renderer/components/app.tsx +++ b/src/renderer/components/app.tsx @@ -31,7 +31,6 @@ import { Events } from "./+events/events"; import { DeploymentScaleDialog } from "./+workloads-deployments/deployment-scale-dialog"; import { CronJobTriggerDialog } from "./+workloads-cronjobs/cronjob-trigger-dialog"; import { CustomResources } from "./+custom-resources/custom-resources"; -import { isAllowedResource } from "../../common/rbac"; import logger from "../../main/logger"; import { webFrame } from "electron"; import { ClusterPageRegistry, getExtensionPageUrl } from "../../extensions/registries/page-registry"; @@ -55,7 +54,7 @@ import { TabLayout, TabLayoutRoute } from "./layout/tab-layout"; import { ErrorBoundary } from "./error-boundary"; import { MainLayout } from "./layout/main-layout"; import { Notifications } from "./notifications"; -import { KubeObjectDetails } from "./kube-object"; +import { KubeObjectDetails } from "./kube-object-details"; import { KubeConfigDialog } from "./kubeconfig-dialog"; import { Terminal } from "./dock/terminal"; import { namespaceStore } from "./+namespaces/namespace.store"; @@ -72,6 +71,7 @@ import { catalogEntityRegistry } from "../api/catalog-entity-registry"; import { getHostedClusterId } from "../utils"; import { ClusterStore } from "../../common/cluster-store"; import type { ClusterId } from "../../common/cluster-types"; +import { isAllowedResource } from "../../common/utils/allowed-resource"; @observer export class App extends React.Component { diff --git a/src/renderer/components/cluster-settings/components/cluster-node-shell-setting.tsx b/src/renderer/components/cluster-settings/components/cluster-node-shell-setting.tsx index a5b4300fe3..1fb101a15c 100644 --- a/src/renderer/components/cluster-settings/components/cluster-node-shell-setting.tsx +++ b/src/renderer/components/cluster-settings/components/cluster-node-shell-setting.tsx @@ -26,7 +26,7 @@ import React from "react"; import { Input } from "../../input/input"; import { disposeOnUnmount, observer } from "mobx-react"; import { Icon } from "../../icon/icon"; -import { initialNodeShellImage } from "../../../../common/cluster-store"; +import { initialNodeShellImage } from "../../../../common/cluster-types"; interface Props { cluster: Cluster; diff --git a/src/renderer/components/command-palette/command-container.tsx b/src/renderer/components/command-palette/command-container.tsx index f90586fd5a..29c08a4443 100644 --- a/src/renderer/components/command-palette/command-container.tsx +++ b/src/renderer/components/command-palette/command-container.tsx @@ -21,32 +21,15 @@ import "./command-container.scss"; -import { action, observable, makeObservable } from "mobx"; import { observer } from "mobx-react"; import React from "react"; import { Dialog } from "../dialog"; -import { EventEmitter } from "../../../common/event-emitter"; import { ipcRendererOn } from "../../../common/ipc"; import { CommandDialog } from "./command-dialog"; import type { ClusterId } from "../../../common/cluster-types"; import { catalogEntityRegistry } from "../../api/catalog-entity-registry"; import { CommandRegistration, CommandRegistry } from "../../../extensions/registries/command-registry"; - -export type CommandDialogEvent = { - component: React.ReactElement -}; - -const commandDialogBus = new EventEmitter<[CommandDialogEvent]>(); - -export class CommandOverlay { - static open(component: React.ReactElement) { - commandDialogBus.emit({ component }); - } - - static close() { - commandDialogBus.emit({ component: null }); - } -} +import { CommandOverlay } from "./command-overlay"; export interface CommandContainerProps { clusterId?: ClusterId; @@ -54,25 +37,13 @@ export interface CommandContainerProps { @observer export class CommandContainer extends React.Component { - @observable.ref commandComponent: React.ReactNode; - - constructor(props: CommandContainerProps) { - super(props); - makeObservable(this); - } - private escHandler(event: KeyboardEvent) { if (event.key === "Escape") { event.stopPropagation(); - this.closeDialog(); + CommandOverlay.close(); } } - @action - private closeDialog() { - this.commandComponent = null; - } - private findCommandById(commandId: string) { return CommandRegistry.getInstance().getItems().find((command) => command.id === commandId); } @@ -98,16 +69,18 @@ export class CommandContainer extends React.Component { }); } window.addEventListener("keyup", (e) => this.escHandler(e), true); - commandDialogBus.addListener((event) => { - this.commandComponent = event.component; - }); } render() { return ( -

this.commandComponent = null} modal={false}> +
- {this.commandComponent} + {CommandOverlay.component.get()}
); diff --git a/src/renderer/components/command-palette/command-dialog.tsx b/src/renderer/components/command-palette/command-dialog.tsx index 493d9bea70..b99a73ee9f 100644 --- a/src/renderer/components/command-palette/command-dialog.tsx +++ b/src/renderer/components/command-palette/command-dialog.tsx @@ -25,7 +25,7 @@ import { computed, makeObservable, observable } from "mobx"; import { observer } from "mobx-react"; import React from "react"; import { CommandRegistry } from "../../../extensions/registries/command-registry"; -import { CommandOverlay } from "./command-container"; +import { CommandOverlay } from "./command-overlay"; import { broadcastMessage } from "../../../common/ipc"; import { navigate } from "../../navigation"; import { catalogEntityRegistry } from "../../api/catalog-entity-registry"; diff --git a/src/renderer/components/command-palette/command-overlay.ts b/src/renderer/components/command-palette/command-overlay.ts new file mode 100644 index 0000000000..27c7176ca1 --- /dev/null +++ b/src/renderer/components/command-palette/command-overlay.ts @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +import { computed, observable } from "mobx"; +import React from "react"; + +export class CommandOverlay { + static component = observable.box(null, { deep: false }); + + @computed + static get isOpen(): boolean { + return Boolean(CommandOverlay.component.get()); + } + + static open(component: React.ReactElement) { + if (!React.isValidElement(component)) { + throw new TypeError("CommandOverlay.open must be passed a valid ReactElement"); + } + + CommandOverlay.component.set(component); + } + + static close() { + CommandOverlay.component.set(null); + } +} diff --git a/src/renderer/components/command-palette/index.ts b/src/renderer/components/command-palette/index.ts index ea2e83ed31..27169ddae2 100644 --- a/src/renderer/components/command-palette/index.ts +++ b/src/renderer/components/command-palette/index.ts @@ -21,3 +21,4 @@ export * from "./command-container"; export * from "./command-dialog"; +export * from "./command-overlay"; diff --git a/src/renderer/components/context.ts b/src/renderer/components/context.ts index 758e3dd20d..a13e952359 100755 --- a/src/renderer/components/context.ts +++ b/src/renderer/components/context.ts @@ -19,10 +19,10 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import { ClusterStore } from "../../common/cluster-store"; import type { Cluster } from "../../main/cluster"; -import { getHostedClusterId } from "../utils"; +import { ClusterStore } from "../../common/cluster-store"; import { namespaceStore } from "./+namespaces/namespace.store"; +import { getHostedClusterId } from "../utils"; export interface ClusterContext { cluster?: Cluster; diff --git a/src/renderer/components/dock/create-resource.tsx b/src/renderer/components/dock/create-resource.tsx index f3423a7771..73a2649f6f 100644 --- a/src/renderer/components/dock/create-resource.tsx +++ b/src/renderer/components/dock/create-resource.tsx @@ -34,7 +34,6 @@ import type { DockTab } from "./dock.store"; import { EditorPanel } from "./editor-panel"; import { InfoPanel } from "./info-panel"; import { resourceApplierApi } from "../../api/endpoints/resource-applier.api"; -import type { JsonApiErrorParsed } from "../../api/json-api"; import { Notifications } from "../notifications"; interface Props { @@ -103,10 +102,14 @@ export class CreateResource extends React.Component { const errors: string[] = []; await Promise.all( - resources.map(data => { - return resourceApplierApi.update(data) - .then(item => createdResources.push(item.getName())) - .catch((err: JsonApiErrorParsed) => errors.push(err.toString())); + resources.map(async data => { + try { + const { metadata: { name } } = await resourceApplierApi.update(data); + + createdResources.push(name); + } catch (err) { + errors.push(err.toString()); + } }) ); diff --git a/src/renderer/components/dock/dock.store.ts b/src/renderer/components/dock/dock.store.ts index eb5902d7db..e906656692 100644 --- a/src/renderer/components/dock/dock.store.ts +++ b/src/renderer/components/dock/dock.store.ts @@ -282,6 +282,7 @@ export class DockStore implements DockStorageState { if (newTab?.kind === TabKind.TERMINAL) { // close the dock when selected sibling inactive terminal tab + // eslint-disable-next-line import/no-cycle const { TerminalStore } = await import("./terminal.store"); if (!TerminalStore.getInstance(false)?.isConnected(newTab.id)) this.close(); diff --git a/src/renderer/components/hotbar/hotbar-menu.tsx b/src/renderer/components/hotbar/hotbar-menu.tsx index 56fa7a25fc..8a05ad1c97 100644 --- a/src/renderer/components/hotbar/hotbar-menu.tsx +++ b/src/renderer/components/hotbar/hotbar-menu.tsx @@ -26,13 +26,14 @@ import { observer } from "mobx-react"; import { HotbarEntityIcon } from "./hotbar-entity-icon"; import { cssNames, IClassName } from "../../utils"; import { catalogEntityRegistry } from "../../api/catalog-entity-registry"; -import { defaultHotbarCells, HotbarItem, HotbarStore } from "../../../common/hotbar-store"; +import { HotbarStore } from "../../../common/hotbar-store"; import { CatalogEntity, catalogEntityRunContext } from "../../api/catalog-entity"; import { DragDropContext, Draggable, Droppable, DropResult } from "react-beautiful-dnd"; import { HotbarSelector } from "./hotbar-selector"; import { HotbarCell } from "./hotbar-cell"; import { HotbarIcon } from "./hotbar-icon"; import { computed } from "mobx"; +import { HotbarItem, defaultHotbarCells } from "../../../common/hotbar-types"; interface Props { className?: IClassName; diff --git a/src/renderer/components/hotbar/hotbar-selector.tsx b/src/renderer/components/hotbar/hotbar-selector.tsx index cc9617aa47..0144f2befd 100644 --- a/src/renderer/components/hotbar/hotbar-selector.tsx +++ b/src/renderer/components/hotbar/hotbar-selector.tsx @@ -23,12 +23,13 @@ import "./hotbar-selector.scss"; import React from "react"; import { Icon } from "../icon"; import { Badge } from "../badge"; -import { Hotbar, HotbarStore } from "../../../common/hotbar-store"; +import { HotbarStore } from "../../../common/hotbar-store"; import { CommandOverlay } from "../command-palette"; import { HotbarSwitchCommand } from "./hotbar-switch-command"; import { hotbarDisplayIndex } from "./hotbar-display-label"; import { TooltipPosition } from "../tooltip"; import { observer } from "mobx-react"; +import type { Hotbar } from "../../../common/hotbar-types"; interface Props { hotbar: Hotbar; diff --git a/src/main/proxy/index.ts b/src/renderer/components/kube-details/index.ts similarity index 92% rename from src/main/proxy/index.ts rename to src/renderer/components/kube-details/index.ts index def9c80b5a..146e52e6dd 100644 --- a/src/main/proxy/index.ts +++ b/src/renderer/components/kube-details/index.ts @@ -19,7 +19,4 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -// Don't export the contents here -// It will break the extension webpack - -export default {}; +export * from "./params"; diff --git a/src/renderer/components/kube-details/params.ts b/src/renderer/components/kube-details/params.ts new file mode 100644 index 0000000000..fa1f2cab83 --- /dev/null +++ b/src/renderer/components/kube-details/params.ts @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +import { createPageParam, navigation } from "../../navigation"; + +/** + * Used to store `object.selfLink` to show more info about resource in the details panel. + */ +export const kubeDetailsUrlParam = createPageParam({ + name: "kube-details", +}); + +/** + * Used to highlight last active/selected table row with the resource. + * + * @example + * If we go to "Nodes (page) -> Node (details) -> Pod (details)", + * last clicked Node should be "active" while Pod details are shown). + */ +export const kubeSelectedUrlParam = createPageParam({ + name: "kube-selected", + get defaultValue() { + return kubeDetailsUrlParam.get(); + } +}); + +export function showDetails(selfLink = "", resetSelected = true) { + const detailsUrl = getDetailsUrl(selfLink, resetSelected); + + navigation.merge({ search: detailsUrl }); +} + +export function hideDetails() { + showDetails(); +} + +export function getDetailsUrl(selfLink: string, resetSelected = false, mergeGlobals = true) { + const params = new URLSearchParams(mergeGlobals ? navigation.searchParams : ""); + + params.set(kubeDetailsUrlParam.name, selfLink); + + if (resetSelected) { + params.delete(kubeSelectedUrlParam.name); + } else { + params.set(kubeSelectedUrlParam.name, kubeSelectedUrlParam.get()); + } + + return `?${params}`; +} diff --git a/src/renderer/components/kube-object-details/index.ts b/src/renderer/components/kube-object-details/index.ts new file mode 100644 index 0000000000..9675c16f58 --- /dev/null +++ b/src/renderer/components/kube-object-details/index.ts @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +export * from "./kube-object-details"; diff --git a/src/renderer/components/kube-object/kube-object-details.scss b/src/renderer/components/kube-object-details/kube-object-details.scss similarity index 100% rename from src/renderer/components/kube-object/kube-object-details.scss rename to src/renderer/components/kube-object-details/kube-object-details.scss diff --git a/src/renderer/components/kube-object/kube-object-details.tsx b/src/renderer/components/kube-object-details/kube-object-details.tsx similarity index 73% rename from src/renderer/components/kube-object/kube-object-details.tsx rename to src/renderer/components/kube-object-details/kube-object-details.tsx index b7a178c3ab..db370649c2 100644 --- a/src/renderer/components/kube-object/kube-object-details.tsx +++ b/src/renderer/components/kube-object-details/kube-object-details.tsx @@ -24,61 +24,14 @@ import "./kube-object-details.scss"; import React from "react"; import { disposeOnUnmount, observer } from "mobx-react"; import { computed, observable, reaction, makeObservable } from "mobx"; -import { createPageParam, navigation } from "../../navigation"; import { Drawer } from "../drawer"; import type { KubeObject } from "../../api/kube-object"; import { Spinner } from "../spinner"; import { apiManager } from "../../api/api-manager"; import { crdStore } from "../+custom-resources/crd.store"; -import { KubeObjectMenu } from "./kube-object-menu"; +import { KubeObjectMenu } from "../kube-object-menu"; import { KubeObjectDetailRegistry } from "../../api/kube-object-detail-registry"; -import logger from "../../../main/logger"; - -/** - * Used to store `object.selfLink` to show more info about resource in the details panel. - */ -export const kubeDetailsUrlParam = createPageParam({ - name: "kube-details", -}); - -/** - * Used to highlight last active/selected table row with the resource. - * - * @example - * If we go to "Nodes (page) -> Node (details) -> Pod (details)", - * last clicked Node should be "active" while Pod details are shown). - */ -export const kubeSelectedUrlParam = createPageParam({ - name: "kube-selected", - get defaultValue() { - return kubeDetailsUrlParam.get(); - } -}); - -export function showDetails(selfLink = "", resetSelected = true) { - const detailsUrl = getDetailsUrl(selfLink, resetSelected); - - navigation.merge({ search: detailsUrl }); -} - -export function hideDetails() { - showDetails(); -} - -export function getDetailsUrl(selfLink: string, resetSelected = false, mergeGlobals = true) { - logger.debug("getDetailsUrl", { selfLink, resetSelected, mergeGlobals }); - const params = new URLSearchParams(mergeGlobals ? navigation.searchParams : ""); - - params.set(kubeDetailsUrlParam.name, selfLink); - - if (resetSelected) { - params.delete(kubeSelectedUrlParam.name); - } else { - params.set(kubeSelectedUrlParam.name, kubeSelectedUrlParam.get()); - } - - return `?${params}`; -} +import { kubeDetailsUrlParam, hideDetails } from "../kube-details"; export interface KubeObjectDetailsProps { className?: string; @@ -105,7 +58,7 @@ export class KubeObjectDetails extends React.Component { .getStore(this.path) ?.getByPath(this.path); } catch (error) { - logger.error(`[KUBE-OBJECT-DETAILS]: failed to get store or object: ${error}`, { path: this.path }); + console.error(`[KUBE-OBJECT-DETAILS]: failed to get store or object: ${error}`, { path: this.path }); return undefined; } diff --git a/src/renderer/components/kube-object/index.ts b/src/renderer/components/kube-object-list-layout/index.ts similarity index 91% rename from src/renderer/components/kube-object/index.ts rename to src/renderer/components/kube-object-list-layout/index.ts index 399b7643be..619820ebcc 100644 --- a/src/renderer/components/kube-object/index.ts +++ b/src/renderer/components/kube-object-list-layout/index.ts @@ -19,7 +19,4 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -export * from "./kube-object-details"; export * from "./kube-object-list-layout"; -export * from "./kube-object-menu"; -export * from "./kube-object-meta"; diff --git a/src/renderer/components/kube-object/kube-object-list-layout.tsx b/src/renderer/components/kube-object-list-layout/kube-object-list-layout.tsx similarity index 96% rename from src/renderer/components/kube-object/kube-object-list-layout.tsx rename to src/renderer/components/kube-object-list-layout/kube-object-list-layout.tsx index edc9d967cc..ce89ce476d 100644 --- a/src/renderer/components/kube-object/kube-object-list-layout.tsx +++ b/src/renderer/components/kube-object-list-layout/kube-object-list-layout.tsx @@ -26,8 +26,8 @@ import { cssNames } from "../../utils"; import type { KubeObject } from "../../api/kube-object"; import { ItemListLayout, ItemListLayoutProps } from "../item-object-list/item-list-layout"; import type { KubeObjectStore } from "../../kube-object.store"; -import { KubeObjectMenu } from "./kube-object-menu"; -import { kubeSelectedUrlParam, showDetails } from "./kube-object-details"; +import { KubeObjectMenu } from "../kube-object-menu/kube-object-menu"; +import { kubeSelectedUrlParam, showDetails } from "../kube-details"; import { kubeWatchApi } from "../../api/kube-watch-api"; import { clusterContext } from "../context"; import { NamespaceSelectFilter } from "../+namespaces/namespace-select-filter"; diff --git a/src/renderer/components/kube-object-menu/index.ts b/src/renderer/components/kube-object-menu/index.ts new file mode 100644 index 0000000000..43cd5ea4a0 --- /dev/null +++ b/src/renderer/components/kube-object-menu/index.ts @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +export * from "./kube-object-menu"; diff --git a/src/renderer/components/kube-object/kube-object-menu.tsx b/src/renderer/components/kube-object-menu/kube-object-menu.tsx similarity index 93% rename from src/renderer/components/kube-object/kube-object-menu.tsx rename to src/renderer/components/kube-object-menu/kube-object-menu.tsx index f614ffc980..f51cb5c575 100644 --- a/src/renderer/components/kube-object/kube-object-menu.tsx +++ b/src/renderer/components/kube-object-menu/kube-object-menu.tsx @@ -24,7 +24,7 @@ import { boundMethod, cssNames } from "../../utils"; import type { KubeObject } from "../../api/kube-object"; import { editResourceTab } from "../dock/edit-resource.store"; import { MenuActions, MenuActionsProps } from "../menu/menu-actions"; -import { hideDetails } from "./kube-object-details"; +import { hideDetails } from "../kube-details"; import { apiManager } from "../../api/api-manager"; import { KubeObjectMenuRegistry } from "../../../extensions/registries/kube-object-menu-registry"; @@ -83,9 +83,7 @@ export class KubeObjectMenu extends React.Component extends React.Component extends React.Component - {this.getMenuItems()} + {this.getMenuItems(object)} ); } diff --git a/src/renderer/components/kube-object-meta/index.ts b/src/renderer/components/kube-object-meta/index.ts new file mode 100644 index 0000000000..2a413f9bd1 --- /dev/null +++ b/src/renderer/components/kube-object-meta/index.ts @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +export * from "./kube-object-meta"; diff --git a/src/renderer/components/kube-object/kube-object-meta.tsx b/src/renderer/components/kube-object-meta/kube-object-meta.tsx similarity index 95% rename from src/renderer/components/kube-object/kube-object-meta.tsx rename to src/renderer/components/kube-object-meta/kube-object-meta.tsx index f41b3d0991..83b81ee60b 100644 --- a/src/renderer/components/kube-object/kube-object-meta.tsx +++ b/src/renderer/components/kube-object-meta/kube-object-meta.tsx @@ -22,11 +22,11 @@ import React from "react"; import type { KubeMetaField, KubeObject } from "../../api/kube-object"; import { DrawerItem, DrawerItemLabels } from "../drawer"; -import { lookupApiLink } from "../../api/kube-api"; import { Link } from "react-router-dom"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; import { LocaleDate } from "../locale-date"; -import { getDetailsUrl } from "./kube-object-details"; +import { getDetailsUrl } from "../kube-details"; +import { apiManager } from "../../api/api-manager"; export interface KubeObjectMetaProps { object: KubeObject; @@ -93,7 +93,7 @@ export class KubeObjectMeta extends React.Component { { ownerRefs.map(ref => { const { name, kind } = ref; - const ownerDetailsUrl = getDetailsUrl(lookupApiLink(ref, object)); + const ownerDetailsUrl = getDetailsUrl(apiManager.lookupApiLink(ref, object)); return (

diff --git a/src/renderer/components/layout/sidebar.tsx b/src/renderer/components/layout/sidebar.tsx index 96e3a26dac..44e57e9202 100644 --- a/src/renderer/components/layout/sidebar.tsx +++ b/src/renderer/components/layout/sidebar.tsx @@ -33,7 +33,7 @@ import { Network } from "../+network"; import { crdStore } from "../+custom-resources/crd.store"; import { CustomResources } from "../+custom-resources/custom-resources"; import { isActiveRoute } from "../../navigation"; -import { isAllowedResource } from "../../../common/rbac"; +import { isAllowedResource } from "../../../common/utils/allowed-resource"; import { Spinner } from "../spinner"; import { ClusterPageMenuRegistration, ClusterPageMenuRegistry, ClusterPageRegistry, getExtensionPageUrl } from "../../../extensions/registries"; import { SidebarItem } from "./sidebar-item"; diff --git a/src/renderer/components/menu/menu-actions.tsx b/src/renderer/components/menu/menu-actions.tsx index 28747fec99..c7ec3fe59a 100644 --- a/src/renderer/components/menu/menu-actions.tsx +++ b/src/renderer/components/menu/menu-actions.tsx @@ -27,7 +27,7 @@ import { observer } from "mobx-react"; import { boundMethod, cssNames } from "../../utils"; import { ConfirmDialog } from "../confirm-dialog"; import { Icon, IconProps } from "../icon"; -import { Menu, MenuItem, MenuProps } from "../menu"; +import { Menu, MenuItem, MenuProps } from "./menu"; import uniqueId from "lodash/uniqueId"; import isString from "lodash/isString"; import { RenderDelay } from "../render-delay/render-delay"; diff --git a/src/renderer/components/table/react-table.tsx b/src/renderer/components/table/react-table.tsx index 016ad16337..59a97861fb 100644 --- a/src/renderer/components/table/react-table.tsx +++ b/src/renderer/components/table/react-table.tsx @@ -20,8 +20,7 @@ */ import styles from "./react-table.module.css"; -import React from "react"; -import { useCallback, useMemo } from "react"; +import React, { useCallback, useMemo } from "react"; import { useFlexLayout, useSortBy, useTable, UseTableOptions } from "react-table"; import { Icon } from "../icon"; import { cssNames } from "../../utils"; diff --git a/src/renderer/initializers/kube-object-detail-registry.tsx b/src/renderer/initializers/kube-object-detail-registry.tsx index ddc7617f45..5e7d929532 100644 --- a/src/renderer/initializers/kube-object-detail-registry.tsx +++ b/src/renderer/initializers/kube-object-detail-registry.tsx @@ -54,8 +54,7 @@ import { JobDetails } from "../components/+workloads-jobs"; import { PodDetails } from "../components/+workloads-pods"; import { ReplicaSetDetails } from "../components/+workloads-replicasets"; import { StatefulSetDetails } from "../components/+workloads-statefulsets"; -import type { KubeObjectDetailsProps } from "../components/kube-object"; -import type { CustomResourceDefinition } from "../api/endpoints"; +import type { KubeObjectDetailsProps } from "../components/kube-object-details"; export function intiKubeObjectDetailRegistry() { KubeObjectDetailRegistry.getInstance() @@ -450,7 +449,7 @@ export function intiKubeObjectDetailRegistry() { kind: "CustomResourceDefinition", apiVersions: ["apiextensions.k8s.io/v1"], components: { - Details: (props: KubeObjectDetailsProps) => , + Details: (props: KubeObjectDetailsProps) => , } } ]); diff --git a/src/renderer/initializers/workloads-overview-detail-registry.tsx b/src/renderer/initializers/workloads-overview-detail-registry.tsx index b374bb11af..b8aec840bf 100644 --- a/src/renderer/initializers/workloads-overview-detail-registry.tsx +++ b/src/renderer/initializers/workloads-overview-detail-registry.tsx @@ -20,7 +20,7 @@ */ import React from "react"; -import { isAllowedResource } from "../../common/rbac"; +import { isAllowedResource } from "../../common/utils/allowed-resource"; import { WorkloadsOverviewDetailRegistry } from "../../extensions/registries"; import { Events } from "../components/+events"; import { OverviewStatuses } from "../components/+workloads-overview/overview-statuses"; diff --git a/src/renderer/kube-object.store.ts b/src/renderer/kube-object.store.ts index 14dbbc6152..1c8b89b4f9 100644 --- a/src/renderer/kube-object.store.ts +++ b/src/renderer/kube-object.store.ts @@ -279,7 +279,8 @@ export abstract class KubeObjectStore extends ItemStore } async update(item: T, data: Partial): Promise { - const newItem = await item.update(data); + const rawItem = await item.update(data); + const newItem = new this.api.objectConstructor(rawItem); ensureObjectSelfLink(this.api, newItem); diff --git a/src/renderer/utils/createStorage.ts b/src/renderer/utils/createStorage.ts index 3636180c35..ba1325bf8c 100755 --- a/src/renderer/utils/createStorage.ts +++ b/src/renderer/utils/createStorage.ts @@ -26,7 +26,6 @@ import { app, remote } from "electron"; import { comparer, observable, reaction, toJS, when } from "mobx"; import fse from "fs-extra"; import { StorageHelper } from "./storageHelper"; -import { ClusterStore } from "../../common/cluster-store"; import logger from "../../main/logger"; import { getHostedClusterId } from "../../common/utils"; @@ -73,11 +72,6 @@ export function createAppStorage(key: string, defaultValue: T, clusterId?: st equals: comparer.structural, // save only when something really changed }); - // remove json-file when cluster deleted - if (clusterId !== undefined) { - when(() => ClusterStore.getInstance(false)?.removedClusters.has(clusterId)).then(removeFile); - } - async function saveFile(state: Record = {}) { logger.info(`${logPrefix} saving ${filePath}`); @@ -90,11 +84,6 @@ export function createAppStorage(key: string, defaultValue: T, clusterId?: st }); } } - - function removeFile() { - logger.debug(`${logPrefix} removing ${filePath}`); - fse.unlink(filePath).catch(Function); - } } return new StorageHelper(key, { diff --git a/src/renderer/utils/storageHelper.ts b/src/renderer/utils/storageHelper.ts index a7931ae41e..bb42fa167c 100755 --- a/src/renderer/utils/storageHelper.ts +++ b/src/renderer/utils/storageHelper.ts @@ -22,7 +22,7 @@ // Helper for working with storages (e.g. window.localStorage, NodeJS/file-system, etc.) import { action, comparer, makeObservable, observable, toJS, when, } from "mobx"; -import produce, { Draft } from "immer"; +import { Draft, produce } from "immer"; import { isEqual, isFunction, isPlainObject } from "lodash"; import logger from "../../main/logger"; diff --git a/yarn.lock b/yarn.lock index 3cd9056b43..a5623ba642 100644 --- a/yarn.lock +++ b/yarn.lock @@ -953,14 +953,14 @@ "@sentry/utils" "6.7.1" tslib "^1.9.3" -"@sentry/browser@6.8.0": - version "6.8.0" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.8.0.tgz#023707cd2302f6818014e9a7e124856b2d064178" - integrity sha512-nxa71csHlG5sMHUxI4e4xxuCWtbCv/QbBfMsYw7ncJSfCKG3yNlCVh8NJ7NS0rZW/MJUT6S6+r93zw0HetNDOA== +"@sentry/browser@6.9.0": + version "6.9.0" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.9.0.tgz#b75ac1a6ff8fe60d451b14aea94d66f9dcd5570f" + integrity sha512-4JnEPcwoNs6JqeEd4wscBq+hxpotEJ0DJ4eOIsaNZIMyqEHXBHTXCk/gfrSsiZFrkHM4PgvUHOxaC0HcZ92oBA== dependencies: - "@sentry/core" "6.8.0" - "@sentry/types" "6.8.0" - "@sentry/utils" "6.8.0" + "@sentry/core" "6.9.0" + "@sentry/types" "6.9.0" + "@sentry/utils" "6.9.0" tslib "^1.9.3" "@sentry/core@6.7.1": @@ -974,21 +974,21 @@ "@sentry/utils" "6.7.1" tslib "^1.9.3" -"@sentry/core@6.8.0": - version "6.8.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-6.8.0.tgz#bfac76844deee9126460c18dc6166015992efdc3" - integrity sha512-vJzWt/znEB+JqVwtwfjkRrAYRN+ep+l070Ti8GhJnvwU4IDtVlV3T/jVNrj6rl6UChcczaJQMxVxtG5x0crlAA== +"@sentry/core@6.9.0": + version "6.9.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-6.9.0.tgz#43b25290f3b1eb2c23f665e1c0fcbadd06d06012" + integrity sha512-oFX2qQcMLujCeIuCQGlhpTUIOXiU5n6V2lqDnvMXUV8gKpplBPalwdlR9bgbSi+VO8u7LjHR1IKM0RAPWgNHWw== dependencies: - "@sentry/hub" "6.8.0" - "@sentry/minimal" "6.8.0" - "@sentry/types" "6.8.0" - "@sentry/utils" "6.8.0" + "@sentry/hub" "6.9.0" + "@sentry/minimal" "6.9.0" + "@sentry/types" "6.9.0" + "@sentry/utils" "6.9.0" tslib "^1.9.3" "@sentry/electron@^2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@sentry/electron/-/electron-2.5.0.tgz#4168ff04ee01cb5a99ce042f3435660a510c634d" - integrity sha512-OiJWi9BKtlj4UeoaCArVXIvfW808fgW1GLmeiC7wD7B64ALHSYSwu8tkqZK+IMVhPmQN04AUyoYXrZohfJ7sOg== + version "2.5.1" + resolved "https://registry.yarnpkg.com/@sentry/electron/-/electron-2.5.1.tgz#6d1d42117e074c4b9f2f200def8ffb602c0221b6" + integrity sha512-1rVE1IgGZTAy2qlLQxDsuhv7/0sT88oHYyD4f6ZTDzge3lsReeMu4xA32M4ldo4yRlRQM5gpdSS/D7Q/4huH0A== dependencies: "@sentry/browser" "6.7.1" "@sentry/core" "6.7.1" @@ -1007,22 +1007,22 @@ "@sentry/utils" "6.7.1" tslib "^1.9.3" -"@sentry/hub@6.8.0": - version "6.8.0" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.8.0.tgz#cb0f8509093919ed3c1ef98ef8cf63dc102a6524" - integrity sha512-hFrI2Ss1fTov7CH64FJpigqRxH7YvSnGeqxT9Jc1BL7nzW/vgCK+Oh2mOZbosTcrzoDv+lE8ViOnSN3w/fo+rg== +"@sentry/hub@6.9.0": + version "6.9.0" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.9.0.tgz#21068e12769cc745825e8d122c7e81858f609708" + integrity sha512-5mors7ojbo7G85ZmoVPQBgFBMONAJwyZfV0LNLy14GenoaVNuxTPyvAQiJb1FYq+x6YZ3CvqGX6r74KRKQU87w== dependencies: - "@sentry/types" "6.8.0" - "@sentry/utils" "6.8.0" + "@sentry/types" "6.9.0" + "@sentry/utils" "6.9.0" tslib "^1.9.3" "@sentry/integrations@^6.8.0": - version "6.8.0" - resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-6.8.0.tgz#990d042d683ed4b45fcbe0cbf3e8077587a45f85" - integrity sha512-K8xmWGQFKxkKj5rMwGENm0SbbUs/SVhHE+V8+KkhXFmHAwfNAYTFaNg0Ryu9DADAJ4QYzZvYeRxl8voFecOqzA== + version "6.9.0" + resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-6.9.0.tgz#40efd6dd933f7b9589da0c53ac19a52560f17a26" + integrity sha512-p4z+PsPhimoII1iiT55Favjd0wxeXVio/oHEGivaYd7Al4G2CYLVsDu25OAejxizwNn6rJE8A3WIhXC3DXN84g== dependencies: - "@sentry/types" "6.8.0" - "@sentry/utils" "6.8.0" + "@sentry/types" "6.9.0" + "@sentry/utils" "6.9.0" localforage "^1.8.1" tslib "^1.9.3" @@ -1035,13 +1035,13 @@ "@sentry/types" "6.7.1" tslib "^1.9.3" -"@sentry/minimal@6.8.0": - version "6.8.0" - resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.8.0.tgz#d6c3e4c96f231367aeb2b8a87a83b53d28e7c6db" - integrity sha512-MRxUKXiiYwKjp8mOQMpTpEuIby1Jh3zRTU0cmGZtfsZ38BC1JOle8xlwC4FdtOH+VvjSYnPBMya5lgNHNPUJDQ== +"@sentry/minimal@6.9.0": + version "6.9.0" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.9.0.tgz#e6201eb237753994be83ec33866e3fdae9a79bf3" + integrity sha512-GBZ6wG2Rc1wInYEl2BZTZc/t57O1Da876ifLsSPpEQAEnGWbqZWb8RLjZskH09ZIL/K4XCIDDi5ySzN8kFUWJw== dependencies: - "@sentry/hub" "6.8.0" - "@sentry/types" "6.8.0" + "@sentry/hub" "6.9.0" + "@sentry/types" "6.9.0" tslib "^1.9.3" "@sentry/node@6.7.1": @@ -1060,14 +1060,14 @@ tslib "^1.9.3" "@sentry/react@^6.8.0": - version "6.8.0" - resolved "https://registry.yarnpkg.com/@sentry/react/-/react-6.8.0.tgz#3cf4a2e1ef042ee227836e268e702e9cb3b67e41" - integrity sha512-yXNnDaVw8kIacbwQjA27w8DA74WxmDVw4RlUTJGtq35SDmWsaGN1mwvU+mE1u3zEg927QTCBYig2Zqk8Tdt/fQ== + version "6.9.0" + resolved "https://registry.yarnpkg.com/@sentry/react/-/react-6.9.0.tgz#2db02de48481f3680e21e52a0821fd28e90f8347" + integrity sha512-ccMhpL+YHcq171EhSHU02IYh476mBjPfK1zq+vW2fJkaigg+mEqbOHnQV0Uu3zFYHGqVg4CZKZc6v92cvbBwEg== dependencies: - "@sentry/browser" "6.8.0" - "@sentry/minimal" "6.8.0" - "@sentry/types" "6.8.0" - "@sentry/utils" "6.8.0" + "@sentry/browser" "6.9.0" + "@sentry/minimal" "6.9.0" + "@sentry/types" "6.9.0" + "@sentry/utils" "6.9.0" hoist-non-react-statics "^3.3.2" tslib "^1.9.3" @@ -1087,10 +1087,10 @@ resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.7.1.tgz#c8263e1886df5e815570c4668eb40a1cfaa1c88b" integrity sha512-9AO7HKoip2MBMNQJEd6+AKtjj2+q9Ze4ooWUdEvdOVSt5drg7BGpK221/p9JEOyJAZwEPEXdcMd3VAIMiOb4MA== -"@sentry/types@6.8.0", "@sentry/types@^6.8.0": - version "6.8.0" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.8.0.tgz#97fd531a0ed1e75e65b4a24b26509fb7c15eb7b8" - integrity sha512-PbSxqlh6Fd5thNU5f8EVYBVvX+G7XdPA+ThNb2QvSK8yv3rIf0McHTyF6sIebgJ38OYN7ZFK7vvhC/RgSAfYTA== +"@sentry/types@6.9.0", "@sentry/types@^6.8.0": + version "6.9.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.9.0.tgz#ef1a541c4240df6a7c6f5f31d7cdddd7d92c15f1" + integrity sha512-v52HJqLoLapEnqS2NdVtUXPvT+aezQgNXQkp8hiQ3RUdTm5cffwBVG7wlbpE6OsOOIZxd6p1zKylFkwCypiIIA== "@sentry/utils@6.7.1": version "6.7.1" @@ -1100,12 +1100,12 @@ "@sentry/types" "6.7.1" tslib "^1.9.3" -"@sentry/utils@6.8.0": - version "6.8.0" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.8.0.tgz#0ffafa5b69fe0cdeabad5c4a6cc68a426eaa6b37" - integrity sha512-OYlI2JNrcWKMdvYbWNdQwR4QBVv2V0y5wK0U6f53nArv6RsyO5TzwRu5rMVSIZofUUqjoE5hl27jqnR+vpUrsA== +"@sentry/utils@6.9.0": + version "6.9.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.9.0.tgz#6bf0bf290a6d37a27078b7c1331a06d8a7e313c5" + integrity sha512-PimDr6KAi4cCp5hQZ8Az2/pDcdfhTu7WAU30Dd9MZwknpHSTmD4G6QvkdrB5er6kMMnNQOC7rMo6w/Do3m6X3w== dependencies: - "@sentry/types" "6.8.0" + "@sentry/types" "6.9.0" tslib "^1.9.3" "@sideway/address@^4.1.0": @@ -1578,6 +1578,11 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad" integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA== +"@types/json-schema@^7.0.7": + version "7.0.8" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.8.tgz#edf1bf1dbf4e04413ca8e5b17b3b7d7d54b59818" + integrity sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg== + "@types/json5@^0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" @@ -1820,9 +1825,9 @@ "@types/react" "*" "@types/react-virtualized-auto-sizer@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.0.tgz#fc32f30a8dab527b5816f3a757e1e1d040c8f272" - integrity sha512-NMErdIdSnm2j/7IqMteRiRvRulpjoELnXWUwdbucYCz84xG9PHcoOrr7QfXwB/ku7wd6egiKFrzt/+QK4Imeeg== + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.1.tgz#b3187dae1dfc4c15880c9cfc5b45f2719ea6ebd4" + integrity sha512-GH8sAnBEM5GV9LTeiz56r4ZhMOUSrP43tAQNSRVxNexDjcNKLCEtnxusAItg1owFUFE6k0NslV26gqVClVvong== dependencies: "@types/react" "*" @@ -2092,7 +2097,20 @@ dependencies: "@types/node" "*" -"@typescript-eslint/eslint-plugin@^4.14.2", "@typescript-eslint/eslint-plugin@^4.5.0": +"@typescript-eslint/eslint-plugin@^4.28.3": + version "4.28.3" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.3.tgz#36cdcd9ca6f9e5cb49b9f61b970b1976708d084b" + integrity sha512-jW8sEFu1ZeaV8xzwsfi6Vgtty2jf7/lJmQmDkDruBjYAbx5DA8JtbcMnP0rNPUG+oH5GoQBTSp+9613BzuIpYg== + dependencies: + "@typescript-eslint/experimental-utils" "4.28.3" + "@typescript-eslint/scope-manager" "4.28.3" + debug "^4.3.1" + functional-red-black-tree "^1.0.1" + regexpp "^3.1.0" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/eslint-plugin@^4.5.0": version "4.14.2" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.14.2.tgz#47a15803cfab89580b96933d348c2721f3d2f6fe" integrity sha512-uMGfG7GFYK/nYutK/iqYJv6K/Xuog/vrRRZX9aEP4Zv1jsYXuvFUMDFLhUnc8WFv3D2R5QhNQL3VYKmvLS5zsQ== @@ -2118,15 +2136,27 @@ eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@^4.0.0": - version "4.8.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.8.2.tgz#78dccbe5124de2b8dea2d4c363dee9f769151ca8" - integrity sha512-u0leyJqmclYr3KcXOqd2fmx6SDGBO0MUNHHAjr0JS4Crbb3C3d8dwAdlazy133PLCcPn+aOUFiHn72wcuc5wYw== +"@typescript-eslint/experimental-utils@4.28.3": + version "4.28.3" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.3.tgz#976f8c1191b37105fd06658ed57ddfee4be361ca" + integrity sha512-zZYl9TnrxwEPi3FbyeX0ZnE8Hp7j3OCR+ELoUfbwGHGxWnHg9+OqSmkw2MoCVpZksPCZYpQzC559Ee9pJNHTQw== dependencies: - "@typescript-eslint/scope-manager" "4.8.2" - "@typescript-eslint/types" "4.8.2" - "@typescript-eslint/typescript-estree" "4.8.2" - debug "^4.1.1" + "@types/json-schema" "^7.0.7" + "@typescript-eslint/scope-manager" "4.28.3" + "@typescript-eslint/types" "4.28.3" + "@typescript-eslint/typescript-estree" "4.28.3" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + +"@typescript-eslint/parser@^4.28.3": + version "4.28.3" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.28.3.tgz#95f1d475c08268edffdcb2779993c488b6434b44" + integrity sha512-ZyWEn34bJexn/JNYvLQab0Mo5e+qqQNhknxmc8azgNd4XqspVYR5oHq9O11fLwdZMRcj4by15ghSlIEq+H5ltQ== + dependencies: + "@typescript-eslint/scope-manager" "4.28.3" + "@typescript-eslint/types" "4.28.3" + "@typescript-eslint/typescript-estree" "4.28.3" + debug "^4.3.1" "@typescript-eslint/scope-manager@4.14.2": version "4.14.2" @@ -2136,23 +2166,23 @@ "@typescript-eslint/types" "4.14.2" "@typescript-eslint/visitor-keys" "4.14.2" -"@typescript-eslint/scope-manager@4.8.2": - version "4.8.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.8.2.tgz#a18388c63ae9c17adde519384f539392f2c4f0d9" - integrity sha512-qHQ8ODi7mMin4Sq2eh/6eu03uVzsf5TX+J43xRmiq8ujng7ViQSHNPLOHGw/Wr5dFEoxq/ubKhzClIIdQy5q3g== +"@typescript-eslint/scope-manager@4.28.3": + version "4.28.3" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.28.3.tgz#c32ad4491b3726db1ba34030b59ea922c214e371" + integrity sha512-/8lMisZ5NGIzGtJB+QizQ5eX4Xd8uxedFfMBXOKuJGP0oaBBVEMbJVddQKDXyyB0bPlmt8i6bHV89KbwOelJiQ== dependencies: - "@typescript-eslint/types" "4.8.2" - "@typescript-eslint/visitor-keys" "4.8.2" + "@typescript-eslint/types" "4.28.3" + "@typescript-eslint/visitor-keys" "4.28.3" "@typescript-eslint/types@4.14.2": version "4.14.2" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.14.2.tgz#d96da62be22dc9dc6a06647f3633815350fb3174" integrity sha512-LltxawRW6wXy4Gck6ZKlBD05tCHQUj4KLn4iR69IyRiDHX3d3NCAhO+ix5OR2Q+q9bjCrHE/HKt+riZkd1At8Q== -"@typescript-eslint/types@4.8.2": - version "4.8.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.8.2.tgz#c862dd0e569d9478eb82d6aee662ea53f5661a36" - integrity sha512-z1/AVcVF8ju5ObaHe2fOpZYEQrwHyZ7PTOlmjd3EoFeX9sv7UekQhfrCmgUO7PruLNfSHrJGQvrW3Q7xQ8EoAw== +"@typescript-eslint/types@4.28.3": + version "4.28.3" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.28.3.tgz#8fffd436a3bada422c2c1da56060a0566a9506c7" + integrity sha512-kQFaEsQBQVtA9VGVyciyTbIg7S3WoKHNuOp/UF5RG40900KtGqfoiETWD/v0lzRXc+euVE9NXmfer9dLkUJrkA== "@typescript-eslint/typescript-estree@4.14.2": version "4.14.2" @@ -2168,19 +2198,18 @@ semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/typescript-estree@4.8.2": - version "4.8.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.8.2.tgz#eeec34707d8577600fb21661b5287226cc8b3bed" - integrity sha512-HToGNwI6fekH0dOw3XEVESUm71Onfam0AKin6f26S2FtUmO7o3cLlWgrIaT1q3vjB3wCTdww3Dx2iGq5wtUOCg== +"@typescript-eslint/typescript-estree@4.28.3": + version "4.28.3" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.3.tgz#253d7088100b2a38aefe3c8dd7bd1f8232ec46fb" + integrity sha512-YAb1JED41kJsqCQt1NcnX5ZdTA93vKFCMP4lQYG6CFxd0VzDJcKttRlMrlG+1qiWAw8+zowmHU1H0OzjWJzR2w== dependencies: - "@typescript-eslint/types" "4.8.2" - "@typescript-eslint/visitor-keys" "4.8.2" - debug "^4.1.1" - globby "^11.0.1" + "@typescript-eslint/types" "4.28.3" + "@typescript-eslint/visitor-keys" "4.28.3" + debug "^4.3.1" + globby "^11.0.3" is-glob "^4.0.1" - lodash "^4.17.15" - semver "^7.3.2" - tsutils "^3.17.1" + semver "^7.3.5" + tsutils "^3.21.0" "@typescript-eslint/visitor-keys@4.14.2": version "4.14.2" @@ -2190,12 +2219,12 @@ "@typescript-eslint/types" "4.14.2" eslint-visitor-keys "^2.0.0" -"@typescript-eslint/visitor-keys@4.8.2": - version "4.8.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.8.2.tgz#62cd3fbbbf65f8eccfbe6f159eb1b84a243a3f77" - integrity sha512-Vg+/SJTMZJEKKGHW7YC21QxgKJrSbxoYYd3MEUGtW7zuytHuEcksewq0DUmo4eh/CTNrVJGSdIY9AtRb6riWFw== +"@typescript-eslint/visitor-keys@4.28.3": + version "4.28.3" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.3.tgz#26ac91e84b23529968361045829da80a4e5251c4" + integrity sha512-ri1OzcLnk1HH4gORmr1dllxDzzrN6goUIz/P4MHFV0YZJDCADPR3RvYNp0PW2SetKTThar6wlbFTL00hV2Q+fg== dependencies: - "@typescript-eslint/types" "4.8.2" + "@typescript-eslint/types" "4.28.3" eslint-visitor-keys "^2.0.0" "@webassemblyjs/ast@1.9.0": @@ -2803,6 +2832,15 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= +array.prototype.flat@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz#6ef638b43312bd401b4c6199fdec7e2dc9e9a123" + integrity sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + array.prototype.flatmap@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.4.tgz#94cfd47cc1556ec0747d97f7c7738c58122004c9" @@ -4672,7 +4710,7 @@ debug@3.1.0, debug@~3.1.0: dependencies: ms "2.0.0" -debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2: +debug@4, debug@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== @@ -4686,13 +4724,27 @@ debug@4.1.0: dependencies: ms "^2.1.1" -debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6: +debug@^3.0.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +debug@^3.1.0, debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== dependencies: ms "^2.1.1" +debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== + dependencies: + ms "2.1.2" + debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" @@ -5112,9 +5164,9 @@ domhandler@^2.3.0: domelementtype "1" dompurify@^2.0.17: - version "2.0.17" - resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.0.17.tgz#505ffa126a580603df4007e034bdc9b6b738668e" - integrity sha512-nNwwJfW55r8akD8MSFz6k75bzyT2y6JEa1O3JrZFBf+Y5R9JXXU4OsRl0B9hKoPgHTw2b7ER5yJ5Md97MMUJPg== + version "2.3.0" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.0.tgz#07bb39515e491588e5756b1d3e8375b5964814e2" + integrity sha512-VV5C6Kr53YVHGOBKO/F86OYX6/iLTw2yVSI721gKetxpHCK/V5TaLEf9ODjRgl1KLSWRMY6cUhAbv/c+IUnwQw== domutils@1.5.1: version "1.5.1" @@ -5575,9 +5627,9 @@ esbuild@^0.11.19: integrity sha512-iaiZZ9vUF5wJV8ob1tl+5aJTrwDczlvGP0JoMmnpC2B0ppiMCu8n8gmy5ZTGl5bcG081XBVn+U+jP+mPFm5T5Q== esbuild@^0.12.12: - version "0.12.12" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.12.12.tgz#2c3815c508e20f771cf6b2ffb03aa7349e651657" - integrity sha512-fdB/8HRg9u95Zi4/qV+osrfzpvLzubFKUr8SkZf/kUKImLiX61Y7qBzV14FCKphFk7YoXWY85nbPGkI6pq+Zeg== + version "0.12.15" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.12.15.tgz#9d99cf39aeb2188265c5983e983e236829f08af0" + integrity sha512-72V4JNd2+48eOVCXx49xoSWHgC3/cCy96e7mbXKY+WOWghN00cCmlGnwVLRhRHorvv0dgCyuMYBZlM2xDM5OQw== escalade@^3.1.1: version "3.1.1" @@ -5621,11 +5673,48 @@ escodegen@^1.14.1, escodegen@^1.8.1: optionalDependencies: source-map "~0.6.1" +eslint-import-resolver-node@^0.3.4: + version "0.3.4" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717" + integrity sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA== + dependencies: + debug "^2.6.9" + resolve "^1.13.1" + +eslint-module-utils@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.1.tgz#b51be1e473dd0de1c5ea638e22429c2490ea8233" + integrity sha512-ZXI9B8cxAJIH4nfkhTwcRTEAnrVfobYqwjWy/QMCZ8rHkZHFjf9yO4BzpiF9kCSfNlMG54eKigISHpX0+AaT4A== + dependencies: + debug "^3.2.7" + pkg-dir "^2.0.0" + eslint-plugin-header@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/eslint-plugin-header/-/eslint-plugin-header-3.1.1.tgz#6ce512432d57675265fac47292b50d1eff11acd6" integrity sha512-9vlKxuJ4qf793CmeeSrZUvVClw6amtpghq3CuWcB5cUNnWHQhgcqy5eF8oVKFk1G3Y/CbchGfEaw3wiIJaNmVg== +eslint-plugin-import@^2.23.4: + version "2.23.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.23.4.tgz#8dceb1ed6b73e46e50ec9a5bb2411b645e7d3d97" + integrity sha512-6/wP8zZRsnQFiR3iaPFgh5ImVRM1WN5NUWfTIRqwOdeiGJlBcSk82o1FEVq8yXmy4lkIzTo7YhHCIxlU/2HyEQ== + dependencies: + array-includes "^3.1.3" + array.prototype.flat "^1.2.4" + debug "^2.6.9" + doctrine "^2.1.0" + eslint-import-resolver-node "^0.3.4" + eslint-module-utils "^2.6.1" + find-up "^2.0.0" + has "^1.0.3" + is-core-module "^2.4.0" + minimatch "^3.0.4" + object.values "^1.1.3" + pkg-up "^2.0.0" + read-pkg-up "^3.0.0" + resolve "^1.20.0" + tsconfig-paths "^3.9.0" + eslint-plugin-react-hooks@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz#8c229c268d468956334c943bb45fc860280f5556" @@ -5688,6 +5777,13 @@ eslint-utils@^2.0.0, eslint-utils@^2.1.0: dependencies: eslint-visitor-keys "^1.1.0" +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" @@ -6287,7 +6383,7 @@ find-up@^1.0.0: path-exists "^2.0.0" pinkie-promise "^2.0.0" -find-up@^2.0.0: +find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= @@ -6852,6 +6948,18 @@ globby@^11.0.1: merge2 "^1.3.0" slash "^3.0.0" +globby@^11.0.3: + version "11.0.4" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" + integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + globby@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" @@ -7768,6 +7876,13 @@ is-core-module@^2.2.0: dependencies: has "^1.0.3" +is-core-module@^2.4.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.5.0.tgz#f754843617c70bfd29b7bd87327400cda5c18491" + integrity sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg== + dependencies: + has "^1.0.3" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -8431,11 +8546,11 @@ jest-message-util@^26.6.2: stack-utils "^2.0.2" jest-mock-extended@^1.0.16: - version "1.0.16" - resolved "https://registry.yarnpkg.com/jest-mock-extended/-/jest-mock-extended-1.0.16.tgz#f6a96c795acc2f5ae9ee74d7b048c3b4399c6fc8" - integrity sha512-W1lI7cO0ZYmTQUBZH11nSDKyU36SxAyzBjZNxBWcpFnCKHGNWIPdFA8RJMhmobLQ8WLI4y9AMIbYzMN9q/GiRQ== + version "1.0.18" + resolved "https://registry.yarnpkg.com/jest-mock-extended/-/jest-mock-extended-1.0.18.tgz#27a40e882c09f8230243fc6765fe7285b03f2b4b" + integrity sha512-qf1n7lIa2dTxxPIBr+FlXrbj3hnV1sG9DPZsrr2H/8W+Jw0wt6OmeOQsPcjRuW8EXIECC9pDXsSIfEdn+HP7JQ== dependencies: - ts-essentials "^4.0.0" + ts-essentials "^7.0.2" jest-mock@^26.6.2: version "26.6.2" @@ -9256,6 +9371,16 @@ load-json-file@^2.0.0: pify "^2.0.0" strip-bom "^3.0.0" +load-json-file@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" + integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= + dependencies: + graceful-fs "^4.1.2" + parse-json "^4.0.0" + pify "^3.0.0" + strip-bom "^3.0.0" + loader-runner@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" @@ -10759,7 +10884,7 @@ object.pick@^1.3.0: dependencies: isobject "^3.0.1" -object.values@^1.1.4: +object.values@^1.1.3, object.values@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.4.tgz#0d273762833e816b693a637d30073e7051535b30" integrity sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg== @@ -11317,6 +11442,13 @@ path-type@^2.0.0: dependencies: pify "^2.0.0" +path-type@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" + integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== + dependencies: + pify "^3.0.0" + path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -11382,6 +11514,13 @@ pirates@^4.0.1: dependencies: node-modules-regexp "^1.0.0" +pkg-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" + integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= + dependencies: + find-up "^2.1.0" + pkg-dir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" @@ -11396,6 +11535,13 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" +pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" + integrity sha1-yBmscoBZpGHKscOImivjxJoATX8= + dependencies: + find-up "^2.1.0" + pkg-up@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" @@ -12184,6 +12330,14 @@ read-pkg-up@^2.0.0: find-up "^2.0.0" read-pkg "^2.0.0" +read-pkg-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" + integrity sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc= + dependencies: + find-up "^2.0.0" + read-pkg "^3.0.0" + read-pkg-up@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" @@ -12211,6 +12365,15 @@ read-pkg@^2.0.0: normalize-package-data "^2.3.2" path-type "^2.0.0" +read-pkg@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" + integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= + dependencies: + load-json-file "^4.0.0" + normalize-package-data "^2.3.2" + path-type "^3.0.0" + read-pkg@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-4.0.1.tgz#963625378f3e1c4d48c85872b5a6ec7d5d093237" @@ -12564,7 +12727,7 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.18.1, resolve@^1.20.0, resolve@^1.3.2: +resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.18.1, resolve@^1.20.0, resolve@^1.3.2: version "1.20.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== @@ -14269,10 +14432,10 @@ truncate-utf8-bytes@^1.0.0: dependencies: utf8-byte-length "^1.0.1" -ts-essentials@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-4.0.0.tgz#506c42b270bbd0465574b90416533175b09205ab" - integrity sha512-uQJX+SRY9mtbKU+g9kl5Fi7AEMofPCvHfJkQlaygpPmHPZrtgaBqbWFOYyiA47RhnSwwnXdepUJrgqUYxoUyhQ== +ts-essentials@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-7.0.2.tgz#e21142df8034dbd444cb9573ed204d0b85fc64fb" + integrity sha512-qWPVC1xZGdefbsgFP7tPo+bsgSA2ZIXL1XeEe5M2WoMZxIOr/HbsHxP/Iv75IFhiMHMDGL7cOOwi5SXcgx9mHw== ts-jest@26.5.6: version "26.5.6" @@ -14344,6 +14507,13 @@ tsutils@^3.17.1: dependencies: tslib "^1.8.1" +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" @@ -14416,9 +14586,9 @@ type-fest@^0.8.1: integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== type-fest@^1.0.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.2.1.tgz#232990aa513f3f5223abf54363975dfe3a121a2e" - integrity sha512-SbmIRuXhJs8KTneu77Ecylt9zuqL683tuiLYpTRil4H++eIhqCmx6ko6KAFem9dty8sOdnEiX7j4K1nRE628fQ== + version "1.2.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.2.2.tgz#1930bc36b2064f7ab4aa307a6d1b65965199c698" + integrity sha512-pfkPYCcuV0TJoo/jlsUeWNV8rk7uMU6ocnYNvca1Vu+pyKi8Rl8Zo2scPt9O72gCsXIm+dMxOOWuA3VFDSdzWA== type-fest@^1.0.2: version "1.0.2"