diff --git a/src/extensions/extension-discovery.ts b/src/extensions/extension-discovery.ts index 2b26d79a9c..c03a5a2ee5 100644 --- a/src/extensions/extension-discovery.ts +++ b/src/extensions/extension-discovery.ts @@ -266,18 +266,30 @@ export class ExtensionDiscovery { logger.info(`${logModule} loading extensions from ${extensionInstaller.extensionPackagesRoot}`); - if (fs.existsSync(path.join(extensionInstaller.extensionPackagesRoot, "package-lock.json"))) { + if (await fs.pathExists(path.join(extensionInstaller.extensionPackagesRoot, "package-lock.json"))) { await fs.remove(path.join(extensionInstaller.extensionPackagesRoot, "package-lock.json")); } try { + // Verify write access to static/extensions, which is needed for symlinking await fs.access(this.inTreeFolderPath, fs.constants.W_OK); + + // Set bundled folder path to static/extensions this.bundledFolderPath = this.inTreeFolderPath; } catch { - // we need to copy in-tree extensions so that we can symlink them properly on "npm install" + // If there is error accessing static/extensions, we need to copy in-tree extensions so that we can symlink them properly on "npm install". + // The error can happen if there is read-only rights to static/extensions, which would fail symlinking. + + // Remove e.g. /Users//Library/Application Support/LensDev/extensions await fs.remove(this.inTreeTargetPath); + + // Create folder e.g. /Users//Library/Application Support/LensDev/extensions await fs.ensureDir(this.inTreeTargetPath); + + // Copy static/extensions to e.g. /Users//Library/Application Support/LensDev/extensions await fs.copy(this.inTreeFolderPath, this.inTreeTargetPath); + + // Set bundled folder path to e.g. /Users//Library/Application Support/LensDev/extensions this.bundledFolderPath = this.inTreeTargetPath; } diff --git a/src/extensions/extension-installer.ts b/src/extensions/extension-installer.ts index 2143c62287..59f416d4e3 100644 --- a/src/extensions/extension-installer.ts +++ b/src/extensions/extension-installer.ts @@ -41,8 +41,8 @@ export class ExtensionInstaller { child.on("close", () => { resolve(); }); - child.on("error", (err) => { - reject(err); + child.on("error", error => { + reject(error); }); }); } diff --git a/src/main/index.ts b/src/main/index.ts index ea3c53f9b9..1a349f9484 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -94,17 +94,21 @@ app.on("ready", async () => { windowManager = WindowManager.getInstance(proxyPort); // call after windowManager to see splash earlier - const extensions = await extensionDiscovery.load(); + try { + const extensions = await extensionDiscovery.load(); - // Subscribe to extensions that are copied or deleted to/from the extensions folder - extensionDiscovery.events.on("add", (extension: InstalledExtension) => { - extensionLoader.addExtension(extension); - }); - extensionDiscovery.events.on("remove", (lensExtensionId: LensExtensionId) => { - extensionLoader.removeExtension(lensExtensionId); - }); + // Subscribe to extensions that are copied or deleted to/from the extensions folder + extensionDiscovery.events.on("add", (extension: InstalledExtension) => { + extensionLoader.addExtension(extension); + }); + extensionDiscovery.events.on("remove", (lensExtensionId: LensExtensionId) => { + extensionLoader.removeExtension(lensExtensionId); + }); - extensionLoader.initExtensions(extensions); + extensionLoader.initExtensions(extensions); + } catch (error ){ + dialog.showErrorBox("Lens Error", `Could not load extensions: ${error?.message || ""}`); + } setTimeout(() => { appEventBus.emit({ name: "service", action: "start" });