diff --git a/src/extensions/extension-discovery/extension-discovery.injectable.ts b/src/extensions/extension-discovery/extension-discovery.injectable.ts index 09d0f3b0ae..2f5c4b66b0 100644 --- a/src/extensions/extension-discovery/extension-discovery.injectable.ts +++ b/src/extensions/extension-discovery/extension-discovery.injectable.ts @@ -9,7 +9,7 @@ import isCompatibleExtensionInjectable from "./is-compatible-extension/is-compat import extensionsStoreInjectable from "../extensions-store/extensions-store.injectable"; import extensionInstallationStateStoreInjectable from "../extension-installation-state-store/extension-installation-state-store.injectable"; import installExtensionInjectable from "../extension-installer/install-extension/install-extension.injectable"; -import extensionPackageRootDirectoryInjectable from "../extension-installer/extension-package-root-directory/extension-package-root-directory.injectable"; +import extensionPackageRootDirectoryInjectable from "../extension-installer/extension-package-root-directory.injectable"; import installExtensionsInjectable from "../extension-installer/install-extensions/install-extensions.injectable"; import staticFilesDirectoryInjectable from "../../common/vars/static-files-directory.injectable"; import readJsonFileInjectable from "../../common/fs/read-json-file.injectable"; diff --git a/src/extensions/extension-discovery/extension-discovery.ts b/src/extensions/extension-discovery/extension-discovery.ts index c7781d78a6..9c6842e67b 100644 --- a/src/extensions/extension-discovery/extension-discovery.ts +++ b/src/extensions/extension-discovery/extension-discovery.ts @@ -32,12 +32,13 @@ import type { GetDirnameOfPath } from "../../common/path/get-dirname.injectable" import type { GetRelativePath } from "../../common/path/get-relative-path.injectable"; import type { RemovePath } from "../../common/fs/remove-path.injectable"; import type TypedEventEmitter from "typed-emitter"; +import type { LazyInitializableState } from "../../common/initializable-state/create-lazy"; interface Dependencies { readonly extensionLoader: ExtensionLoader; readonly extensionsStore: ExtensionsStore; readonly extensionInstallationStateStore: ExtensionInstallationStateStore; - readonly extensionPackageRootDirectory: string; + readonly extensionPackageRootDirectory: LazyInitializableState; readonly staticFilesDirectory: string; readonly logger: Logger; readonly isProduction: boolean; @@ -134,11 +135,11 @@ export class ExtensionDiscovery { } get packageJsonPath(): string { - return this.dependencies.joinPaths(this.dependencies.extensionPackageRootDirectory, manifestFilename); + return this.dependencies.joinPaths(this.dependencies.extensionPackageRootDirectory.get(), manifestFilename); } get inTreeTargetPath(): string { - return this.dependencies.joinPaths(this.dependencies.extensionPackageRootDirectory, "extensions"); + return this.dependencies.joinPaths(this.dependencies.extensionPackageRootDirectory.get(), "extensions"); } get inTreeFolderPath(): string { @@ -146,7 +147,7 @@ export class ExtensionDiscovery { } get nodeModulesPath(): string { - return this.dependencies.joinPaths(this.dependencies.extensionPackageRootDirectory, "node_modules"); + return this.dependencies.joinPaths(this.dependencies.extensionPackageRootDirectory.get(), "node_modules"); } /** @@ -322,13 +323,15 @@ export class ExtensionDiscovery { throw new Error("ExtensionDiscovery.load() can be only be called once"); } + const extensionPackageRootDirectory = this.dependencies.extensionPackageRootDirectory.get(); + this.loadStarted = true; this.dependencies.logger.info( - `${logModule} loading extensions from ${this.dependencies.extensionPackageRootDirectory}`, + `${logModule} loading extensions from ${extensionPackageRootDirectory}`, ); - await this.dependencies.removePath(this.dependencies.joinPaths(this.dependencies.extensionPackageRootDirectory, "package-lock.json")); + await this.dependencies.removePath(this.dependencies.joinPaths(this.dependencies.extensionPackageRootDirectory.get(), "package-lock.json")); const canWriteToInTreeFolder = await this.dependencies.accessPath(this.inTreeFolderPath, constants.W_OK); diff --git a/src/extensions/extension-installer/extension-installer.injectable.ts b/src/extensions/extension-installer/extension-installer.injectable.ts index 169b758049..acdd2733e9 100644 --- a/src/extensions/extension-installer/extension-installer.injectable.ts +++ b/src/extensions/extension-installer/extension-installer.injectable.ts @@ -4,17 +4,14 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { ExtensionInstaller } from "./extension-installer"; -import extensionPackageRootDirectoryInjectable from "./extension-package-root-directory/extension-package-root-directory.injectable"; +import extensionPackageRootDirectoryInjectable from "./extension-package-root-directory.injectable"; const extensionInstallerInjectable = getInjectable({ id: "extension-installer", - instantiate: (di) => - new ExtensionInstaller({ - extensionPackageRootDirectory: di.inject( - extensionPackageRootDirectoryInjectable, - ), - }), + instantiate: (di) => new ExtensionInstaller({ + extensionPackageRootDirectory: di.inject(extensionPackageRootDirectoryInjectable), + }), }); export default extensionInstallerInjectable; diff --git a/src/extensions/extension-installer/extension-installer.ts b/src/extensions/extension-installer/extension-installer.ts index 1764435a54..011b829681 100644 --- a/src/extensions/extension-installer/extension-installer.ts +++ b/src/extensions/extension-installer/extension-installer.ts @@ -9,11 +9,12 @@ import fs from "fs-extra"; import path from "path"; import logger from "../../main/logger"; import type { PackageJson } from "type-fest"; +import type { LazyInitializableState } from "../../common/initializable-state/create-lazy"; const logModule = "[EXTENSION-INSTALLER]"; interface Dependencies { - extensionPackageRootDirectory: string; + readonly extensionPackageRootDirectory: LazyInitializableState; } /** @@ -22,7 +23,7 @@ interface Dependencies { export class ExtensionInstaller { private installLock = new AwaitLock(); - constructor(private dependencies: Dependencies) {} + constructor(private readonly dependencies: Dependencies) {} get npmPath() { return __non_webpack_require__.resolve("npm"); @@ -35,15 +36,17 @@ export class ExtensionInstaller { // Mutual exclusion to install packages in sequence await this.installLock.acquireAsync(); + const extensionPackageRootDirectory = this.dependencies.extensionPackageRootDirectory.get(); + try { // Write the package.json which will be installed in .installDependencies() await fs.writeFile(path.join(packageJsonPath), JSON.stringify(packagesJson, null, 2), { mode: 0o600, }); - logger.info(`${logModule} installing dependencies at ${this.dependencies.extensionPackageRootDirectory}`); + logger.info(`${logModule} installing dependencies at ${extensionPackageRootDirectory}`); await this.npm(["install", "--audit=false", "--fund=false", "--only=prod", "--prefer-offline"]); - logger.info(`${logModule} dependencies installed at ${this.dependencies.extensionPackageRootDirectory}`); + logger.info(`${logModule} dependencies installed at ${extensionPackageRootDirectory}`); } finally { this.installLock.release(); } @@ -55,20 +58,23 @@ export class ExtensionInstaller { installPackage = async (name: string): Promise => { // Mutual exclusion to install packages in sequence await this.installLock.acquireAsync(); + const extensionPackageRootDirectory = this.dependencies.extensionPackageRootDirectory.get(); try { - logger.info(`${logModule} installing package from ${name} to ${this.dependencies.extensionPackageRootDirectory}`); + logger.info(`${logModule} installing package from ${name} to ${extensionPackageRootDirectory}`); await this.npm(["install", "--audit=false", "--fund=false", "--only=prod", "--prefer-offline", name]); - logger.info(`${logModule} package ${name} installed to ${this.dependencies.extensionPackageRootDirectory}`); + logger.info(`${logModule} package ${name} installed to ${extensionPackageRootDirectory}`); } finally { this.installLock.release(); } }; private npm(args: string[]): Promise { + const extensionPackageRootDirectory = this.dependencies.extensionPackageRootDirectory.get(); + return new Promise((resolve, reject) => { const child = child_process.fork(this.npmPath, args, { - cwd: this.dependencies.extensionPackageRootDirectory, + cwd: extensionPackageRootDirectory, silent: true, env: {}, }); diff --git a/src/extensions/extension-installer/extension-package-root-directory.injectable.ts b/src/extensions/extension-installer/extension-package-root-directory.injectable.ts new file mode 100644 index 0000000000..e578506f61 --- /dev/null +++ b/src/extensions/extension-installer/extension-package-root-directory.injectable.ts @@ -0,0 +1,13 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import directoryForUserDataInjectable from "../../common/app-paths/directory-for-user-data.injectable"; +import { createLazyInitializableState } from "../../common/initializable-state/create-lazy"; + +const extensionPackageRootDirectoryInjectable = createLazyInitializableState({ + id: "extension-package-root-directory", + init: (di) => di.inject(directoryForUserDataInjectable).get(), +}); + +export default extensionPackageRootDirectoryInjectable; diff --git a/src/extensions/extension-installer/extension-package-root-directory/extension-package-root-directory.injectable.ts b/src/extensions/extension-installer/extension-package-root-directory/extension-package-root-directory.injectable.ts deleted file mode 100644 index d43b38b8bc..0000000000 --- a/src/extensions/extension-installer/extension-package-root-directory/extension-package-root-directory.injectable.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * 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 directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data.injectable"; - -const extensionPackageRootDirectoryInjectable = getInjectable({ - id: "extension-package-root-directory", - - instantiate: (di) => di.inject(directoryForUserDataInjectable), -}); - -export default extensionPackageRootDirectoryInjectable; diff --git a/src/extensions/extension-packages-root/extension-packages-root.injectable.ts b/src/extensions/extension-packages-root/extension-packages-root.injectable.ts deleted file mode 100644 index 721b04eaaf..0000000000 --- a/src/extensions/extension-packages-root/extension-packages-root.injectable.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * 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 directoryForUserDataInjectable - from "../../common/app-paths/directory-for-user-data.injectable"; - -const extensionPackagesRootInjectable = getInjectable({ - id: "extension-packages-root", - instantiate: (di) => di.inject(directoryForUserDataInjectable), -}); - -export default extensionPackagesRootInjectable;