diff --git a/docs/extensions/guides/stores.md b/docs/extensions/guides/stores.md index 44f231667c..2eaa589198 100644 --- a/docs/extensions/guides/stores.md +++ b/docs/extensions/guides/stores.md @@ -25,7 +25,7 @@ The following example code creates a store for the `appPreferences` guide exampl ``` typescript import { Store } from "@k8slens/extensions"; -import { observable, toJS, makeObservable } from "mobx"; +import { observable, makeObservable } from "mobx"; export type ExamplePreferencesModel = { enabled: boolean; @@ -51,7 +51,7 @@ export class ExamplePreferencesStore extends Store.ExtensionStore(); constructor() { makeObservable(this); } - @action add(category: CatalogCategory) { + @action + add(category: CatalogCategory) { this.categories.push(category); } - @action remove(category: CatalogCategory) { - this.categories = this.categories.filter((cat) => cat.apiVersion !== category.apiVersion && cat.kind !== category.kind); - } + @action + remove(category: CatalogCategory) { + const categories = this.categories.filter((cat) => cat.apiVersion !== category.apiVersion && cat.kind !== category.kind); - @computed get items() { - return toJS(this.categories); + this.categories.replace(categories); + } + + @computed get items(): CatalogCategory[] { + return Array.from(this.categories); } getForGroupKind(group: string, kind: string) { diff --git a/src/common/catalog/catalog-entity-registry.ts b/src/common/catalog/catalog-entity-registry.ts index ae42a6693a..e8297bc6c9 100644 --- a/src/common/catalog/catalog-entity-registry.ts +++ b/src/common/catalog/catalog-entity-registry.ts @@ -1,27 +1,20 @@ -import { - action, - computed, - observable, - IComputedValue, - IObservableArray, - makeObservable, -} from "mobx"; +import { action, computed, IComputedValue, IObservableArray, makeObservable, observable } from "mobx"; import { CatalogEntity } from "./catalog-entity"; -import { iter } from "../utils"; export class CatalogEntityRegistry { - protected sources = observable.map>([], { deep: true }); + protected sources = observable.map>(); constructor() { makeObservable(this); } - @action addObservableSource(id: string, source: IObservableArray) { - this.sources.set(id, computed(() => source)); - } - - @action addComputedSource(id: string, source: IComputedValue) { - this.sources.set(id, source); + @action + addObservableSource(id: string, source: IObservableArray | IComputedValue) { + if (Array.isArray(source)) { + this.sources.set(id, computed(() => source.toJSON())); + } else { + this.sources.set(id, source); + } } @action removeSource(id: string) { @@ -29,7 +22,9 @@ export class CatalogEntityRegistry { } @computed get items(): CatalogEntity[] { - return Array.from(iter.flatMap(this.sources.values(), source => source.get())); + return Array.from(this.sources.values()) + .map(source => source.get()) + .flat(); } getItemsForApiKind(apiVersion: string, kind: string): T[] { diff --git a/src/main/catalog-pusher.ts b/src/main/catalog-pusher.ts index fc68b9f8da..e522210f8a 100644 --- a/src/main/catalog-pusher.ts +++ b/src/main/catalog-pusher.ts @@ -1,27 +1,28 @@ import { reaction } from "mobx"; import { broadcastMessage, subscribeToBroadcast, unsubscribeFromBroadcast } from "../common/ipc"; -import { CatalogEntityRegistry} from "../common/catalog"; +import { CatalogEntityRegistry } from "../common/catalog"; import "../common/catalog-entities/kubernetes-cluster"; -import { Disposer, toJS } from "../common/utils"; +import { Disposer } from "../common/utils"; export class CatalogPusher { static init(catalog: CatalogEntityRegistry) { new CatalogPusher(catalog).init(); } - private constructor(private catalog: CatalogEntityRegistry) {} + private constructor(private catalog: CatalogEntityRegistry) { + } init() { - const disposers: Disposer[] = []; - - disposers.push(reaction(() => toJS(this.catalog.items), (items) => { - broadcastMessage("catalog:items", items); - }, { - fireImmediately: true, - })); + const disposers: Disposer[] = [ + reaction( + () => this.catalog.items, + (items) => broadcastMessage("catalog:items", items), + { fireImmediately: true } + ), + ]; const listener = subscribeToBroadcast("catalog:broadcast", () => { - broadcastMessage("catalog:items", toJS(this.catalog.items)); + broadcastMessage("catalog:items", this.catalog.items); }); disposers.push(() => unsubscribeFromBroadcast("catalog:broadcast", listener)); diff --git a/src/main/catalog-sources/kubeconfig-sync.ts b/src/main/catalog-sources/kubeconfig-sync.ts index 4fbbb83a1c..4dbcb6469e 100644 --- a/src/main/catalog-sources/kubeconfig-sync.ts +++ b/src/main/catalog-sources/kubeconfig-sync.ts @@ -1,12 +1,4 @@ -import { - action, - observable, - IComputedValue, - computed, - ObservableMap, - runInAction, - makeObservable, -} from "mobx"; +import { action, computed, IComputedValue, makeObservable, observable, ObservableMap, runInAction, } from "mobx"; import { CatalogEntity, catalogEntityRegistry } from "../../common/catalog"; import { watch } from "chokidar"; import fs from "fs"; @@ -47,7 +39,7 @@ export class KubeconfigSyncManager extends Singleton { logger.info(`${logPrefix} starting requested syncs`); - catalogEntityRegistry.addComputedSource(KubeconfigSyncManager.syncName, computed(() => ( + catalogEntityRegistry.addObservableSource(KubeconfigSyncManager.syncName, computed(() => ( Array.from(iter.flatMap( this.sources.values(), ([entities]) => entities.get() diff --git a/src/main/cluster-manager.ts b/src/main/cluster-manager.ts index 7d88ea903d..e2bf0267cb 100644 --- a/src/main/cluster-manager.ts +++ b/src/main/cluster-manager.ts @@ -6,7 +6,7 @@ import { ClusterStore, getClusterIdFromHost } from "../common/cluster-store"; import { Cluster } from "./cluster"; import logger from "./logger"; import { apiKubePrefix } from "../common/vars"; -import { Singleton, toJS } from "../common/utils"; +import { Singleton } from "../common/utils"; import { catalogEntityRegistry } from "../common/catalog"; import { KubernetesCluster } from "../common/catalog-entities/kubernetes-cluster"; diff --git a/src/main/extension-filesystem.ts b/src/main/extension-filesystem.ts index b30854904a..f475fdb627 100644 --- a/src/main/extension-filesystem.ts +++ b/src/main/extension-filesystem.ts @@ -2,7 +2,7 @@ import { randomBytes } from "crypto"; import { SHA256 } from "crypto-js"; import { app, remote } from "electron"; import fse from "fs-extra"; -import { action, observable, makeObservable } from "mobx"; +import { action, makeObservable, observable } from "mobx"; import path from "path"; import { BaseStore } from "../common/base-store"; import { LensExtensionId } from "../extensions/lens-extension"; @@ -13,7 +13,7 @@ interface FSProvisionModel { } export class FilesystemProvisionerStore extends BaseStore { - @observable registeredExtensions = observable.map(); + registeredExtensions = observable.map(); constructor() { super({ diff --git a/src/main/window-manager.ts b/src/main/window-manager.ts index d72a9b4ce1..d11b15a6f3 100644 --- a/src/main/window-manager.ts +++ b/src/main/window-manager.ts @@ -10,7 +10,7 @@ import { Singleton } from "../common/utils"; import { ClusterFrameInfo, clusterFrameMap } from "../common/cluster-frames"; import { IpcRendererNavigationEvents } from "../renderer/navigation/events"; import logger from "./logger"; -import { isProduction, productName } from "../common/vars"; +import { productName } from "../common/vars"; import { LensProxy } from "./proxy/lens-proxy"; export class WindowManager extends Singleton { diff --git a/src/renderer/components/dock/dock-tab.store.ts b/src/renderer/components/dock/dock-tab.store.ts index 39e13c3c2d..4c0a11e232 100644 --- a/src/renderer/components/dock/dock-tab.store.ts +++ b/src/renderer/components/dock/dock-tab.store.ts @@ -34,7 +34,7 @@ export class DockTabStore { this.storage = createStorage(storageKey, {}); this.storage.whenReady.then(() => { this.data.replace(this.storage.get()); - reaction(() => this.getStorableData(), data => this.storage.set(data)); + reaction(() => this.toJSON(), data => this.storage.set(data)); }); } @@ -54,14 +54,14 @@ export class DockTabStore { return data; } - protected getStorableData(): DockTabStorageState { - const allTabsData = toJS(this.data); + protected toJSON(): DockTabStorageState { + const deepCopy = toJS(this.data); - return Object.fromEntries( - Object.entries(allTabsData).map(([tabId, tabData]) => { - return [tabId, this.finalizeDataForSave(tabData)]; - }) - ); + deepCopy.forEach((tabData, key) => { + deepCopy.set(key, this.finalizeDataForSave(tabData)); + }); + + return Object.fromEntries(deepCopy); } isReady(tabId: TabId): boolean { diff --git a/src/renderer/components/dock/terminal-tab.tsx b/src/renderer/components/dock/terminal-tab.tsx index 701d0ca8f6..546a3c1f9d 100644 --- a/src/renderer/components/dock/terminal-tab.tsx +++ b/src/renderer/components/dock/terminal-tab.tsx @@ -7,7 +7,7 @@ import { DockTab, DockTabProps } from "./dock-tab"; import { Icon } from "../icon"; import { terminalStore } from "./terminal.store"; import { dockStore } from "./dock.store"; -import { reaction, makeObservable } from "mobx"; +import { reaction } from "mobx"; interface Props extends DockTabProps { } diff --git a/src/renderer/components/dock/terminal.ts b/src/renderer/components/dock/terminal.ts index e8b1408edc..7e60d9f886 100644 --- a/src/renderer/components/dock/terminal.ts +++ b/src/renderer/components/dock/terminal.ts @@ -5,7 +5,7 @@ import { FitAddon } from "xterm-addon-fit"; import { dockStore, TabId } from "./dock.store"; import { TerminalApi } from "../../api/terminal-api"; import { ThemeStore } from "../../theme.store"; -import { boundMethod, toJS } from "../../utils"; +import { boundMethod } from "../../utils"; import { isMac } from "../../../common/vars"; import { camelCase } from "lodash"; @@ -104,7 +104,7 @@ export class Terminal { window.addEventListener("resize", this.onResize); this.disposers.push( - reaction(() => toJS(ThemeStore.getInstance().activeTheme.colors), this.setTheme, { + reaction(() => ThemeStore.getInstance().activeTheme.colors, this.setTheme, { fireImmediately: true }), dockStore.onResize(this.onResize), @@ -132,7 +132,7 @@ export class Terminal { const { cols, rows } = this.xterm; this.api.sendTerminalSize(cols, rows); - } catch(error) { + } catch (error) { console.error(error); return; // see https://github.com/lensapp/lens/issues/1891 @@ -183,12 +183,12 @@ export class Terminal { // Handle custom hotkey bindings if (ctrlKey) { switch (code) { - // Ctrl+C: prevent terminal exit on windows / linux (?) + // Ctrl+C: prevent terminal exit on windows / linux (?) case "KeyC": if (this.xterm.hasSelection()) return false; break; - // Ctrl+W: prevent unexpected terminal tab closing, e.g. editing file in vim + // Ctrl+W: prevent unexpected terminal tab closing, e.g. editing file in vim case "KeyW": evt.preventDefault(); break; diff --git a/src/renderer/utils/createStorage.ts b/src/renderer/utils/createStorage.ts index 8045875fe9..f04d9ae6f9 100755 --- a/src/renderer/utils/createStorage.ts +++ b/src/renderer/utils/createStorage.ts @@ -8,7 +8,7 @@ import { StorageHelper } from "./storageHelper"; import { ClusterStore, getHostedClusterId } from "../../common/cluster-store"; import logger from "../../main/logger"; -const LOG_PREFIX = '[LocalStorageHelper]:'; +const LOG_PREFIX = "[LocalStorageHelper]:"; const storage = observable({ initialized: false, @@ -56,6 +56,7 @@ export function createStorage(key: string, defaultValue: T) { async function saveFile(state: Record = {}) { logger.info(`${LOG_PREFIX} saving ${filePath}`); + try { await fse.ensureDir(folder, { mode: 0o755 }); await fse.writeJson(filePath, state, { spaces: 2 }); diff --git a/src/renderer/utils/storageHelper.ts b/src/renderer/utils/storageHelper.ts index a35ea17215..c296744a83 100755 --- a/src/renderer/utils/storageHelper.ts +++ b/src/renderer/utils/storageHelper.ts @@ -1,6 +1,6 @@ // Helper for working with storages (e.g. window.localStorage, NodeJS/file-system, etc.) -import { action, CreateObservableOptions, IObservableValue, makeObservable, observable, toJS, when, } from "mobx"; +import { action, IObservableValue, makeObservable, observable, toJS, when, } from "mobx"; import produce, { Draft } from "immer"; import { isEqual, isFunction, isPlainObject } from "lodash"; import logger from "../../main/logger";