From 97645f43279cb710925185b047fc40144b41b5d3 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Tue, 23 Jun 2020 12:09:17 -0400 Subject: [PATCH] Clean up electron-store based stores - Add some type script types for better editor experience - Remove redundent global of a singleton Signed-off-by: Sebastian Malton --- spec/src/common/cluster-store_spec.ts | 10 +++--- spec/src/common/user-store_spec.ts | 26 +++++++--------- src/common/__mocks__/user-store.ts | 9 ------ src/common/cluster-store.ts | 6 +--- src/common/request.ts | 4 +-- src/common/tracker.ts | 4 +-- src/common/user-store.ts | 6 +--- src/common/workspace-store.ts | 25 ++++++++++++--- src/main/cluster-manager.ts | 12 +++---- src/main/cluster.ts | 31 ++++++------------- src/main/index.ts | 4 +-- src/main/kubectl.ts | 6 ++-- src/main/routes/config.ts | 4 +-- src/renderer/components/MainMenu/MainMenu.vue | 4 +-- src/renderer/store/index.js | 21 +++++-------- src/renderer/store/modules/clusters.ts | 4 +-- src/renderer/store/modules/workspaces.ts | 18 +++++------ 17 files changed, 87 insertions(+), 107 deletions(-) delete mode 100644 src/common/__mocks__/user-store.ts diff --git a/spec/src/common/cluster-store_spec.ts b/spec/src/common/cluster-store_spec.ts index ec65f91b38..f016ebd5bc 100644 --- a/spec/src/common/cluster-store_spec.ts +++ b/spec/src/common/cluster-store_spec.ts @@ -197,7 +197,7 @@ describe("for a pre 2.0 config with an existing cluster", () => { it("migrates to modern format with kubeconfig under a key", async () => { const clusterStore = ClusterStore.getInstance() - const storedCluster = clusterStore.store.get('clusters')[0] + const storedCluster = clusterStore.getAllClusters()[0] expect(storedCluster.kubeConfig).toBe('kubeconfig content') }) }) @@ -231,7 +231,7 @@ describe("for a pre 2.4.1 config with an existing cluster", () => { it("migrates to modern format throwing out the state related data", async () => { const clusterStore = ClusterStore.getInstance() - const storedClusterData = clusterStore.store.get('clusters')[0] + const storedClusterData = clusterStore.getAllClusters()[0] expect(storedClusterData.hasOwnProperty('online')).toBe(false) expect(storedClusterData.hasOwnProperty('accessible')).toBe(false) expect(storedClusterData.hasOwnProperty('failureReason')).toBe(false) @@ -264,7 +264,7 @@ describe("for a pre 2.6.0 config with a cluster that has arrays in auth config", it("replaces array format access token and expiry into string", async () => { const clusterStore = ClusterStore.getInstance() - const storedClusterData = clusterStore.store.get('clusters')[0] + const storedClusterData = clusterStore.getAllClusters()[0] const kc = yaml.safeLoad(storedClusterData.kubeConfig) expect(kc.users[0].user['auth-provider'].config['access-token']).toBe("should be string") expect(kc.users[0].user['auth-provider'].config['expiry']).toBe("should be string") @@ -301,7 +301,7 @@ describe("for a pre 2.6.0 config with a cluster icon", () => { it("moves the icon into preferences", async () => { const clusterStore = ClusterStore.getInstance() - const storedClusterData = clusterStore.store.get('clusters')[0] + const storedClusterData = clusterStore.getAllClusters()[0] expect(storedClusterData.hasOwnProperty('icon')).toBe(false) expect(storedClusterData.preferences.hasOwnProperty('icon')).toBe(true) expect(storedClusterData.preferences.icon).toBe("icon path") @@ -338,7 +338,7 @@ describe("for a pre 2.7.0-beta.0 config without a workspace", () => { it("adds cluster to default workspace", async () => { const clusterStore = ClusterStore.getInstance() - const storedClusterData = clusterStore.store.get("clusters")[0] + const storedClusterData = clusterStore.getAllClusters()[0] expect(storedClusterData.workspace).toBe('default') }) }) diff --git a/spec/src/common/user-store_spec.ts b/spec/src/common/user-store_spec.ts index 6d29b253b4..2de480f6b8 100644 --- a/spec/src/common/user-store_spec.ts +++ b/spec/src/common/user-store_spec.ts @@ -14,7 +14,7 @@ jest.mock("electron", () => { // Console.log needs to be called before fs-mocks, see https://github.com/tschaub/mock-fs/issues/234 console.log(""); -import { userStore, User, UserPreferences, UserStore } from "../../../src/common/user-store" +import { UserStore } from "../../../src/common/user-store" describe("for an empty config", () => { beforeEach(() => { @@ -25,7 +25,6 @@ describe("for an empty config", () => { } } mockFs(mockOpts) - const userStore = UserStore.getInstance() }) afterEach(() => { @@ -33,31 +32,31 @@ describe("for an empty config", () => { }) it("allows setting and retrieving lastSeenAppVersion", async () => { - userStore.setLastSeenAppVersion("1.2.3"); - expect(userStore.lastSeenAppVersion()).toBe("1.2.3"); + UserStore.getInstance().setLastSeenAppVersion("1.2.3"); + expect(UserStore.getInstance().lastSeenAppVersion()).toBe("1.2.3"); }) it("allows adding and listing seen contexts", async () => { - userStore.storeSeenContext(['foo']) - expect(userStore.getSeenContexts().length).toBe(1) - userStore.storeSeenContext(['foo', 'bar']) - const seenContexts = userStore.getSeenContexts() + UserStore.getInstance().storeSeenContext(['foo']) + expect(UserStore.getInstance().getSeenContexts().length).toBe(1) + UserStore.getInstance().storeSeenContext(['foo', 'bar']) + const seenContexts = UserStore.getInstance().getSeenContexts() expect(seenContexts.length).toBe(2) // check 'foo' isn't added twice expect(seenContexts[0]).toBe('foo') expect(seenContexts[1]).toBe('bar') }) it("allows setting and getting preferences", async () => { - userStore.setPreferences({ + UserStore.getInstance().setPreferences({ httpsProxy: 'abcd://defg', }) - const storedPreferences = userStore.getPreferences() + const storedPreferences = UserStore.getInstance().getPreferences() expect(storedPreferences.httpsProxy).toBe('abcd://defg') expect(storedPreferences.colorTheme).toBe('dark') // defaults to dark - userStore.setPreferences({ + UserStore.getInstance().setPreferences({ colorTheme: 'light' }) - expect(userStore.getPreferences().colorTheme).toBe('light') + expect(UserStore.getInstance().getPreferences().colorTheme).toBe('light') }) }) @@ -74,7 +73,6 @@ describe("migrations", () => { } } mockFs(mockOpts) - const userStore = UserStore.getInstance() }) afterEach(() => { @@ -82,6 +80,6 @@ describe("migrations", () => { }) it("sets last seen app version to 0.0.0", async () => { - expect(userStore.lastSeenAppVersion()).toBe('0.0.0') + expect(UserStore.getInstance().lastSeenAppVersion()).toBe('0.0.0') }) }) diff --git a/src/common/__mocks__/user-store.ts b/src/common/__mocks__/user-store.ts deleted file mode 100644 index 21fc8355f8..0000000000 --- a/src/common/__mocks__/user-store.ts +++ /dev/null @@ -1,9 +0,0 @@ -const userStore = { - getPreferences: jest.fn(() => { - return { - downloadMirror: "default" - } - }) -} - -export { userStore }; diff --git a/src/common/cluster-store.ts b/src/common/cluster-store.ts index 1885570fde..02bf765181 100644 --- a/src/common/cluster-store.ts +++ b/src/common/cluster-store.ts @@ -10,7 +10,7 @@ import * as version270Beta1 from "./migrations/cluster-store/2.7.0-beta.1" export class ClusterStore { private static instance: ClusterStore; - public store: ElectronStore; + private store: ElectronStore; private constructor() { this.store = new ElectronStore({ @@ -107,7 +107,3 @@ export class ClusterStore { ClusterStore.instance = null } } - -const clusterStore: ClusterStore = ClusterStore.getInstance(); - -export { clusterStore }; diff --git a/src/common/request.ts b/src/common/request.ts index 0b0f2b893f..c41197d7cc 100644 --- a/src/common/request.ts +++ b/src/common/request.ts @@ -1,8 +1,8 @@ import * as request from "request" -import { userStore } from "../common/user-store" +import { UserStore } from "../common/user-store" export function globalRequestOpts(requestOpts: request.Options ) { - const userPrefs = userStore.getPreferences() + const userPrefs = UserStore.getInstance().getPreferences() if (userPrefs.httpsProxy) { requestOpts.proxy = userPrefs.httpsProxy } diff --git a/src/common/tracker.ts b/src/common/tracker.ts index 8075440632..3da7c4b4fb 100644 --- a/src/common/tracker.ts +++ b/src/common/tracker.ts @@ -1,5 +1,5 @@ import { machineIdSync } from 'node-machine-id' -import { userStore } from "../common/user-store" +import { UserStore } from "../common/user-store" import * as ua from "universal-analytics" const GA_ID = "UA-159377374-1" @@ -36,7 +36,7 @@ export class Tracker { } protected telemetryAllowed() { - const userPrefs = userStore.getPreferences() + const userPrefs = UserStore.getInstance().getPreferences() return !!userPrefs.allowTelemetry } } diff --git a/src/common/user-store.ts b/src/common/user-store.ts index 3a53122174..c3b052d80b 100644 --- a/src/common/user-store.ts +++ b/src/common/user-store.ts @@ -16,7 +16,7 @@ export interface UserPreferences { export class UserStore { private static instance: UserStore; - public store: ElectronStore; + private store: ElectronStore; private constructor() { this.store = new ElectronStore({ @@ -78,7 +78,3 @@ export class UserStore { UserStore.instance = null } } - -const userStore: UserStore = UserStore.getInstance(); - -export { userStore }; diff --git a/src/common/workspace-store.ts b/src/common/workspace-store.ts index 9ab9172f37..8a4525926f 100644 --- a/src/common/workspace-store.ts +++ b/src/common/workspace-store.ts @@ -1,5 +1,5 @@ import * as ElectronStore from "electron-store" -import { clusterStore } from "./cluster-store" +import { ClusterStore } from "./cluster-store" export interface WorkspaceData { id: string; @@ -7,6 +7,10 @@ export interface WorkspaceData { description?: string; } +interface WorkspaceStoreData { + workspaces: WorkspaceData[]; +} + export class Workspace implements WorkspaceData { public id: string public name: string @@ -20,14 +24,21 @@ export class Workspace implements WorkspaceData { export class WorkspaceStore { public static defaultId = "default" private static instance: WorkspaceStore; - public store: ElectronStore; + private store: ElectronStore; private constructor() { this.store = new ElectronStore({ - name: "lens-workspace-store" + name: "lens-workspace-store", }) - } + if (this.store.get("workspaces", []).length === 0) { + this.store.set("workspaces", [{ + id: "default", + name: "default" + }]); + } + } + public storeWorkspace(workspace: WorkspaceData) { const workspaces = this.getAllWorkspaces() const index = workspaces.findIndex((w) => w.id === workspace.id) @@ -46,12 +57,16 @@ export class WorkspaceStore { const workspaces = this.getAllWorkspaces() const index = workspaces.findIndex((w) => w.id === workspace.id) if (index !== -1) { - clusterStore.removeClustersByWorkspace(workspace.id) + ClusterStore.getInstance().removeClustersByWorkspace(workspace.id) workspaces.splice(index, 1) this.store.set("workspaces", workspaces) } } + public getWorkspace(id: string): Workspace | null { + return this.store.get("workspaces", []).find(wsd => wsd.id == id) || null; + } + public getAllWorkspaces(): Array { const workspacesData: WorkspaceData[] = this.store.get("workspaces", []) diff --git a/src/main/cluster-manager.ts b/src/main/cluster-manager.ts index 882604fcc2..0e04aa2afc 100644 --- a/src/main/cluster-manager.ts +++ b/src/main/cluster-manager.ts @@ -2,7 +2,7 @@ import { KubeConfig } from "@kubernetes/client-node" import { PromiseIpc } from "electron-promise-ipc" import * as http from "http" import { Cluster, ClusterBaseInfo } from "./cluster" -import { clusterStore } from "../common/cluster-store" +import { ClusterStore } from "../common/cluster-store" import * as k8s from "./k8s" import logger from "./logger" import { LensProxy } from "./proxy" @@ -177,10 +177,10 @@ export class ClusterManager { } try { const clusterIcon = await this.uploadClusterIcon(cluster, fileUpload.name, fileUpload.path) - clusterStore.reloadCluster(cluster); + ClusterStore.getInstance().reloadCluster(cluster); if(!cluster.preferences) cluster.preferences = {}; cluster.preferences.icon = clusterIcon - clusterStore.storeCluster(cluster); + ClusterStore.getInstance().storeCluster(cluster); return {success: true, cluster: this.clusterResponse(cluster), message: ""} } catch(error) { return {success: false, message: error} @@ -192,7 +192,7 @@ export class ClusterManager { const cluster = this.getCluster(id) if (cluster && cluster.preferences) { cluster.preferences.icon = null; - clusterStore.storeCluster(cluster) + ClusterStore.getInstance().storeCluster(cluster) return {success: true, cluster: this.clusterResponse(cluster), message: ""} } else { return {success: false, message: "Cluster not found"} @@ -224,7 +224,7 @@ export class ClusterManager { logger.debug(`IPC: clusterStored: ${clusterId}`) const cluster = this.clusters.get(clusterId) if (cluster) { - clusterStore.reloadCluster(cluster); + ClusterStore.getInstance().reloadCluster(cluster); cluster.stopServer() } }); @@ -247,7 +247,7 @@ export class ClusterManager { const cluster = this.clusters.get(id) if (cluster) { cluster.stopServer() - clusterStore.removeCluster(cluster.id); + ClusterStore.getInstance().removeCluster(cluster.id); this.clusters.delete(cluster.id) } return Array.from(this.clusters.values()) diff --git a/src/main/cluster.ts b/src/main/cluster.ts index 4971abe5cc..26ecb7bcfe 100644 --- a/src/main/cluster.ts +++ b/src/main/cluster.ts @@ -1,7 +1,7 @@ import { ContextHandler } from "./context-handler" import { FeatureStatusMap } from "./feature" import * as k8s from "./k8s" -import { clusterStore } from "../common/cluster-store" +import { ClusterStore } from "../common/cluster-store" import logger from "./logger" import { KubeConfig, CoreV1Api, AuthorizationV1Api, V1ResourceAttributes } from "@kubernetes/client-node" import * as fm from "./feature-manager"; @@ -119,20 +119,13 @@ export class Cluster implements ClusterInfo { } public async refreshCluster() { - clusterStore.reloadCluster(this) + ClusterStore.getInstance().reloadCluster(this) this.contextHandler.setClusterPreferences(this.preferences) const connectionStatus = await this.getConnectionStatus() - if (connectionStatus == ClusterStatus.AccessGranted) { - this.accessible = true - } else { - this.accessible = false - } - if (connectionStatus > ClusterStatus.Offline) { - this.online = true - } else { - this.online = false - } + this.accessible = connectionStatus == ClusterStatus.AccessGranted; + this.online = connectionStatus > ClusterStatus.Offline; + if (this.accessible) { this.distribution = this.detectKubernetesDistribution(this.version) this.features = await fm.getFeatures(this.contextHandler) @@ -145,7 +138,7 @@ export class Cluster implements ClusterInfo { } public updateKubeconfig(kubeconfig: string) { - const storedCluster = clusterStore.getCluster(this.id) + const storedCluster = ClusterStore.getInstance().getCluster(this.id) if (!storedCluster) { return } this.kubeConfig = kubeconfig @@ -153,18 +146,15 @@ export class Cluster implements ClusterInfo { } public getPrometheusApiPrefix() { - if (!this.preferences.prometheus?.prefix) { - return "" - } - return this.preferences.prometheus.prefix + return this.preferences.prometheus?.prefix || ""; } public save() { - clusterStore.storeCluster(this) + ClusterStore.getInstance().storeCluster(this) } public toClusterInfo(): ClusterInfo { - const clusterInfo: ClusterInfo = { + return { id: this.id, workspace: this.workspace, url: this.url, @@ -181,8 +171,7 @@ export class Cluster implements ClusterInfo { kubeCtl: this.kubeCtl, kubeConfig: this.kubeConfig, preferences: this.preferences - } - return clusterInfo; + }; } protected async k8sRequest(path: string, opts?: request.RequestPromiseOptions) { diff --git a/src/main/index.ts b/src/main/index.ts index 0e94fb5226..c06120a02a 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -7,7 +7,7 @@ import logger from "./logger" import initMenu from "./menu" import * as proxy from "./proxy" import { WindowManager } from "./window-manager"; -import { clusterStore } from "../common/cluster-store" +import { ClusterStore } from "../common/cluster-store" import { tracker } from "./tracker" import { ClusterManager } from "./cluster-manager"; import AppUpdater from "./app-updater" @@ -57,7 +57,7 @@ async function main() { } // create cluster manager - clusterManager = new ClusterManager(clusterStore.getAllClusterObjects(), port) + clusterManager = new ClusterManager(ClusterStore.getInstance().getAllClusterObjects(), port) // run proxy try { proxyServer = proxy.listen(port, clusterManager) diff --git a/src/main/kubectl.ts b/src/main/kubectl.ts index 7939799b3e..fb9fc4b7a7 100644 --- a/src/main/kubectl.ts +++ b/src/main/kubectl.ts @@ -9,7 +9,7 @@ import * as md5File from "md5-file" import { globalRequestOpts } from "../common/request" import * as lockFile from "proper-lockfile" import { helmCli } from "./helm-cli" -import { userStore } from "../common/user-store" +import { UserStore } from "../common/user-store" const bundledVersion = require("../../package.json").config.bundledKubectlVersion const kubectlMap: Map = new Map([ @@ -138,7 +138,7 @@ export class Kubectl { logger.error(`Local kubectl is version ${version}, expected ${this.kubectlVersion}, unlinking`) } catch(err) { - logger.error(`Local kubectl failed to run properly (${err.message}), unlinking`) + logger.error(`Local kubectl failed to run properly (${err.message}), unlinking`) } await fs.promises.unlink(this.path) } @@ -288,7 +288,7 @@ export class Kubectl { if (process.platform == "darwin") { return packageMirrors.get("default") // MacOS packages are only available from default } - const mirror = packageMirrors.get(userStore.getPreferences().downloadMirror) + const mirror = packageMirrors.get(UserStore.getInstance().getPreferences().downloadMirror) if (mirror) { return mirror } return packageMirrors.get("default") diff --git a/src/main/routes/config.ts b/src/main/routes/config.ts index 6becb76afb..5192a86134 100644 --- a/src/main/routes/config.ts +++ b/src/main/routes/config.ts @@ -1,6 +1,6 @@ import { LensApiRequest } from "../router" import { LensApi } from "../lens-api" -import { userStore } from "../../common/user-store" +import { UserStore } from "../../common/user-store" import { getAppVersion } from "../../common/app-utils" import { CoreV1Api, AuthorizationV1Api } from "@kubernetes/client-node" import { Cluster } from "../cluster" @@ -81,7 +81,7 @@ class ConfigRoute extends LensApi { const data = { clusterName: cluster.contextName, lensVersion: getAppVersion(), - lensTheme: `kontena-${userStore.getPreferences().colorTheme}`, + lensTheme: `kontena-${UserStore.getInstance().getPreferences().colorTheme}`, kubeVersion: cluster.version, chartsEnabled: true, isClusterAdmin: cluster.isAdmin, diff --git a/src/renderer/components/MainMenu/MainMenu.vue b/src/renderer/components/MainMenu/MainMenu.vue index 79124a6021..14f5ffc60d 100644 --- a/src/renderer/components/MainMenu/MainMenu.vue +++ b/src/renderer/components/MainMenu/MainMenu.vue @@ -22,7 +22,7 @@ import ClusterMenuItem from "@/components/MainMenu/ClusterMenuItem"; import AddClusterMenuItem from "@/components/MainMenu/AddClusterMenuItem"; import draggable from 'vuedraggable' -import { clusterStore } from "@/../common/cluster-store"; +import { ClusterStore } from "@/../common/cluster-store"; import * as os from "os"; const { remote } = require('electron') @@ -50,7 +50,7 @@ export default { }, set: function(clusters) { this.$store.commit("updateClusters", clusters); - clusterStore.storeClusters(clusters); + ClusterStore.getInstance().storeClusters(clusters); } } }, diff --git a/src/renderer/store/index.js b/src/renderer/store/index.js index cfdd850d02..69633f9cfe 100644 --- a/src/renderer/store/index.js +++ b/src/renderer/store/index.js @@ -1,6 +1,6 @@ import Vue from 'vue' import Vuex from 'vuex' -import { userStore } from "../../common/user-store" +import { UserStore } from "../../common/user-store" import KubeContexts from './modules/kube-contexts' import Clusters from './modules/clusters' import HelmRepos from './modules/helm-repos' @@ -31,29 +31,24 @@ export default new Vuex.Store({ hud: { isMenuVisible: true, }, - seenContexts: userStore.getSeenContexts(), - lastSeenAppVersion: userStore.lastSeenAppVersion(), + seenContexts: UserStore.getInstance().getSeenContexts(), + lastSeenAppVersion: UserStore.getInstance().lastSeenAppVersion(), }, mutations: { storeSeenContexts(state, context) { - const seenContexts = userStore.storeSeenContext(context); - state.seenContexts = seenContexts + state.seenContexts = UserStore.getInstance().storeSeenContext(context) }, updateLastSeenAppVersion(state, appVersion) { state.lastSeenAppVersion = appVersion; - userStore.setLastSeenAppVersion(appVersion) + UserStore.getInstance().setLastSeenAppVersion(appVersion) }, loadPreferences(state) { - this.commit("savePreferences", userStore.getPreferences()); + this.commit("savePreferences", UserStore.getInstance().getPreferences()); }, savePreferences(state, prefs) { - if (prefs.allowTelemetry) { - tracker.event("telemetry", "enabled") - } else { - tracker.event("telemetry", "disabled") - } + tracker.event("telemetry", prefs.allowTelemetry ? "enabled" : "disabled") state.preferences = prefs; - userStore.setPreferences(prefs); + UserStore.getInstance().setPreferences(prefs); this.dispatch("destroyWebviews") promiseIpc.send("preferencesSaved") }, diff --git a/src/renderer/store/modules/clusters.ts b/src/renderer/store/modules/clusters.ts index cb2b8caaf8..f54cd51657 100644 --- a/src/renderer/store/modules/clusters.ts +++ b/src/renderer/store/modules/clusters.ts @@ -4,7 +4,7 @@ import { MutationTree, ActionTree, GetterTree } from "vuex" import { PromiseIpc } from 'electron-promise-ipc' import { Tracker } from "../../../common/tracker" import { remote } from "electron" -import { clusterStore } from "../../../common/cluster-store" +import { ClusterStore } from "../../../common/cluster-store" import { Workspace } from "../../../common/workspace-store" const promiseIpc = new PromiseIpc( { maxTimeoutMs: 120000 } ); @@ -217,7 +217,7 @@ const actions: ActionTree = { }) }, storeCluster({commit}, cluster: ClusterInfo) { - clusterStore.storeCluster(cluster); + ClusterStore.getInstance().storeCluster(cluster); commit("updateCluster", cluster) promiseIpc.send("clusterStored", cluster.id) } diff --git a/src/renderer/store/modules/workspaces.ts b/src/renderer/store/modules/workspaces.ts index 2836090754..e05b86e434 100644 --- a/src/renderer/store/modules/workspaces.ts +++ b/src/renderer/store/modules/workspaces.ts @@ -1,5 +1,5 @@ import { MutationTree, ActionTree, GetterTree } from "vuex" -import { workspaceStore, Workspace, WorkspaceData } from "../../../common/workspace-store" +import { WorkspaceStore, Workspace, WorkspaceData } from "../../../common/workspace-store" export interface WorkspaceState { workspaces: Array; @@ -7,8 +7,8 @@ export interface WorkspaceState { } const state: WorkspaceState = { - workspaces: workspaceStore.getAllWorkspaces(), - currentWorkspace: workspaceStore.getAllWorkspaces().find((w) => w.id === "default") + workspaces: WorkspaceStore.getInstance().getAllWorkspaces(), + currentWorkspace: WorkspaceStore.getInstance().getAllWorkspaces().find((w) => w.id === "default"), } const actions: ActionTree = { @@ -27,16 +27,16 @@ const mutations: MutationTree = { state.currentWorkspace = workspace }, addWorkspace(state, workspace: WorkspaceData) { - workspaceStore.storeWorkspace(workspace) - state.workspaces = workspaceStore.getAllWorkspaces() + WorkspaceStore.getInstance().storeWorkspace(workspace) + state.workspaces = WorkspaceStore.getInstance().getAllWorkspaces() }, updateWorkspace(state, workspace: WorkspaceData) { - workspaceStore.storeWorkspace(workspace) - state.workspaces = workspaceStore.getAllWorkspaces() + WorkspaceStore.getInstance().storeWorkspace(workspace) + state.workspaces = WorkspaceStore.getInstance().getAllWorkspaces() }, removeWorkspace(state, workspace: Workspace) { - workspaceStore.removeWorkspace(workspace) - state.workspaces = workspaceStore.getAllWorkspaces() + WorkspaceStore.getInstance().removeWorkspace(workspace) + state.workspaces = WorkspaceStore.getInstance().getAllWorkspaces() } }