diff --git a/packages/core/src/common/utils/find-key-contains.injectable.ts b/packages/core/src/common/utils/find-key-contains.injectable.ts new file mode 100644 index 0000000000..3a38c663b7 --- /dev/null +++ b/packages/core/src/common/utils/find-key-contains.injectable.ts @@ -0,0 +1,27 @@ +/** + * 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"; + +export type FindKeyContains = (map: Map, text: string) => T | undefined; + +const findKeyContainsInjectable = getInjectable({ + id: "find-key-contains", + + instantiate: (): FindKeyContains => { + return (map: Map, text: string) => { + const entries = map.entries(); + + for (const [key, value] of entries) { + if (key.includes(text)) { + return value; + } + } + + return undefined; + }; + }, +}); + +export default findKeyContainsInjectable; diff --git a/packages/core/src/common/utils/find-key-contains.test.ts b/packages/core/src/common/utils/find-key-contains.test.ts new file mode 100644 index 0000000000..088c8511b1 --- /dev/null +++ b/packages/core/src/common/utils/find-key-contains.test.ts @@ -0,0 +1,50 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getDiForUnitTesting } from "../../renderer/getDiForUnitTesting"; +import type { FindKeyContains } from "./find-key-contains.injectable"; +import findKeyContainsInjectable from "./find-key-contains.injectable"; + +describe("find-key-contains", () => { + let map: Map; + + let findKeyContains: FindKeyContains; + + beforeEach(() => { + const di = getDiForUnitTesting({ doGeneralOverrides: true }); + + findKeyContains = di.inject(findKeyContainsInjectable); + }); + + describe("map with entries", () => { + beforeEach(() => { + map = new Map(); + map.set("some-key", "some-value"); + }); + + it("given key starts with key, returns value", () => { + expect(findKeyContains(map, "some")).toEqual("some-value"); + }); + + it("given key ends with key, returns value", () => { + expect(findKeyContains(map, "key")).toEqual("some-value"); + }); + + it("given key is in middle of key, returns value", () => { + map.set("some-long-key", "some-value-for-long-key"); + + expect(findKeyContains(map, "long")).toEqual("some-value-for-long-key"); + }); + + it("given key does not include text, returns undefined", () => { + expect(findKeyContains(map, "not")).toEqual(undefined); + }); + }); + + describe("map with no entries", () => { + it("it returns undefined", () => { + expect(findKeyContains(map, "some-text")).toEqual(undefined); + }); + }); +}); diff --git a/packages/core/src/extensions/extension-loader/file-system-provisioner-store/ensure-hashed-directory-for-extension.injectable.ts b/packages/core/src/extensions/extension-loader/file-system-provisioner-store/ensure-hashed-directory-for-extension.injectable.ts index 6b696f663d..31f8a8147d 100644 --- a/packages/core/src/extensions/extension-loader/file-system-provisioner-store/ensure-hashed-directory-for-extension.injectable.ts +++ b/packages/core/src/extensions/extension-loader/file-system-provisioner-store/ensure-hashed-directory-for-extension.injectable.ts @@ -12,6 +12,7 @@ import joinPathsInjectable from "../../../common/path/join-paths.injectable"; import directoryForExtensionDataInjectable from "./directory-for-extension-data.injectable"; import ensureDirInjectable from "../../../common/fs/ensure-dir.injectable"; import getHashInjectable from "./get-hash.injectable"; +import findKeyContainsInjectable from "../../../common/utils/find-key-contains.injectable"; export type EnsureHashedDirectoryForExtension = (extensionName: string, registeredExtensions: ObservableMap) => Promise; @@ -24,8 +25,15 @@ const ensureHashedDirectoryForExtensionInjectable = getInjectable({ const directoryForExtensionData = di.inject(directoryForExtensionDataInjectable); const ensureDirectory = di.inject(ensureDirInjectable); const getHash = di.inject(getHashInjectable); + const findKeyContains = di.inject(findKeyContainsInjectable); return async (extensionName, registeredExtensions) => { + const legacyDirPath = findKeyContains(registeredExtensions, extensionName); + + if (legacyDirPath) { + return legacyDirPath; + } + const dirPath = await getOrInsertWithAsync(registeredExtensions, extensionName, async () => { const salt = (await randomBytes(32)).toString("hex"); const hashedName = getHash(`${extensionName}/${salt}`); diff --git a/packages/core/src/extensions/extension-loader/file-system-provisioner-store/ensure-hashed-directory-for-extension.test.ts b/packages/core/src/extensions/extension-loader/file-system-provisioner-store/ensure-hashed-directory-for-extension.test.ts new file mode 100644 index 0000000000..4c09565732 --- /dev/null +++ b/packages/core/src/extensions/extension-loader/file-system-provisioner-store/ensure-hashed-directory-for-extension.test.ts @@ -0,0 +1,67 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { ObservableMap } from "mobx"; +import { observable, runInAction } from "mobx"; +import { getDiForUnitTesting } from "../../../main/getDiForUnitTesting"; +import type { EnsureHashedDirectoryForExtension } from "./ensure-hashed-directory-for-extension.injectable"; +import ensureHashedDirectoryForExtensionInjectable from "./ensure-hashed-directory-for-extension.injectable"; +import ensureDirInjectable from "../../../common/fs/ensure-dir.injectable"; +import directoryForExtensionDataInjectable from "./directory-for-extension-data.injectable"; + +describe("ensure-hashed-directory-for-extension", () => { + let ensureHashedDirectoryForExtension: EnsureHashedDirectoryForExtension; + let ensureDirMock: jest.Mock; + let registeredExtensions: ObservableMap; + + beforeEach(() => { + const di = getDiForUnitTesting({ doGeneralOverrides: true }); + + ensureDirMock = jest.fn(); + + di.override(ensureDirInjectable, () => ensureDirMock); + di.override(directoryForExtensionDataInjectable, () => "some-directory-for-extension-data"); + + ensureHashedDirectoryForExtension = di.inject( + ensureHashedDirectoryForExtensionInjectable, + ); + + registeredExtensions = observable.map(); + }); + + it("given registered extension exists, returns existing directory", async () => { + runInAction(() => { + registeredExtensions.set("some-extension-name", "some-directory"); + }); + + const actual = await ensureHashedDirectoryForExtension( + "some-extension-name", + registeredExtensions, + ); + + expect(actual).toBe("some-directory"); + }); + + it("given registered extension does not exist, returns random directory", async () => { + const actual = await ensureHashedDirectoryForExtension( + "some-extension-name", + registeredExtensions, + ); + + expect(actual).not.toBe("some-directory"); + }); + + it("given extension directory was saved based on extension's package.json path, returns existing directory", async () => { + runInAction(() => { + registeredExtensions.set("/Users/some-user/Library/Application Support/Lens/node_modules/some-extension-name/package.json", "some-directory"); + }); + const actual = await ensureHashedDirectoryForExtension( + "some-extension-name", + registeredExtensions, + ); + + expect(actual).toBe("some-directory"); + }); + +});