From 01d3914b5ae2429dbb3bec6ab070df2593a06f8d Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Fri, 2 Dec 2022 17:27:25 -0500 Subject: [PATCH] Fully injectable-ize BaseStore so that ApplicationBuilder tests work Signed-off-by: Sebastian Malton --- src/common/__tests__/base-store.test.ts | 154 ------------------ src/common/__tests__/cluster-store.test.ts | 2 - src/common/base-store/base-store.ts | 146 ++++++----------- src/common/base-store/channel-prefix.ts | 10 ++ src/common/base-store/disable-sync.ts | 10 ++ src/common/base-store/save-to-file.ts | 12 ++ .../cluster-store/cluster-store.injectable.ts | 10 ++ src/common/cluster-store/cluster-store.ts | 5 - ...le-model.global-override-for-injectable.ts | 19 ++- src/common/hotbars/store.injectable.ts | 10 ++ src/common/hotbars/store.ts | 12 +- .../user-store/user-store.injectable.ts | 10 ++ .../weblink-store.injectable.ts | 10 ++ ...ile-system-provisioner-store.injectable.ts | 10 ++ src/extensions/extension-store.ts | 10 ++ .../extensions-store.injectable.ts | 10 ++ ...disable-sync-in-ipc-listener.injectable.ts | 14 ++ .../ipc-channel-prefix.injectable.ts | 14 ++ .../persist-state-to-config.injectable.ts | 25 +++ ...disable-sync-in-ipc-listener.injectable.ts | 14 ++ .../ipc-channel-prefix.injectable.ts | 14 ++ .../persist-state-to-config.injectable.ts | 15 ++ 22 files changed, 266 insertions(+), 270 deletions(-) delete mode 100644 src/common/__tests__/base-store.test.ts create mode 100644 src/common/base-store/channel-prefix.ts create mode 100644 src/common/base-store/disable-sync.ts create mode 100644 src/common/base-store/save-to-file.ts create mode 100644 src/main/base-store/disable-sync-in-ipc-listener.injectable.ts create mode 100644 src/main/base-store/ipc-channel-prefix.injectable.ts create mode 100644 src/main/base-store/persist-state-to-config.injectable.ts create mode 100644 src/renderer/base-store/disable-sync-in-ipc-listener.injectable.ts create mode 100644 src/renderer/base-store/ipc-channel-prefix.injectable.ts create mode 100644 src/renderer/base-store/persist-state-to-config.injectable.ts diff --git a/src/common/__tests__/base-store.test.ts b/src/common/__tests__/base-store.test.ts deleted file mode 100644 index 7c71727b77..0000000000 --- a/src/common/__tests__/base-store.test.ts +++ /dev/null @@ -1,154 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import mockFs from "mock-fs"; -import type { BaseStoreDependencies } from "../base-store/base-store"; -import { BaseStore } from "../base-store/base-store"; -import { action, comparer, makeObservable, observable, toJS } from "mobx"; -import { readFileSync } from "fs"; -import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable"; -import { getDiForUnitTesting } from "../../main/getDiForUnitTesting"; -import getConfigurationFileModelInjectable from "../get-configuration-file-model/get-configuration-file-model.injectable"; -import loggerInjectable from "../logger.injectable"; -import storeMigrationVersionInjectable from "../vars/store-migration-version.injectable"; - -jest.mock("electron", () => ({ - ipcMain: { - on: jest.fn(), - off: jest.fn(), - }, -})); - -interface TestStoreModel { - a: string; - b: string; - c: string; -} - -class TestStore extends BaseStore { - @observable a = ""; - @observable b = ""; - @observable c = ""; - - constructor(deps: BaseStoreDependencies) { - super(deps, { - configName: "test-store", - accessPropertiesByDotNotation: false, // To make dots safe in cluster context names - syncOptions: { - equals: comparer.structural, - }, - }); - - makeObservable(this); - this.load(); - } - - @action updateAll(data: TestStoreModel) { - this.a = data.a; - this.b = data.b; - this.c = data.c; - } - - @action fromStore(data: Partial = {}) { - this.a = data.a || ""; - this.b = data.b || ""; - this.c = data.c || ""; - } - - onSync(data: TestStoreModel) { - super.onSync(data); - } - - async saveToFile(model: TestStoreModel) { - return super.saveToFile(model); - } - - toJSON(): TestStoreModel { - const data: TestStoreModel = { - a: this.a, - b: this.b, - c: this.c, - }; - - return toJS(data); - } -} - -describe("BaseStore", () => { - let store: TestStore; - - beforeEach(() => { - const mainDi = getDiForUnitTesting({ doGeneralOverrides: true }); - - mainDi.override(directoryForUserDataInjectable, () => "some-user-data-directory"); - mainDi.permitSideEffects(getConfigurationFileModelInjectable); - - const mockOpts = { - "some-user-data-directory": { - "test-store.json": JSON.stringify({}), - }, - }; - - mockFs(mockOpts); - - store = new TestStore({ - directoryForUserData: mainDi.inject(directoryForUserDataInjectable), - getConfigurationFileModel: mainDi.inject(getConfigurationFileModelInjectable), - logger: mainDi.inject(loggerInjectable), - storeMigrationVersion: mainDi.inject(storeMigrationVersionInjectable), - migrations: {}, - }); - }); - - afterEach(() => { - mockFs.restore(); - store.disableSync(); - }); - - describe("persistence", () => { - it("persists changes to the filesystem", () => { - store.updateAll({ - a: "foo", b: "bar", c: "hello", - }); - - const data = JSON.parse(readFileSync("some-user-data-directory/test-store.json").toString()); - - expect(data).toMatchObject({ a: "foo", b: "bar", c: "hello" }); - }); - - it("persists transaction only once", () => { - const fileSpy = jest.spyOn(store, "saveToFile"); - - store.updateAll({ - a: "foo", b: "bar", c: "hello", - }); - - expect(fileSpy).toHaveBeenCalledTimes(1); - }); - - it("persists changes one-by-one without transaction", () => { - const fileSpy = jest.spyOn(store, "saveToFile"); - - store.a = "a"; - store.b = "b"; - - expect(fileSpy).toHaveBeenCalledTimes(2); - - const data = JSON.parse(readFileSync("some-user-data-directory/test-store.json").toString()); - - expect(data).toMatchObject({ a: "a", b: "b", c: "" }); - }); - - it("persists changes coming via onSync (sync from different process)", () => { - const fileSpy = jest.spyOn(store, "saveToFile"); - - store.onSync({ a: "foo", b: "", c: "bar" }); - - expect(store.toJSON()).toMatchObject({ a: "foo", b: "", c: "bar" }); - - expect(fileSpy).toHaveBeenCalledTimes(1); - }); - }); -}); diff --git a/src/common/__tests__/cluster-store.test.ts b/src/common/__tests__/cluster-store.test.ts index 2253c7662f..b799d687c7 100644 --- a/src/common/__tests__/cluster-store.test.ts +++ b/src/common/__tests__/cluster-store.test.ts @@ -122,8 +122,6 @@ describe("cluster-store", () => { createCluster = mainDi.inject(createClusterInjectionToken); clusterStore = mainDi.inject(clusterStoreInjectable); - - clusterStore.unregisterIpcListener(); }); afterEach(() => { diff --git a/src/common/base-store/base-store.ts b/src/common/base-store/base-store.ts index 1144c5192c..f8ba209ed6 100644 --- a/src/common/base-store/base-store.ts +++ b/src/common/base-store/base-store.ts @@ -3,19 +3,19 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import path from "path"; import type Config from "conf"; import type { Migrations, Options as ConfOptions } from "conf/dist/source/types"; -import { ipcMain, ipcRenderer } from "electron"; import type { IEqualsComparer } from "mobx"; -import { makeObservable, reaction, runInAction } from "mobx"; -import type { Disposer } from "../utils"; -import { isPromiseLike, toJS } from "../utils"; -import { broadcastMessage, ipcMainOn, ipcRendererOn } from "../ipc"; +import { makeObservable, reaction } from "mobx"; +import { disposer, isPromiseLike, toJS } from "../utils"; +import { broadcastMessage } from "../ipc"; import isEqual from "lodash/isEqual"; import { kebabCase } from "lodash"; import type { GetConfigurationFileModel } from "../get-configuration-file-model/get-configuration-file-model.injectable"; import type { Logger } from "../logger"; +import type { PersistStateToConfig } from "./save-to-file"; +import type { GetBasenameOfPath } from "../path/get-basename.injectable"; +import type { EnlistMessageChannelListener } from "../utils/channel/enlist-message-channel-listener-injection-token"; export interface BaseStoreParams extends Omit, "migrations"> { syncOptions?: { @@ -30,15 +30,19 @@ export interface BaseStoreDependencies { readonly storeMigrationVersion: string; readonly directoryForUserData: string; readonly migrations: Migrations>; + readonly ipcChannelPrefix: string; + readonly shouldDisableSyncInListener: boolean; getConfigurationFileModel: GetConfigurationFileModel; + persistStateToConfig: PersistStateToConfig; + getBasenameOfPath: GetBasenameOfPath; + enlistMessageChannelListener: EnlistMessageChannelListener; } /** * Note: T should only contain base JSON serializable types. */ export abstract class BaseStore { - protected storeConfig?: Config; - protected syncDisposers: Disposer[] = []; + private readonly syncDisposers = disposer(); readonly displayName = kebabCase(this.params.configName).toUpperCase(); @@ -54,7 +58,8 @@ export abstract class BaseStore { */ load() { this.dependencies.logger.info(`[${this.displayName}]: LOADING ...`); - this.storeConfig = this.dependencies.getConfigurationFileModel({ + + const config = this.dependencies.getConfigurationFileModel({ projectName: "lens", projectVersion: this.dependencies.storeMigrationVersion, cwd: this.cwd(), @@ -62,107 +67,60 @@ export abstract class BaseStore { migrations: this.dependencies.migrations as Migrations, }); - const res = this.fromStore(this.storeConfig.store); + const res = this.fromStore(config.store); if (isPromiseLike(res)) { this.dependencies.logger.error(`${this.displayName} extends BaseStore's fromStore method returns a Promise or promise-like object. This is an error and must be fixed.`); } - this.enableSync(); - this.dependencies.logger.info(`[${this.displayName}]: LOADED from ${this.path}`); - } - - get name() { - return path.basename(this.path); - } - - protected get syncRendererChannel() { - return `store-sync-renderer:${this.path}`; - } - - protected get syncMainChannel() { - return `store-sync-main:${this.path}`; - } - - get path() { - return this.storeConfig?.path || ""; + this.startSyncing(config); + this.dependencies.logger.info(`[${this.displayName}]: LOADED from ${config.path}`); } protected cwd() { return this.dependencies.directoryForUserData; } - protected saveToFile(model: T) { - this.dependencies.logger.info(`[${this.displayName}]: SAVING ${this.path}`); + private startSyncing(config: Config) { + const name = this.dependencies.getBasenameOfPath(config.path); + const channelName = `${this.dependencies.ipcChannelPrefix}:${config.path}`; - // todo: update when fixed https://github.com/sindresorhus/conf/issues/114 - if (this.storeConfig) { - for (const [key, value] of Object.entries(model)) { - this.storeConfig.set(key, value); - } - } - } + const disableSync = () => this.syncDisposers(); + const enableSync = () => { + this.syncDisposers.push( + reaction( + () => toJS(this.toJSON()), // unwrap possible observables and react to everything + model => { + this.dependencies.persistStateToConfig(config, model); + broadcastMessage(channelName, model); + }, + this.params.syncOptions, + ), + this.dependencies.enlistMessageChannelListener({ + channel: { + id: channelName, + }, + handler: (model) => { + this.dependencies.logger.silly(`[${this.displayName}]: syncing ${name}`, { model }); - enableSync() { - this.syncDisposers.push( - reaction( - () => toJS(this.toJSON()), // unwrap possible observables and react to everything - model => this.onModelChange(model), - this.params.syncOptions, - ), - ); + if (this.dependencies.shouldDisableSyncInListener) { + disableSync(); + } - if (ipcMain) { - this.syncDisposers.push(ipcMainOn(this.syncMainChannel, (event, model: T) => { - this.dependencies.logger.silly(`[${this.displayName}]: SYNC ${this.name} from renderer`, { model }); - this.onSync(model); - })); - } + // todo: use "resourceVersion" if merge required (to avoid equality checks => better performance) + if (!isEqual(this.toJSON(), model)) { + this.fromStore(model as T); + } - if (ipcRenderer) { - this.syncDisposers.push(ipcRendererOn(this.syncRendererChannel, (event, model: T) => { - this.dependencies.logger.silly(`[${this.displayName}]: SYNC ${this.name} from main`, { model }); - this.onSyncFromMain(model); - })); - } - } + if (this.dependencies.shouldDisableSyncInListener) { + enableSync(); + } + }, + }), + ); + }; - protected onSyncFromMain(model: T) { - this.applyWithoutSync(() => { - this.onSync(model); - }); - } - - unregisterIpcListener() { - ipcRenderer?.removeAllListeners(this.syncMainChannel); - ipcRenderer?.removeAllListeners(this.syncRendererChannel); - } - - disableSync() { - this.syncDisposers.forEach(dispose => dispose()); - this.syncDisposers.length = 0; - } - - protected applyWithoutSync(callback: () => void) { - this.disableSync(); - runInAction(callback); - this.enableSync(); - } - - protected onSync(model: T) { - // todo: use "resourceVersion" if merge required (to avoid equality checks => better performance) - if (!isEqual(this.toJSON(), model)) { - this.fromStore(model); - } - } - - protected onModelChange(model: T) { - if (ipcMain) { - this.saveToFile(model); // save config file - broadcastMessage(this.syncRendererChannel, model); - } else { - broadcastMessage(this.syncMainChannel, model); - } + enableSync(); } /** diff --git a/src/common/base-store/channel-prefix.ts b/src/common/base-store/channel-prefix.ts new file mode 100644 index 0000000000..8d54e2b624 --- /dev/null +++ b/src/common/base-store/channel-prefix.ts @@ -0,0 +1,10 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { getInjectionToken } from "@ogre-tools/injectable"; + +export const baseStoreIpcChannelPrefixInjectionToken = getInjectionToken({ + id: "base-store-ipc-channel-prefix-token", +}); diff --git a/src/common/base-store/disable-sync.ts b/src/common/base-store/disable-sync.ts new file mode 100644 index 0000000000..ce7abd16a1 --- /dev/null +++ b/src/common/base-store/disable-sync.ts @@ -0,0 +1,10 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { getInjectionToken } from "@ogre-tools/injectable"; + +export const shouldBaseStoreDisableSyncInIpcListenerInjectionToken = getInjectionToken({ + id: "should-base-store-disable-sync-in-ipc-listener-token", +}); diff --git a/src/common/base-store/save-to-file.ts b/src/common/base-store/save-to-file.ts new file mode 100644 index 0000000000..b4d21ea950 --- /dev/null +++ b/src/common/base-store/save-to-file.ts @@ -0,0 +1,12 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectionToken } from "@ogre-tools/injectable"; +import type Config from "conf"; + +export type PersistStateToConfig = (config: Config, state: T) => void; + +export const persistStateToConfigInjectionToken = getInjectionToken({ + id: "persist-state-to-config-token", +}); diff --git a/src/common/cluster-store/cluster-store.injectable.ts b/src/common/cluster-store/cluster-store.injectable.ts index 14b2b674c3..d6948bd410 100644 --- a/src/common/cluster-store/cluster-store.injectable.ts +++ b/src/common/cluster-store/cluster-store.injectable.ts @@ -13,6 +13,11 @@ import loggerInjectable from "../logger.injectable"; import storeMigrationVersionInjectable from "../vars/store-migration-version.injectable"; import storeMigrationsInjectable from "../base-store/migrations.injectable"; import { clusterStoreMigrationInjectionToken } from "./migration-token"; +import { baseStoreIpcChannelPrefixInjectionToken } from "../base-store/channel-prefix"; +import { shouldBaseStoreDisableSyncInIpcListenerInjectionToken } from "../base-store/disable-sync"; +import { persistStateToConfigInjectionToken } from "../base-store/save-to-file"; +import getBasenameOfPathInjectable from "../path/get-basename.injectable"; +import { enlistMessageChannelListenerInjectionToken } from "../utils/channel/enlist-message-channel-listener-injection-token"; const clusterStoreInjectable = getInjectable({ id: "cluster-store", @@ -26,6 +31,11 @@ const clusterStoreInjectable = getInjectable({ logger: di.inject(loggerInjectable), storeMigrationVersion: di.inject(storeMigrationVersionInjectable), migrations: di.inject(storeMigrationsInjectable, clusterStoreMigrationInjectionToken), + getBasenameOfPath: di.inject(getBasenameOfPathInjectable), + ipcChannelPrefix: di.inject(baseStoreIpcChannelPrefixInjectionToken), + persistStateToConfig: di.inject(persistStateToConfigInjectionToken), + enlistMessageChannelListener: di.inject(enlistMessageChannelListenerInjectionToken), + shouldDisableSyncInListener: di.inject(shouldBaseStoreDisableSyncInIpcListenerInjectionToken), }), }); diff --git a/src/common/cluster-store/cluster-store.ts b/src/common/cluster-store/cluster-store.ts index c0730f9675..1952f5ddc2 100644 --- a/src/common/cluster-store/cluster-store.ts +++ b/src/common/cluster-store/cluster-store.ts @@ -70,11 +70,6 @@ export class ClusterStore extends BaseStore { }); } - unregisterIpcListener() { - super.unregisterIpcListener(); - this.disposer(); - } - pushState() { this.clusters.forEach((c) => { c.pushState(); diff --git a/src/common/get-configuration-file-model/get-configuration-file-model.global-override-for-injectable.ts b/src/common/get-configuration-file-model/get-configuration-file-model.global-override-for-injectable.ts index a2201ed52a..b82dc1404e 100644 --- a/src/common/get-configuration-file-model/get-configuration-file-model.global-override-for-injectable.ts +++ b/src/common/get-configuration-file-model/get-configuration-file-model.global-override-for-injectable.ts @@ -4,7 +4,6 @@ */ import assert from "assert"; -import { action } from "mobx"; import path from "path"; import { getGlobalOverride } from "../test-utils/get-global-override"; import getConfigurationFileModelInjectable from "./get-configuration-file-model.injectable"; @@ -21,17 +20,20 @@ export default getGlobalOverride(getConfigurationFileModelInjectable, (di) => { assert(options.configName, "Missing options.configName"); const configFilePath = path.posix.join(options.cwd, options.configName); + let store: object = {}; + + try { + store = readJsonSync(configFilePath); + } catch { + // ignore + } return { get store() { - try { - return readJsonSync(configFilePath); - } catch { - return {}; - } + return store; }, path: configFilePath, - set: action((key: string, value: unknown) => { + set: (key: string, value: unknown) => { let currentState: object; try { @@ -44,7 +46,8 @@ export default getGlobalOverride(getConfigurationFileModelInjectable, (di) => { ...currentState, [key]: value, }); - }), + store = readJsonSync(configFilePath); + }, } as Partial as Config; }; }); diff --git a/src/common/hotbars/store.injectable.ts b/src/common/hotbars/store.injectable.ts index 3b4e8307bb..c85446c23c 100644 --- a/src/common/hotbars/store.injectable.ts +++ b/src/common/hotbars/store.injectable.ts @@ -11,6 +11,11 @@ import getConfigurationFileModelInjectable from "../get-configuration-file-model import storeMigrationVersionInjectable from "../vars/store-migration-version.injectable"; import storeMigrationsInjectable from "../base-store/migrations.injectable"; import { hotbarStoreMigrationInjectionToken } from "./migrations-token"; +import getBasenameOfPathInjectable from "../path/get-basename.injectable"; +import { baseStoreIpcChannelPrefixInjectionToken } from "../base-store/channel-prefix"; +import { persistStateToConfigInjectionToken } from "../base-store/save-to-file"; +import { enlistMessageChannelListenerInjectionToken } from "../utils/channel/enlist-message-channel-listener-injection-token"; +import { shouldBaseStoreDisableSyncInIpcListenerInjectionToken } from "../base-store/disable-sync"; const hotbarStoreInjectable = getInjectable({ id: "hotbar-store", @@ -22,6 +27,11 @@ const hotbarStoreInjectable = getInjectable({ getConfigurationFileModel: di.inject(getConfigurationFileModelInjectable), storeMigrationVersion: di.inject(storeMigrationVersionInjectable), migrations: di.inject(storeMigrationsInjectable, hotbarStoreMigrationInjectionToken), + getBasenameOfPath: di.inject(getBasenameOfPathInjectable), + ipcChannelPrefix: di.inject(baseStoreIpcChannelPrefixInjectionToken), + persistStateToConfig: di.inject(persistStateToConfigInjectionToken), + enlistMessageChannelListener: di.inject(enlistMessageChannelListenerInjectionToken), + shouldDisableSyncInListener: di.inject(shouldBaseStoreDisableSyncInIpcListenerInjectionToken), }), }); diff --git a/src/common/hotbars/store.ts b/src/common/hotbars/store.ts index 427a764650..7a08a1c057 100644 --- a/src/common/hotbars/store.ts +++ b/src/common/hotbars/store.ts @@ -38,7 +38,6 @@ export class HotbarStore extends BaseStore { equals: comparer.structural, }, }); - makeObservable(this); } @@ -54,6 +53,7 @@ export class HotbarStore extends BaseStore { if (typeof hotbar === "number") { if (hotbar >= 0 && hotbar < this.hotbars.length) { this._activeHotbarId = this.hotbars[hotbar].id; + console.log("in _activeHotbarId", this._activeHotbarId); } } else if (typeof hotbar === "string") { if (this.findById(hotbar)) { @@ -97,21 +97,19 @@ export class HotbarStore extends BaseStore { this.hotbars.forEach(ensureExactHotbarItemLength); if (data.activeHotbarId) { - this.setActiveHotbar(data.activeHotbarId); + this._activeHotbarId = data.activeHotbarId; } if (!this.activeHotbarId) { - this.setActiveHotbar(0); + this._activeHotbarId = this.hotbars[0].id; } } toJSON(): HotbarStoreModel { - const model: HotbarStoreModel = { + return toJS({ hotbars: this.hotbars, activeHotbarId: this.activeHotbarId, - }; - - return toJS(model); + }); } getActive(): Hotbar { diff --git a/src/common/user-store/user-store.injectable.ts b/src/common/user-store/user-store.injectable.ts index e242a9fe91..0e4735931d 100644 --- a/src/common/user-store/user-store.injectable.ts +++ b/src/common/user-store/user-store.injectable.ts @@ -12,6 +12,11 @@ import loggerInjectable from "../logger.injectable"; import storeMigrationVersionInjectable from "../vars/store-migration-version.injectable"; import storeMigrationsInjectable from "../base-store/migrations.injectable"; import { userStoreMigrationInjectionToken } from "./migrations-token"; +import { baseStoreIpcChannelPrefixInjectionToken } from "../base-store/channel-prefix"; +import { shouldBaseStoreDisableSyncInIpcListenerInjectionToken } from "../base-store/disable-sync"; +import { persistStateToConfigInjectionToken } from "../base-store/save-to-file"; +import getBasenameOfPathInjectable from "../path/get-basename.injectable"; +import { enlistMessageChannelListenerInjectionToken } from "../utils/channel/enlist-message-channel-listener-injection-token"; const userStoreInjectable = getInjectable({ id: "user-store", @@ -24,6 +29,11 @@ const userStoreInjectable = getInjectable({ logger: di.inject(loggerInjectable), storeMigrationVersion: di.inject(storeMigrationVersionInjectable), migrations: di.inject(storeMigrationsInjectable, userStoreMigrationInjectionToken), + getBasenameOfPath: di.inject(getBasenameOfPathInjectable), + ipcChannelPrefix: di.inject(baseStoreIpcChannelPrefixInjectionToken), + persistStateToConfig: di.inject(persistStateToConfigInjectionToken), + enlistMessageChannelListener: di.inject(enlistMessageChannelListenerInjectionToken), + shouldDisableSyncInListener: di.inject(shouldBaseStoreDisableSyncInIpcListenerInjectionToken), }), }); diff --git a/src/common/weblinks-store/weblink-store.injectable.ts b/src/common/weblinks-store/weblink-store.injectable.ts index 1f8f45e3f2..f46e5eef2a 100644 --- a/src/common/weblinks-store/weblink-store.injectable.ts +++ b/src/common/weblinks-store/weblink-store.injectable.ts @@ -4,9 +4,14 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable"; +import { baseStoreIpcChannelPrefixInjectionToken } from "../base-store/channel-prefix"; +import { shouldBaseStoreDisableSyncInIpcListenerInjectionToken } from "../base-store/disable-sync"; import storeMigrationsInjectable from "../base-store/migrations.injectable"; +import { persistStateToConfigInjectionToken } from "../base-store/save-to-file"; import getConfigurationFileModelInjectable from "../get-configuration-file-model/get-configuration-file-model.injectable"; import loggerInjectable from "../logger.injectable"; +import getBasenameOfPathInjectable from "../path/get-basename.injectable"; +import { enlistMessageChannelListenerInjectionToken } from "../utils/channel/enlist-message-channel-listener-injection-token"; import storeMigrationVersionInjectable from "../vars/store-migration-version.injectable"; import { weblinkStoreMigrationInjectionToken } from "./migration-token"; import { WeblinkStore } from "./weblink-store"; @@ -19,6 +24,11 @@ const weblinkStoreInjectable = getInjectable({ logger: di.inject(loggerInjectable), storeMigrationVersion: di.inject(storeMigrationVersionInjectable), migrations: di.inject(storeMigrationsInjectable, weblinkStoreMigrationInjectionToken), + getBasenameOfPath: di.inject(getBasenameOfPathInjectable), + ipcChannelPrefix: di.inject(baseStoreIpcChannelPrefixInjectionToken), + persistStateToConfig: di.inject(persistStateToConfigInjectionToken), + enlistMessageChannelListener: di.inject(enlistMessageChannelListenerInjectionToken), + shouldDisableSyncInListener: di.inject(shouldBaseStoreDisableSyncInIpcListenerInjectionToken), }), }); diff --git a/src/extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store.injectable.ts b/src/extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store.injectable.ts index 48d729f5ef..5508124621 100644 --- a/src/extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store.injectable.ts +++ b/src/extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store.injectable.ts @@ -12,6 +12,11 @@ import directoryForUserDataInjectable from "../../../common/app-paths/directory- import getConfigurationFileModelInjectable from "../../../common/get-configuration-file-model/get-configuration-file-model.injectable"; import loggerInjectable from "../../../common/logger.injectable"; import storeMigrationVersionInjectable from "../../../common/vars/store-migration-version.injectable"; +import { baseStoreIpcChannelPrefixInjectionToken } from "../../../common/base-store/channel-prefix"; +import { shouldBaseStoreDisableSyncInIpcListenerInjectionToken } from "../../../common/base-store/disable-sync"; +import { persistStateToConfigInjectionToken } from "../../../common/base-store/save-to-file"; +import getBasenameOfPathInjectable from "../../../common/path/get-basename.injectable"; +import { enlistMessageChannelListenerInjectionToken } from "../../../common/utils/channel/enlist-message-channel-listener-injection-token"; const fileSystemProvisionerStoreInjectable = getInjectable({ id: "file-system-provisioner-store", @@ -26,6 +31,11 @@ const fileSystemProvisionerStoreInjectable = getInjectable({ logger: di.inject(loggerInjectable), storeMigrationVersion: di.inject(storeMigrationVersionInjectable), migrations: {}, + getBasenameOfPath: di.inject(getBasenameOfPathInjectable), + ipcChannelPrefix: di.inject(baseStoreIpcChannelPrefixInjectionToken), + persistStateToConfig: di.inject(persistStateToConfigInjectionToken), + enlistMessageChannelListener: di.inject(enlistMessageChannelListenerInjectionToken), + shouldDisableSyncInListener: di.inject(shouldBaseStoreDisableSyncInIpcListenerInjectionToken), }), }); diff --git a/src/extensions/extension-store.ts b/src/extensions/extension-store.ts index 844ee51d72..ef518afbfa 100644 --- a/src/extensions/extension-store.ts +++ b/src/extensions/extension-store.ts @@ -16,6 +16,11 @@ import getConfigurationFileModelInjectable from "../common/get-configuration-fil import loggerInjectable from "../common/logger.injectable"; import storeMigrationVersionInjectable from "../common/vars/store-migration-version.injectable"; import type { Migrations } from "conf/dist/source/types"; +import { baseStoreIpcChannelPrefixInjectionToken } from "../common/base-store/channel-prefix"; +import { shouldBaseStoreDisableSyncInIpcListenerInjectionToken } from "../common/base-store/disable-sync"; +import { persistStateToConfigInjectionToken } from "../common/base-store/save-to-file"; +import getBasenameOfPathInjectable from "../common/path/get-basename.injectable"; +import { enlistMessageChannelListenerInjectionToken } from "../common/utils/channel/enlist-message-channel-listener-injection-token"; export interface ExtensionStoreParams extends BaseStoreParams { migrations?: Migrations; @@ -53,6 +58,11 @@ export abstract class ExtensionStore extends BaseStore { logger: di.inject(loggerInjectable), storeMigrationVersion: di.inject(storeMigrationVersionInjectable), migrations: migrations as Migrations>, + getBasenameOfPath: di.inject(getBasenameOfPathInjectable), + ipcChannelPrefix: di.inject(baseStoreIpcChannelPrefixInjectionToken), + persistStateToConfig: di.inject(persistStateToConfigInjectionToken), + enlistMessageChannelListener: di.inject(enlistMessageChannelListenerInjectionToken), + shouldDisableSyncInListener: di.inject(shouldBaseStoreDisableSyncInIpcListenerInjectionToken), }, params); } diff --git a/src/extensions/extensions-store/extensions-store.injectable.ts b/src/extensions/extensions-store/extensions-store.injectable.ts index 671eac3823..b271b2b1cc 100644 --- a/src/extensions/extensions-store/extensions-store.injectable.ts +++ b/src/extensions/extensions-store/extensions-store.injectable.ts @@ -4,8 +4,13 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import directoryForUserDataInjectable from "../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; +import { baseStoreIpcChannelPrefixInjectionToken } from "../../common/base-store/channel-prefix"; +import { shouldBaseStoreDisableSyncInIpcListenerInjectionToken } from "../../common/base-store/disable-sync"; +import { persistStateToConfigInjectionToken } from "../../common/base-store/save-to-file"; import getConfigurationFileModelInjectable from "../../common/get-configuration-file-model/get-configuration-file-model.injectable"; import loggerInjectable from "../../common/logger.injectable"; +import getBasenameOfPathInjectable from "../../common/path/get-basename.injectable"; +import { enlistMessageChannelListenerInjectionToken } from "../../common/utils/channel/enlist-message-channel-listener-injection-token"; import storeMigrationVersionInjectable from "../../common/vars/store-migration-version.injectable"; import { ExtensionsStore } from "./extensions-store"; @@ -17,6 +22,11 @@ const extensionsStoreInjectable = getInjectable({ logger: di.inject(loggerInjectable), storeMigrationVersion: di.inject(storeMigrationVersionInjectable), migrations: {}, + getBasenameOfPath: di.inject(getBasenameOfPathInjectable), + ipcChannelPrefix: di.inject(baseStoreIpcChannelPrefixInjectionToken), + persistStateToConfig: di.inject(persistStateToConfigInjectionToken), + enlistMessageChannelListener: di.inject(enlistMessageChannelListenerInjectionToken), + shouldDisableSyncInListener: di.inject(shouldBaseStoreDisableSyncInIpcListenerInjectionToken), }), }); diff --git a/src/main/base-store/disable-sync-in-ipc-listener.injectable.ts b/src/main/base-store/disable-sync-in-ipc-listener.injectable.ts new file mode 100644 index 0000000000..2e7af0c723 --- /dev/null +++ b/src/main/base-store/disable-sync-in-ipc-listener.injectable.ts @@ -0,0 +1,14 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { shouldBaseStoreDisableSyncInIpcListenerInjectionToken } from "../../common/base-store/disable-sync"; + +const shouldBaseStoreDisableSyncInIpcListenerInjectable = getInjectable({ + id: "should-base-store-disable-sync-in-ipc-listener", + instantiate: () => false, + injectionToken: shouldBaseStoreDisableSyncInIpcListenerInjectionToken, +}); + +export default shouldBaseStoreDisableSyncInIpcListenerInjectable; diff --git a/src/main/base-store/ipc-channel-prefix.injectable.ts b/src/main/base-store/ipc-channel-prefix.injectable.ts new file mode 100644 index 0000000000..f4586a234b --- /dev/null +++ b/src/main/base-store/ipc-channel-prefix.injectable.ts @@ -0,0 +1,14 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { baseStoreIpcChannelPrefixInjectionToken } from "../../common/base-store/channel-prefix"; + +const baseStoreIpcChannelPrefixInjectable = getInjectable({ + id: "base-store-ipc-channel-prefix", + instantiate: () => "store-sync-main", + injectionToken: baseStoreIpcChannelPrefixInjectionToken, +}); + +export default baseStoreIpcChannelPrefixInjectable; diff --git a/src/main/base-store/persist-state-to-config.injectable.ts b/src/main/base-store/persist-state-to-config.injectable.ts new file mode 100644 index 0000000000..f6d28982ec --- /dev/null +++ b/src/main/base-store/persist-state-to-config.injectable.ts @@ -0,0 +1,25 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { persistStateToConfigInjectionToken } from "../../common/base-store/save-to-file"; +import loggerInjectable from "../../common/logger.injectable"; + +const persistStateToConfigInjectable = getInjectable({ + id: "persist-state-to-config", + instantiate: (di) => { + const logger = di.inject(loggerInjectable); + + return (config, state) => { + logger.info(`[BASE-STORE]: saving ${config.path}...`); + + for (const [key, value] of Object.entries(state)) { + config.set(key, value); + } + }; + }, + injectionToken: persistStateToConfigInjectionToken, +}); + +export default persistStateToConfigInjectable; diff --git a/src/renderer/base-store/disable-sync-in-ipc-listener.injectable.ts b/src/renderer/base-store/disable-sync-in-ipc-listener.injectable.ts new file mode 100644 index 0000000000..82670d8e1b --- /dev/null +++ b/src/renderer/base-store/disable-sync-in-ipc-listener.injectable.ts @@ -0,0 +1,14 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { shouldBaseStoreDisableSyncInIpcListenerInjectionToken } from "../../common/base-store/disable-sync"; + +const shouldBaseStoreDisableSyncInIpcListenerInjectable = getInjectable({ + id: "should-base-store-disable-sync-in-ipc-listener", + instantiate: () => true, + injectionToken: shouldBaseStoreDisableSyncInIpcListenerInjectionToken, +}); + +export default shouldBaseStoreDisableSyncInIpcListenerInjectable; diff --git a/src/renderer/base-store/ipc-channel-prefix.injectable.ts b/src/renderer/base-store/ipc-channel-prefix.injectable.ts new file mode 100644 index 0000000000..9edb925fc1 --- /dev/null +++ b/src/renderer/base-store/ipc-channel-prefix.injectable.ts @@ -0,0 +1,14 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { baseStoreIpcChannelPrefixInjectionToken } from "../../common/base-store/channel-prefix"; + +const baseStoreIpcChannelPrefixInjectable = getInjectable({ + id: "base-store-ipc-channel-prefix", + instantiate: () => "store-sync-renderer", + injectionToken: baseStoreIpcChannelPrefixInjectionToken, +}); + +export default baseStoreIpcChannelPrefixInjectable; diff --git a/src/renderer/base-store/persist-state-to-config.injectable.ts b/src/renderer/base-store/persist-state-to-config.injectable.ts new file mode 100644 index 0000000000..a1c8c5919a --- /dev/null +++ b/src/renderer/base-store/persist-state-to-config.injectable.ts @@ -0,0 +1,15 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { persistStateToConfigInjectionToken } from "../../common/base-store/save-to-file"; +import { noop } from "../utils"; + +const persistStateToConfigInjectable = getInjectable({ + id: "persist-state-to-config", + instantiate: () => noop, + injectionToken: persistStateToConfigInjectionToken, +}); + +export default persistStateToConfigInjectable;