Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace CatalogEntityDetailRegistry with an injectable solution #6605

Merged
merged 13 commits into from
Dec 2, 2022
4 changes: 2 additions & 2 deletions __mocks__/react-beautiful-dnd.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ import type {
} from "react-beautiful-dnd";

export const DragDropContext = ({ children }: DragDropContextProps) => <>{ children }</>;
export const Draggable = ({ children }: DraggableProps) => <>{ children }</>;
export const Droppable = ({ children }: DroppableProps) => <>{ children }</>;
export const Draggable = ({ children }: DraggableProps) => <>{ children({} as any, {} as any, {} as any) }</>;
export const Droppable = ({ children }: DroppableProps) => <>{ children({} as any, {} as any) }</>;
9 changes: 5 additions & 4 deletions src/common/catalog-entities/web-link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/

import { getLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
import { Environments, getEnvironmentSpecificLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
import type { CatalogEntityContextMenuContext, CatalogEntityMetadata, CatalogEntityStatus } from "../catalog";
import { CatalogCategory, CatalogEntity, categoryVersion } from "../catalog/catalog-entity";
import productNameInjectable from "../vars/product-name.injectable";
import { WeblinkStore } from "../weblink-store";
import weblinkStoreInjectable from "../weblink-store.injectable";

export type WebLinkStatusPhase = "available" | "unavailable";

Expand All @@ -31,14 +31,15 @@ export class WebLink extends CatalogEntity<CatalogEntityMetadata, WebLinkStatus,
}

onContextMenuOpen(context: CatalogEntityContextMenuContext) {
const di = getLegacyGlobalDiForExtensionApi();
// NOTE: this is safe because `onContextMenuOpen` is only supposed to be called in the renderer
const di = getEnvironmentSpecificLegacyGlobalDiForExtensionApi(Environments.renderer);
const productName = di.inject(productNameInjectable);

if (this.metadata.source === "local") {
context.menuItems.push({
title: "Delete",
icon: "delete",
onClick: async () => WeblinkStore.getInstance().removeById(this.getId()),
onClick: async () => di.inject(weblinkStoreInjectable).removeById(this.getId()),
confirm: {
message: `Remove Web Link "${this.getName()}" from ${productName}?`,
},
Expand Down
2 changes: 1 addition & 1 deletion src/common/protocol-handler/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { RoutingError, RoutingErrorType } from "./error";
import type { ExtensionsStore } from "../../extensions/extensions-store/extensions-store";
import type { ExtensionLoader } from "../../extensions/extension-loader";
import type { LensExtension } from "../../extensions/lens-extension";
import type { RouteHandler, RouteParams } from "../../extensions/registries/protocol-handler";
import type { RouteHandler, RouteParams } from "./registration";
import { when } from "mobx";
import { ipcRenderer } from "electron";
import type { Logger } from "../logger";
Expand Down
6 changes: 3 additions & 3 deletions src/extensions/common-api/registrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ export type { KubeObjectMenuRegistration, KubeObjectMenuComponents } from "../..
export type { AppPreferenceRegistration, AppPreferenceComponents } from "../../features/preferences/renderer/compliance-for-legacy-extension-api/app-preference-registration";
export type { KubeObjectDetailRegistration, KubeObjectDetailComponents } from "../../renderer/components/kube-object-details/kube-object-detail-registration";
export type { KubeObjectStatusRegistration } from "../../renderer/components/kube-object-status-icon/kube-object-status-registration";
export type { PageRegistration, RegisteredPage, PageParams, PageComponentProps, PageComponents, PageTarget } from "../registries/page-registry";
export type { ClusterPageMenuRegistration, ClusterPageMenuComponents } from "../registries/page-menu-registry";
export type { ProtocolHandlerRegistration, RouteParams as ProtocolRouteParams, RouteHandler as ProtocolRouteHandler } from "../registries/protocol-handler";
export type { PageRegistration, RegisteredPage, PageParams, PageComponentProps, PageComponents, PageTarget } from "../../renderer/routes/page-registration";
export type { ClusterPageMenuRegistration, ClusterPageMenuComponents } from "../../renderer/components/layout/cluster-page-menu";
export type { ProtocolHandlerRegistration, RouteParams as ProtocolRouteParams, RouteHandler as ProtocolRouteHandler } from "../../common/protocol-handler/registration";
export type { CustomCategoryViewProps, CustomCategoryViewComponents, CustomCategoryViewRegistration } from "../../renderer/components/+catalog/custom-views";
export type { ShellEnvModifier, ShellEnvContext } from "../../main/shell-session/shell-env-modifier/shell-env-modifier-registration";
export type { KubeObjectContextMenuItem, KubeObjectOnContextMenuOpenContext, KubeObjectOnContextMenuOpen, KubeObjectHandlers, KubeObjectHandlerRegistration } from "../../renderer/kube-object/handler";
Expand Down
48 changes: 8 additions & 40 deletions src/extensions/extension-loader/extension-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,9 @@ import { isEqual } from "lodash";
import type { ObservableMap } from "mobx";
import { action, computed, makeObservable, observable, observe, reaction, when } from "mobx";
import { broadcastMessage, ipcMainOn, ipcRendererOn, ipcMainHandle } from "../../common/ipc";
import type { Disposer } from "../../common/utils";
import { isDefined, toJS } from "../../common/utils";
import type { InstalledExtension } from "../extension-discovery/extension-discovery";
import type { LensExtension, LensExtensionConstructor, LensExtensionId } from "../lens-extension";
import type { LensRendererExtension } from "../lens-renderer-extension";
import * as registries from "../registries";
import type { LensExtensionState } from "../extensions-store/extensions-store";
import { extensionLoaderFromMainChannel, extensionLoaderFromRendererChannel } from "../../common/ipc/extension-handling";
import { requestExtensionLoaderInitialState } from "../../renderer/ipc";
Expand Down Expand Up @@ -203,7 +200,7 @@ export class ExtensionLoader {

protected async initMain() {
this.isLoaded = true;
this.loadOnMain();
await this.autoInitExtensions();

ipcMainHandle(extensionLoaderFromMainChannel, () => {
return Array.from(this.toJSON());
Expand Down Expand Up @@ -251,38 +248,7 @@ export class ExtensionLoader {
});
}

loadOnMain() {
this.autoInitExtensions(() => Promise.resolve([]));
}

loadOnClusterManagerRenderer = () => {
this.dependencies.logger.debug(`${logModule}: load on main renderer (cluster manager)`);

return this.autoInitExtensions(async (ext) => {
const extension = ext as LensRendererExtension;
const removeItems = [
registries.CatalogEntityDetailRegistry.getInstance().add(extension.catalogEntityDetailItems),
];

this.onRemoveExtensionId.addListener((removedExtensionId) => {
if (removedExtensionId === extension.id) {
removeItems.forEach(remove => {
remove();
});
}
});

return removeItems;
});
};

loadOnClusterRenderer = () => {
this.dependencies.logger.debug(`${logModule}: load on cluster renderer (dashboard)`);

this.autoInitExtensions(async () => []);
};

protected async loadExtensions(installedExtensions: Map<string, InstalledExtension>, register: (ext: LensExtension) => Promise<Disposer[]>) {
protected async loadExtensions(installedExtensions: Map<string, InstalledExtension>) {
// Steps of the function:
// 1. require and call .activate for each Extension
// 2. Wait until every extension's onActivate has been resolved
Expand Down Expand Up @@ -346,7 +312,7 @@ export class ExtensionLoader {

// Return ExtensionLoading[]
return extensions.map(extension => {
const loaded = extension.instance.enable(register).catch((err) => {
const loaded = extension.instance.enable().catch((err) => {
this.dependencies.logger.error(`${logModule}: failed to enable`, { ext: extension, err });
});

Expand All @@ -357,12 +323,14 @@ export class ExtensionLoader {
});
}

protected autoInitExtensions(register: (ext: LensExtension) => Promise<Disposer[]>) {
autoInitExtensions() {
this.dependencies.logger.info(`${logModule}: auto initializing extensions`);

// Setup reaction to load extensions on JSON changes
reaction(() => this.toJSON(), installedExtensions => this.loadExtensions(installedExtensions, register));
reaction(() => this.toJSON(), installedExtensions => this.loadExtensions(installedExtensions));

// Load initial extensions
return this.loadExtensions(this.toJSON(), register);
return this.loadExtensions(this.toJSON());
}

protected requireExtension(extension: InstalledExtension): LensExtensionConstructor | null {
Expand Down
2 changes: 2 additions & 0 deletions src/extensions/lens-extension-set-dependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ import type { CatalogEntityRegistry as RendererCatalogEntityRegistry } from "../
import type { GetExtensionPageParameters } from "../renderer/routes/get-extension-page-parameters.injectable";
import type { FileSystemProvisionerStore } from "./extension-loader/file-system-provisioner-store/file-system-provisioner-store";
import type { NavigateForExtension } from "../main/start-main-application/lens-window/navigate-for-extension.injectable";
import type { Logger } from "../common/logger";

export interface LensExtensionDependencies {
readonly fileSystemProvisionerStore: FileSystemProvisionerStore;
readonly logger: Logger;
}

export interface LensMainExtensionDependencies extends LensExtensionDependencies {
Expand Down
21 changes: 6 additions & 15 deletions src/extensions/lens-extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@

import type { InstalledExtension } from "./extension-discovery/extension-discovery";
import { action, computed, makeObservable, observable } from "mobx";
import logger from "../main/logger";
import type { ProtocolHandlerRegistration } from "./registries";
import type { PackageJson } from "type-fest";
import type { Disposer } from "../common/utils";
import { disposer } from "../common/utils";
import type { LensExtensionDependencies } from "./lens-extension-set-dependencies";
import type { ProtocolHandlerRegistration } from "./common-api/registrations";

export type LensExtensionId = string; // path to manifest (package.json)
export type LensExtensionConstructor = new (...args: ConstructorParameters<typeof LensExtension>) => LensExtension;
Expand Down Expand Up @@ -88,20 +86,13 @@ export class LensExtension<Dependencies extends LensExtensionDependencies = Lens
}

@action
async enable(register: (ext: this) => Promise<Disposer[]>) {
async enable() {
if (this._isEnabled) {
return;
}

try {
this._isEnabled = true;

this[Disposers].push(...await register(this));
logger.info(`[EXTENSION]: enabled ${this.name}@${this.version}`);

} catch (error) {
logger.error(`[EXTENSION]: failed to activate ${this.name}@${this.version}: ${error}`);
}
this._isEnabled = true;
this[lensExtensionDependencies].logger.info(`[EXTENSION]: enabled ${this.name}@${this.version}`);
}

@action
Expand All @@ -115,9 +106,9 @@ export class LensExtension<Dependencies extends LensExtensionDependencies = Lens
try {
await this.onDeactivate();
this[Disposers]();
logger.info(`[EXTENSION]: disabled ${this.name}@${this.version}`);
this[lensExtensionDependencies].logger.info(`[EXTENSION]: disabled ${this.name}@${this.version}`);
} catch (error) {
logger.error(`[EXTENSION]: disabling ${this.name}@${this.version} threw an error: ${error}`);
this[lensExtensionDependencies].logger.error(`[EXTENSION]: disabling ${this.name}@${this.version} threw an error: ${error}`);
}
}

Expand Down
11 changes: 6 additions & 5 deletions src/extensions/lens-renderer-extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/

import type * as registries from "./registries";
import { Disposers, LensExtension, lensExtensionDependencies } from "./lens-extension";
import type { CatalogEntity } from "../common/catalog";
import type { Disposer } from "../common/utils";
Expand All @@ -30,11 +29,13 @@ import type { AppPreferenceTabRegistration } from "../features/preferences/rende
import type { KubeObjectDetailRegistration } from "../renderer/components/kube-object-details/kube-object-detail-registration";
import type { ClusterFrameChildComponent } from "../renderer/frames/cluster-frame/cluster-frame-child-component-injection-token";
import type { EntitySettingRegistration } from "../renderer/components/+entity-settings/extension-registrator.injectable";
import type { CatalogEntityDetailRegistration } from "../renderer/components/+catalog/entity-details/token";
import type { ClusterPageMenuRegistration, PageRegistration } from "./common-api/registrations";

export class LensRendererExtension extends LensExtension<LensRendererExtensionDependencies> {
globalPages: registries.PageRegistration[] = [];
clusterPages: registries.PageRegistration[] = [];
clusterPageMenus: registries.ClusterPageMenuRegistration[] = [];
globalPages: PageRegistration[] = [];
clusterPages: PageRegistration[] = [];
clusterPageMenus: ClusterPageMenuRegistration[] = [];
clusterFrameComponents: ClusterFrameChildComponent[] = [];
kubeObjectStatusTexts: KubeObjectStatusRegistration[] = [];
appPreferences: AppPreferenceRegistration[] = [];
Expand All @@ -47,7 +48,7 @@ export class LensRendererExtension extends LensExtension<LensRendererExtensionDe
commands: CommandRegistration[] = [];
welcomeMenus: WelcomeMenuRegistration[] = [];
welcomeBanners: WelcomeBannerRegistration[] = [];
catalogEntityDetailItems: registries.CatalogEntityDetailRegistration<CatalogEntity>[] = [];
catalogEntityDetailItems: CatalogEntityDetailRegistration<CatalogEntity>[] = [];
topBarItems: TopBarRegistration[] = [];
additionalCategoryColumns: AdditionalCategoryColumnRegistration[] = [];
customCategoryViews: CustomCategoryViewRegistration[] = [];
Expand Down
46 changes: 0 additions & 46 deletions src/extensions/registries/base-registry.ts

This file was deleted.

38 changes: 0 additions & 38 deletions src/extensions/registries/catalog-entity-detail-registry.ts

This file was deleted.

11 changes: 0 additions & 11 deletions src/extensions/registries/index.ts

This file was deleted.

Loading