diff --git a/src/common/__tests__/event-bus.test.ts b/src/common/__tests__/event-bus.test.ts index f90381eb44..0dbd07c63c 100644 --- a/src/common/__tests__/event-bus.test.ts +++ b/src/common/__tests__/event-bus.test.ts @@ -4,24 +4,29 @@ */ import type { AppEvent } from "../app-event-bus/event-bus"; -import { appEventBus } from "../app-event-bus/event-bus"; -import { assert, Console } from "console"; -import { stdout, stderr } from "process"; - -console = new Console(stdout, stderr); +import { getDiForUnitTesting } from "../../main/getDiForUnitTesting"; +import appEventBusInjectable from "../app-event-bus/app-event-bus.injectable"; +import type { EventEmitter } from "../event-emitter"; describe("event bus tests", () => { + let appEventBus: EventEmitter<[AppEvent]>; + + beforeEach(() => { + const di = getDiForUnitTesting(); + + appEventBus = di.inject(appEventBusInjectable); + }); + describe("emit", () => { it("emits an event", () => { - let event: AppEvent | undefined; + let event!: AppEvent; appEventBus.addListener((data) => { event = data; }); appEventBus.emit({ name: "foo", action: "bar" }); - assert(event); - expect(event?.name).toBe("foo"); + expect(event.name).toBe("foo"); }); }); }); diff --git a/src/common/app-event-bus/app-event-bus.injectable.ts b/src/common/app-event-bus/app-event-bus.injectable.ts index 31ed3dd3a1..a4c57612d1 100644 --- a/src/common/app-event-bus/app-event-bus.injectable.ts +++ b/src/common/app-event-bus/app-event-bus.injectable.ts @@ -3,12 +3,12 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { appEventBus } from "./event-bus"; +import { EventEmitter } from "../event-emitter"; +import type { AppEvent } from "./event-bus"; const appEventBusInjectable = getInjectable({ id: "app-event-bus", - instantiate: () => appEventBus, - causesSideEffects: true, + instantiate: () => new EventEmitter<[AppEvent]>(), }); export default appEventBusInjectable; diff --git a/src/common/app-event-bus/emit-event.injectable.ts b/src/common/app-event-bus/emit-event.injectable.ts index 47bf2ca691..842af570c9 100644 --- a/src/common/app-event-bus/emit-event.injectable.ts +++ b/src/common/app-event-bus/emit-event.injectable.ts @@ -4,10 +4,17 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import appEventBusInjectable from "./app-event-bus.injectable"; +import type { AppEvent } from "./event-bus"; + +export type EmitEvent = (event: AppEvent) => void; const emitEventInjectable = getInjectable({ id: "emit-event", - instantiate: (di) => di.inject(appEventBusInjectable).emit, + instantiate: (di): EmitEvent => { + const appEventBus = di.inject(appEventBusInjectable); + + return (event) => appEventBus.emit(event); + }, }); export default emitEventInjectable; diff --git a/src/common/app-event-bus/event-bus.ts b/src/common/app-event-bus/event-bus.ts index 67d23587c7..04ec73f3f8 100644 --- a/src/common/app-event-bus/event-bus.ts +++ b/src/common/app-event-bus/event-bus.ts @@ -3,13 +3,12 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { EventEmitter } from "../event-emitter"; - +/** + * The shape of an event that can be emitted for telemetry purposes + */ export interface AppEvent { name: string; action: string; destination?: string; params?: Record; } - -export const appEventBus = new EventEmitter<[AppEvent]>(); diff --git a/src/common/cluster-store/cluster-store.injectable.ts b/src/common/cluster-store/cluster-store.injectable.ts index 8be7fd8c71..7628dc4003 100644 --- a/src/common/cluster-store/cluster-store.injectable.ts +++ b/src/common/cluster-store/cluster-store.injectable.ts @@ -11,6 +11,7 @@ import directoryForUserDataInjectable from "../app-paths/directory-for-user-data import appVersionInjectable from "../get-configuration-file-model/app-version/app-version.injectable"; import getConfigurationFileModelInjectable from "../get-configuration-file-model/get-configuration-file-model.injectable"; import loggerInjectable from "../logger.injectable"; +import emitEventInjectable from "../app-event-bus/emit-event.injectable"; const clusterStoreInjectable = getInjectable({ id: "cluster-store", @@ -26,6 +27,7 @@ const clusterStoreInjectable = getInjectable({ appVersion: di.inject(appVersionInjectable), directoryForUserData: di.inject(directoryForUserDataInjectable), getConfigurationFileModel: di.inject(getConfigurationFileModelInjectable), + emitEvent: di.inject(emitEventInjectable), }); }, diff --git a/src/common/cluster-store/cluster-store.ts b/src/common/cluster-store/cluster-store.ts index 4163ad6f76..0de3c67385 100644 --- a/src/common/cluster-store/cluster-store.ts +++ b/src/common/cluster-store/cluster-store.ts @@ -9,7 +9,6 @@ import { action, comparer, computed, makeObservable, observable, reaction } from import type { BaseStoreDependencies } from "../base-store"; import { BaseStore } from "../base-store"; import { Cluster } from "../cluster/cluster"; -import type { AppEvent } from "../app-event-bus/event-bus"; import { ipcMainHandle } from "../ipc"; import { disposer, toJS } from "../utils"; import type { ClusterModel, ClusterId, ClusterState } from "../cluster-types"; @@ -18,7 +17,7 @@ import { clusterStates } from "../ipc/cluster"; import type { CreateCluster } from "../cluster/create-cluster-injection-token"; import type { ReadClusterConfigSync } from "./read-cluster-config.injectable"; import type { Migrations } from "conf/dist/source/types"; -import type { EventEmitter } from "../event-emitter"; +import type { EmitEvent } from "../app-event-bus/emit-event.injectable"; export interface ClusterStoreModel { clusters?: ClusterModel[]; @@ -27,8 +26,8 @@ export interface ClusterStoreModel { interface ClusterStoreDependencies extends BaseStoreDependencies { createCluster: CreateCluster; readClusterConfigSync: ReadClusterConfigSync; + emitEvent: EmitEvent; readonly migrations: Migrations | undefined; - readonly appEventBus: EventEmitter<[AppEvent]>; } export class ClusterStore extends BaseStore { @@ -118,7 +117,7 @@ export class ClusterStore extends BaseStore { } addCluster(clusterOrModel: ClusterModel | Cluster): Cluster { - this.dependencies.appEventBus.emit({ name: "cluster", action: "add" }); + this.dependencies.emitEvent({ name: "cluster", action: "add" }); const cluster = clusterOrModel instanceof Cluster ? clusterOrModel diff --git a/src/common/event-emitter.ts b/src/common/event-emitter.ts index 4d7f5ca53c..03f8e2754b 100644 --- a/src/common/event-emitter.ts +++ b/src/common/event-emitter.ts @@ -29,7 +29,7 @@ export class EventEmitter { this.listeners.length = 0; } - emit = (...data: D) => { + emit(...data: D) { for (const [callback, { once }] of this.listeners) { if (once) { this.removeListener(callback); @@ -39,5 +39,5 @@ export class EventEmitter { break; } } - }; + } } diff --git a/src/common/k8s-api/api-base.ts b/src/common/k8s-api/api-base.ts index e511dd8454..ee93b3eb60 100644 --- a/src/common/k8s-api/api-base.ts +++ b/src/common/k8s-api/api-base.ts @@ -3,38 +3,12 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { JsonApi } from "./json-api"; -import { apiPrefix, isDebugging, isDevelopment } from "../vars"; -import { appEventBus } from "../app-event-bus/event-bus"; +import type { JsonApi } from "./json-api"; +import { getInjectionToken } from "@ogre-tools/injectable"; +import { asLegacyGlobalForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api"; -export let apiBase: JsonApi; +export const apiBaseInjectionToken = getInjectionToken({ + id: "api-base-token", +}); -if (typeof window === "undefined") { - appEventBus.addListener((event) => { - if (event.name !== "lens-proxy" && event.action !== "listen") return; - - const params = event.params as { port?: number }; - - if (!params.port) return; - - apiBase = new JsonApi({ - serverAddress: `http://127.0.0.1:${params.port}`, - apiBase: apiPrefix, - debug: isDevelopment || isDebugging, - }, { - headers: { - "Host": `localhost:${params.port}`, - }, - }); - }); -} else { - apiBase = new JsonApi({ - serverAddress: `http://127.0.0.1:${window.location.port}`, - apiBase: apiPrefix, - debug: isDevelopment || isDebugging, - }, { - headers: { - "Host": window.location.host, - }, - }); -} +export const apiBase = asLegacyGlobalForExtensionApi(apiBaseInjectionToken); diff --git a/src/common/user-store/user-store.injectable.ts b/src/common/user-store/user-store.injectable.ts index dbda8f629e..4d6fcf812e 100644 --- a/src/common/user-store/user-store.injectable.ts +++ b/src/common/user-store/user-store.injectable.ts @@ -10,6 +10,7 @@ import directoryForUserDataInjectable from "../app-paths/directory-for-user-data import appVersionInjectable from "../get-configuration-file-model/app-version/app-version.injectable"; import getConfigurationFileModelInjectable from "../get-configuration-file-model/get-configuration-file-model.injectable"; import loggerInjectable from "../logger.injectable"; +import emitEventInjectable from "../app-event-bus/emit-event.injectable"; const userStoreInjectable = getInjectable({ id: "user-store", @@ -30,6 +31,7 @@ const userStoreInjectable = getInjectable({ appVersion: di.inject(appVersionInjectable), directoryForUserData: di.inject(directoryForUserDataInjectable), getConfigurationFileModel: di.inject(getConfigurationFileModelInjectable), + emitEvent: di.inject(emitEventInjectable), }); }, diff --git a/src/common/user-store/user-store.ts b/src/common/user-store/user-store.ts index bd453723eb..a2df5fca89 100644 --- a/src/common/user-store/user-store.ts +++ b/src/common/user-store/user-store.ts @@ -10,13 +10,13 @@ import type { BaseStoreDependencies } from "../base-store"; import { BaseStore } from "../base-store"; import { getAppVersion } from "../utils/app-version"; import { kubeConfigDefaultPath } from "../kube-helpers"; -import { appEventBus } from "../app-event-bus/event-bus"; import { getOrInsertSet, toggle, toJS, object } from "../../renderer/utils"; import { DESCRIPTORS } from "./preferences-helpers"; import type { UserPreferencesModel, StoreType } from "./preferences-helpers"; import type { SelectedUpdateChannel } from "../application-update/selected-update-channel/selected-update-channel.injectable"; import type { UpdateChannelId } from "../application-update/update-channels"; import type { Migrations } from "conf/dist/source/types"; +import type { EmitEvent } from "../app-event-bus/emit-event.injectable"; export interface UserStoreModel { lastSeenAppVersion: string; @@ -26,6 +26,7 @@ export interface UserStoreModel { interface UserStoreDependencies extends BaseStoreDependencies { readonly selectedUpdateChannel: SelectedUpdateChannel; readonly migrations: Migrations | undefined; + emitEvent: EmitEvent; } export class UserStore extends BaseStore /* implements UserStoreFlatModel (when strict null is enabled) */ { @@ -154,7 +155,7 @@ export class UserStore extends BaseStore /* implements UserStore @action saveLastSeenAppVersion() { - appEventBus.emit({ name: "app", action: "whats-new-seen" }); + this.dependencies.emitEvent({ name: "app", action: "whats-new-seen" }); this.lastSeenAppVersion = getAppVersion(); } diff --git a/src/common/vars.ts b/src/common/vars.ts index 663703d7d0..3b4a542703 100644 --- a/src/common/vars.ts +++ b/src/common/vars.ts @@ -25,7 +25,11 @@ export const isWindows = process.platform === "win32"; */ export const isLinux = process.platform === "linux"; +/** + * @deprecated Use `di.inject(isDebuggingInjectable)` instead + */ export const isDebugging = ["true", "1", "yes", "y", "on"].includes((process.env.DEBUG ?? "").toLowerCase()); + export const isSnap = !!process.env.SNAP; /** diff --git a/src/common/vars/is-debugging.injectable.ts b/src/common/vars/is-debugging.injectable.ts new file mode 100644 index 0000000000..079086e628 --- /dev/null +++ b/src/common/vars/is-debugging.injectable.ts @@ -0,0 +1,13 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; + +const isDebuggingInjectable = getInjectable({ + id: "is-debugging", + instantiate: () => ["true", "1", "yes", "y", "on"].includes((process.env.DEBUG ?? "").toLowerCase()), + causesSideEffects: true, +}); + +export default isDebuggingInjectable; diff --git a/src/extensions/common-api/event-bus.ts b/src/extensions/common-api/event-bus.ts index c6d2a1a34b..d95e3f49d4 100644 --- a/src/extensions/common-api/event-bus.ts +++ b/src/extensions/common-api/event-bus.ts @@ -3,5 +3,9 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -export { appEventBus } from "../../common/app-event-bus/event-bus"; +import appEventBusInjectable from "../../common/app-event-bus/app-event-bus.injectable"; +import { asLegacyGlobalForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api"; + export type { AppEvent } from "../../common/app-event-bus/event-bus"; + +export const appEventBus = asLegacyGlobalForExtensionApi(appEventBusInjectable); diff --git a/src/main/electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.injectable.ts b/src/main/electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.injectable.ts index 24f90f01b3..f6e604c4a0 100644 --- a/src/main/electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.injectable.ts +++ b/src/main/electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.injectable.ts @@ -4,6 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import directoryForLensLocalStorageInjectable from "../../../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable"; +import type { SetupIpcMainHandlersDependencies } from "./setup-ipc-main-handlers"; import { setupIpcMainHandlers } from "./setup-ipc-main-handlers"; import loggerInjectable from "../../../../common/logger.injectable"; import clusterManagerInjectable from "../../../cluster-manager.injectable"; @@ -14,39 +15,29 @@ import { onLoadOfApplicationInjectionToken } from "../../../start-main-applicati import operatingSystemThemeInjectable from "../../../theme/operating-system-theme.injectable"; import catalogEntityRegistryInjectable from "../../../catalog/entity-registry.injectable"; import askUserForFilePathsInjectable from "../../../ipc/ask-user-for-file-paths.injectable"; +import emitEventInjectable from "../../../../common/app-event-bus/emit-event.injectable"; const setupIpcMainHandlersInjectable = getInjectable({ id: "setup-ipc-main-handlers", instantiate: (di) => { const logger = di.inject(loggerInjectable); - - const directoryForLensLocalStorage = di.inject( - directoryForLensLocalStorageInjectable, - ); - - const clusterManager = di.inject(clusterManagerInjectable); - const applicationMenuItems = di.inject(applicationMenuItemsInjectable); - const getAbsolutePath = di.inject(getAbsolutePathInjectable); - const catalogEntityRegistry = di.inject(catalogEntityRegistryInjectable); - const clusterStore = di.inject(clusterStoreInjectable); - const operatingSystemTheme = di.inject(operatingSystemThemeInjectable); - const askUserForFilePaths = di.inject(askUserForFilePathsInjectable); + const deps: SetupIpcMainHandlersDependencies = { + directoryForLensLocalStorage: di.inject(directoryForLensLocalStorageInjectable), + clusterManager: di.inject(clusterManagerInjectable), + applicationMenuItems: di.inject(applicationMenuItemsInjectable), + getAbsolutePath: di.inject(getAbsolutePathInjectable), + catalogEntityRegistry: di.inject(catalogEntityRegistryInjectable), + clusterStore: di.inject(clusterStoreInjectable), + operatingSystemTheme: di.inject(operatingSystemThemeInjectable), + askUserForFilePaths: di.inject(askUserForFilePathsInjectable), + emitEvent: di.inject(emitEventInjectable), + }; return { run: () => { logger.debug("[APP-MAIN] initializing ipc main handlers"); - - setupIpcMainHandlers({ - applicationMenuItems, - getAbsolutePath, - directoryForLensLocalStorage, - clusterManager, - catalogEntityRegistry, - clusterStore, - operatingSystemTheme, - askUserForFilePaths, - }); + setupIpcMainHandlers(deps); }, }; }, diff --git a/src/main/electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.ts b/src/main/electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.ts index 9342696c77..6b0c534b52 100644 --- a/src/main/electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.ts +++ b/src/main/electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.ts @@ -8,7 +8,6 @@ import { clusterFrameMap } from "../../../../common/cluster-frames"; import { clusterActivateHandler, clusterSetFrameIdHandler, clusterVisibilityHandler, clusterRefreshHandler, clusterDisconnectHandler, clusterKubectlApplyAllHandler, clusterKubectlDeleteAllHandler, clusterDeleteHandler, clusterSetDeletingHandler, clusterClearDeletingHandler } from "../../../../common/ipc/cluster"; import type { ClusterId } from "../../../../common/cluster-types"; import { ClusterStore } from "../../../../common/cluster-store/cluster-store"; -import { appEventBus } from "../../../../common/app-event-bus/event-bus"; import { broadcastMainChannel, broadcastMessage, ipcMainHandle, ipcMainOn } from "../../../../common/ipc"; import type { CatalogEntityRegistry } from "../../../catalog"; import { pushCatalogToRenderer } from "../../../catalog-pusher"; @@ -24,8 +23,9 @@ import { openFilePickingDialogChannel } from "../../../../common/ipc/dialog"; import { getNativeThemeChannel } from "../../../../common/ipc/native-theme"; import type { Theme } from "../../../theme/operating-system-theme-state.injectable"; import type { AskUserForFilePaths } from "../../../ipc/ask-user-for-file-paths.injectable"; +import type { EmitEvent } from "../../../../common/app-event-bus/emit-event.injectable"; -interface Dependencies { +export interface SetupIpcMainHandlersDependencies { directoryForLensLocalStorage: string; getAbsolutePath: GetAbsolutePath; applicationMenuItems: IComputedValue; @@ -34,9 +34,20 @@ interface Dependencies { clusterStore: ClusterStore; operatingSystemTheme: IComputedValue; askUserForFilePaths: AskUserForFilePaths; + emitEvent: EmitEvent; } -export const setupIpcMainHandlers = ({ applicationMenuItems, directoryForLensLocalStorage, getAbsolutePath, clusterManager, catalogEntityRegistry, clusterStore, operatingSystemTheme, askUserForFilePaths }: Dependencies) => { +export const setupIpcMainHandlers = ({ + applicationMenuItems, + directoryForLensLocalStorage, + getAbsolutePath, + clusterManager, + catalogEntityRegistry, + clusterStore, + operatingSystemTheme, + askUserForFilePaths, + emitEvent, +}: SetupIpcMainHandlersDependencies) => { ipcMainHandle(clusterActivateHandler, (event, clusterId: ClusterId, force = false) => { return ClusterStore.getInstance() .getById(clusterId) @@ -65,7 +76,7 @@ export const setupIpcMainHandlers = ({ applicationMenuItems, directoryForLensLoc }); ipcMainHandle(clusterDisconnectHandler, (event, clusterId: ClusterId) => { - appEventBus.emit({ name: "cluster", action: "stop" }); + emitEvent({ name: "cluster", action: "stop" }); const cluster = ClusterStore.getInstance().getById(clusterId); if (cluster) { @@ -75,7 +86,7 @@ export const setupIpcMainHandlers = ({ applicationMenuItems, directoryForLensLoc }); ipcMainHandle(clusterDeleteHandler, async (event, clusterId: ClusterId) => { - appEventBus.emit({ name: "cluster", action: "remove" }); + emitEvent({ name: "cluster", action: "remove" }); const clusterStore = ClusterStore.getInstance(); const cluster = clusterStore.getById(clusterId); @@ -109,7 +120,7 @@ export const setupIpcMainHandlers = ({ applicationMenuItems, directoryForLensLoc }); ipcMainHandle(clusterKubectlApplyAllHandler, async (event, clusterId: ClusterId, resources: string[], extraArgs: string[]) => { - appEventBus.emit({ name: "cluster", action: "kubectl-apply-all" }); + emitEvent({ name: "cluster", action: "kubectl-apply-all" }); const cluster = ClusterStore.getInstance().getById(clusterId); if (cluster) { @@ -128,7 +139,7 @@ export const setupIpcMainHandlers = ({ applicationMenuItems, directoryForLensLoc }); ipcMainHandle(clusterKubectlDeleteAllHandler, async (event, clusterId: ClusterId, resources: string[], extraArgs: string[]) => { - appEventBus.emit({ name: "cluster", action: "kubectl-delete-all" }); + emitEvent({ name: "cluster", action: "kubectl-delete-all" }); const cluster = ClusterStore.getInstance().getById(clusterId); if (cluster) { diff --git a/src/main/getDiForUnitTesting.ts b/src/main/getDiForUnitTesting.ts index 0d5f356d1f..8a09dbeab5 100644 --- a/src/main/getDiForUnitTesting.ts +++ b/src/main/getDiForUnitTesting.ts @@ -28,9 +28,6 @@ import { getAbsolutePathFake } from "../common/test-utils/get-absolute-path-fake import joinPathsInjectable from "../common/path/join-paths.injectable"; import { joinPathsFake } from "../common/test-utils/join-paths-fake"; import hotbarStoreInjectable from "../common/hotbars/store.injectable"; -import appEventBusInjectable from "../common/app-event-bus/app-event-bus.injectable"; -import { EventEmitter } from "../common/event-emitter"; -import type { AppEvent } from "../common/app-event-bus/event-bus"; import commandLineArgumentsInjectable from "./utils/command-line-arguments.injectable"; import initializeExtensionsInjectable from "./start-main-application/runnables/initialize-extensions.injectable"; import lensResourcesDirInjectable from "../common/vars/lens-resources-dir.injectable"; @@ -178,9 +175,6 @@ export function getDiForUnitTesting(opts: { doGeneralOverrides?: boolean } = {}) execFileInjectable, ]); - // TODO: Remove usages of globally exported appEventBus to get rid of this - di.override(appEventBusInjectable, () => new EventEmitter<[AppEvent]>()); - di.override(appNameInjectable, () => "some-app-name"); di.override(broadcastMessageInjectable, () => (channel) => { throw new Error(`Tried to broadcast message to channel "${channel}" over IPC without explicit override.`); diff --git a/src/main/k8s-api/api-base.injectable.ts b/src/main/k8s-api/api-base.injectable.ts new file mode 100644 index 0000000000..480cc13157 --- /dev/null +++ b/src/main/k8s-api/api-base.injectable.ts @@ -0,0 +1,35 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { getInjectable } from "@ogre-tools/injectable"; +import { apiBaseInjectionToken } from "../../common/k8s-api/api-base"; +import { JsonApi } from "../../common/k8s-api/json-api"; +import { apiPrefix } from "../../common/vars"; +import isDebuggingInjectable from "../../common/vars/is-debugging.injectable"; +import isDevelopmentInjectable from "../../common/vars/is-development.injectable"; +import lensProxyPortInjectable from "../lens-proxy/lens-proxy-port.injectable"; + +const apiBaseInjectable = getInjectable({ + id: "api-base", + instantiate: (di) => { + const lensProxyPort = di.inject(lensProxyPortInjectable); + const isDevelopment = di.inject(isDevelopmentInjectable); + const isDebugging= di.inject(isDebuggingInjectable); + const proxyPort = lensProxyPort.get(); + + return new JsonApi({ + serverAddress: `http://127.0.0.1:${proxyPort}`, + apiBase: apiPrefix, + debug: isDevelopment || isDebugging, + }, { + headers: { + "Host": `localhost:${proxyPort}`, + }, + }); + }, + injectionToken: apiBaseInjectionToken, +}); + +export default apiBaseInjectable; diff --git a/src/main/lens-proxy/lens-proxy.injectable.ts b/src/main/lens-proxy/lens-proxy.injectable.ts index 34cb327339..b65b1dfcae 100644 --- a/src/main/lens-proxy/lens-proxy.injectable.ts +++ b/src/main/lens-proxy/lens-proxy.injectable.ts @@ -10,26 +10,20 @@ import httpProxy from "http-proxy"; import clusterManagerInjectable from "../cluster-manager.injectable"; import shellApiRequestInjectable from "./proxy-functions/shell-api-request/shell-api-request.injectable"; import lensProxyPortInjectable from "./lens-proxy-port.injectable"; +import emitEventInjectable from "../../common/app-event-bus/emit-event.injectable"; const lensProxyInjectable = getInjectable({ id: "lens-proxy", - instantiate: (di) => { - const clusterManager = di.inject(clusterManagerInjectable); - const router = di.inject(routerInjectable); - const shellApiRequest = di.inject(shellApiRequestInjectable); - const proxy = httpProxy.createProxy(); - const lensProxyPort = di.inject(lensProxyPortInjectable); - - return new LensProxy({ - router, - proxy, - kubeApiUpgradeRequest, - shellApiRequest, - getClusterForRequest: clusterManager.getClusterForRequest, - lensProxyPort, - }); - }, + instantiate: (di) => new LensProxy({ + router: di.inject(routerInjectable), + proxy: httpProxy.createProxy(), + kubeApiUpgradeRequest, + shellApiRequest: di.inject(shellApiRequestInjectable), + getClusterForRequest: di.inject(clusterManagerInjectable).getClusterForRequest, + lensProxyPort: di.inject(lensProxyPortInjectable), + emitEvent: di.inject(emitEventInjectable), + }), }); export default lensProxyInjectable; diff --git a/src/main/lens-proxy/lens-proxy.ts b/src/main/lens-proxy/lens-proxy.ts index 5e58104d60..4263b5b798 100644 --- a/src/main/lens-proxy/lens-proxy.ts +++ b/src/main/lens-proxy/lens-proxy.ts @@ -13,10 +13,10 @@ import type { ClusterContextHandler } from "../context-handler/context-handler"; import logger from "../logger"; import type { Cluster } from "../../common/cluster/cluster"; import type { ProxyApiRequestArgs } from "./proxy-functions"; -import { appEventBus } from "../../common/app-event-bus/event-bus"; import { getBoolean } from "../utils/parse-query"; import assert from "assert"; import type { SetRequired } from "type-fest"; +import type { EmitEvent } from "../../common/app-event-bus/emit-event.injectable"; type GetClusterForRequest = (req: http.IncomingMessage) => Cluster | undefined; @@ -29,6 +29,7 @@ interface Dependencies { router: Router; proxy: httpProxy; lensProxyPort: { set: (portNumber: number) => void }; + emitEvent: EmitEvent; } const watchParam = "watch"; @@ -116,7 +117,7 @@ export class LensProxy { logger.info(`[LENS-PROXY]: Subsequent error: ${error}`); }); - appEventBus.emit({ name: "lens-proxy", action: "listen", params: { port }}); + this.dependencies.emitEvent({ name: "lens-proxy", action: "listen", params: { port }}); resolve(port); }) .once("error", (error) => { diff --git a/src/main/resource-applier.ts b/src/main/resource-applier.ts index 30c85e8fa0..66de685d0e 100644 --- a/src/main/resource-applier.ts +++ b/src/main/resource-applier.ts @@ -11,13 +11,24 @@ import * as yaml from "js-yaml"; import path from "path"; import tempy from "tempy"; import logger from "./logger"; -import { appEventBus } from "../common/app-event-bus/event-bus"; import { isChildProcessError } from "../common/utils"; import type { Patch } from "rfc6902"; import { promiseExecFile } from "../common/utils/promise-exec"; +import type { EmitEvent } from "../common/app-event-bus/emit-event.injectable"; +import emitEventInjectable from "../common/app-event-bus/emit-event.injectable"; +import { getEnvironmentSpecificLegacyGlobalDiForExtensionApi, Environments } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; export class ResourceApplier { - constructor(protected cluster: Cluster) {} + private readonly dependencies: { emitEvent: EmitEvent }; + + constructor(protected cluster: Cluster) { + // TODO: replace with dependencies + const di = getEnvironmentSpecificLegacyGlobalDiForExtensionApi(Environments.main); + + this.dependencies = { + emitEvent: di.inject(emitEventInjectable), + }; + } /** * Patch a kube resource's manifest, throwing any error that occurs. @@ -27,7 +38,7 @@ export class ResourceApplier { * @param ns The optional namespace of the kube resource */ async patch(name: string, kind: string, patch: Patch, ns?: string): Promise { - appEventBus.emit({ name: "resource", action: "patch" }); + this.dependencies.emitEvent({ name: "resource", action: "patch" }); const kubectl = await this.cluster.ensureKubectl(); const kubectlPath = await kubectl.getPath(); @@ -64,7 +75,7 @@ export class ResourceApplier { async apply(resource: KubernetesObject | any): Promise { resource = this.sanitizeObject(resource); - appEventBus.emit({ name: "resource", action: "apply" }); + this.dependencies.emitEvent({ name: "resource", action: "apply" }); return this.kubectlApply(yaml.dump(resource)); } diff --git a/src/main/shell-session/shell-session.ts b/src/main/shell-session/shell-session.ts index 42286ee24d..7d460120a7 100644 --- a/src/main/shell-session/shell-session.ts +++ b/src/main/shell-session/shell-session.ts @@ -14,11 +14,12 @@ import os from "os"; import { isMac, isWindows } from "../../common/vars"; import { UserStore } from "../../common/user-store"; import * as pty from "node-pty"; -import { appEventBus } from "../../common/app-event-bus/event-bus"; import logger from "../logger"; import { stat } from "fs/promises"; import { getOrInsertWith } from "../../common/utils"; import { type TerminalMessage, TerminalChannels } from "../../common/terminal/channels"; +import emitEventInjectable from "../../common/app-event-bus/emit-event.injectable"; +import { Environments, getEnvironmentSpecificLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; export class ShellOpenError extends Error { constructor(message: string, options?: ErrorOptions) { @@ -287,7 +288,11 @@ export abstract class ShellSession { } }); - appEventBus.emit({ name: this.ShellType, action: "open" }); + // TODO: replace with dependencies + const di = getEnvironmentSpecificLegacyGlobalDiForExtensionApi(Environments.main); + const emitEvent = di.inject(emitEventInjectable); + + emitEvent({ name: this.ShellType, action: "open" }); } protected getPathEntries(): string[] { diff --git a/src/renderer/components/+add-cluster/add-cluster.tsx b/src/renderer/components/+add-cluster/add-cluster.tsx index 6630420ad6..f7f22e1baa 100644 --- a/src/renderer/components/+add-cluster/add-cluster.tsx +++ b/src/renderer/components/+add-cluster/add-cluster.tsx @@ -13,7 +13,6 @@ import { observer } from "mobx-react"; import path from "path"; import React from "react"; import * as uuid from "uuid"; -import { appEventBus } from "../../../common/app-event-bus/event-bus"; import { loadConfigFromString, splitConfig } from "../../../common/kube-helpers"; import { docsUrl } from "../../../common/vars"; import { isDefined, iter } from "../../utils"; @@ -25,6 +24,8 @@ import { withInjectables } from "@ogre-tools/injectable-react"; import getCustomKubeConfigDirectoryInjectable from "../../../common/app-paths/get-custom-kube-config-directory/get-custom-kube-config-directory.injectable"; import type { NavigateToCatalog } from "../../../common/front-end-routing/routes/catalog/navigate-to-catalog.injectable"; import navigateToCatalogInjectable from "../../../common/front-end-routing/routes/catalog/navigate-to-catalog.injectable"; +import type { EmitEvent } from "../../../common/app-event-bus/emit-event.injectable"; +import emitEventInjectable from "../../../common/app-event-bus/emit-event.injectable"; interface Option { config: KubeConfig; @@ -34,6 +35,7 @@ interface Option { interface Dependencies { getCustomKubeConfigDirectory: (directoryName: string) => string; navigateToCatalog: NavigateToCatalog; + emitEvent: EmitEvent; } function getContexts(config: KubeConfig): Map { @@ -59,7 +61,7 @@ class NonInjectedAddCluster extends React.Component { } componentDidMount() { - appEventBus.emit({ name: "cluster-add", action: "start" }); + this.props.emitEvent({ name: "cluster-add", action: "start" }); } @computed get allErrors(): string[] { @@ -85,7 +87,7 @@ class NonInjectedAddCluster extends React.Component { addClusters = action(async () => { this.isWaiting = true; - appEventBus.emit({ name: "cluster-add", action: "click" }); + this.props.emitEvent({ name: "cluster-add", action: "click" }); try { const absPath = this.props.getCustomKubeConfigDirectory(uuid.v4()); @@ -155,10 +157,8 @@ class NonInjectedAddCluster extends React.Component { export const AddCluster = withInjectables(NonInjectedAddCluster, { getProps: (di) => ({ - getCustomKubeConfigDirectory: di.inject( - getCustomKubeConfigDirectoryInjectable, - ), - + getCustomKubeConfigDirectory: di.inject(getCustomKubeConfigDirectoryInjectable), navigateToCatalog: di.inject(navigateToCatalogInjectable), + emitEvent: di.inject(emitEventInjectable), }), }); diff --git a/src/renderer/components/+catalog/catalog.tsx b/src/renderer/components/+catalog/catalog.tsx index 723c21da13..7a0ac49678 100644 --- a/src/renderer/components/+catalog/catalog.tsx +++ b/src/renderer/components/+catalog/catalog.tsx @@ -38,7 +38,6 @@ import navigateToCatalogInjectable from "../../../common/front-end-routing/route import catalogRouteParametersInjectable from "./catalog-route-parameters.injectable"; import { browseCatalogTab } from "./catalog-browse-tab"; import type { AppEvent } from "../../../common/app-event-bus/event-bus"; -import appEventBusInjectable from "../../../common/app-event-bus/app-event-bus.injectable"; import hotbarStoreInjectable from "../../../common/hotbars/store.injectable"; import type { HotbarStore } from "../../../common/hotbars/store"; import type { VisitEntityContextMenu } from "../../../common/catalog/visit-entity-context-menu.injectable"; @@ -48,6 +47,7 @@ import type { Navigate } from "../../navigation/navigate.injectable"; import navigateInjectable from "../../navigation/navigate.injectable"; import type { NormalizeCatalogEntityContextMenu } from "../../catalog/normalize-menu-item.injectable"; import normalizeCatalogEntityContextMenuInjectable from "../../catalog/normalize-menu-item.injectable"; +import emitEventInjectable from "../../../common/app-event-bus/emit-event.injectable"; interface Dependencies { catalogPreviousActiveTabStorage: StorageLayer; @@ -356,7 +356,7 @@ export const Catalog = withInjectables(NonInjectedCatalog, { customCategoryViews: di.inject(customCategoryViewsInjectable), routeParameters: di.inject(catalogRouteParametersInjectable), navigateToCatalog: di.inject(navigateToCatalogInjectable), - emitEvent: di.inject(appEventBusInjectable).emit, + emitEvent: di.inject(emitEventInjectable), hotbarStore: di.inject(hotbarStoreInjectable), catalogCategoryRegistry: di.inject(catalogCategoryRegistryInjectable), visitEntityContextMenu: di.inject(visitEntityContextMenuInjectable), diff --git a/src/renderer/frames/cluster-frame/init-cluster-frame/init-cluster-frame.injectable.ts b/src/renderer/frames/cluster-frame/init-cluster-frame/init-cluster-frame.injectable.ts index 9dd4f59702..cfb3f62973 100644 --- a/src/renderer/frames/cluster-frame/init-cluster-frame/init-cluster-frame.injectable.ts +++ b/src/renderer/frames/cluster-frame/init-cluster-frame/init-cluster-frame.injectable.ts @@ -8,9 +8,9 @@ import extensionLoaderInjectable from "../../../../extensions/extension-loader/e import catalogEntityRegistryInjectable from "../../../api/catalog/entity/registry.injectable"; import frameRoutingIdInjectable from "./frame-routing-id/frame-routing-id.injectable"; import hostedClusterInjectable from "../../../cluster-frame-context/hosted-cluster.injectable"; -import appEventBusInjectable from "../../../../common/app-event-bus/app-event-bus.injectable"; import clusterFrameContextInjectable from "../../../cluster-frame-context/cluster-frame-context.injectable"; import assert from "assert"; +import emitEventInjectable from "../../../../common/app-event-bus/emit-event.injectable"; const initClusterFrameInjectable = getInjectable({ id: "init-cluster-frame", @@ -25,7 +25,7 @@ const initClusterFrameInjectable = getInjectable({ loadExtensions: di.inject(extensionLoaderInjectable).loadOnClusterRenderer, catalogEntityRegistry: di.inject(catalogEntityRegistryInjectable), frameRoutingId: di.inject(frameRoutingIdInjectable), - emitEvent: di.inject(appEventBusInjectable).emit, + emitEvent: di.inject(emitEventInjectable), clusterFrameContext: di.inject(clusterFrameContextInjectable), }); }, diff --git a/src/renderer/k8s/api-base.injectable.ts b/src/renderer/k8s/api-base.injectable.ts new file mode 100644 index 0000000000..5eda130eea --- /dev/null +++ b/src/renderer/k8s/api-base.injectable.ts @@ -0,0 +1,31 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { apiBaseInjectionToken } from "../../common/k8s-api/api-base"; +import { JsonApi } from "../../common/k8s-api/json-api"; +import { apiPrefix } from "../../common/vars"; +import isDebuggingInjectable from "../../common/vars/is-debugging.injectable"; +import isDevelopmentInjectable from "../../common/vars/is-development.injectable"; + +const apiBaseInjectable = getInjectable({ + id: "api-base", + instantiate: (di) => { + const isDevelopment = di.inject(isDevelopmentInjectable); + const isDebugging= di.inject(isDebuggingInjectable); + + return new JsonApi({ + serverAddress: `http://127.0.0.1:${window.location.port}`, + apiBase: apiPrefix, + debug: isDevelopment || isDebugging, + }, { + headers: { + "Host": window.location.host, + }, + }); + }, + injectionToken: apiBaseInjectionToken, +}); + +export default apiBaseInjectable;