diff --git a/extensions/example-extension/renderer.tsx b/extensions/example-extension/renderer.tsx
index 4deb08558b..2f1db0dd7a 100644
--- a/extensions/example-extension/renderer.tsx
+++ b/extensions/example-extension/renderer.tsx
@@ -8,16 +8,16 @@ export default class ExampleExtension extends LensRendererExtension {
}
registerClusterPage(registry: Registry.ClusterPageRegistry) {
- this.disposers.push(
- registry.add({
+ return [
+ {
path: "/extension-example",
title: "Example Extension",
components: {
Page: () => ,
MenuIcon: ExampleIcon,
}
- })
- )
+ }
+ ]
}
onDeactivate() {
diff --git a/extensions/metrics-cluster-feature/renderer.tsx b/extensions/metrics-cluster-feature/renderer.tsx
index 2b4b4f07e9..9189ddc77e 100644
--- a/extensions/metrics-cluster-feature/renderer.tsx
+++ b/extensions/metrics-cluster-feature/renderer.tsx
@@ -4,8 +4,8 @@ import React from "react"
export default class ClusterMetricsFeatureExtension extends LensRendererExtension {
registerClusterFeatures(registry: Registry.ClusterFeatureRegistry) {
- this.disposers.push(
- registry.add({
+ return [
+ {
title: "Metrics Stack",
components: {
Description: () => {
@@ -19,7 +19,7 @@ export default class ClusterMetricsFeatureExtension extends LensRendererExtensio
}
},
feature: new MetricsFeature()
- })
- )
+ }
+ ]
}
}
diff --git a/extensions/node-menu/renderer.tsx b/extensions/node-menu/renderer.tsx
index b3e3ffd121..8cc8d5f2bc 100644
--- a/extensions/node-menu/renderer.tsx
+++ b/extensions/node-menu/renderer.tsx
@@ -1,6 +1,6 @@
import { Registry, LensRendererExtension } from "@k8slens/extensions";
import React from "react"
-import { NodeMenu } from "./src/node-menu"
+import { NodeMenu, NodeMenuProps } from "./src/node-menu"
export default class NodeMenuRendererExtension extends LensRendererExtension {
async onActivate() {
@@ -8,14 +8,14 @@ export default class NodeMenuRendererExtension extends LensRendererExtension {
}
registerKubeObjectMenus(registry: Registry.KubeObjectMenuRegistry) {
- this.disposers.push(
- registry.add({
+ return [
+ {
kind: "Node",
apiVersions: ["v1"],
components: {
- MenuItem: (props) =>
+ MenuItem: (props: NodeMenuProps) =>
}
- })
- )
+ }
+ ]
}
}
diff --git a/extensions/node-menu/src/node-menu.tsx b/extensions/node-menu/src/node-menu.tsx
index 09ef251d60..8c7466694e 100644
--- a/extensions/node-menu/src/node-menu.tsx
+++ b/extensions/node-menu/src/node-menu.tsx
@@ -1,7 +1,10 @@
import React from "react";
import { Component, K8sApi, Navigation} from "@k8slens/extensions"
-export function NodeMenu(props: Component.KubeObjectMenuProps) {
+export interface NodeMenuProps extends Component.KubeObjectMenuProps {
+}
+
+export function NodeMenu(props: NodeMenuProps) {
const { object: node, toolbar } = props;
if (!node) return null;
const nodeName = node.getName();
diff --git a/extensions/pod-menu/renderer.tsx b/extensions/pod-menu/renderer.tsx
index 1340d835d0..3e5445b22c 100644
--- a/extensions/pod-menu/renderer.tsx
+++ b/extensions/pod-menu/renderer.tsx
@@ -1,6 +1,6 @@
import { Registry, LensRendererExtension } from "@k8slens/extensions";
-import { PodShellMenu } from "./src/shell-menu"
-import { PodLogsMenu } from "./src/logs-menu"
+import { PodShellMenu, PodShellMenuProps } from "./src/shell-menu"
+import { PodLogsMenu, PodLogsMenuProps } from "./src/logs-menu"
import React from "react"
export default class PodMenuRendererExtension extends LensRendererExtension {
@@ -9,23 +9,21 @@ export default class PodMenuRendererExtension extends LensRendererExtension {
}
registerKubeObjectMenus(registry: Registry.KubeObjectMenuRegistry) {
- this.disposers.push(
- registry.add({
+ return [
+ {
kind: "Pod",
apiVersions: ["v1"],
components: {
- MenuItem: (props) =>
+ MenuItem: (props: PodShellMenuProps) =>
}
- })
- )
- this.disposers.push(
- registry.add({
+ },
+ {
kind: "Pod",
apiVersions: ["v1"],
components: {
- MenuItem: (props) =>
+ MenuItem: (props: PodLogsMenuProps) =>
}
- })
- )
+ }
+ ]
}
}
diff --git a/extensions/pod-menu/src/logs-menu.tsx b/extensions/pod-menu/src/logs-menu.tsx
index 8932318dc6..7ea6056caa 100644
--- a/extensions/pod-menu/src/logs-menu.tsx
+++ b/extensions/pod-menu/src/logs-menu.tsx
@@ -1,10 +1,10 @@
import React from "react";
import { Component, K8sApi, Util, Navigation } from "@k8slens/extensions";
-interface Props extends Component.KubeObjectMenuProps {
+export interface PodLogsMenuProps extends Component.KubeObjectMenuProps {
}
-export class PodLogsMenu extends React.Component {
+export class PodLogsMenu extends React.Component {
showLogs(container: K8sApi.IPodContainer) {
Navigation.hideDetails();
const pod = this.props.object;
diff --git a/extensions/pod-menu/src/shell-menu.tsx b/extensions/pod-menu/src/shell-menu.tsx
index 74a0180516..d16188c6e7 100644
--- a/extensions/pod-menu/src/shell-menu.tsx
+++ b/extensions/pod-menu/src/shell-menu.tsx
@@ -3,10 +3,10 @@
import React from "react";
import { Component, K8sApi, Util, Navigation } from "@k8slens/extensions";
-interface Props extends Component.KubeObjectMenuProps {
+export interface PodShellMenuProps extends Component.KubeObjectMenuProps {
}
-export class PodShellMenu extends React.Component {
+export class PodShellMenu extends React.Component {
async execShell(container?: string) {
Navigation.hideDetails();
const { object: pod } = this.props
diff --git a/extensions/support-page/main.ts b/extensions/support-page/main.ts
index 133df0b890..875e83d17c 100644
--- a/extensions/support-page/main.ts
+++ b/extensions/support-page/main.ts
@@ -6,9 +6,9 @@ export default class SupportPageMainExtension extends LensMainExtension {
console.log("support page extension activated")
}
- async registerAppMenus(registry: Registry.MenuRegistry) {
- this.disposers.push(
- registry.add({
+ registerAppMenus(registry: Registry.MenuRegistry) {
+ return [
+ {
parentId: "help",
label: "Support",
click() {
@@ -17,7 +17,7 @@ export default class SupportPageMainExtension extends LensMainExtension {
url: supportPageURL(),
});
}
- })
- )
+ }
+ ]
}
}
diff --git a/extensions/support-page/renderer.tsx b/extensions/support-page/renderer.tsx
index 84e7f87f65..c607ef6cdb 100644
--- a/extensions/support-page/renderer.tsx
+++ b/extensions/support-page/renderer.tsx
@@ -8,22 +8,22 @@ export default class SupportPageRendererExtension extends LensRendererExtension
console.log("support page extension activated")
}
- registerGlobalPage(registry: Registry.GlobalPageRegistry) {
- this.disposers.push(
- registry.add({
+ registerGlobalPages(registry: Registry.GlobalPageRegistry) {
+ return [
+ {
...supportPageRoute,
url: supportPageURL(),
hideInMenu: true,
components: {
Page: Support,
}
- })
- )
+ }
+ ]
}
- registerStatusBarItem(registry: Registry.StatusBarRegistry) {
- this.disposers.push(
- registry.add({
+ registerStatusBarItems(registry: Registry.StatusBarRegistry) {
+ return [
+ {
item: (
Support
)
- })
- )
+ }
+ ]
}
}
diff --git a/extensions/telemetry/renderer.tsx b/extensions/telemetry/renderer.tsx
index 3988e97097..cbd219e245 100644
--- a/extensions/telemetry/renderer.tsx
+++ b/extensions/telemetry/renderer.tsx
@@ -12,15 +12,15 @@ export default class TelemetryRendererExtension extends LensRendererExtension {
}
registerAppPreferences(registry: Registry.AppPreferenceRegistry) {
- this.disposers.push(
- registry.add({
+ return [
+ {
title: "Telemetry & Usage Tracking",
components: {
Hint: () => ,
Input: () =>
}
- })
- )
+ }
+ ]
}
onDeactivate() {
diff --git a/src/extensions/extension-loader.ts b/src/extensions/extension-loader.ts
index 0e831af9f8..4609a3b355 100644
--- a/src/extensions/extension-loader.ts
+++ b/src/extensions/extension-loader.ts
@@ -36,26 +36,26 @@ export class ExtensionLoader {
loadOnMain() {
logger.info('[EXTENSIONS-LOADER]: load on main')
- this.autoloadExtensions((instance: LensMainExtension) => {
- instance.registerAppMenus(menuRegistry);
+ this.autoloadExtensions((extension: LensMainExtension) => {
+ extension.register(menuRegistry, extension.registerAppMenus(menuRegistry))
})
}
loadOnClusterManagerRenderer() {
logger.info('[EXTENSIONS-LOADER]: load on main renderer (cluster manager)')
- this.autoloadExtensions((instance: LensRendererExtension) => {
- instance.registerGlobalPage(globalPageRegistry)
- instance.registerAppPreferences(appPreferenceRegistry)
- instance.registerClusterFeatures(clusterFeatureRegistry)
- instance.registerStatusBarItem(statusBarRegistry)
+ this.autoloadExtensions((extension: LensRendererExtension) => {
+ extension.register(globalPageRegistry, extension.registerGlobalPages(globalPageRegistry))
+ extension.register(appPreferenceRegistry, extension.registerAppPreferences(appPreferenceRegistry))
+ extension.register(clusterFeatureRegistry, extension.registerClusterFeatures(clusterFeatureRegistry))
+ extension.register(statusBarRegistry, extension.registerStatusBarItems(statusBarRegistry))
})
}
loadOnClusterRenderer() {
logger.info('[EXTENSIONS-LOADER]: load on cluster renderer (dashboard)')
- this.autoloadExtensions((instance: LensRendererExtension) => {
- instance.registerClusterPage(clusterPageRegistry)
- instance.registerKubeObjectMenus(kubeObjectMenuRegistry)
+ this.autoloadExtensions((extension: LensRendererExtension) => {
+ extension.register(clusterPageRegistry, extension.registerClusterPages(clusterPageRegistry))
+ extension.register(kubeObjectMenuRegistry, extension.registerKubeObjectMenus(kubeObjectMenuRegistry))
})
}
diff --git a/src/extensions/lens-extension.ts b/src/extensions/lens-extension.ts
index b348cd6868..b8aba8c6a3 100644
--- a/src/extensions/lens-extension.ts
+++ b/src/extensions/lens-extension.ts
@@ -1,6 +1,7 @@
import { readJsonSync } from "fs-extra";
import { action, observable, toJS } from "mobx";
import logger from "../main/logger";
+import { BaseRegistry } from "./registries/base-registry";
export type ExtensionId = string | ExtensionPackageJsonPath;
export type ExtensionPackageJsonPath = string;
@@ -25,7 +26,7 @@ export interface ExtensionManifest extends ExtensionModel {
export class LensExtension implements ExtensionModel {
public id: ExtensionId;
public updateUrl: string;
- protected disposers: Function[] = [];
+ protected disposers: (() => void)[] = [];
@observable name = "";
@observable description = "";
@@ -77,6 +78,14 @@ export class LensExtension implements ExtensionModel {
// mock
}
+ register(registry: BaseRegistry, registryItems: T[]) {
+ const disposers = registryItems.map(item => registry.add(item));
+ this.disposers.push(...disposers);
+ return () => {
+ this.disposers = this.disposers.filter(disposer => !disposers.includes(disposer))
+ };
+ }
+
getMeta() {
return toJS({
id: this.id,
diff --git a/src/extensions/lens-main-extension.ts b/src/extensions/lens-main-extension.ts
index 9ad858d0c6..45a2c0e8e1 100644
--- a/src/extensions/lens-main-extension.ts
+++ b/src/extensions/lens-main-extension.ts
@@ -1,12 +1,12 @@
import { LensExtension } from "./lens-extension"
-import type { MenuRegistry } from "./registries/menu-registry";
+import type { MenuRegistration, MenuRegistry } from "./registries/menu-registry";
export class LensMainExtension extends LensExtension {
- registerAppMenus(registry: MenuRegistry) {
- //
+ registerAppMenus(registry: MenuRegistry): MenuRegistration[] {
+ return []
}
- registerPrometheusProviders(registry: any) {
- //
+ registerPrometheusProviders(registry: any): any[] {
+ return []
}
}
diff --git a/src/extensions/lens-renderer-extension.ts b/src/extensions/lens-renderer-extension.ts
index 4c2e25ebdf..2134dad696 100644
--- a/src/extensions/lens-renderer-extension.ts
+++ b/src/extensions/lens-renderer-extension.ts
@@ -1,28 +1,28 @@
import { LensExtension } from "./lens-extension"
-import type { GlobalPageRegistry, ClusterPageRegistry, AppPreferenceRegistry, StatusBarRegistry, KubeObjectMenuRegistry, ClusterFeatureRegistry } from "./registries"
+import type { GlobalPageRegistry, ClusterPageRegistry, AppPreferenceRegistry, StatusBarRegistry, KubeObjectMenuRegistry, ClusterFeatureRegistry, PageRegistration, AppPreferenceRegistration, ClusterFeatureRegistration, StatusBarRegistration, KubeObjectMenuRegistration } from "./registries"
export class LensRendererExtension extends LensExtension {
- registerGlobalPage(registry: GlobalPageRegistry) {
- return
+ registerGlobalPages(registry: GlobalPageRegistry): PageRegistration[] {
+ return []
}
- registerClusterPage(registry: ClusterPageRegistry) {
- return
+ registerClusterPages(registry: ClusterPageRegistry): PageRegistration[] {
+ return []
}
- registerAppPreferences(registry: AppPreferenceRegistry) {
- return
+ registerAppPreferences(registry: AppPreferenceRegistry): AppPreferenceRegistration[] {
+ return []
}
- registerClusterFeatures(registry: ClusterFeatureRegistry) {
- return
+ registerClusterFeatures(registry: ClusterFeatureRegistry): ClusterFeatureRegistration[] {
+ return []
}
- registerStatusBarItem(registry: StatusBarRegistry) {
- return
+ registerStatusBarItems(registry: StatusBarRegistry): StatusBarRegistration[] {
+ return []
}
- registerKubeObjectMenus(registry: KubeObjectMenuRegistry) {
- return
+ registerKubeObjectMenus(registry: KubeObjectMenuRegistry): KubeObjectMenuRegistration[] {
+ return []
}
}
diff --git a/src/extensions/registries/menu-registry.ts b/src/extensions/registries/menu-registry.ts
index d31d124f30..4b98201073 100644
--- a/src/extensions/registries/menu-registry.ts
+++ b/src/extensions/registries/menu-registry.ts
@@ -1,11 +1,10 @@
// Extensions API -> Global menu customizations
-import type { MenuTopId } from "../../main/menu";
import type { MenuItemConstructorOptions } from "electron";
import { BaseRegistry } from "./base-registry";
export interface MenuRegistration extends MenuItemConstructorOptions {
- parentId?: MenuTopId;
+ parentId: string;
}
export class MenuRegistry extends BaseRegistry {
diff --git a/src/main/menu.ts b/src/main/menu.ts
index 7bb340b5ce..935d71b519 100644
--- a/src/main/menu.ts
+++ b/src/main/menu.ts
@@ -209,7 +209,7 @@ export function buildMenu(windowManager: WindowManager) {
// Modify menu from extensions-api
menuRegistry.getItems().forEach(({ parentId, ...menuItem }) => {
try {
- const topMenu = appMenu[parentId].submenu as MenuItemConstructorOptions[];
+ const topMenu = appMenu[parentId as MenuTopId].submenu as MenuItemConstructorOptions[];
topMenu.push(menuItem);
} catch (err) {
logger.error(`[MENU]: can't register menu item, parentId=${parentId}`, { menuItem })