mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Remove Singleton from BaseStore to remove global shared state
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
1 parent
2fa09ba10d
commit
257082e699
14 files changed
+97
-72
No files matched your search
+9
-9
@@ -5,19 +5,19 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { FileSystemProvisionerStore } from "./file-system-provisioner-store";
|
||||
import directoryForExtensionDataInjectable from "./directory-for-extension-data.injectable";
|
||||
import ensureDirectoryInjectable from "../../../common/fs/ensure-dir.injectable";
|
||||
import joinPathsInjectable from "../../../common/path/join-paths.injectable";
|
||||
import randomBytesInjectable from "../../../common/utils/random-bytes.injectable";
|
||||
|
||||
const fileSystemProvisionerStoreInjectable = getInjectable({
|
||||
id: "file-system-provisioner-store",
|
||||
|
||||
instantiate: (di) => {
|
||||
FileSystemProvisionerStore.resetInstance();
|
||||
|
||||
return FileSystemProvisionerStore.createInstance({
|
||||
directoryForExtensionData: di.inject(directoryForExtensionDataInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
causesSideEffects: true,
|
||||
instantiate: (di) => new FileSystemProvisionerStore({
|
||||
directoryForExtensionData: di.inject(directoryForExtensionDataInjectable),
|
||||
ensureDirectory: di.inject(ensureDirectoryInjectable),
|
||||
joinPaths: di.inject(joinPathsInjectable),
|
||||
randomBytes: di.inject(randomBytesInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
export default fileSystemProvisionerStoreInjectable;
|
||||
+14
-11
@@ -3,28 +3,31 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { randomBytes } from "crypto";
|
||||
import { SHA256 } from "crypto-js";
|
||||
import fse from "fs-extra";
|
||||
import { action, makeObservable, observable } from "mobx";
|
||||
import path from "path";
|
||||
import { BaseStore } from "../../../common/base-store";
|
||||
import type { LensExtensionId } from "../../lens-extension";
|
||||
import { getOrInsertWith, toJS } from "../../../common/utils";
|
||||
import { getOrInsertWithAsync, toJS } from "../../../common/utils";
|
||||
import type { EnsureDirectory } from "../../../common/fs/ensure-dir.injectable";
|
||||
import type { JoinPaths } from "../../../common/path/join-paths.injectable";
|
||||
import type { RandomBytes } from "../../../common/utils/random-bytes.injectable";
|
||||
|
||||
interface FSProvisionModel {
|
||||
extensions: Record<string, string>; // extension names to paths
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
directoryForExtensionData: string;
|
||||
readonly directoryForExtensionData: string;
|
||||
ensureDirectory: EnsureDirectory;
|
||||
joinPaths: JoinPaths;
|
||||
randomBytes: RandomBytes;
|
||||
}
|
||||
|
||||
export class FileSystemProvisionerStore extends BaseStore<FSProvisionModel> {
|
||||
readonly displayName = "FilesystemProvisionerStore";
|
||||
registeredExtensions = observable.map<LensExtensionId, string>();
|
||||
readonly registeredExtensions = observable.map<LensExtensionId, string>();
|
||||
|
||||
constructor(private dependencies: Dependencies) {
|
||||
constructor(private readonly dependencies: Dependencies) {
|
||||
super({
|
||||
configName: "lens-filesystem-provisioner-store",
|
||||
accessPropertiesByDotNotation: false, // To make dots safe in cluster context names
|
||||
@@ -41,14 +44,14 @@ export class FileSystemProvisionerStore extends BaseStore<FSProvisionModel> {
|
||||
* @returns path to the folder that the extension can safely write files to.
|
||||
*/
|
||||
async requestDirectory(extensionName: string): Promise<string> {
|
||||
const dirPath = getOrInsertWith(this.registeredExtensions, extensionName, () => {
|
||||
const salt = randomBytes(32).toString("hex");
|
||||
const dirPath = await getOrInsertWithAsync(this.registeredExtensions, extensionName, async () => {
|
||||
const salt = (await this.dependencies.randomBytes(32)).toString("hex");
|
||||
const hashedName = SHA256(`${extensionName}/${salt}`).toString();
|
||||
|
||||
return path.resolve(this.dependencies.directoryForExtensionData, hashedName);
|
||||
return this.dependencies.joinPaths(this.dependencies.directoryForExtensionData, hashedName);
|
||||
});
|
||||
|
||||
await fse.ensureDir(dirPath);
|
||||
await this.dependencies.ensureDirectory(dirPath);
|
||||
|
||||
return dirPath;
|
||||
}
|
||||
|
||||
@@ -7,8 +7,39 @@ import { BaseStore } from "../common/base-store";
|
||||
import * as path from "path";
|
||||
import type { LensExtension } from "./lens-extension";
|
||||
import assert from "assert";
|
||||
import type { StaticThis } from "../common/utils";
|
||||
import { getOrInsertWith } from "../common/utils";
|
||||
|
||||
export abstract class ExtensionStore<T extends object> extends BaseStore<T> {
|
||||
private static readonly instances = new WeakMap<object, ExtensionStore<object>>();
|
||||
|
||||
/**
|
||||
* @deprecated This is a form of global shared state. Just call `new Store(...)`
|
||||
*/
|
||||
static createInstance<T extends ExtensionStore<object>, R extends any[]>(this: StaticThis<T, R>, ...args: R): T {
|
||||
return getOrInsertWith(ExtensionStore.instances, this, () => new this(...args)) as T;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This is a form of global shared state. Just call `new Store(...)`
|
||||
*/
|
||||
static getInstance<T, R extends any[]>(this: StaticThis<T, R>, strict?: true): T;
|
||||
static getInstance<T, R extends any[]>(this: StaticThis<T, R>, strict: false): T | undefined;
|
||||
static getInstance<T, R extends any[]>(this: StaticThis<T, R>, strict = true): T | undefined {
|
||||
if (!ExtensionStore.instances.has(this) && strict) {
|
||||
throw new TypeError(`instance of ${this.name} is not created`);
|
||||
}
|
||||
|
||||
return ExtensionStore.instances.get(this) as (T | undefined);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This is a form of global shared state. Just call `new Store(...)`
|
||||
*/
|
||||
static resetInstance() {
|
||||
ExtensionStore.instances.delete(this);
|
||||
}
|
||||
|
||||
readonly displayName = "ExtensionStore<T>";
|
||||
protected extension?: LensExtension;
|
||||
|
||||
|
||||
@@ -7,14 +7,7 @@ import { ExtensionsStore } from "./extensions-store";
|
||||
|
||||
const extensionsStoreInjectable = getInjectable({
|
||||
id: "extensions-store",
|
||||
|
||||
instantiate: () => {
|
||||
ExtensionsStore.resetInstance();
|
||||
|
||||
return ExtensionsStore.createInstance();
|
||||
},
|
||||
|
||||
causesSideEffects: true,
|
||||
instantiate: () => new ExtensionsStore(),
|
||||
});
|
||||
|
||||
export default extensionsStoreInjectable;
|
||||
Reference in new issue
Block a user