Remove Singleton from BaseStore to remove global shared state

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton committed 2022-12-06 09:18:58 -05:00
1 parent 2fa09ba10d
commit 257082e699
14 files changed
+97 -72

No files matched your search

@@ -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;
@@ -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;
}