1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Extract BaseStore deps into constructor argument

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2022-11-30 15:01:43 -05:00
parent 1c277a96fb
commit 3dce6f916e
17 changed files with 153 additions and 70 deletions

View File

@ -4,12 +4,15 @@
*/ */
import mockFs from "mock-fs"; import mockFs from "mock-fs";
import type { BaseStoreDependencies } from "../base-store";
import { BaseStore } from "../base-store"; import { BaseStore } from "../base-store";
import { action, comparer, makeObservable, observable, toJS } from "mobx"; import { action, comparer, makeObservable, observable, toJS } from "mobx";
import { readFileSync } from "fs"; import { readFileSync } from "fs";
import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable"; import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable";
import { getDiForUnitTesting } from "../../main/getDiForUnitTesting"; import { getDiForUnitTesting } from "../../main/getDiForUnitTesting";
import getConfigurationFileModelInjectable from "../get-configuration-file-model/get-configuration-file-model.injectable"; 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", () => ({ jest.mock("electron", () => ({
ipcMain: { ipcMain: {
@ -29,8 +32,8 @@ class TestStore extends BaseStore<TestStoreModel> {
@observable b = ""; @observable b = "";
@observable c = ""; @observable c = "";
constructor() { constructor(deps: BaseStoreDependencies) {
super({ super(deps, {
configName: "test-store", configName: "test-store",
accessPropertiesByDotNotation: false, // To make dots safe in cluster context names accessPropertiesByDotNotation: false, // To make dots safe in cluster context names
syncOptions: { syncOptions: {
@ -90,7 +93,12 @@ describe("BaseStore", () => {
mockFs(mockOpts); mockFs(mockOpts);
store = new TestStore(); store = new TestStore({
directoryForUserData: mainDi.inject(directoryForUserDataInjectable),
getConfigurationFileModel: mainDi.inject(getConfigurationFileModelInjectable),
logger: mainDi.inject(loggerInjectable),
storeMigrationVersion: mainDi.inject(storeMigrationVersionInjectable),
});
}); });
afterEach(() => { afterEach(() => {

View File

@ -10,22 +10,26 @@ import { ipcMain, ipcRenderer } from "electron";
import type { IEqualsComparer } from "mobx"; import type { IEqualsComparer } from "mobx";
import { makeObservable, reaction, runInAction } from "mobx"; import { makeObservable, reaction, runInAction } from "mobx";
import type { Disposer } from "./utils"; import type { Disposer } from "./utils";
import { toJS } from "./utils"; import { isPromiseLike, toJS } from "./utils";
import logger from "../main/logger";
import { broadcastMessage, ipcMainOn, ipcRendererOn } from "./ipc"; import { broadcastMessage, ipcMainOn, ipcRendererOn } from "./ipc";
import isEqual from "lodash/isEqual"; import isEqual from "lodash/isEqual";
import { isTestEnv } from "./vars";
import { kebabCase } from "lodash"; import { kebabCase } from "lodash";
import { getLegacyGlobalDiForExtensionApi } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; import type { GetConfigurationFileModel } from "./get-configuration-file-model/get-configuration-file-model.injectable";
import directoryForUserDataInjectable from "./app-paths/directory-for-user-data/directory-for-user-data.injectable"; import type { Logger } from "./logger";
import getConfigurationFileModelInjectable from "./get-configuration-file-model/get-configuration-file-model.injectable";
import storeMigrationVersionInjectable from "./vars/store-migration-version.injectable";
export interface BaseStoreParams<T> extends ConfOptions<T> { export interface BaseStoreParams<T> extends ConfOptions<T> {
syncOptions?: { syncOptions?: {
fireImmediately?: boolean; fireImmediately?: boolean;
equals?: IEqualsComparer<T>; equals?: IEqualsComparer<T>;
}; };
configName: string;
}
export interface BaseStoreDependencies {
readonly logger: Logger;
readonly storeMigrationVersion: string;
readonly directoryForUserData: string;
getConfigurationFileModel: GetConfigurationFileModel;
} }
/** /**
@ -35,13 +39,18 @@ export abstract class BaseStore<T extends object> {
protected storeConfig?: Config<T>; protected storeConfig?: Config<T>;
protected syncDisposers: Disposer[] = []; protected syncDisposers: Disposer[] = [];
readonly displayName: string = this.constructor.name; readonly displayName: string;
protected constructor(protected params: BaseStoreParams<T>) { protected constructor(
protected readonly dependencies: BaseStoreDependencies,
protected readonly params: BaseStoreParams<T>,
) {
makeObservable(this); makeObservable(this);
this.displayName = this.params.configName;
if (ipcRenderer) { if (ipcRenderer) {
params.migrations = undefined; // don't run migrations on renderer this.params.migrations = undefined; // don't run migrations on renderer
} }
} }
@ -49,32 +58,22 @@ export abstract class BaseStore<T extends object> {
* This must be called after the last child's constructor is finished (or just before it finishes) * This must be called after the last child's constructor is finished (or just before it finishes)
*/ */
load() { load() {
if (!isTestEnv) { this.dependencies.logger.info(`[${kebabCase(this.displayName).toUpperCase()}]: LOADING ...`);
logger.info(`[${kebabCase(this.displayName).toUpperCase()}]: LOADING from ${this.path} ...`); this.storeConfig = this.dependencies.getConfigurationFileModel({
}
const di = getLegacyGlobalDiForExtensionApi();
const getConfigurationFileModel = di.inject(getConfigurationFileModelInjectable);
this.storeConfig = getConfigurationFileModel({
projectName: "lens", projectName: "lens",
projectVersion: di.inject(storeMigrationVersionInjectable), projectVersion: this.dependencies.storeMigrationVersion,
cwd: this.cwd(), cwd: this.cwd(),
...this.params, ...this.params,
}); });
const res: any = this.fromStore(this.storeConfig.store); const res = this.fromStore(this.storeConfig.store);
if (res instanceof Promise || (typeof res === "object" && res && typeof res.then === "function")) { if (isPromiseLike(res)) {
console.error(`${this.displayName} extends BaseStore<T>'s fromStore method returns a Promise or promise-like object. This is an error and must be fixed.`); this.dependencies.logger.error(`${this.displayName} extends BaseStore<T>'s fromStore method returns a Promise or promise-like object. This is an error and must be fixed.`);
} }
this.enableSync(); this.enableSync();
this.dependencies.logger.info(`[${kebabCase(this.displayName).toUpperCase()}]: LOADED from ${this.path}`);
if (!isTestEnv) {
logger.info(`[${kebabCase(this.displayName).toUpperCase()}]: LOADED from ${this.path}`);
}
} }
get name() { get name() {
@ -94,13 +93,11 @@ export abstract class BaseStore<T extends object> {
} }
protected cwd() { protected cwd() {
const di = getLegacyGlobalDiForExtensionApi(); return this.dependencies.directoryForUserData;
return di.inject(directoryForUserDataInjectable);
} }
protected saveToFile(model: T) { protected saveToFile(model: T) {
logger.info(`[STORE]: SAVING ${this.path}`); this.dependencies.logger.info(`[STORE]: SAVING ${this.path}`);
// todo: update when fixed https://github.com/sindresorhus/conf/issues/114 // todo: update when fixed https://github.com/sindresorhus/conf/issues/114
if (this.storeConfig) { if (this.storeConfig) {
@ -121,14 +118,14 @@ export abstract class BaseStore<T extends object> {
if (ipcMain) { if (ipcMain) {
this.syncDisposers.push(ipcMainOn(this.syncMainChannel, (event, model: T) => { this.syncDisposers.push(ipcMainOn(this.syncMainChannel, (event, model: T) => {
logger.silly(`[STORE]: SYNC ${this.name} from renderer`, { model }); this.dependencies.logger.silly(`[STORE]: SYNC ${this.name} from renderer`, { model });
this.onSync(model); this.onSync(model);
})); }));
} }
if (ipcRenderer) { if (ipcRenderer) {
this.syncDisposers.push(ipcRendererOn(this.syncRendererChannel, (event, model: T) => { this.syncDisposers.push(ipcRendererOn(this.syncRendererChannel, (event, model: T) => {
logger.silly(`[STORE]: SYNC ${this.name} from main`, { model }); this.dependencies.logger.silly(`[STORE]: SYNC ${this.name} from main`, { model });
this.onSyncFromMain(model); this.onSyncFromMain(model);
})); }));
} }

View File

@ -7,6 +7,10 @@ import { ClusterStore } from "./cluster-store";
import { createClusterInjectionToken } from "../cluster/create-cluster-injection-token"; import { createClusterInjectionToken } from "../cluster/create-cluster-injection-token";
import readClusterConfigSyncInjectable from "./read-cluster-config.injectable"; import readClusterConfigSyncInjectable from "./read-cluster-config.injectable";
import emitAppEventInjectable from "../app-event-bus/emit-event.injectable"; import emitAppEventInjectable from "../app-event-bus/emit-event.injectable";
import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable";
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";
const clusterStoreInjectable = getInjectable({ const clusterStoreInjectable = getInjectable({
id: "cluster-store", id: "cluster-store",
@ -15,9 +19,11 @@ const clusterStoreInjectable = getInjectable({
createCluster: di.inject(createClusterInjectionToken), createCluster: di.inject(createClusterInjectionToken),
readClusterConfigSync: di.inject(readClusterConfigSyncInjectable), readClusterConfigSync: di.inject(readClusterConfigSyncInjectable),
emitAppEvent: di.inject(emitAppEventInjectable), emitAppEvent: di.inject(emitAppEventInjectable),
directoryForUserData: di.inject(directoryForUserDataInjectable),
getConfigurationFileModel: di.inject(getConfigurationFileModelInjectable),
logger: di.inject(loggerInjectable),
storeMigrationVersion: di.inject(storeMigrationVersionInjectable),
}), }),
causesSideEffects: true,
}); });
export default clusterStoreInjectable; export default clusterStoreInjectable;

View File

@ -6,10 +6,10 @@
import { ipcMain, ipcRenderer, webFrame } from "electron"; import { ipcMain, ipcRenderer, webFrame } from "electron";
import { action, comparer, computed, makeObservable, observable, reaction } from "mobx"; import { action, comparer, computed, makeObservable, observable, reaction } from "mobx";
import type { BaseStoreDependencies } from "../base-store";
import { BaseStore } from "../base-store"; import { BaseStore } from "../base-store";
import { Cluster } from "../cluster/cluster"; import { Cluster } from "../cluster/cluster";
import migrations from "../../migrations/cluster-store"; import migrations from "../../migrations/cluster-store";
import logger from "../../main/logger";
import { disposer, toJS } from "../utils"; import { disposer, toJS } from "../utils";
import type { ClusterModel, ClusterId, ClusterState } from "../cluster-types"; import type { ClusterModel, ClusterId, ClusterState } from "../cluster-types";
import { requestInitialClusterStates } from "../../renderer/ipc"; import { requestInitialClusterStates } from "../../renderer/ipc";
@ -21,7 +21,7 @@ export interface ClusterStoreModel {
clusters?: ClusterModel[]; clusters?: ClusterModel[];
} }
interface Dependencies { interface Dependencies extends BaseStoreDependencies {
createCluster: CreateCluster; createCluster: CreateCluster;
readClusterConfigSync: ReadClusterConfigSync; readClusterConfigSync: ReadClusterConfigSync;
emitAppEvent: EmitAppEvent; emitAppEvent: EmitAppEvent;
@ -29,12 +29,12 @@ interface Dependencies {
export class ClusterStore extends BaseStore<ClusterStoreModel> { export class ClusterStore extends BaseStore<ClusterStoreModel> {
readonly displayName = "ClusterStore"; readonly displayName = "ClusterStore";
clusters = observable.map<ClusterId, Cluster>(); readonly clusters = observable.map<ClusterId, Cluster>();
protected disposer = disposer(); protected disposer = disposer();
constructor(private readonly dependencies: Dependencies) { constructor(protected readonly dependencies: Dependencies) {
super({ super(dependencies, {
configName: "lens-cluster-store", configName: "lens-cluster-store",
accessPropertiesByDotNotation: false, // To make dots safe in cluster context names accessPropertiesByDotNotation: false, // To make dots safe in cluster context names
syncOptions: { syncOptions: {
@ -49,7 +49,7 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
} }
async loadInitialOnRenderer() { async loadInitialOnRenderer() {
logger.info("[CLUSTER-STORE] requesting initial state sync"); this.dependencies.logger.info("[CLUSTER-STORE] requesting initial state sync");
for (const { id, state } of await requestInitialClusterStates()) { for (const { id, state } of await requestInitialClusterStates()) {
this.getById(id)?.setState(state); this.getById(id)?.setState(state);
@ -65,7 +65,7 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
} }
registerIpcListener() { registerIpcListener() {
logger.info(`[CLUSTER-STORE] start to listen (${webFrame.routingId})`); this.dependencies.logger.info(`[CLUSTER-STORE] start to listen (${webFrame.routingId})`);
const ipc = ipcMain ?? ipcRenderer; const ipc = ipcMain ?? ipcRenderer;
ipc?.on("cluster:state", (event, clusterId: ClusterId, state: ClusterState) => { ipc?.on("cluster:state", (event, clusterId: ClusterId, state: ClusterState) => {
@ -139,7 +139,7 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
} }
newClusters.set(clusterModel.id, cluster); newClusters.set(clusterModel.id, cluster);
} catch (error) { } catch (error) {
logger.warn(`[CLUSTER-STORE]: Failed to update/create a cluster: ${error}`); this.dependencies.logger.warn(`[CLUSTER-STORE]: Failed to update/create a cluster: ${error}`);
} }
} }

View File

@ -4,11 +4,13 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import Config from "conf"; import Config from "conf";
import type { BaseStoreParams } from "../base-store"; import type { Options as ConfOptions } from "conf/dist/source/types";
export type GetConfigurationFileModel = <T extends object>(content: ConfOptions<T>) => Config<T>;
const getConfigurationFileModelInjectable = getInjectable({ const getConfigurationFileModelInjectable = getInjectable({
id: "get-configuration-file-model", id: "get-configuration-file-model",
instantiate: () => <T extends object>(content: BaseStoreParams<T>) => new Config(content), instantiate: (): GetConfigurationFileModel => (content) => new Config(content),
causesSideEffects: true, causesSideEffects: true,
}); });

View File

@ -6,6 +6,9 @@ import { getInjectable } from "@ogre-tools/injectable";
import catalogCatalogEntityInjectable from "../catalog-entities/general-catalog-entities/implementations/catalog-catalog-entity.injectable"; import catalogCatalogEntityInjectable from "../catalog-entities/general-catalog-entities/implementations/catalog-catalog-entity.injectable";
import { HotbarStore } from "./store"; import { HotbarStore } from "./store";
import loggerInjectable from "../logger.injectable"; import loggerInjectable from "../logger.injectable";
import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable";
import getConfigurationFileModelInjectable from "../get-configuration-file-model/get-configuration-file-model.injectable";
import storeMigrationVersionInjectable from "../vars/store-migration-version.injectable";
const hotbarStoreInjectable = getInjectable({ const hotbarStoreInjectable = getInjectable({
id: "hotbar-store", id: "hotbar-store",
@ -13,9 +16,10 @@ const hotbarStoreInjectable = getInjectable({
instantiate: (di) => new HotbarStore({ instantiate: (di) => new HotbarStore({
catalogCatalogEntity: di.inject(catalogCatalogEntityInjectable), catalogCatalogEntity: di.inject(catalogCatalogEntityInjectable),
logger: di.inject(loggerInjectable), logger: di.inject(loggerInjectable),
directoryForUserData: di.inject(directoryForUserDataInjectable),
getConfigurationFileModel: di.inject(getConfigurationFileModelInjectable),
storeMigrationVersion: di.inject(storeMigrationVersionInjectable),
}), }),
causesSideEffects: true,
}); });
export default hotbarStoreInjectable; export default hotbarStoreInjectable;

View File

@ -4,6 +4,7 @@
*/ */
import { action, comparer, observable, makeObservable, computed } from "mobx"; import { action, comparer, observable, makeObservable, computed } from "mobx";
import type { BaseStoreDependencies } from "../base-store";
import { BaseStore } from "../base-store"; import { BaseStore } from "../base-store";
import migrations from "../../migrations/hotbar-store"; import migrations from "../../migrations/hotbar-store";
import { toJS } from "../utils"; import { toJS } from "../utils";
@ -21,7 +22,7 @@ export interface HotbarStoreModel {
activeHotbarId: string; activeHotbarId: string;
} }
interface Dependencies { interface Dependencies extends BaseStoreDependencies {
readonly catalogCatalogEntity: GeneralEntity; readonly catalogCatalogEntity: GeneralEntity;
readonly logger: Logger; readonly logger: Logger;
} }
@ -31,8 +32,8 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
@observable hotbars: Hotbar[] = []; @observable hotbars: Hotbar[] = [];
@observable private _activeHotbarId!: string; @observable private _activeHotbarId!: string;
constructor(private readonly dependencies: Dependencies) { constructor(protected readonly dependencies: Dependencies) {
super({ super(dependencies, {
configName: "lens-hotbar-store", configName: "lens-hotbar-store",
accessPropertiesByDotNotation: false, // To make dots safe in cluster context names accessPropertiesByDotNotation: false, // To make dots safe in cluster context names
syncOptions: { syncOptions: {
@ -148,7 +149,7 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
const index = this.hotbars.findIndex((hotbar) => hotbar.id === id); const index = this.hotbars.findIndex((hotbar) => hotbar.id === id);
if (index < 0) { if (index < 0) {
return void console.warn( return this.dependencies.logger.warn(
`[HOTBAR-STORE]: cannot setHotbarName: unknown id`, `[HOTBAR-STORE]: cannot setHotbarName: unknown id`,
{ id }, { id },
); );

View File

@ -6,6 +6,10 @@ import { getInjectable } from "@ogre-tools/injectable";
import { UserStore } from "./user-store"; import { UserStore } from "./user-store";
import selectedUpdateChannelInjectable from "../../features/application-update/common/selected-update-channel/selected-update-channel.injectable"; import selectedUpdateChannelInjectable from "../../features/application-update/common/selected-update-channel/selected-update-channel.injectable";
import emitAppEventInjectable from "../app-event-bus/emit-event.injectable"; import emitAppEventInjectable from "../app-event-bus/emit-event.injectable";
import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable";
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";
const userStoreInjectable = getInjectable({ const userStoreInjectable = getInjectable({
id: "user-store", id: "user-store",
@ -13,9 +17,11 @@ const userStoreInjectable = getInjectable({
instantiate: (di) => new UserStore({ instantiate: (di) => new UserStore({
selectedUpdateChannel: di.inject(selectedUpdateChannelInjectable), selectedUpdateChannel: di.inject(selectedUpdateChannelInjectable),
emitAppEvent: di.inject(emitAppEventInjectable), emitAppEvent: di.inject(emitAppEventInjectable),
directoryForUserData: di.inject(directoryForUserDataInjectable),
getConfigurationFileModel: di.inject(getConfigurationFileModelInjectable),
logger: di.inject(loggerInjectable),
storeMigrationVersion: di.inject(storeMigrationVersionInjectable),
}), }),
causesSideEffects: true,
}); });
export default userStoreInjectable; export default userStoreInjectable;

View File

@ -5,12 +5,12 @@
import { app } from "electron"; import { app } from "electron";
import { action, observable, reaction, makeObservable, isObservableArray, isObservableSet, isObservableMap } from "mobx"; import { action, observable, reaction, makeObservable, isObservableArray, isObservableSet, isObservableMap } from "mobx";
import type { BaseStoreDependencies } from "../base-store";
import { BaseStore } from "../base-store"; import { BaseStore } from "../base-store";
import migrations from "../../migrations/user-store"; import migrations from "../../migrations/user-store";
import { getOrInsertSet, toggle, toJS, object } from "../../renderer/utils"; import { getOrInsertSet, toggle, toJS, object } from "../../renderer/utils";
import { DESCRIPTORS } from "./preferences-helpers"; import { DESCRIPTORS } from "./preferences-helpers";
import type { UserPreferencesModel, StoreType } from "./preferences-helpers"; import type { UserPreferencesModel, StoreType } from "./preferences-helpers";
import logger from "../../main/logger";
import type { EmitAppEvent } from "../app-event-bus/emit-event.injectable"; import type { EmitAppEvent } from "../app-event-bus/emit-event.injectable";
// TODO: Remove coupling with Feature // TODO: Remove coupling with Feature
@ -22,7 +22,7 @@ export interface UserStoreModel {
preferences: UserPreferencesModel; preferences: UserPreferencesModel;
} }
interface Dependencies { interface Dependencies extends BaseStoreDependencies {
readonly selectedUpdateChannel: SelectedUpdateChannel; readonly selectedUpdateChannel: SelectedUpdateChannel;
emitAppEvent: EmitAppEvent; emitAppEvent: EmitAppEvent;
} }
@ -30,8 +30,8 @@ interface Dependencies {
export class UserStore extends BaseStore<UserStoreModel> /* implements UserStoreFlatModel (when strict null is enabled) */ { export class UserStore extends BaseStore<UserStoreModel> /* implements UserStoreFlatModel (when strict null is enabled) */ {
readonly displayName = "UserStore"; readonly displayName = "UserStore";
constructor(private readonly dependencies: Dependencies) { constructor(protected readonly dependencies: Dependencies) {
super({ super(dependencies, {
configName: "lens-user-store", configName: "lens-user-store",
migrations, migrations,
}); });
@ -138,7 +138,7 @@ export class UserStore extends BaseStore<UserStoreModel> /* implements UserStore
@action @action
protected fromStore({ lastSeenAppVersion, preferences }: Partial<UserStoreModel> = {}) { protected fromStore({ lastSeenAppVersion, preferences }: Partial<UserStoreModel> = {}) {
logger.debug("UserStore.fromStore()", { lastSeenAppVersion, preferences }); this.dependencies.logger.debug("UserStore.fromStore()", { lastSeenAppVersion, preferences });
if (lastSeenAppVersion) { if (lastSeenAppVersion) {
this.lastSeenAppVersion = lastSeenAppVersion; this.lastSeenAppVersion = lastSeenAppVersion;

View File

@ -123,6 +123,10 @@ export function isDefined<T>(val: T | undefined | null): val is T {
return val != null; return val != null;
} }
export function isFunction(val: unknown): val is (...args: unknown[]) => unknown {
return typeof val === "function";
}
/** /**
* Checks if the value in the second position is non-nullable * Checks if the value in the second position is non-nullable
*/ */
@ -146,6 +150,15 @@ export function hasDefiniteField<Field extends keyof T, T>(field: Field): (val:
return (val): val is T & { [f in Field]-?: NonNullable<T[Field]> } => val[field] != null; return (val): val is T & { [f in Field]-?: NonNullable<T[Field]> } => val[field] != null;
} }
export function isPromiseLike(res: unknown): res is (Promise<unknown> | { then: () => unknown }) {
if (res instanceof Promise) {
return true;
}
return isObject(res)
&& hasTypedProperty(res, "then", isFunction);
}
export function isPromiseSettledRejected<T>(result: PromiseSettledResult<T>): result is PromiseRejectedResult { export function isPromiseSettledRejected<T>(result: PromiseSettledResult<T>): result is PromiseRejectedResult {
return result.status === "rejected"; return result.status === "rejected";
} }

View File

@ -3,11 +3,20 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import directoryForUserDataInjectable from "./app-paths/directory-for-user-data/directory-for-user-data.injectable";
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";
import { WeblinkStore } from "./weblink-store"; import { WeblinkStore } from "./weblink-store";
const weblinkStoreInjectable = getInjectable({ const weblinkStoreInjectable = getInjectable({
id: "weblink-store", id: "weblink-store",
instantiate: () => new WeblinkStore(), instantiate: (di) => new WeblinkStore({
directoryForUserData: di.inject(directoryForUserDataInjectable),
getConfigurationFileModel: di.inject(getConfigurationFileModelInjectable),
logger: di.inject(loggerInjectable),
storeMigrationVersion: di.inject(storeMigrationVersionInjectable),
}),
}); });
export default weblinkStoreInjectable; export default weblinkStoreInjectable;

View File

@ -4,6 +4,7 @@
*/ */
import { action, comparer, observable, makeObservable } from "mobx"; import { action, comparer, observable, makeObservable } from "mobx";
import type { BaseStoreDependencies } from "./base-store";
import { BaseStore } from "./base-store"; import { BaseStore } from "./base-store";
import migrations from "../migrations/weblinks-store"; import migrations from "../migrations/weblinks-store";
import * as uuid from "uuid"; import * as uuid from "uuid";
@ -30,8 +31,8 @@ export class WeblinkStore extends BaseStore<WeblinkStoreModel> {
readonly displayName = "WeblinkStore"; readonly displayName = "WeblinkStore";
@observable weblinks: WeblinkData[] = []; @observable weblinks: WeblinkData[] = [];
constructor() { constructor(deps: BaseStoreDependencies) {
super({ super(deps, {
configName: "lens-weblink-store", configName: "lens-weblink-store",
accessPropertiesByDotNotation: false, // To make dots safe in cluster context names accessPropertiesByDotNotation: false, // To make dots safe in cluster context names
syncOptions: { syncOptions: {

View File

@ -8,6 +8,10 @@ import directoryForExtensionDataInjectable from "./directory-for-extension-data.
import ensureDirectoryInjectable from "../../../common/fs/ensure-dir.injectable"; import ensureDirectoryInjectable from "../../../common/fs/ensure-dir.injectable";
import joinPathsInjectable from "../../../common/path/join-paths.injectable"; import joinPathsInjectable from "../../../common/path/join-paths.injectable";
import randomBytesInjectable from "../../../common/utils/random-bytes.injectable"; import randomBytesInjectable from "../../../common/utils/random-bytes.injectable";
import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
import getConfigurationFileModelInjectable from "../../../common/get-configuration-file-model/get-configuration-file-model.injectable";
import loggerInjectable from "../../../common/logger.injectable";
import storeMigrationVersionInjectable from "../../../common/vars/store-migration-version.injectable";
const fileSystemProvisionerStoreInjectable = getInjectable({ const fileSystemProvisionerStoreInjectable = getInjectable({
id: "file-system-provisioner-store", id: "file-system-provisioner-store",
@ -17,6 +21,10 @@ const fileSystemProvisionerStoreInjectable = getInjectable({
ensureDirectory: di.inject(ensureDirectoryInjectable), ensureDirectory: di.inject(ensureDirectoryInjectable),
joinPaths: di.inject(joinPathsInjectable), joinPaths: di.inject(joinPathsInjectable),
randomBytes: di.inject(randomBytesInjectable), randomBytes: di.inject(randomBytesInjectable),
directoryForUserData: di.inject(directoryForUserDataInjectable),
getConfigurationFileModel: di.inject(getConfigurationFileModelInjectable),
logger: di.inject(loggerInjectable),
storeMigrationVersion: di.inject(storeMigrationVersionInjectable),
}), }),
}); });

View File

@ -5,6 +5,7 @@
import { SHA256 } from "crypto-js"; import { SHA256 } from "crypto-js";
import { action, makeObservable, observable } from "mobx"; import { action, makeObservable, observable } from "mobx";
import type { BaseStoreDependencies } from "../../../common/base-store";
import { BaseStore } from "../../../common/base-store"; import { BaseStore } from "../../../common/base-store";
import type { LensExtensionId } from "../../lens-extension"; import type { LensExtensionId } from "../../lens-extension";
import { getOrInsertWithAsync, toJS } from "../../../common/utils"; import { getOrInsertWithAsync, toJS } from "../../../common/utils";
@ -16,7 +17,7 @@ interface FSProvisionModel {
extensions: Record<string, string>; // extension names to paths extensions: Record<string, string>; // extension names to paths
} }
interface Dependencies { interface Dependencies extends BaseStoreDependencies {
readonly directoryForExtensionData: string; readonly directoryForExtensionData: string;
ensureDirectory: EnsureDirectory; ensureDirectory: EnsureDirectory;
joinPaths: JoinPaths; joinPaths: JoinPaths;
@ -27,8 +28,8 @@ export class FileSystemProvisionerStore extends BaseStore<FSProvisionModel> {
readonly displayName = "FilesystemProvisionerStore"; readonly displayName = "FilesystemProvisionerStore";
readonly registeredExtensions = observable.map<LensExtensionId, string>(); readonly registeredExtensions = observable.map<LensExtensionId, string>();
constructor(private readonly dependencies: Dependencies) { constructor(protected readonly dependencies: Dependencies) {
super({ super(dependencies, {
configName: "lens-filesystem-provisioner-store", configName: "lens-filesystem-provisioner-store",
accessPropertiesByDotNotation: false, // To make dots safe in cluster context names accessPropertiesByDotNotation: false, // To make dots safe in cluster context names
}); });

View File

@ -3,12 +3,18 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import type { BaseStoreParams } from "../common/base-store";
import { BaseStore } from "../common/base-store"; import { BaseStore } from "../common/base-store";
import * as path from "path"; import * as path from "path";
import type { LensExtension } from "./lens-extension"; import type { LensExtension } from "./lens-extension";
import assert from "assert"; import assert from "assert";
import type { StaticThis } from "../common/utils"; import type { StaticThis } from "../common/utils";
import { getOrInsertWith } from "../common/utils"; import { getOrInsertWith } from "../common/utils";
import { getLegacyGlobalDiForExtensionApi } from "./as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
import directoryForUserDataInjectable from "../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
import getConfigurationFileModelInjectable from "../common/get-configuration-file-model/get-configuration-file-model.injectable";
import loggerInjectable from "../common/logger.injectable";
import storeMigrationVersionInjectable from "../common/vars/store-migration-version.injectable";
export abstract class ExtensionStore<T extends object> extends BaseStore<T> { export abstract class ExtensionStore<T extends object> extends BaseStore<T> {
private static readonly instances = new WeakMap<object, ExtensionStore<object>>(); private static readonly instances = new WeakMap<object, ExtensionStore<object>>();
@ -33,6 +39,17 @@ export abstract class ExtensionStore<T extends object> extends BaseStore<T> {
return ExtensionStore.instances.get(this) as (T | undefined); return ExtensionStore.instances.get(this) as (T | undefined);
} }
constructor(params: BaseStoreParams<T>) {
const di = getLegacyGlobalDiForExtensionApi();
super({
directoryForUserData: di.inject(directoryForUserDataInjectable),
getConfigurationFileModel: di.inject(getConfigurationFileModelInjectable),
logger: di.inject(loggerInjectable),
storeMigrationVersion: di.inject(storeMigrationVersionInjectable),
}, params);
}
/** /**
* @deprecated This is a form of global shared state. Just call `new Store(...)` * @deprecated This is a form of global shared state. Just call `new Store(...)`
*/ */

View File

@ -3,11 +3,20 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import directoryForUserDataInjectable from "../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
import getConfigurationFileModelInjectable from "../../common/get-configuration-file-model/get-configuration-file-model.injectable";
import loggerInjectable from "../../common/logger.injectable";
import storeMigrationVersionInjectable from "../../common/vars/store-migration-version.injectable";
import { ExtensionsStore } from "./extensions-store"; import { ExtensionsStore } from "./extensions-store";
const extensionsStoreInjectable = getInjectable({ const extensionsStoreInjectable = getInjectable({
id: "extensions-store", id: "extensions-store",
instantiate: () => new ExtensionsStore(), instantiate: (di) => new ExtensionsStore({
directoryForUserData: di.inject(directoryForUserDataInjectable),
getConfigurationFileModel: di.inject(getConfigurationFileModelInjectable),
logger: di.inject(loggerInjectable),
storeMigrationVersion: di.inject(storeMigrationVersionInjectable),
}),
}); });
export default extensionsStoreInjectable; export default extensionsStoreInjectable;

View File

@ -6,6 +6,7 @@
import type { LensExtensionId } from "../lens-extension"; import type { LensExtensionId } from "../lens-extension";
import { action, computed, makeObservable, observable } from "mobx"; import { action, computed, makeObservable, observable } from "mobx";
import { toJS } from "../../common/utils"; import { toJS } from "../../common/utils";
import type { BaseStoreDependencies } from "../../common/base-store";
import { BaseStore } from "../../common/base-store"; import { BaseStore } from "../../common/base-store";
export interface LensExtensionsStoreModel { export interface LensExtensionsStoreModel {
@ -24,8 +25,8 @@ export interface IsEnabledExtensionDescriptor {
export class ExtensionsStore extends BaseStore<LensExtensionsStoreModel> { export class ExtensionsStore extends BaseStore<LensExtensionsStoreModel> {
readonly displayName = "ExtensionsStore"; readonly displayName = "ExtensionsStore";
constructor() { constructor(deps: BaseStoreDependencies) {
super({ super(deps, {
configName: "lens-extensions", configName: "lens-extensions",
}); });
makeObservable(this); makeObservable(this);