1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Remove all global uses of AppEventBus

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2022-07-08 13:36:05 -04:00
parent dade4eba52
commit a51a4e75f2
25 changed files with 212 additions and 129 deletions

View File

@ -4,24 +4,29 @@
*/ */
import type { AppEvent } from "../app-event-bus/event-bus"; import type { AppEvent } from "../app-event-bus/event-bus";
import { appEventBus } from "../app-event-bus/event-bus"; import { getDiForUnitTesting } from "../../main/getDiForUnitTesting";
import { assert, Console } from "console"; import appEventBusInjectable from "../app-event-bus/app-event-bus.injectable";
import { stdout, stderr } from "process"; import type { EventEmitter } from "../event-emitter";
console = new Console(stdout, stderr);
describe("event bus tests", () => { describe("event bus tests", () => {
let appEventBus: EventEmitter<[AppEvent]>;
beforeEach(() => {
const di = getDiForUnitTesting();
appEventBus = di.inject(appEventBusInjectable);
});
describe("emit", () => { describe("emit", () => {
it("emits an event", () => { it("emits an event", () => {
let event: AppEvent | undefined; let event!: AppEvent;
appEventBus.addListener((data) => { appEventBus.addListener((data) => {
event = data; event = data;
}); });
appEventBus.emit({ name: "foo", action: "bar" }); appEventBus.emit({ name: "foo", action: "bar" });
assert(event); expect(event.name).toBe("foo");
expect(event?.name).toBe("foo");
}); });
}); });
}); });

View File

@ -3,12 +3,12 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; 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({ const appEventBusInjectable = getInjectable({
id: "app-event-bus", id: "app-event-bus",
instantiate: () => appEventBus, instantiate: () => new EventEmitter<[AppEvent]>(),
causesSideEffects: true,
}); });
export default appEventBusInjectable; export default appEventBusInjectable;

View File

@ -4,10 +4,17 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import appEventBusInjectable from "./app-event-bus.injectable"; import appEventBusInjectable from "./app-event-bus.injectable";
import type { AppEvent } from "./event-bus";
export type EmitEvent = (event: AppEvent) => void;
const emitEventInjectable = getInjectable({ const emitEventInjectable = getInjectable({
id: "emit-event", 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; export default emitEventInjectable;

View File

@ -3,13 +3,12 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * 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 { export interface AppEvent {
name: string; name: string;
action: string; action: string;
destination?: string; destination?: string;
params?: Record<string, any>; params?: Record<string, any>;
} }
export const appEventBus = new EventEmitter<[AppEvent]>();

View File

@ -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 appVersionInjectable from "../get-configuration-file-model/app-version/app-version.injectable";
import getConfigurationFileModelInjectable from "../get-configuration-file-model/get-configuration-file-model.injectable"; import getConfigurationFileModelInjectable from "../get-configuration-file-model/get-configuration-file-model.injectable";
import loggerInjectable from "../logger.injectable"; import loggerInjectable from "../logger.injectable";
import emitEventInjectable from "../app-event-bus/emit-event.injectable";
const clusterStoreInjectable = getInjectable({ const clusterStoreInjectable = getInjectable({
id: "cluster-store", id: "cluster-store",
@ -26,6 +27,7 @@ const clusterStoreInjectable = getInjectable({
appVersion: di.inject(appVersionInjectable), appVersion: di.inject(appVersionInjectable),
directoryForUserData: di.inject(directoryForUserDataInjectable), directoryForUserData: di.inject(directoryForUserDataInjectable),
getConfigurationFileModel: di.inject(getConfigurationFileModelInjectable), getConfigurationFileModel: di.inject(getConfigurationFileModelInjectable),
emitEvent: di.inject(emitEventInjectable),
}); });
}, },

View File

@ -9,7 +9,6 @@ import { action, comparer, computed, makeObservable, observable, reaction } from
import type { BaseStoreDependencies } from "../base-store"; import type { BaseStoreDependencies } from "../base-store";
import { BaseStore } from "../base-store"; import { BaseStore } from "../base-store";
import { Cluster } from "../cluster/cluster"; import { Cluster } from "../cluster/cluster";
import type { AppEvent } from "../app-event-bus/event-bus";
import { ipcMainHandle } from "../ipc"; import { ipcMainHandle } from "../ipc";
import { disposer, toJS } from "../utils"; import { disposer, toJS } from "../utils";
import type { ClusterModel, ClusterId, ClusterState } from "../cluster-types"; 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 { CreateCluster } from "../cluster/create-cluster-injection-token";
import type { ReadClusterConfigSync } from "./read-cluster-config.injectable"; import type { ReadClusterConfigSync } from "./read-cluster-config.injectable";
import type { Migrations } from "conf/dist/source/types"; 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 { export interface ClusterStoreModel {
clusters?: ClusterModel[]; clusters?: ClusterModel[];
@ -27,8 +26,8 @@ export interface ClusterStoreModel {
interface ClusterStoreDependencies extends BaseStoreDependencies { interface ClusterStoreDependencies extends BaseStoreDependencies {
createCluster: CreateCluster; createCluster: CreateCluster;
readClusterConfigSync: ReadClusterConfigSync; readClusterConfigSync: ReadClusterConfigSync;
emitEvent: EmitEvent;
readonly migrations: Migrations<ClusterStoreModel> | undefined; readonly migrations: Migrations<ClusterStoreModel> | undefined;
readonly appEventBus: EventEmitter<[AppEvent]>;
} }
export class ClusterStore extends BaseStore<ClusterStoreModel> { export class ClusterStore extends BaseStore<ClusterStoreModel> {
@ -118,7 +117,7 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
} }
addCluster(clusterOrModel: ClusterModel | Cluster): Cluster { 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 const cluster = clusterOrModel instanceof Cluster
? clusterOrModel ? clusterOrModel

View File

@ -29,7 +29,7 @@ export class EventEmitter<D extends [...any[]]> {
this.listeners.length = 0; this.listeners.length = 0;
} }
emit = (...data: D) => { emit(...data: D) {
for (const [callback, { once }] of this.listeners) { for (const [callback, { once }] of this.listeners) {
if (once) { if (once) {
this.removeListener(callback); this.removeListener(callback);
@ -39,5 +39,5 @@ export class EventEmitter<D extends [...any[]]> {
break; break;
} }
} }
}; }
} }

View File

@ -3,38 +3,12 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { JsonApi } from "./json-api"; import type { JsonApi } from "./json-api";
import { apiPrefix, isDebugging, isDevelopment } from "../vars"; import { getInjectionToken } from "@ogre-tools/injectable";
import { appEventBus } from "../app-event-bus/event-bus"; 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<JsonApi>({
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 { export const apiBase = asLegacyGlobalForExtensionApi(apiBaseInjectionToken);
apiBase = new JsonApi({
serverAddress: `http://127.0.0.1:${window.location.port}`,
apiBase: apiPrefix,
debug: isDevelopment || isDebugging,
}, {
headers: {
"Host": window.location.host,
},
});
}

View File

@ -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 appVersionInjectable from "../get-configuration-file-model/app-version/app-version.injectable";
import getConfigurationFileModelInjectable from "../get-configuration-file-model/get-configuration-file-model.injectable"; import getConfigurationFileModelInjectable from "../get-configuration-file-model/get-configuration-file-model.injectable";
import loggerInjectable from "../logger.injectable"; import loggerInjectable from "../logger.injectable";
import emitEventInjectable from "../app-event-bus/emit-event.injectable";
const userStoreInjectable = getInjectable({ const userStoreInjectable = getInjectable({
id: "user-store", id: "user-store",
@ -30,6 +31,7 @@ const userStoreInjectable = getInjectable({
appVersion: di.inject(appVersionInjectable), appVersion: di.inject(appVersionInjectable),
directoryForUserData: di.inject(directoryForUserDataInjectable), directoryForUserData: di.inject(directoryForUserDataInjectable),
getConfigurationFileModel: di.inject(getConfigurationFileModelInjectable), getConfigurationFileModel: di.inject(getConfigurationFileModelInjectable),
emitEvent: di.inject(emitEventInjectable),
}); });
}, },

View File

@ -10,13 +10,13 @@ import type { BaseStoreDependencies } from "../base-store";
import { BaseStore } from "../base-store"; import { BaseStore } from "../base-store";
import { getAppVersion } from "../utils/app-version"; import { getAppVersion } from "../utils/app-version";
import { kubeConfigDefaultPath } from "../kube-helpers"; import { kubeConfigDefaultPath } from "../kube-helpers";
import { appEventBus } from "../app-event-bus/event-bus";
import { getOrInsertSet, toggle, toJS, object } from "../../renderer/utils"; import { getOrInsertSet, toggle, toJS, object } from "../../renderer/utils";
import { DESCRIPTORS } from "./preferences-helpers"; import { DESCRIPTORS } from "./preferences-helpers";
import type { UserPreferencesModel, StoreType } 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 { SelectedUpdateChannel } from "../application-update/selected-update-channel/selected-update-channel.injectable";
import type { UpdateChannelId } from "../application-update/update-channels"; import type { UpdateChannelId } from "../application-update/update-channels";
import type { Migrations } from "conf/dist/source/types"; import type { Migrations } from "conf/dist/source/types";
import type { EmitEvent } from "../app-event-bus/emit-event.injectable";
export interface UserStoreModel { export interface UserStoreModel {
lastSeenAppVersion: string; lastSeenAppVersion: string;
@ -26,6 +26,7 @@ export interface UserStoreModel {
interface UserStoreDependencies extends BaseStoreDependencies { interface UserStoreDependencies extends BaseStoreDependencies {
readonly selectedUpdateChannel: SelectedUpdateChannel; readonly selectedUpdateChannel: SelectedUpdateChannel;
readonly migrations: Migrations<UserStoreModel> | undefined; readonly migrations: Migrations<UserStoreModel> | undefined;
emitEvent: EmitEvent;
} }
export class UserStore extends BaseStore<UserStoreModel> /* implements UserStoreFlatModel (when strict null is enabled) */ { export class UserStore extends BaseStore<UserStoreModel> /* implements UserStoreFlatModel (when strict null is enabled) */ {
@ -154,7 +155,7 @@ export class UserStore extends BaseStore<UserStoreModel> /* implements UserStore
@action @action
saveLastSeenAppVersion() { saveLastSeenAppVersion() {
appEventBus.emit({ name: "app", action: "whats-new-seen" }); this.dependencies.emitEvent({ name: "app", action: "whats-new-seen" });
this.lastSeenAppVersion = getAppVersion(); this.lastSeenAppVersion = getAppVersion();
} }

View File

@ -25,7 +25,11 @@ export const isWindows = process.platform === "win32";
*/ */
export const isLinux = process.platform === "linux"; 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 isDebugging = ["true", "1", "yes", "y", "on"].includes((process.env.DEBUG ?? "").toLowerCase());
export const isSnap = !!process.env.SNAP; export const isSnap = !!process.env.SNAP;
/** /**

View File

@ -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;

View File

@ -3,5 +3,9 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * 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 type { AppEvent } from "../../common/app-event-bus/event-bus";
export const appEventBus = asLegacyGlobalForExtensionApi(appEventBusInjectable);

View File

@ -4,6 +4,7 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import directoryForLensLocalStorageInjectable from "../../../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.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 { setupIpcMainHandlers } from "./setup-ipc-main-handlers";
import loggerInjectable from "../../../../common/logger.injectable"; import loggerInjectable from "../../../../common/logger.injectable";
import clusterManagerInjectable from "../../../cluster-manager.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 operatingSystemThemeInjectable from "../../../theme/operating-system-theme.injectable";
import catalogEntityRegistryInjectable from "../../../catalog/entity-registry.injectable"; import catalogEntityRegistryInjectable from "../../../catalog/entity-registry.injectable";
import askUserForFilePathsInjectable from "../../../ipc/ask-user-for-file-paths.injectable"; import askUserForFilePathsInjectable from "../../../ipc/ask-user-for-file-paths.injectable";
import emitEventInjectable from "../../../../common/app-event-bus/emit-event.injectable";
const setupIpcMainHandlersInjectable = getInjectable({ const setupIpcMainHandlersInjectable = getInjectable({
id: "setup-ipc-main-handlers", id: "setup-ipc-main-handlers",
instantiate: (di) => { instantiate: (di) => {
const logger = di.inject(loggerInjectable); const logger = di.inject(loggerInjectable);
const deps: SetupIpcMainHandlersDependencies = {
const directoryForLensLocalStorage = di.inject( directoryForLensLocalStorage: di.inject(directoryForLensLocalStorageInjectable),
directoryForLensLocalStorageInjectable, clusterManager: di.inject(clusterManagerInjectable),
); applicationMenuItems: di.inject(applicationMenuItemsInjectable),
getAbsolutePath: di.inject(getAbsolutePathInjectable),
const clusterManager = di.inject(clusterManagerInjectable); catalogEntityRegistry: di.inject(catalogEntityRegistryInjectable),
const applicationMenuItems = di.inject(applicationMenuItemsInjectable); clusterStore: di.inject(clusterStoreInjectable),
const getAbsolutePath = di.inject(getAbsolutePathInjectable); operatingSystemTheme: di.inject(operatingSystemThemeInjectable),
const catalogEntityRegistry = di.inject(catalogEntityRegistryInjectable); askUserForFilePaths: di.inject(askUserForFilePathsInjectable),
const clusterStore = di.inject(clusterStoreInjectable); emitEvent: di.inject(emitEventInjectable),
const operatingSystemTheme = di.inject(operatingSystemThemeInjectable); };
const askUserForFilePaths = di.inject(askUserForFilePathsInjectable);
return { return {
run: () => { run: () => {
logger.debug("[APP-MAIN] initializing ipc main handlers"); logger.debug("[APP-MAIN] initializing ipc main handlers");
setupIpcMainHandlers(deps);
setupIpcMainHandlers({
applicationMenuItems,
getAbsolutePath,
directoryForLensLocalStorage,
clusterManager,
catalogEntityRegistry,
clusterStore,
operatingSystemTheme,
askUserForFilePaths,
});
}, },
}; };
}, },

View File

@ -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 { clusterActivateHandler, clusterSetFrameIdHandler, clusterVisibilityHandler, clusterRefreshHandler, clusterDisconnectHandler, clusterKubectlApplyAllHandler, clusterKubectlDeleteAllHandler, clusterDeleteHandler, clusterSetDeletingHandler, clusterClearDeletingHandler } from "../../../../common/ipc/cluster";
import type { ClusterId } from "../../../../common/cluster-types"; import type { ClusterId } from "../../../../common/cluster-types";
import { ClusterStore } from "../../../../common/cluster-store/cluster-store"; 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 { broadcastMainChannel, broadcastMessage, ipcMainHandle, ipcMainOn } from "../../../../common/ipc";
import type { CatalogEntityRegistry } from "../../../catalog"; import type { CatalogEntityRegistry } from "../../../catalog";
import { pushCatalogToRenderer } from "../../../catalog-pusher"; import { pushCatalogToRenderer } from "../../../catalog-pusher";
@ -24,8 +23,9 @@ import { openFilePickingDialogChannel } from "../../../../common/ipc/dialog";
import { getNativeThemeChannel } from "../../../../common/ipc/native-theme"; import { getNativeThemeChannel } from "../../../../common/ipc/native-theme";
import type { Theme } from "../../../theme/operating-system-theme-state.injectable"; import type { Theme } from "../../../theme/operating-system-theme-state.injectable";
import type { AskUserForFilePaths } from "../../../ipc/ask-user-for-file-paths.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; directoryForLensLocalStorage: string;
getAbsolutePath: GetAbsolutePath; getAbsolutePath: GetAbsolutePath;
applicationMenuItems: IComputedValue<MenuItemOpts[]>; applicationMenuItems: IComputedValue<MenuItemOpts[]>;
@ -34,9 +34,20 @@ interface Dependencies {
clusterStore: ClusterStore; clusterStore: ClusterStore;
operatingSystemTheme: IComputedValue<Theme>; operatingSystemTheme: IComputedValue<Theme>;
askUserForFilePaths: AskUserForFilePaths; 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) => { ipcMainHandle(clusterActivateHandler, (event, clusterId: ClusterId, force = false) => {
return ClusterStore.getInstance() return ClusterStore.getInstance()
.getById(clusterId) .getById(clusterId)
@ -65,7 +76,7 @@ export const setupIpcMainHandlers = ({ applicationMenuItems, directoryForLensLoc
}); });
ipcMainHandle(clusterDisconnectHandler, (event, clusterId: ClusterId) => { ipcMainHandle(clusterDisconnectHandler, (event, clusterId: ClusterId) => {
appEventBus.emit({ name: "cluster", action: "stop" }); emitEvent({ name: "cluster", action: "stop" });
const cluster = ClusterStore.getInstance().getById(clusterId); const cluster = ClusterStore.getInstance().getById(clusterId);
if (cluster) { if (cluster) {
@ -75,7 +86,7 @@ export const setupIpcMainHandlers = ({ applicationMenuItems, directoryForLensLoc
}); });
ipcMainHandle(clusterDeleteHandler, async (event, clusterId: ClusterId) => { ipcMainHandle(clusterDeleteHandler, async (event, clusterId: ClusterId) => {
appEventBus.emit({ name: "cluster", action: "remove" }); emitEvent({ name: "cluster", action: "remove" });
const clusterStore = ClusterStore.getInstance(); const clusterStore = ClusterStore.getInstance();
const cluster = clusterStore.getById(clusterId); const cluster = clusterStore.getById(clusterId);
@ -109,7 +120,7 @@ export const setupIpcMainHandlers = ({ applicationMenuItems, directoryForLensLoc
}); });
ipcMainHandle(clusterKubectlApplyAllHandler, async (event, clusterId: ClusterId, resources: string[], extraArgs: string[]) => { 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); const cluster = ClusterStore.getInstance().getById(clusterId);
if (cluster) { if (cluster) {
@ -128,7 +139,7 @@ export const setupIpcMainHandlers = ({ applicationMenuItems, directoryForLensLoc
}); });
ipcMainHandle(clusterKubectlDeleteAllHandler, async (event, clusterId: ClusterId, resources: string[], extraArgs: string[]) => { 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); const cluster = ClusterStore.getInstance().getById(clusterId);
if (cluster) { if (cluster) {

View File

@ -28,9 +28,6 @@ import { getAbsolutePathFake } from "../common/test-utils/get-absolute-path-fake
import joinPathsInjectable from "../common/path/join-paths.injectable"; import joinPathsInjectable from "../common/path/join-paths.injectable";
import { joinPathsFake } from "../common/test-utils/join-paths-fake"; import { joinPathsFake } from "../common/test-utils/join-paths-fake";
import hotbarStoreInjectable from "../common/hotbars/store.injectable"; 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 commandLineArgumentsInjectable from "./utils/command-line-arguments.injectable";
import initializeExtensionsInjectable from "./start-main-application/runnables/initialize-extensions.injectable"; import initializeExtensionsInjectable from "./start-main-application/runnables/initialize-extensions.injectable";
import lensResourcesDirInjectable from "../common/vars/lens-resources-dir.injectable"; import lensResourcesDirInjectable from "../common/vars/lens-resources-dir.injectable";
@ -178,9 +175,6 @@ export function getDiForUnitTesting(opts: { doGeneralOverrides?: boolean } = {})
execFileInjectable, 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(appNameInjectable, () => "some-app-name");
di.override(broadcastMessageInjectable, () => (channel) => { di.override(broadcastMessageInjectable, () => (channel) => {
throw new Error(`Tried to broadcast message to channel "${channel}" over IPC without explicit override.`); throw new Error(`Tried to broadcast message to channel "${channel}" over IPC without explicit override.`);

View File

@ -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;

View File

@ -10,26 +10,20 @@ import httpProxy from "http-proxy";
import clusterManagerInjectable from "../cluster-manager.injectable"; import clusterManagerInjectable from "../cluster-manager.injectable";
import shellApiRequestInjectable from "./proxy-functions/shell-api-request/shell-api-request.injectable"; import shellApiRequestInjectable from "./proxy-functions/shell-api-request/shell-api-request.injectable";
import lensProxyPortInjectable from "./lens-proxy-port.injectable"; import lensProxyPortInjectable from "./lens-proxy-port.injectable";
import emitEventInjectable from "../../common/app-event-bus/emit-event.injectable";
const lensProxyInjectable = getInjectable({ const lensProxyInjectable = getInjectable({
id: "lens-proxy", id: "lens-proxy",
instantiate: (di) => { instantiate: (di) => new LensProxy({
const clusterManager = di.inject(clusterManagerInjectable); router: di.inject(routerInjectable),
const router = di.inject(routerInjectable); proxy: httpProxy.createProxy(),
const shellApiRequest = di.inject(shellApiRequestInjectable);
const proxy = httpProxy.createProxy();
const lensProxyPort = di.inject(lensProxyPortInjectable);
return new LensProxy({
router,
proxy,
kubeApiUpgradeRequest, kubeApiUpgradeRequest,
shellApiRequest, shellApiRequest: di.inject(shellApiRequestInjectable),
getClusterForRequest: clusterManager.getClusterForRequest, getClusterForRequest: di.inject(clusterManagerInjectable).getClusterForRequest,
lensProxyPort, lensProxyPort: di.inject(lensProxyPortInjectable),
}); emitEvent: di.inject(emitEventInjectable),
}, }),
}); });
export default lensProxyInjectable; export default lensProxyInjectable;

View File

@ -13,10 +13,10 @@ import type { ClusterContextHandler } from "../context-handler/context-handler";
import logger from "../logger"; import logger from "../logger";
import type { Cluster } from "../../common/cluster/cluster"; import type { Cluster } from "../../common/cluster/cluster";
import type { ProxyApiRequestArgs } from "./proxy-functions"; import type { ProxyApiRequestArgs } from "./proxy-functions";
import { appEventBus } from "../../common/app-event-bus/event-bus";
import { getBoolean } from "../utils/parse-query"; import { getBoolean } from "../utils/parse-query";
import assert from "assert"; import assert from "assert";
import type { SetRequired } from "type-fest"; import type { SetRequired } from "type-fest";
import type { EmitEvent } from "../../common/app-event-bus/emit-event.injectable";
type GetClusterForRequest = (req: http.IncomingMessage) => Cluster | undefined; type GetClusterForRequest = (req: http.IncomingMessage) => Cluster | undefined;
@ -29,6 +29,7 @@ interface Dependencies {
router: Router; router: Router;
proxy: httpProxy; proxy: httpProxy;
lensProxyPort: { set: (portNumber: number) => void }; lensProxyPort: { set: (portNumber: number) => void };
emitEvent: EmitEvent;
} }
const watchParam = "watch"; const watchParam = "watch";
@ -116,7 +117,7 @@ export class LensProxy {
logger.info(`[LENS-PROXY]: Subsequent error: ${error}`); 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); resolve(port);
}) })
.once("error", (error) => { .once("error", (error) => {

View File

@ -11,13 +11,24 @@ import * as yaml from "js-yaml";
import path from "path"; import path from "path";
import tempy from "tempy"; import tempy from "tempy";
import logger from "./logger"; import logger from "./logger";
import { appEventBus } from "../common/app-event-bus/event-bus";
import { isChildProcessError } from "../common/utils"; import { isChildProcessError } from "../common/utils";
import type { Patch } from "rfc6902"; import type { Patch } from "rfc6902";
import { promiseExecFile } from "../common/utils/promise-exec"; 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 { 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. * 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 * @param ns The optional namespace of the kube resource
*/ */
async patch(name: string, kind: string, patch: Patch, ns?: string): Promise<string> { async patch(name: string, kind: string, patch: Patch, ns?: string): Promise<string> {
appEventBus.emit({ name: "resource", action: "patch" }); this.dependencies.emitEvent({ name: "resource", action: "patch" });
const kubectl = await this.cluster.ensureKubectl(); const kubectl = await this.cluster.ensureKubectl();
const kubectlPath = await kubectl.getPath(); const kubectlPath = await kubectl.getPath();
@ -64,7 +75,7 @@ export class ResourceApplier {
async apply(resource: KubernetesObject | any): Promise<string> { async apply(resource: KubernetesObject | any): Promise<string> {
resource = this.sanitizeObject(resource); resource = this.sanitizeObject(resource);
appEventBus.emit({ name: "resource", action: "apply" }); this.dependencies.emitEvent({ name: "resource", action: "apply" });
return this.kubectlApply(yaml.dump(resource)); return this.kubectlApply(yaml.dump(resource));
} }

View File

@ -14,11 +14,12 @@ import os from "os";
import { isMac, isWindows } from "../../common/vars"; import { isMac, isWindows } from "../../common/vars";
import { UserStore } from "../../common/user-store"; import { UserStore } from "../../common/user-store";
import * as pty from "node-pty"; import * as pty from "node-pty";
import { appEventBus } from "../../common/app-event-bus/event-bus";
import logger from "../logger"; import logger from "../logger";
import { stat } from "fs/promises"; import { stat } from "fs/promises";
import { getOrInsertWith } from "../../common/utils"; import { getOrInsertWith } from "../../common/utils";
import { type TerminalMessage, TerminalChannels } from "../../common/terminal/channels"; 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 { export class ShellOpenError extends Error {
constructor(message: string, options?: ErrorOptions) { 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[] { protected getPathEntries(): string[] {

View File

@ -13,7 +13,6 @@ import { observer } from "mobx-react";
import path from "path"; import path from "path";
import React from "react"; import React from "react";
import * as uuid from "uuid"; import * as uuid from "uuid";
import { appEventBus } from "../../../common/app-event-bus/event-bus";
import { loadConfigFromString, splitConfig } from "../../../common/kube-helpers"; import { loadConfigFromString, splitConfig } from "../../../common/kube-helpers";
import { docsUrl } from "../../../common/vars"; import { docsUrl } from "../../../common/vars";
import { isDefined, iter } from "../../utils"; 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 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 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 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 { interface Option {
config: KubeConfig; config: KubeConfig;
@ -34,6 +35,7 @@ interface Option {
interface Dependencies { interface Dependencies {
getCustomKubeConfigDirectory: (directoryName: string) => string; getCustomKubeConfigDirectory: (directoryName: string) => string;
navigateToCatalog: NavigateToCatalog; navigateToCatalog: NavigateToCatalog;
emitEvent: EmitEvent;
} }
function getContexts(config: KubeConfig): Map<string, Option> { function getContexts(config: KubeConfig): Map<string, Option> {
@ -59,7 +61,7 @@ class NonInjectedAddCluster extends React.Component<Dependencies> {
} }
componentDidMount() { componentDidMount() {
appEventBus.emit({ name: "cluster-add", action: "start" }); this.props.emitEvent({ name: "cluster-add", action: "start" });
} }
@computed get allErrors(): string[] { @computed get allErrors(): string[] {
@ -85,7 +87,7 @@ class NonInjectedAddCluster extends React.Component<Dependencies> {
addClusters = action(async () => { addClusters = action(async () => {
this.isWaiting = true; this.isWaiting = true;
appEventBus.emit({ name: "cluster-add", action: "click" }); this.props.emitEvent({ name: "cluster-add", action: "click" });
try { try {
const absPath = this.props.getCustomKubeConfigDirectory(uuid.v4()); const absPath = this.props.getCustomKubeConfigDirectory(uuid.v4());
@ -155,10 +157,8 @@ class NonInjectedAddCluster extends React.Component<Dependencies> {
export const AddCluster = withInjectables<Dependencies>(NonInjectedAddCluster, { export const AddCluster = withInjectables<Dependencies>(NonInjectedAddCluster, {
getProps: (di) => ({ getProps: (di) => ({
getCustomKubeConfigDirectory: di.inject( getCustomKubeConfigDirectory: di.inject(getCustomKubeConfigDirectoryInjectable),
getCustomKubeConfigDirectoryInjectable,
),
navigateToCatalog: di.inject(navigateToCatalogInjectable), navigateToCatalog: di.inject(navigateToCatalogInjectable),
emitEvent: di.inject(emitEventInjectable),
}), }),
}); });

View File

@ -38,7 +38,6 @@ import navigateToCatalogInjectable from "../../../common/front-end-routing/route
import catalogRouteParametersInjectable from "./catalog-route-parameters.injectable"; import catalogRouteParametersInjectable from "./catalog-route-parameters.injectable";
import { browseCatalogTab } from "./catalog-browse-tab"; import { browseCatalogTab } from "./catalog-browse-tab";
import type { AppEvent } from "../../../common/app-event-bus/event-bus"; 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 hotbarStoreInjectable from "../../../common/hotbars/store.injectable";
import type { HotbarStore } from "../../../common/hotbars/store"; import type { HotbarStore } from "../../../common/hotbars/store";
import type { VisitEntityContextMenu } from "../../../common/catalog/visit-entity-context-menu.injectable"; 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 navigateInjectable from "../../navigation/navigate.injectable";
import type { NormalizeCatalogEntityContextMenu } from "../../catalog/normalize-menu-item.injectable"; import type { NormalizeCatalogEntityContextMenu } from "../../catalog/normalize-menu-item.injectable";
import normalizeCatalogEntityContextMenuInjectable 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 { interface Dependencies {
catalogPreviousActiveTabStorage: StorageLayer<string | null>; catalogPreviousActiveTabStorage: StorageLayer<string | null>;
@ -356,7 +356,7 @@ export const Catalog = withInjectables<Dependencies>(NonInjectedCatalog, {
customCategoryViews: di.inject(customCategoryViewsInjectable), customCategoryViews: di.inject(customCategoryViewsInjectable),
routeParameters: di.inject(catalogRouteParametersInjectable), routeParameters: di.inject(catalogRouteParametersInjectable),
navigateToCatalog: di.inject(navigateToCatalogInjectable), navigateToCatalog: di.inject(navigateToCatalogInjectable),
emitEvent: di.inject(appEventBusInjectable).emit, emitEvent: di.inject(emitEventInjectable),
hotbarStore: di.inject(hotbarStoreInjectable), hotbarStore: di.inject(hotbarStoreInjectable),
catalogCategoryRegistry: di.inject(catalogCategoryRegistryInjectable), catalogCategoryRegistry: di.inject(catalogCategoryRegistryInjectable),
visitEntityContextMenu: di.inject(visitEntityContextMenuInjectable), visitEntityContextMenu: di.inject(visitEntityContextMenuInjectable),

View File

@ -8,9 +8,9 @@ import extensionLoaderInjectable from "../../../../extensions/extension-loader/e
import catalogEntityRegistryInjectable from "../../../api/catalog/entity/registry.injectable"; import catalogEntityRegistryInjectable from "../../../api/catalog/entity/registry.injectable";
import frameRoutingIdInjectable from "./frame-routing-id/frame-routing-id.injectable"; import frameRoutingIdInjectable from "./frame-routing-id/frame-routing-id.injectable";
import hostedClusterInjectable from "../../../cluster-frame-context/hosted-cluster.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 clusterFrameContextInjectable from "../../../cluster-frame-context/cluster-frame-context.injectable";
import assert from "assert"; import assert from "assert";
import emitEventInjectable from "../../../../common/app-event-bus/emit-event.injectable";
const initClusterFrameInjectable = getInjectable({ const initClusterFrameInjectable = getInjectable({
id: "init-cluster-frame", id: "init-cluster-frame",
@ -25,7 +25,7 @@ const initClusterFrameInjectable = getInjectable({
loadExtensions: di.inject(extensionLoaderInjectable).loadOnClusterRenderer, loadExtensions: di.inject(extensionLoaderInjectable).loadOnClusterRenderer,
catalogEntityRegistry: di.inject(catalogEntityRegistryInjectable), catalogEntityRegistry: di.inject(catalogEntityRegistryInjectable),
frameRoutingId: di.inject(frameRoutingIdInjectable), frameRoutingId: di.inject(frameRoutingIdInjectable),
emitEvent: di.inject(appEventBusInjectable).emit, emitEvent: di.inject(emitEventInjectable),
clusterFrameContext: di.inject(clusterFrameContextInjectable), clusterFrameContext: di.inject(clusterFrameContextInjectable),
}); });
}, },

View File

@ -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;