Remove global version of appEventBus (#6096)

* Remove global version of appEventBus

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Introduce a temporary but better shape of ExecFileInjectable error

Signed-off-by: Sebastian Malton <sebastian@malton.name>

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton authored and GitHub committed 2022-10-31 14:59:05 +02:00
1 parent ba349e8b8d
commit 900f02fd8c
53 files changed
+330 -283

No files matched your search

-27
View File
@@ -1,27 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
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);
describe("event bus tests", () => {
describe("emit", () => {
it("emits an event", () => {
let event: AppEvent | undefined;
appEventBus.addListener((data) => {
event = data;
});
appEventBus.emit({ name: "foo", action: "bar" });
assert(event);
expect(event?.name).toBe("foo");
});
});
});
@@ -1,8 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getGlobalOverride } from "../test-utils/get-global-override";
import emitEventInjectable from "./emit-event.injectable";
export default getGlobalOverride(emitEventInjectable, () => () => {});
@@ -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]>,
decorable: false,
});
@@ -4,11 +4,18 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import appEventBusInjectable from "./app-event-bus.injectable";
import type { AppEvent } from "./event-bus";
const emitEventInjectable = getInjectable({
id: "emit-event",
instantiate: (di) => di.inject(appEventBusInjectable).emit,
export type EmitAppEvent = (event: AppEvent) => void;
const emitAppEventInjectable = getInjectable({
id: "emit-app-event",
instantiate: (di): EmitAppEvent => {
const bus = di.inject(appEventBusInjectable);
return (event) => bus.emit(event);
},
decorable: false,
});
export default emitEventInjectable;
export default emitAppEventInjectable;
+3 -4
View File
@@ -3,13 +3,12 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { EventEmitter } from "../event-emitter";
/**
* Data for telemetry
*/
export interface AppEvent {
name: string;
action: string;
destination?: string;
params?: Record<string, any>;
}
export const appEventBus = new EventEmitter<[AppEvent]>();
@@ -6,6 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
import { ClusterStore } from "./cluster-store";
import { createClusterInjectionToken } from "../cluster/create-cluster-injection-token";
import readClusterConfigSyncInjectable from "./read-cluster-config.injectable";
import emitAppEventInjectable from "../app-event-bus/emit-event.injectable";
const clusterStoreInjectable = getInjectable({
id: "cluster-store",
@@ -16,6 +17,7 @@ const clusterStoreInjectable = getInjectable({
return ClusterStore.createInstance({
createCluster: di.inject(createClusterInjectionToken),
readClusterConfigSync: di.inject(readClusterConfigSyncInjectable),
emitAppEvent: di.inject(emitAppEventInjectable),
});
},
+4 -3
View File
@@ -10,7 +10,6 @@ import { BaseStore } from "../base-store";
import { Cluster } from "../cluster/cluster";
import migrations from "../../migrations/cluster-store";
import logger from "../../main/logger";
import { appEventBus } from "../app-event-bus/event-bus";
import { ipcMainHandle } from "../ipc";
import { disposer, toJS } from "../utils";
import type { ClusterModel, ClusterId, ClusterState } from "../cluster-types";
@@ -18,6 +17,7 @@ import { requestInitialClusterStates } from "../../renderer/ipc";
import { clusterStates } from "../ipc/cluster";
import type { CreateCluster } from "../cluster/create-cluster-injection-token";
import type { ReadClusterConfigSync } from "./read-cluster-config.injectable";
import type { EmitAppEvent } from "../app-event-bus/emit-event.injectable";
export interface ClusterStoreModel {
clusters?: ClusterModel[];
@@ -26,6 +26,7 @@ export interface ClusterStoreModel {
interface Dependencies {
createCluster: CreateCluster;
readClusterConfigSync: ReadClusterConfigSync;
emitAppEvent: EmitAppEvent;
}
export class ClusterStore extends BaseStore<ClusterStoreModel> {
@@ -34,7 +35,7 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
protected disposer = disposer();
constructor(private dependencies: Dependencies) {
constructor(private readonly dependencies: Dependencies) {
super({
configName: "lens-cluster-store",
accessPropertiesByDotNotation: false, // To make dots safe in cluster context names
@@ -115,7 +116,7 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
}
addCluster(clusterOrModel: ClusterModel | Cluster): Cluster {
appEventBus.emit({ name: "cluster", action: "add" });
this.dependencies.emitAppEvent({ name: "cluster", action: "add" });
const cluster = clusterOrModel instanceof Cluster
? clusterOrModel
+2 -2
View File
@@ -29,7 +29,7 @@ export class EventEmitter<D extends [...any[]]> {
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<D extends [...any[]]> {
break;
}
}
};
}
}
+4 -7
View File
@@ -3,26 +3,23 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { ExecFileOptions } from "child_process";
import type { ExecFileException, ExecFileOptions } from "child_process";
import { execFile } from "child_process";
import type { AsyncResult } from "../utils/async-result";
export interface ExecFile {
(filePath: string, args: string[], options: ExecFileOptions): Promise<AsyncResult<string, { stderr: string; error: Error }>>;
(filePath: string, args: string[], options?: ExecFileOptions): Promise<AsyncResult<string, ExecFileException & { stderr: string }>>;
}
const execFileInjectable = getInjectable({
id: "exec-file",
instantiate: (): ExecFile => (filePath, args, options) => new Promise((resolve) => {
execFile(filePath, args, options, (error, stdout, stderr) => {
execFile(filePath, args, options ?? {}, (error, stdout, stderr) => {
if (error) {
resolve({
callWasSuccessful: false,
error: {
error,
stderr,
},
error: Object.assign(error, { stderr }),
});
} else {
resolve({
@@ -6,7 +6,7 @@ import type { HelmRepo } from "./helm-repo";
import type { AsyncResult } from "../utils/async-result";
import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token";
export type AddHelmRepositoryChannel = RequestChannel<HelmRepo, AsyncResult<string>>;
export type AddHelmRepositoryChannel = RequestChannel<HelmRepo, AsyncResult<void, string>>;
export const addHelmRepositoryChannel: AddHelmRepositoryChannel = {
id: "add-helm-repository-channel",
@@ -6,7 +6,7 @@ import type { AsyncResult } from "../utils/async-result";
import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token";
import type { HelmRepo } from "./helm-repo";
export type RemoveHelmRepositoryChannel = RequestChannel<HelmRepo, AsyncResult<string, string>>;
export type RemoveHelmRepositoryChannel = RequestChannel<HelmRepo, AsyncResult<void, string>>;
export const removeHelmRepositoryChannel: RemoveHelmRepositoryChannel = {
id: "remove-helm-repository-channel",
+8 -3
View File
@@ -5,7 +5,6 @@
import fse from "fs-extra";
import path from "path";
import hb from "handlebars";
import { ResourceApplier } from "../../main/resource-applier";
import type { KubernetesCluster } from "../catalog-entities";
import logger from "../../main/logger";
import { app } from "electron";
@@ -14,6 +13,8 @@ import yaml from "js-yaml";
import { requestKubectlApplyAll, requestKubectlDeleteAll } from "../../renderer/ipc";
import { getLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
import productNameInjectable from "../vars/product-name.injectable";
import { asLegacyGlobalFunctionForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-function-for-extension-api";
import createResourceApplierInjectable from "../../main/resource-applier/create-resource-applier.injectable";
export class ResourceStack {
constructor(protected cluster: KubernetesCluster, protected name: string) {}
@@ -52,7 +53,9 @@ export class ResourceStack {
kubectlArgs = this.appendKubectlArgs(kubectlArgs);
if (app) {
return await new ResourceApplier(clusterModel).kubectlApplyAll(resources, kubectlArgs);
const createResourceApplier = asLegacyGlobalFunctionForExtensionApi(createResourceApplierInjectable);
return await createResourceApplier(clusterModel).kubectlApplyAll(resources, kubectlArgs);
} else {
const response = await requestKubectlApplyAll(this.cluster.getId(), resources, kubectlArgs);
@@ -76,7 +79,9 @@ export class ResourceStack {
kubectlArgs = this.appendKubectlArgs(kubectlArgs);
if (app) {
return await new ResourceApplier(clusterModel).kubectlDeleteAll(resources, kubectlArgs);
const createResourceApplier = asLegacyGlobalFunctionForExtensionApi(createResourceApplierInjectable);
return await createResourceApplier(clusterModel).kubectlDeleteAll(resources, kubectlArgs);
} else {
const response = await requestKubectlDeleteAll(this.cluster.getId(), resources, kubectlArgs);
@@ -5,6 +5,7 @@
import { getInjectable } from "@ogre-tools/injectable";
import { UserStore } from "./user-store";
import selectedUpdateChannelInjectable from "../../features/application-update/common/selected-update-channel/selected-update-channel.injectable";
import emitAppEventInjectable from "../app-event-bus/emit-event.injectable";
const userStoreInjectable = getInjectable({
id: "user-store",
@@ -14,6 +15,7 @@ const userStoreInjectable = getInjectable({
return UserStore.createInstance({
selectedUpdateChannel: di.inject(selectedUpdateChannelInjectable),
emitAppEvent: di.inject(emitAppEventInjectable),
});
},
+2
View File
@@ -11,6 +11,7 @@ import { getOrInsertSet, toggle, toJS, object } from "../../renderer/utils";
import { DESCRIPTORS } from "./preferences-helpers";
import type { UserPreferencesModel, StoreType } from "./preferences-helpers";
import logger from "../../main/logger";
import type { EmitAppEvent } from "../app-event-bus/emit-event.injectable";
// TODO: Remove coupling with Feature
import type { SelectedUpdateChannel } from "../../features/application-update/common/selected-update-channel/selected-update-channel.injectable";
@@ -23,6 +24,7 @@ export interface UserStoreModel {
interface Dependencies {
readonly selectedUpdateChannel: SelectedUpdateChannel;
emitAppEvent: EmitAppEvent;
}
export class UserStore extends BaseStore<UserStoreModel> /* implements UserStoreFlatModel (when strict null is enabled) */ {
+5 -1
View File
@@ -3,5 +3,9 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
export type AsyncResult<Response, Error = string> =
| { callWasSuccessful: true; response: Response }
| (
Response extends void
? { callWasSuccessful: true; response?: undefined }
: { callWasSuccessful: true; response: Response }
)
| { callWasSuccessful: false; error: Error };