diff --git a/package-lock.json b/package-lock.json index 097333fff0..9f974ed20b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10392,14 +10392,14 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.55.0.tgz", - "integrity": "sha512-IZGc50rtbjk+xp5YQoJvmMPmJEYoC53SiKPXyqWfv15XoD2Y5Kju6zN0DwlmaGJp1Iw33JsWJcQ7nw0lGCGjVg==", + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.57.1.tgz", + "integrity": "sha512-1MeobQkQ9tztuleT3v72XmY0XuKXVXusAhryoLuU5YZ+mXoYKZP9SQ7Flulh1NX4DTjpGTc2b/eMu4u7M7dhnQ==", "dependencies": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.55.0", - "@typescript-eslint/type-utils": "5.55.0", - "@typescript-eslint/utils": "5.55.0", + "@typescript-eslint/scope-manager": "5.57.1", + "@typescript-eslint/type-utils": "5.57.1", + "@typescript-eslint/utils": "5.57.1", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -10424,6 +10424,101 @@ } } }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.57.1.tgz", + "integrity": "sha512-N/RrBwEUKMIYxSKl0oDK5sFVHd6VI7p9K5MyUlVYAY6dyNb/wHUqndkTd3XhpGlXgnQsBkRZuu4f9kAHghvgPw==", + "dependencies": { + "@typescript-eslint/types": "5.57.1", + "@typescript-eslint/visitor-keys": "5.57.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.57.1.tgz", + "integrity": "sha512-bSs4LOgyV3bJ08F5RDqO2KXqg3WAdwHCu06zOqcQ6vqbTJizyBhuh1o1ImC69X4bV2g1OJxbH71PJqiO7Y1RuA==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.57.1.tgz", + "integrity": "sha512-A2MZqD8gNT0qHKbk2wRspg7cHbCDCk2tcqt6ScCFLr5Ru8cn+TCfM786DjPhqwseiS+PrYwcXht5ztpEQ6TFTw==", + "dependencies": { + "@typescript-eslint/types": "5.57.1", + "@typescript-eslint/visitor-keys": "5.57.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.57.1.tgz", + "integrity": "sha512-kN6vzzf9NkEtawECqze6v99LtmDiUJCVpvieTFA1uL7/jDghiJGubGZ5csicYHU1Xoqb3oH/R5cN5df6W41Nfg==", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.57.1", + "@typescript-eslint/types": "5.57.1", + "@typescript-eslint/typescript-estree": "5.57.1", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.57.1.tgz", + "integrity": "sha512-RjQrAniDU0CEk5r7iphkm731zKlFiUjvcBS2yHAg8WWqFMCaCrD0rKEVOMUyMMcbGPZ0bPp56srkGWrgfZqLRA==", + "dependencies": { + "@typescript-eslint/types": "5.57.1", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@typescript-eslint/experimental-utils": { "version": "5.55.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.55.0.tgz", @@ -10543,6 +10638,7 @@ "version": "5.55.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.55.0.tgz", "integrity": "sha512-OK+cIO1ZGhJYNCL//a3ROpsd83psf4dUJ4j7pdNVzd5DmIk+ffkuUIX2vcZQbEW/IR41DYsfJTB19tpCboxQuw==", + "peer": true, "dependencies": { "@typescript-eslint/types": "5.55.0", "@typescript-eslint/visitor-keys": "5.55.0" @@ -10556,12 +10652,12 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.55.0.tgz", - "integrity": "sha512-ObqxBgHIXj8rBNm0yh8oORFrICcJuZPZTqtAFh0oZQyr5DnAHZWfyw54RwpEEH+fD8suZaI0YxvWu5tYE/WswA==", + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.57.1.tgz", + "integrity": "sha512-/RIPQyx60Pt6ga86hKXesXkJ2WOS4UemFrmmq/7eOyiYjYv/MUSHPlkhU6k9T9W1ytnTJueqASW+wOmW4KrViw==", "dependencies": { - "@typescript-eslint/typescript-estree": "5.55.0", - "@typescript-eslint/utils": "5.55.0", + "@typescript-eslint/typescript-estree": "5.57.1", + "@typescript-eslint/utils": "5.57.1", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -10581,10 +10677,106 @@ } } }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.57.1.tgz", + "integrity": "sha512-N/RrBwEUKMIYxSKl0oDK5sFVHd6VI7p9K5MyUlVYAY6dyNb/wHUqndkTd3XhpGlXgnQsBkRZuu4f9kAHghvgPw==", + "dependencies": { + "@typescript-eslint/types": "5.57.1", + "@typescript-eslint/visitor-keys": "5.57.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.57.1.tgz", + "integrity": "sha512-bSs4LOgyV3bJ08F5RDqO2KXqg3WAdwHCu06zOqcQ6vqbTJizyBhuh1o1ImC69X4bV2g1OJxbH71PJqiO7Y1RuA==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.57.1.tgz", + "integrity": "sha512-A2MZqD8gNT0qHKbk2wRspg7cHbCDCk2tcqt6ScCFLr5Ru8cn+TCfM786DjPhqwseiS+PrYwcXht5ztpEQ6TFTw==", + "dependencies": { + "@typescript-eslint/types": "5.57.1", + "@typescript-eslint/visitor-keys": "5.57.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.57.1.tgz", + "integrity": "sha512-kN6vzzf9NkEtawECqze6v99LtmDiUJCVpvieTFA1uL7/jDghiJGubGZ5csicYHU1Xoqb3oH/R5cN5df6W41Nfg==", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.57.1", + "@typescript-eslint/types": "5.57.1", + "@typescript-eslint/typescript-estree": "5.57.1", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.57.1.tgz", + "integrity": "sha512-RjQrAniDU0CEk5r7iphkm731zKlFiUjvcBS2yHAg8WWqFMCaCrD0rKEVOMUyMMcbGPZ0bPp56srkGWrgfZqLRA==", + "dependencies": { + "@typescript-eslint/types": "5.57.1", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@typescript-eslint/types": { "version": "5.55.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.55.0.tgz", "integrity": "sha512-M4iRh4AG1ChrOL6Y+mETEKGeDnT7Sparn6fhZ5LtVJF1909D5O4uqK+C5NPbLmpfZ0XIIxCdwzKiijpZUOvOug==", + "peer": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -10597,6 +10789,7 @@ "version": "5.55.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.55.0.tgz", "integrity": "sha512-I7X4A9ovA8gdpWMpr7b1BN9eEbvlEtWhQvpxp/yogt48fy9Lj3iE3ild/1H3jKBBIYj5YYJmS2+9ystVhC7eaQ==", + "peer": true, "dependencies": { "@typescript-eslint/types": "5.55.0", "@typescript-eslint/visitor-keys": "5.55.0", @@ -10623,6 +10816,7 @@ "version": "5.55.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.55.0.tgz", "integrity": "sha512-FkW+i2pQKcpDC3AY6DU54yl8Lfl14FVGYDgBTyGKB75cCwV3KpkpTMFi9d9j2WAJ4271LR2HeC5SEWF/CZmmfw==", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", @@ -10648,6 +10842,7 @@ "version": "5.55.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.55.0.tgz", "integrity": "sha512-q2dlHHwWgirKh1D3acnuApXG+VNXpEY5/AwRxDVuEQpxWaB0jCDe0jFMVMALJ3ebSfuOVE8/rMS+9ZOYGg1GWw==", + "peer": true, "dependencies": { "@typescript-eslint/types": "5.55.0", "eslint-visitor-keys": "^3.3.0" @@ -19388,9 +19583,9 @@ "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" }, "node_modules/immer": { - "version": "9.0.19", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.19.tgz", - "integrity": "sha512-eY+Y0qcsB4TZKwgQzLaE/lqYMlKhv5J9dyd2RhhtGhNo2njPXDqU9XPfcNfa3MIDsdtZt5KlkIsirlo4dHsWdQ==", + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", "funding": { "type": "opencollective", "url": "https://opencollective.com/immer" @@ -38179,7 +38374,7 @@ "history": "^4.10.1", "hpagent": "^1.2.0", "http-proxy": "^1.18.1", - "immer": "^9.0.19", + "immer": "^9.0.21", "joi": "^17.9.1", "js-yaml": "^4.1.0", "lodash": "^4.17.15", @@ -38274,7 +38469,7 @@ "@types/webpack-dev-server": "^4.7.2", "@types/webpack-env": "^1.18.0", "@types/webpack-node-externals": "^2.5.3", - "@typescript-eslint/eslint-plugin": "^5.52.0", + "@typescript-eslint/eslint-plugin": "^5.57.1", "@typescript-eslint/parser": "^5.57.1", "adr": "^1.4.3", "ansi_up": "^5.2.1", diff --git a/packages/core/package.json b/packages/core/package.json index 20abccc569..2ea1d36165 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -142,7 +142,7 @@ "history": "^4.10.1", "hpagent": "^1.2.0", "http-proxy": "^1.18.1", - "immer": "^9.0.19", + "immer": "^9.0.21", "joi": "^17.9.1", "js-yaml": "^4.1.0", "lodash": "^4.17.15", @@ -237,7 +237,7 @@ "@types/webpack-dev-server": "^4.7.2", "@types/webpack-env": "^1.18.0", "@types/webpack-node-externals": "^2.5.3", - "@typescript-eslint/eslint-plugin": "^5.52.0", + "@typescript-eslint/eslint-plugin": "^5.57.1", "@typescript-eslint/parser": "^5.57.1", "adr": "^1.4.3", "ansi_up": "^5.2.1", diff --git a/packages/core/src/common/protocol-handler/router.ts b/packages/core/src/common/protocol-handler/router.ts index 2147e932e2..33bc911f69 100644 --- a/packages/core/src/common/protocol-handler/router.ts +++ b/packages/core/src/common/protocol-handler/router.ts @@ -201,7 +201,7 @@ export abstract class LensProtocolRouter { return name; } - const extension = extensionLoader.getInstanceByName(name); + const extension = extensionLoader.getInstanceByName(name) as LensExtension | undefined; if (!extension) { this.dependencies.logger.info(`${LensProtocolRouter.LoggingPrefix}: Extension ${name} matched, but does not have a class for ${ipcRenderer ? "renderer" : "main"}`); diff --git a/packages/core/src/extensions/__tests__/lens-extension.test.ts b/packages/core/src/extensions/__tests__/lens-extension.test.ts index 7cb90a548b..11635818ab 100644 --- a/packages/core/src/extensions/__tests__/lens-extension.test.ts +++ b/packages/core/src/extensions/__tests__/lens-extension.test.ts @@ -3,17 +3,23 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { LensExtension } from "../lens-extension"; -import { Console } from "console"; -import { stdout, stderr } from "process"; - -console = new Console(stdout, stderr); - -let ext: LensExtension; +import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import { LensMainExtension } from "../lens-main-extension"; describe("lens extension", () => { + let ext: LensMainExtension; + beforeEach(async () => { - ext = new LensExtension({ + const builder = getApplicationBuilder(); + + /** + * This is required because it sets up `AppPaths` which are required by LensMainExtension. + * + * That type isn't used internally so it needs to use "legacy global DI" to get its dependencies. + */ + await builder.render(); + + ext = new LensMainExtension({ manifest: { name: "foo-bar", version: "0.1.1", diff --git a/packages/core/src/extensions/extension-loader/create-extension-instance.token.ts b/packages/core/src/extensions/extension-loader/create-extension-instance.token.ts deleted file mode 100644 index 97ded49d84..0000000000 --- a/packages/core/src/extensions/extension-loader/create-extension-instance.token.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import type { LensExtensionConstructor, BundledInstalledExtension, ExternalInstalledExtension, BundledLensExtensionConstructor } from "@k8slens/legacy-extensions"; -import { getInjectionToken } from "@ogre-tools/injectable"; -import type { LensExtension } from "../lens-extension"; - -export interface CreateExtensionInstance { - (ExtensionClass: LensExtensionConstructor, extension: ExternalInstalledExtension): LensExtension; - (ExtensionClass: BundledLensExtensionConstructor, extension: BundledInstalledExtension): LensExtension; -} - -export const createExtensionInstanceInjectionToken = getInjectionToken({ - id: "create-extension-instance-token", -}); diff --git a/packages/core/src/extensions/extension-loader/extension-instances.injectable.ts b/packages/core/src/extensions/extension-loader/extension-instances.injectable.ts index fe95b858eb..74fb85657d 100644 --- a/packages/core/src/extensions/extension-loader/extension-instances.injectable.ts +++ b/packages/core/src/extensions/extension-loader/extension-instances.injectable.ts @@ -2,14 +2,13 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { LensExtensionId } from "@k8slens/legacy-extensions"; +import type { LegacyLensExtension, LensExtensionId } from "@k8slens/legacy-extensions"; import { getInjectable } from "@ogre-tools/injectable"; import { observable } from "mobx"; -import type { LensExtension } from "../lens-extension"; const extensionInstancesInjectable = getInjectable({ id: "extension-instances", - instantiate: () => observable.map(), + instantiate: () => observable.map(), }); export default extensionInstancesInjectable; diff --git a/packages/core/src/extensions/extension-loader/extension-loader.injectable.ts b/packages/core/src/extensions/extension-loader/extension-loader.injectable.ts index 12187c38c0..9a77273a30 100644 --- a/packages/core/src/extensions/extension-loader/extension-loader.injectable.ts +++ b/packages/core/src/extensions/extension-loader/extension-loader.injectable.ts @@ -4,9 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { ExtensionLoader } from "./extension-loader"; -import { createExtensionInstanceInjectionToken } from "./create-extension-instance.token"; import extensionInstancesInjectable from "./extension-instances.injectable"; -import type { LensExtension } from "../lens-extension"; import extensionInjectable from "./extension/extension.injectable"; import loggerInjectable from "../../common/logger.injectable"; import joinPathsInjectable from "../../common/path/join-paths.injectable"; @@ -20,9 +18,8 @@ const extensionLoaderInjectable = getInjectable({ instantiate: (di) => new ExtensionLoader({ updateExtensionsState: di.inject(updateExtensionsStateInjectable), - createExtensionInstance: di.inject(createExtensionInstanceInjectionToken), extensionInstances: di.inject(extensionInstancesInjectable), - getExtension: (instance: LensExtension) => di.inject(extensionInjectable, instance), + getExtension: (instance) => di.inject(extensionInjectable, instance), bundledExtensions: di.injectMany(bundledExtensionInjectionToken), extensionEntryPointName: di.inject(extensionEntryPointNameInjectionToken), logger: di.inject(loggerInjectable), diff --git a/packages/core/src/extensions/extension-loader/extension-loader.ts b/packages/core/src/extensions/extension-loader/extension-loader.ts index 3ba5a16728..c81d071714 100644 --- a/packages/core/src/extensions/extension-loader/extension-loader.ts +++ b/packages/core/src/extensions/extension-loader/extension-loader.ts @@ -9,13 +9,12 @@ import type { ObservableMap } from "mobx"; import { runInAction, action, computed, toJS, observable, reaction, when } from "mobx"; import { broadcastMessage, ipcMainOn, ipcRendererOn, ipcMainHandle } from "../../common/ipc"; import { isDefined, iter } from "@k8slens/utilities"; -import type { ExternalInstalledExtension, InstalledExtension, LensExtensionConstructor, LensExtensionId, BundledExtension } from "@k8slens/legacy-extensions"; +import type { ExternalInstalledExtension, InstalledExtension, LensExtensionConstructor, LensExtensionId, BundledExtension, BundledInstalledExtension, LegacyLensExtension } from "@k8slens/legacy-extensions"; import type { LensExtension } from "../lens-extension"; import { extensionLoaderFromMainChannel, extensionLoaderFromRendererChannel } from "../../common/ipc/extension-handling"; import { requestExtensionLoaderInitialState } from "../../renderer/ipc"; import assert from "assert"; import { EventEmitter } from "../../common/event-emitter"; -import type { CreateExtensionInstance } from "./create-extension-instance.token"; import type { Extension } from "./extension/extension.injectable"; import type { Logger } from "../../common/logger"; import type { JoinPaths } from "../../common/path/join-paths.injectable"; @@ -25,13 +24,12 @@ import type { UpdateExtensionsState } from "../../features/extensions/enabled/co const logModule = "[EXTENSIONS-LOADER]"; interface Dependencies { - readonly extensionInstances: ObservableMap; + readonly extensionInstances: ObservableMap; readonly bundledExtensions: BundledExtension[]; readonly logger: Logger; readonly extensionEntryPointName: "main" | "renderer"; updateExtensionsState: UpdateExtensionsState; - createExtensionInstance: CreateExtensionInstance; - getExtension: (instance: LensExtension) => Extension; + getExtension: (instance: LegacyLensExtension) => Extension; joinPaths: JoinPaths; getDirnameOfPath: GetDirnameOfPath; } @@ -85,7 +83,7 @@ export class ExtensionLoader { * - `null` if no class definition is provided for the current process * - `undefined` if the name is not known about */ - getInstanceByName(name: string): LensExtension | null | undefined { + getInstanceByName(name: string): LegacyLensExtension | null | undefined { if (this.nonInstancesByName.has(name)) { return null; } @@ -236,7 +234,7 @@ export class ExtensionLoader { return null; } - const installedExtension: InstalledExtension = { + const installedExtension: BundledInstalledExtension = { absolutePath: "irrelevant", id: extension.manifest.name, isBundled: true, @@ -245,10 +243,7 @@ export class ExtensionLoader { manifest: extension.manifest, manifestPath: "irrelevant", }; - const instance = this.dependencies.createExtensionInstance( - LensExtensionClass, - installedExtension, - ); + const instance = new LensExtensionClass(installedExtension); this.dependencies.extensionInstances.set(extension.manifest.name, instance); @@ -307,35 +302,32 @@ export class ExtensionLoader { return [...installedExtensions.entries()] .filter((entry): entry is [string, ExternalInstalledExtension] => !entry[1].isBundled) - .map(([extId, extension]) => { - const alreadyInit = this.dependencies.extensionInstances.has(extId) || this.nonInstancesByName.has(extension.manifest.name); + .map(([extId, installedExtension]) => { + const alreadyInit = this.dependencies.extensionInstances.has(extId) || this.nonInstancesByName.has(installedExtension.manifest.name); - if (extension.isCompatible && extension.isEnabled && !alreadyInit) { + if (installedExtension.isCompatible && installedExtension.isEnabled && !alreadyInit) { try { - const LensExtensionClass = this.requireExtension(extension); + const LensExtensionClass = this.requireExtension(installedExtension); if (!LensExtensionClass) { - this.nonInstancesByName.add(extension.manifest.name); + this.nonInstancesByName.add(installedExtension.manifest.name); return null; } - const instance = this.dependencies.createExtensionInstance( - LensExtensionClass, - extension, - ); + const instance = new LensExtensionClass(installedExtension); this.dependencies.extensionInstances.set(extId, instance); return { instance, - installedExtension: extension, + installedExtension, activated: instance.activate(), } as ExtensionBeingActivated; } catch (err) { - this.dependencies.logger.error(`${logModule}: error loading extension`, { ext: extension, err }); + this.dependencies.logger.error(`${logModule}: error loading extension`, { ext: installedExtension, err }); } - } else if (!extension.isEnabled && alreadyInit) { + } else if (!installedExtension.isEnabled && alreadyInit) { this.removeInstance(extId); } diff --git a/packages/core/src/extensions/extension-loader/extension-registrator-injection-token.ts b/packages/core/src/extensions/extension-loader/extension-registrator-injection-token.ts index 295d3b67a4..7d507debb6 100644 --- a/packages/core/src/extensions/extension-loader/extension-registrator-injection-token.ts +++ b/packages/core/src/extensions/extension-loader/extension-registrator-injection-token.ts @@ -2,13 +2,14 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ +import type { LegacyLensExtension } from "@k8slens/legacy-extensions"; import type { Injectable } from "@ogre-tools/injectable"; import { getInjectionToken } from "@ogre-tools/injectable"; import type { IComputedValue } from "mobx"; -import type { LensExtension } from "../lens-extension"; -export type ExtensionRegistrator = (extension: LensExtension) => - Injectable[] | IComputedValue[]>; +export type Injectables = Injectable[]; +export type Registration = Injectables | IComputedValue; +export type ExtensionRegistrator = (extension: LegacyLensExtension) => Registration; export const extensionRegistratorInjectionToken = getInjectionToken({ id: "extension-registrator-token", diff --git a/packages/core/src/extensions/extension-loader/extension/extension.injectable.ts b/packages/core/src/extensions/extension-loader/extension/extension.injectable.ts index d54d997d09..16b69fa6bd 100644 --- a/packages/core/src/extensions/extension-loader/extension/extension.injectable.ts +++ b/packages/core/src/extensions/extension-loader/extension/extension.injectable.ts @@ -5,9 +5,9 @@ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; import { reaction, runInAction } from "mobx"; import { disposer } from "@k8slens/utilities"; -import type { LensExtension } from "../../lens-extension"; import { extensionRegistratorInjectionToken } from "../extension-registrator-injection-token"; import { injectableDifferencingRegistratorWith } from "../../../common/utils/registrator-helper"; +import type { LegacyLensExtension } from "@k8slens/legacy-extensions"; export interface Extension { register: () => void; @@ -17,7 +17,7 @@ export interface Extension { const extensionInjectable = getInjectable({ id: "extension", - instantiate: (parentDi, instance: LensExtension): Extension => { + instantiate: (parentDi, instance): Extension => { const extensionInjectable = getInjectable({ id: `extension-${instance.sanitizedExtensionId}`, @@ -66,7 +66,7 @@ const extensionInjectable = getInjectable({ }, lifecycle: lifecycleEnum.keyedSingleton({ - getInstanceKey: (di, instance: LensExtension) => instance, + getInstanceKey: (di, instance: LegacyLensExtension) => instance, }), }); diff --git a/packages/core/src/extensions/extensions.injectable.ts b/packages/core/src/extensions/extensions.injectable.ts index 7cc019a318..3e0f0ad898 100644 --- a/packages/core/src/extensions/extensions.injectable.ts +++ b/packages/core/src/extensions/extensions.injectable.ts @@ -2,16 +2,23 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ +import { iter } from "@k8slens/utilities"; import { getInjectable } from "@ogre-tools/injectable"; import { computed } from "mobx"; +import isExtensionEnabledInjectable from "../features/extensions/enabled/common/is-enabled.injectable"; import extensionInstancesInjectable from "./extension-loader/extension-instances.injectable"; const extensionsInjectable = getInjectable({ id: "extensions", instantiate: (di) => { const extensionInstances = di.inject(extensionInstancesInjectable); + const isExtensionEnabled = di.inject(isExtensionEnabledInjectable); - return computed(() => [...extensionInstances.values()].filter(extension => extension.isEnabled)); + return computed(() => ( + iter.chain(extensionInstances.values()) + .filter(extension => extension.isBundled || isExtensionEnabled(extension.id)) + .toArray() + )); }, }); diff --git a/packages/core/src/extensions/ipc/ipc-main.ts b/packages/core/src/extensions/ipc/ipc-main.ts index a4f4ec14df..20190d8774 100644 --- a/packages/core/src/extensions/ipc/ipc-main.ts +++ b/packages/core/src/extensions/ipc/ipc-main.ts @@ -4,16 +4,31 @@ */ import { ipcMain } from "electron"; import { IpcPrefix, IpcRegistrar } from "./ipc-registrar"; -import { Disposers, lensExtensionDependencies } from "../lens-extension"; +import { Disposers } from "../lens-extension"; import type { LensMainExtension } from "../lens-main-extension"; import type { Disposer } from "@k8slens/utilities"; import { once } from "lodash"; import { ipcMainHandle } from "../../common/ipc"; +import type { Logger } from "../common-api"; +import { getEnvironmentSpecificLegacyGlobalDiForExtensionApi } from "../as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; +import loggerInjectable from "../../common/logger.injectable"; + +interface Dependencies { + readonly logger: Logger; +} export abstract class IpcMain extends IpcRegistrar { + private readonly dependencies: Dependencies; + constructor(extension: LensMainExtension) { super(extension); + const di = getEnvironmentSpecificLegacyGlobalDiForExtensionApi("main"); + + this.dependencies = { + logger: di.inject(loggerInjectable), + }; + // Call the static method on the bottom child class. extension[Disposers].push(() => (this.constructor as typeof IpcMain).resetInstance()); } @@ -27,12 +42,12 @@ export abstract class IpcMain extends IpcRegistrar { listen(channel: string, listener: (event: Electron.IpcRendererEvent, ...args: any[]) => any): Disposer { const prefixedChannel = `extensions@${this[IpcPrefix]}:${channel}`; const cleanup = once(() => { - this.extension[lensExtensionDependencies].logger.debug(`[IPC-RENDERER]: removing extension listener`, { channel, extension: { name: this.extension.name, version: this.extension.version }}); + this.dependencies.logger.debug(`[IPC-RENDERER]: removing extension listener`, { channel, extension: { name: this.extension.name, version: this.extension.version }}); return ipcMain.removeListener(prefixedChannel, listener); }); - this.extension[lensExtensionDependencies].logger.debug(`[IPC-RENDERER]: adding extension listener`, { channel, extension: { name: this.extension.name, version: this.extension.version }}); + this.dependencies.logger.debug(`[IPC-RENDERER]: adding extension listener`, { channel, extension: { name: this.extension.name, version: this.extension.version }}); ipcMain.addListener(prefixedChannel, listener); this.extension[Disposers].push(cleanup); @@ -47,10 +62,10 @@ export abstract class IpcMain extends IpcRegistrar { handle(channel: string, handler: (event: Electron.IpcMainInvokeEvent, ...args: any[]) => any): void { const prefixedChannel = `extensions@${this[IpcPrefix]}:${channel}`; - this.extension[lensExtensionDependencies].logger.debug(`[IPC-RENDERER]: adding extension handler`, { channel, extension: { name: this.extension.name, version: this.extension.version }}); + this.dependencies.logger.debug(`[IPC-RENDERER]: adding extension handler`, { channel, extension: { name: this.extension.name, version: this.extension.version }}); ipcMainHandle(prefixedChannel, handler); this.extension[Disposers].push(() => { - this.extension[lensExtensionDependencies].logger.debug(`[IPC-RENDERER]: removing extension handler`, { channel, extension: { name: this.extension.name, version: this.extension.version }}); + this.dependencies.logger.debug(`[IPC-RENDERER]: removing extension handler`, { channel, extension: { name: this.extension.name, version: this.extension.version }}); return ipcMain.removeHandler(prefixedChannel); }); diff --git a/packages/core/src/extensions/lens-extension-set-dependencies.ts b/packages/core/src/extensions/lens-extension-set-dependencies.ts deleted file mode 100644 index aa22b7a1a1..0000000000 --- a/packages/core/src/extensions/lens-extension-set-dependencies.ts +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import type { IComputedValue } from "mobx"; -import type { CatalogCategoryRegistry } from "../common/catalog"; -import type { NavigateToRoute } from "../common/front-end-routing/navigate-to-route-injection-token"; -import type { Route } from "../common/front-end-routing/front-end-route-injection-token"; -import type { CatalogEntityRegistry as MainCatalogEntityRegistry } from "../main/catalog"; -import type { CatalogEntityRegistry as RendererCatalogEntityRegistry } from "../renderer/api/catalog/entity/registry"; -import type { GetExtensionPageParameters } from "../renderer/routes/get-extension-page-parameters.injectable"; -import type { NavigateForExtension } from "../main/start-main-application/lens-window/navigate-for-extension.injectable"; -import type { Logger } from "../common/logger"; -import type { EnsureHashedDirectoryForExtension } from "./extension-loader/file-system-provisioner-store/ensure-hashed-directory-for-extension.injectable"; - -export interface LensExtensionDependencies { - readonly logger: Logger; - ensureHashedDirectoryForExtension: EnsureHashedDirectoryForExtension; -} - -export interface LensMainExtensionDependencies extends LensExtensionDependencies { - readonly entityRegistry: MainCatalogEntityRegistry; - readonly navigate: NavigateForExtension; -} - -export interface LensRendererExtensionDependencies extends LensExtensionDependencies { - navigateToRoute: NavigateToRoute; - getExtensionPageParameters: GetExtensionPageParameters; - readonly routes: IComputedValue[]>; - readonly entityRegistry: RendererCatalogEntityRegistry; - readonly categoryRegistry: CatalogCategoryRegistry; -} diff --git a/packages/core/src/extensions/lens-extension.ts b/packages/core/src/extensions/lens-extension.ts index ea451ca56e..407d4e9aa2 100644 --- a/packages/core/src/extensions/lens-extension.ts +++ b/packages/core/src/extensions/lens-extension.ts @@ -5,19 +5,19 @@ import { action, computed, makeObservable, observable } from "mobx"; import { disposer } from "@k8slens/utilities"; -import type { LensExtensionDependencies } from "./lens-extension-set-dependencies"; import type { ProtocolHandlerRegistration } from "../common/protocol-handler/registration"; -import type { InstalledExtension, LegacyLensExtension, LensExtensionId, LensExtensionManifest } from "@k8slens/legacy-extensions"; +import type { InstalledExtension, LensExtensionId, LensExtensionManifest } from "@k8slens/legacy-extensions"; +import type { Logger } from "./common-api"; +import type { EnsureHashedDirectoryForExtension } from "./extension-loader/file-system-provisioner-store/ensure-hashed-directory-for-extension.injectable"; -export const lensExtensionDependencies = Symbol("lens-extension-dependencies"); export const Disposers = Symbol("disposers"); -export class LensExtension< - /** - * @ignore - */ - Dependencies extends LensExtensionDependencies = LensExtensionDependencies, -> implements LegacyLensExtension { +export interface LensExtensionDependencies { + readonly logger: Logger; + ensureHashedDirectoryForExtension: EnsureHashedDirectoryForExtension; +} + +export class LensExtension { readonly id: LensExtensionId; readonly manifest: LensExtensionManifest; readonly manifestPath: string; @@ -27,6 +27,11 @@ export class LensExtension< return sanitizeExtensionName(this.name); } + /** + * @ignore + */ + protected readonly dependencies: LensExtensionDependencies; + protocolHandlers: ProtocolHandlerRegistration[] = []; @observable private _isEnabled = false; @@ -40,12 +45,12 @@ export class LensExtension< */ [Disposers] = disposer(); - constructor({ id, manifest, manifestPath, isBundled }: InstalledExtension) { - // id is the name of the manifest + constructor(deps: LensExtensionDependencies, { id, manifest, manifestPath, isBundled }: InstalledExtension) { + this.dependencies = deps; this.id = id; this.manifest = manifest as LensExtensionManifest; this.manifestPath = manifestPath; - this.isBundled = !!isBundled; + this.isBundled = isBundled; makeObservable(this); } @@ -66,11 +71,6 @@ export class LensExtension< return this.manifest.storeName || this.name; } - /** - * @ignore - */ - readonly [lensExtensionDependencies]!: Dependencies; - /** * getExtensionFileFolder returns the path to an already created folder. This * folder is for the sole use of this extension. @@ -80,7 +80,7 @@ export class LensExtension< */ async getExtensionFileFolder(): Promise { // storeName is read from the manifest and has a fallback to the manifest name, which equals id - return this[lensExtensionDependencies].ensureHashedDirectoryForExtension(this.storeName); + return this.dependencies.ensureHashedDirectoryForExtension(this.storeName); } @action @@ -90,7 +90,7 @@ export class LensExtension< } this._isEnabled = true; - this[lensExtensionDependencies].logger.info(`[EXTENSION]: enabled ${this.name}@${this.version}`); + this.dependencies.logger.info(`[EXTENSION]: enabled ${this.name}@${this.version}`); } @action @@ -104,9 +104,9 @@ export class LensExtension< try { await this.onDeactivate(); this[Disposers](); - this[lensExtensionDependencies].logger.info(`[EXTENSION]: disabled ${this.name}@${this.version}`); + this.dependencies.logger.info(`[EXTENSION]: disabled ${this.name}@${this.version}`); } catch (error) { - this[lensExtensionDependencies].logger.error(`[EXTENSION]: disabling ${this.name}@${this.version} threw an error: ${error}`); + this.dependencies.logger.error(`[EXTENSION]: disabling ${this.name}@${this.version} threw an error: ${error}`); } } diff --git a/packages/core/src/extensions/lens-main-extension.ts b/packages/core/src/extensions/lens-main-extension.ts index 9f7096f722..69d3594fa7 100644 --- a/packages/core/src/extensions/lens-main-extension.ts +++ b/packages/core/src/extensions/lens-main-extension.ts @@ -3,19 +3,49 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { LensExtension, lensExtensionDependencies } from "./lens-extension"; +import type { LensExtensionDependencies } from "./lens-extension"; +import { LensExtension } from "./lens-extension"; import type { CatalogEntity } from "../common/catalog"; import type { IComputedValue, IObservableArray } from "mobx"; import { isObservableArray } from "mobx"; import type { MenuRegistration } from "../features/application-menu/main/menu-registration"; import type { TrayMenuRegistration } from "../main/tray/tray-menu-registration"; import type { ShellEnvModifier } from "../main/shell-session/shell-env-modifier/shell-env-modifier-registration"; -import type { LensMainExtensionDependencies } from "./lens-extension-set-dependencies"; +import { getEnvironmentSpecificLegacyGlobalDiForExtensionApi } from "./as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; +import type { InstalledExtension } from "./common-api"; +import type { CatalogEntityRegistry } from "../main/catalog"; +import type { NavigateForExtension } from "../main/start-main-application/lens-window/navigate-for-extension.injectable"; +import catalogEntityRegistryInjectable from "../main/catalog/entity-registry.injectable"; +import loggerInjectable from "../common/logger.injectable"; +import navigateForExtensionInjectable from "../main/start-main-application/lens-window/navigate-for-extension.injectable"; +import ensureHashedDirectoryForExtensionInjectable from "./extension-loader/file-system-provisioner-store/ensure-hashed-directory-for-extension.injectable"; -export class LensMainExtension extends LensExtension { +interface LensMainExtensionDependencies extends LensExtensionDependencies { + readonly entityRegistry: CatalogEntityRegistry; + readonly navigate: NavigateForExtension; +} + +export class LensMainExtension extends LensExtension { appMenus: MenuRegistration[] | IComputedValue = []; trayMenus: TrayMenuRegistration[] | IComputedValue = []; + /** + * @ignore + */ + declare readonly dependencies: LensMainExtensionDependencies; + + constructor(extension: InstalledExtension) { + const di = getEnvironmentSpecificLegacyGlobalDiForExtensionApi("main"); + const deps: LensMainExtensionDependencies = { + ensureHashedDirectoryForExtension: di.inject(ensureHashedDirectoryForExtensionInjectable), + navigate: di.inject(navigateForExtensionInjectable), + entityRegistry: di.inject(catalogEntityRegistryInjectable), + logger: di.inject(loggerInjectable), + }; + + super(deps, extension); + } + /** * implement this to modify the shell environment that Lens terminals are opened with. The ShellEnvModifier type has the signature * @@ -32,18 +62,18 @@ export class LensMainExtension extends LensExtension, frameId?: number) { - await this[lensExtensionDependencies].navigate(this.id, pageId, params, frameId); + await this.dependencies.navigate(this.id, pageId, params, frameId); } addCatalogSource(id: string, source: IObservableArray | IComputedValue) { if (isObservableArray(source)) { - this[lensExtensionDependencies].entityRegistry.addObservableSource(`${this.name}:${id}`, source); + this.dependencies.entityRegistry.addObservableSource(`${this.name}:${id}`, source); } else { - this[lensExtensionDependencies].entityRegistry.addComputedSource(`${this.name}:${id}`, source); + this.dependencies.entityRegistry.addComputedSource(`${this.name}:${id}`, source); } } removeCatalogSource(id: string) { - this[lensExtensionDependencies].entityRegistry.removeSource(`${this.name}:${id}`); + this.dependencies.entityRegistry.removeSource(`${this.name}:${id}`); } } diff --git a/packages/core/src/extensions/lens-renderer-extension.ts b/packages/core/src/extensions/lens-renderer-extension.ts index 5a64a6ec6c..c4cdcb3468 100644 --- a/packages/core/src/extensions/lens-renderer-extension.ts +++ b/packages/core/src/extensions/lens-renderer-extension.ts @@ -3,10 +3,11 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { Disposers, LensExtension, lensExtensionDependencies } from "./lens-extension"; -import type { CatalogEntity, CategoryFilter } from "../common/catalog"; +import { Disposers, LensExtension } from "./lens-extension"; import type { Disposer } from "@k8slens/utilities"; -import type { EntityFilter } from "../renderer/api/catalog/entity/registry"; +import type { LensExtensionDependencies } from "./lens-extension"; +import type { CatalogEntity, CategoryFilter, CatalogCategoryRegistry } from "../common/catalog"; +import type { EntityFilter, CatalogEntityRegistry } from "../renderer/api/catalog/entity/registry"; import type { TopBarRegistration } from "../renderer/components/layout/top-bar/top-bar-registration"; import type { KubernetesCluster } from "../common/catalog-entities"; import type { WelcomeMenuRegistration } from "../renderer/components/+welcome/welcome-menu-items/welcome-menu-registration"; @@ -22,7 +23,6 @@ import type { KubeObjectStatusRegistration } from "../renderer/components/kube-o import { fromPairs, map, matches, toPairs } from "lodash/fp"; import { pipeline } from "@ogre-tools/fp"; import { getExtensionRoutePath } from "../renderer/routes/for-extension"; -import type { LensRendererExtensionDependencies } from "./lens-extension-set-dependencies"; import type { KubeObjectHandlerRegistration } from "../renderer/kube-object/handler"; import type { AppPreferenceTabRegistration } from "../features/preferences/renderer/compliance-for-legacy-extension-api/app-preference-tab-registration"; import type { KubeObjectDetailRegistration } from "../renderer/components/kube-object-details/kube-object-detail-registration"; @@ -31,8 +31,29 @@ import type { EntitySettingRegistration } from "../renderer/components/+entity-s import type { CatalogEntityDetailRegistration } from "../renderer/components/+catalog/entity-details/token"; import type { PageRegistration } from "../renderer/routes/page-registration"; import type { ClusterPageMenuRegistration } from "../renderer/components/layout/cluster-page-menu"; +import type { IComputedValue } from "mobx"; +import type { NavigateToRoute } from "../common/front-end-routing/navigate-to-route-injection-token"; +import type { Route } from "../common/front-end-routing/front-end-route-injection-token"; +import type { GetExtensionPageParameters } from "../renderer/routes/get-extension-page-parameters.injectable"; +import type { InstalledExtension } from "./common-api"; +import { getEnvironmentSpecificLegacyGlobalDiForExtensionApi } from "./as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; +import catalogCategoryRegistryInjectable from "../common/catalog/category-registry.injectable"; +import catalogEntityRegistryInjectable from "../renderer/api/catalog/entity/registry.injectable"; +import loggerInjectable from "../common/logger.injectable"; +import getExtensionPageParametersInjectable from "../renderer/routes/get-extension-page-parameters.injectable"; +import navigateToRouteInjectable from "../renderer/routes/navigate-to-route.injectable"; +import routesInjectable from "../renderer/routes/routes.injectable"; +import ensureHashedDirectoryForExtensionInjectable from "./extension-loader/file-system-provisioner-store/ensure-hashed-directory-for-extension.injectable"; -export class LensRendererExtension extends LensExtension { +interface LensRendererExtensionDependencies extends LensExtensionDependencies { + navigateToRoute: NavigateToRoute; + getExtensionPageParameters: GetExtensionPageParameters; + readonly routes: IComputedValue[]>; + readonly entityRegistry: CatalogEntityRegistry; + readonly categoryRegistry: CatalogCategoryRegistry; +} + +export class LensRendererExtension extends LensExtension { globalPages: PageRegistration[] = []; clusterPages: PageRegistration[] = []; clusterPageMenus: ClusterPageMenuRegistration[] = []; @@ -54,8 +75,28 @@ export class LensRendererExtension extends LensExtension registration.id === (pageId || undefined)); @@ -70,7 +111,7 @@ export class LensRendererExtension extends LensExtension