diff --git a/src/extensions/extension-loader/extension-loader.ts b/src/extensions/extension-loader/extension-loader.ts index 0708e11c8e..2957f3f610 100644 --- a/src/extensions/extension-loader/extension-loader.ts +++ b/src/extensions/extension-loader/extension-loader.ts @@ -21,6 +21,7 @@ import type { LensRendererExtension } from "../lens-renderer-extension"; import { NpmJsVersionChecker } from "../npmjs-latest-version.checker"; import * as registries from "../registries"; import type { LensExtensionState } from "../extensions-store/extensions-store"; +import { BundledVersionChecker } from "../bundled-latest-version-checker"; const logModule = "[EXTENSIONS-LOADER]"; @@ -65,6 +66,7 @@ export class ExtensionLoader { private extensionUpdateSources = { github: new GitHubVersionChecker(), npmJs: new NpmJsVersionChecker(), + bundled: new BundledVersionChecker(), }; @observable isLoaded = false; @@ -112,6 +114,10 @@ export class ExtensionLoader { return extensions; } + @computed get bundledExtensions(): InstalledExtension[] { + return [...this.extensions.values()].filter(extension => extension.isBundled) + } + /** * Get the extension instance by its manifest name * @param name The name of the extension @@ -282,9 +288,7 @@ export class ExtensionLoader { } }); - if (!extension.isBundled) { - this.checkForExtensionUpdate(extension); - } + this.checkForExtensionUpdate(extension); return removeItems; }); diff --git a/src/extensions/extension-updater/bundled-extensions-updater.injectable.ts b/src/extensions/extension-updater/bundled-extensions-updater.injectable.ts new file mode 100644 index 0000000000..a2eed21a30 --- /dev/null +++ b/src/extensions/extension-updater/bundled-extensions-updater.injectable.ts @@ -0,0 +1,21 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; +import installFromInputInjectable from "../../renderer/components/+extensions/install-from-input/install-from-input.injectable"; +import extensionLoaderInjectable from "../extension-loader/extension-loader.injectable"; +import { BundledExtensionsUpdater } from "./bundled-extensions-updater"; + +const bundledExtensionsUpdaterInjectable = getInjectable({ + instantiate: (di) => + new BundledExtensionsUpdater({ + installFromInput: di.inject(installFromInputInjectable), + extensions: di.inject(extensionLoaderInjectable).bundledExtensions + }), + + lifecycle: lifecycleEnum.singleton, +}); + +export default bundledExtensionsUpdaterInjectable; \ No newline at end of file diff --git a/src/extensions/extension-updater/bundled-extensions-updater.ts b/src/extensions/extension-updater/bundled-extensions-updater.ts new file mode 100644 index 0000000000..2ed277e808 --- /dev/null +++ b/src/extensions/extension-updater/bundled-extensions-updater.ts @@ -0,0 +1,34 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { BundledExtensionsLoaded, ipcRendererOn } from "../../common/ipc" +import { logger } from "../common-api"; +import type { InstalledExtension } from "../extension-discovery/extension-discovery"; +import { ExtensionUpdater, UpdaterDependencies } from "./extension-updater"; + +interface Dependencies extends UpdaterDependencies { + extensions: InstalledExtension[]; +} + +export class BundledExtensionsUpdater extends ExtensionUpdater { + constructor(protected dependencies: Dependencies) { + super(dependencies); + } + + init() { + ipcRendererOn(BundledExtensionsLoaded, (event) => { + this.updateAll(); + }); + } + + private async updateAll() { + logger.info("[EXTENSIONS-UPDATER]: Bundled extensions update started."); + + const updates = this.dependencies.extensions.map(this.update); + await Promise.allSettled(updates); + + logger.info("[EXTENSIONS-UPDATER]: Bundled extensions update finished."); + } +} \ No newline at end of file diff --git a/src/extensions/extension-updater/extension-updater.ts b/src/extensions/extension-updater/extension-updater.ts new file mode 100644 index 0000000000..b1589aed85 --- /dev/null +++ b/src/extensions/extension-updater/extension-updater.ts @@ -0,0 +1,28 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type { InstalledExtension } from "../extension-discovery/extension-discovery" + +export interface UpdaterDependencies { + installFromInput: (input: string) => Promise; +} + +export class ExtensionUpdater { + constructor(protected dependencies : UpdaterDependencies) { + } + + async update({ availableUpdate, manifest }: InstalledExtension): Promise { + return new Promise(resolve => { + if (availableUpdate) { + console.info(`[EXTENSIONS-UPDATER]: Trying to update ${manifest.name} extension`); + + resolve(); + // TODO: actual install + // this.dependencies.installFromInput(availableUpdate.input); + } + }); + + } +} \ No newline at end of file diff --git a/src/renderer/frames/root-frame/init-root-frame/init-root-frame.injectable.ts b/src/renderer/frames/root-frame/init-root-frame/init-root-frame.injectable.ts index 6827bb3008..4bde2637d6 100644 --- a/src/renderer/frames/root-frame/init-root-frame/init-root-frame.injectable.ts +++ b/src/renderer/frames/root-frame/init-root-frame/init-root-frame.injectable.ts @@ -9,6 +9,7 @@ import ipcRendererInjectable from "../../../app-paths/get-value-from-registered- import bindProtocolAddRouteHandlersInjectable from "../../../protocol-handler/bind-protocol-add-route-handlers/bind-protocol-add-route-handlers.injectable"; import lensProtocolRouterRendererInjectable from "../../../protocol-handler/lens-protocol-router-renderer/lens-protocol-router-renderer.injectable"; import catalogEntityRegistryInjectable from "../../../api/catalog-entity-registry/catalog-entity-registry.injectable"; +import bundledExtensionsUpdaterInjectable from "../../../../extensions/extension-updater/bundled-extensions-updater.injectable"; const initRootFrameInjectable = getInjectable({ instantiate: (di) => { @@ -28,6 +29,8 @@ const initRootFrameInjectable = getInjectable({ ), catalogEntityRegistry: di.inject(catalogEntityRegistryInjectable), + + bundledExtensionsUpdater: di.inject(bundledExtensionsUpdaterInjectable) }); }, diff --git a/src/renderer/frames/root-frame/init-root-frame/init-root-frame.ts b/src/renderer/frames/root-frame/init-root-frame/init-root-frame.ts index c166847e2c..45fea5cf6e 100644 --- a/src/renderer/frames/root-frame/init-root-frame/init-root-frame.ts +++ b/src/renderer/frames/root-frame/init-root-frame/init-root-frame.ts @@ -9,6 +9,7 @@ import logger from "../../../../common/logger"; import { unmountComponentAtNode } from "react-dom"; import type { ExtensionLoading } from "../../../../extensions/extension-loader"; import type { CatalogEntityRegistry } from "../../../api/catalog-entity-registry"; +import type { BundledExtensionsUpdater } from "../../../../extensions/extension-updater/bundled-extensions-updater"; interface Dependencies { loadExtensions: () => Promise; @@ -20,6 +21,8 @@ interface Dependencies { bindProtocolAddRouteHandlers: () => void; lensProtocolRouterRenderer: { init: () => void }; catalogEntityRegistry: CatalogEntityRegistry; + + bundledExtensionsUpdater: BundledExtensionsUpdater; } const logPrefix = "[ROOT-FRAME]:"; @@ -30,11 +33,12 @@ export const initRootFrame = bindProtocolAddRouteHandlers, lensProtocolRouterRenderer, ipcRenderer, - catalogEntityRegistry, + bundledExtensionsUpdater, }: Dependencies) => async (rootElem: HTMLElement) => { catalogEntityRegistry.init(); + bundledExtensionsUpdater.init(); try { // maximum time to let bundled extensions finish loading