diff --git a/src/common/app-paths/app-paths-channel.injectable.ts b/src/common/app-paths/app-paths-channel.injectable.ts deleted file mode 100644 index 99fc738b41..0000000000 --- a/src/common/app-paths/app-paths-channel.injectable.ts +++ /dev/null @@ -1,22 +0,0 @@ -/** - * 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 type { AppPaths } from "./app-path-injection-token"; -import type { RequestChannel } from "../utils/channel/request-channel-injection-token"; -import { messageChannelInjectionToken } from "../utils/channel/message-channel-injection-token"; - -export type AppPathsChannel = RequestChannel; - -const appPathsChannelInjectable = getInjectable({ - id: "app-paths-channel", - - instantiate: (): AppPathsChannel => ({ - id: "app-paths", - }), - - injectionToken: messageChannelInjectionToken, -}); - -export default appPathsChannelInjectable; diff --git a/src/common/app-paths/app-paths-channel.ts b/src/common/app-paths/app-paths-channel.ts new file mode 100644 index 0000000000..4502569d3b --- /dev/null +++ b/src/common/app-paths/app-paths-channel.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 type { AppPaths } from "./app-path-injection-token"; +import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token"; + +export type AppPathsChannel = RequestChannel; + +export const appPathsChannel: AppPathsChannel = { + id: "app-paths", +}; + diff --git a/src/common/application-update/restart-and-install-update-channel.ts b/src/common/application-update/restart-and-install-update-channel.ts new file mode 100644 index 0000000000..1d45d6330f --- /dev/null +++ b/src/common/application-update/restart-and-install-update-channel.ts @@ -0,0 +1,11 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token"; + +export type RestartAndInstallUpdateChannel = MessageChannel; + +export const restartAndInstallUpdateChannel: RestartAndInstallUpdateChannel = { + id: "restart-and-install-update-channel", +}; diff --git a/src/common/application-update/restart-and-install-update-channel/restart-and-install-update-channel.injectable.ts b/src/common/application-update/restart-and-install-update-channel/restart-and-install-update-channel.injectable.ts deleted file mode 100644 index b6d811e101..0000000000 --- a/src/common/application-update/restart-and-install-update-channel/restart-and-install-update-channel.injectable.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * 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 type { MessageChannel } from "../../utils/channel/message-channel-injection-token"; -import { messageChannelInjectionToken } from "../../utils/channel/message-channel-injection-token"; - -export type RestartAndInstallUpdateChannel = MessageChannel; - -const restartAndInstallUpdateChannel = getInjectable({ - id: "restart-and-install-update-channel", - - instantiate: (): RestartAndInstallUpdateChannel => ({ - id: "restart-and-install-update-channel", - }), - - injectionToken: messageChannelInjectionToken, -}); - -export default restartAndInstallUpdateChannel; diff --git a/src/common/application-update/selected-update-channel/selected-update-channel.injectable.ts b/src/common/application-update/selected-update-channel/selected-update-channel.injectable.ts index 8ca31e00aa..d11778b9bd 100644 --- a/src/common/application-update/selected-update-channel/selected-update-channel.injectable.ts +++ b/src/common/application-update/selected-update-channel/selected-update-channel.injectable.ts @@ -19,7 +19,7 @@ const selectedUpdateChannelInjectable = getInjectable({ instantiate: (di): SelectedUpdateChannel => { const defaultUpdateChannel = di.inject(defaultUpdateChannelInjectable); - const state = observable.box(); + const state = observable.box(undefined, { deep: false }); return { value: computed(() => state.get() ?? defaultUpdateChannel.get()), diff --git a/src/common/front-end-routing/app-navigation-channel.injectable.ts b/src/common/front-end-routing/app-navigation-channel.injectable.ts deleted file mode 100644 index 869fbfdecd..0000000000 --- a/src/common/front-end-routing/app-navigation-channel.injectable.ts +++ /dev/null @@ -1,22 +0,0 @@ -/** - * 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 { IpcRendererNavigationEvents } from "../../renderer/navigation/events"; -import type { MessageChannel } from "../utils/channel/message-channel-injection-token"; -import { messageChannelInjectionToken } from "../utils/channel/message-channel-injection-token"; - -export type AppNavigationChannel = MessageChannel; - -const appNavigationChannelInjectable = getInjectable({ - id: "app-navigation-channel", - - instantiate: (): AppNavigationChannel => ({ - id: IpcRendererNavigationEvents.NAVIGATE_IN_APP, - }), - - injectionToken: messageChannelInjectionToken, -}); - -export default appNavigationChannelInjectable; diff --git a/src/common/front-end-routing/app-navigation-channel.ts b/src/common/front-end-routing/app-navigation-channel.ts new file mode 100644 index 0000000000..e0b881eff9 --- /dev/null +++ b/src/common/front-end-routing/app-navigation-channel.ts @@ -0,0 +1,12 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { IpcRendererNavigationEvents } from "../../renderer/navigation/events"; +import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token"; + +export type AppNavigationChannel = MessageChannel; + +export const appNavigationChannel: AppNavigationChannel = { + id: IpcRendererNavigationEvents.NAVIGATE_IN_APP, +}; diff --git a/src/common/front-end-routing/cluster-frame-navigation-channel.injectable.ts b/src/common/front-end-routing/cluster-frame-navigation-channel.injectable.ts deleted file mode 100644 index 596bd6d351..0000000000 --- a/src/common/front-end-routing/cluster-frame-navigation-channel.injectable.ts +++ /dev/null @@ -1,22 +0,0 @@ -/** - * 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 { IpcRendererNavigationEvents } from "../../renderer/navigation/events"; -import type { MessageChannel } from "../utils/channel/message-channel-injection-token"; -import { messageChannelInjectionToken } from "../utils/channel/message-channel-injection-token"; - -export type ClusterFrameNavigationChannel = MessageChannel; - -const clusterFrameNavigationChannelInjectable = getInjectable({ - id: "cluster-frame-navigation-channel", - - instantiate: (): ClusterFrameNavigationChannel => ({ - id: IpcRendererNavigationEvents.NAVIGATE_IN_CLUSTER, - }), - - injectionToken: messageChannelInjectionToken, -}); - -export default clusterFrameNavigationChannelInjectable; diff --git a/src/common/front-end-routing/cluster-frame-navigation-channel.ts b/src/common/front-end-routing/cluster-frame-navigation-channel.ts new file mode 100644 index 0000000000..9d9a1904af --- /dev/null +++ b/src/common/front-end-routing/cluster-frame-navigation-channel.ts @@ -0,0 +1,12 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { IpcRendererNavigationEvents } from "../../renderer/navigation/events"; +import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token"; + +export type ClusterFrameNavigationChannel = MessageChannel; + +export const clusterFrameNavigationChannel: ClusterFrameNavigationChannel = { + id: IpcRendererNavigationEvents.NAVIGATE_IN_CLUSTER, +}; diff --git a/src/common/fs/exec-file.injectable.ts b/src/common/fs/exec-file.injectable.ts index 15d0ad48dc..8db31c602f 100644 --- a/src/common/fs/exec-file.injectable.ts +++ b/src/common/fs/exec-file.injectable.ts @@ -5,22 +5,33 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { ExecFileOptions } from "child_process"; import { execFile } from "child_process"; -import { promisify } from "util"; +import type { AsyncResult } from "../utils/async-result"; -export type ExecFile = (filePath: string, args: string[], options: ExecFileOptions) => Promise; +export interface ExecFile { + (filePath: string, args: string[], options: ExecFileOptions): Promise>; +} const execFileInjectable = getInjectable({ id: "exec-file", - instantiate: (): ExecFile => { - const asyncExecFile = promisify(execFile); - - return async (filePath, args, options) => { - const result = await asyncExecFile(filePath, args, options); - - return result.stdout; - }; - }, + instantiate: (): ExecFile => (filePath, args, options) => new Promise((resolve) => { + execFile(filePath, args, options, (error, stdout, stderr) => { + if (error) { + resolve({ + callWasSuccessful: false, + error: { + error, + stderr, + }, + }); + } else { + resolve({ + callWasSuccessful: true, + response: stdout, + }); + } + }); + }), causesSideEffects: true, }); diff --git a/src/common/helm/add-helm-repository-channel.injectable.ts b/src/common/helm/add-helm-repository-channel.ts similarity index 50% rename from src/common/helm/add-helm-repository-channel.injectable.ts rename to src/common/helm/add-helm-repository-channel.ts index 0bc10564ad..44471fe426 100644 --- a/src/common/helm/add-helm-repository-channel.injectable.ts +++ b/src/common/helm/add-helm-repository-channel.ts @@ -2,22 +2,12 @@ * 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 type { HelmRepo } from "./helm-repo"; -import type { RequestChannel } from "../utils/channel/request-channel-injection-token"; -import { requestChannelInjectionToken } from "../utils/channel/request-channel-injection-token"; import type { AsyncResult } from "../utils/async-result"; +import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token"; export type AddHelmRepositoryChannel = RequestChannel>; -const addHelmRepositoryChannelInjectable = getInjectable({ +export const addHelmRepositoryChannel: AddHelmRepositoryChannel = { id: "add-helm-repository-channel", - - instantiate: (): AddHelmRepositoryChannel => ({ - id: "add-helm-repository-channel", - }), - - injectionToken: requestChannelInjectionToken, -}); - -export default addHelmRepositoryChannelInjectable; +}; diff --git a/src/common/helm/get-active-helm-repositories-channel.injectable.ts b/src/common/helm/get-active-helm-repositories-channel.injectable.ts deleted file mode 100644 index ac7355ace7..0000000000 --- a/src/common/helm/get-active-helm-repositories-channel.injectable.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * 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 type { RequestChannel } from "../utils/channel/request-channel-injection-token"; -import type { HelmRepo } from "./helm-repo"; -import { requestChannelInjectionToken } from "../utils/channel/request-channel-injection-token"; -import type { AsyncResult } from "../utils/async-result"; - -export type GetHelmRepositoriesChannel = RequestChannel>; - -const getActiveHelmRepositoriesChannelInjectable = getInjectable({ - id: "get-active-helm-repositories-channel", - - instantiate: (): GetHelmRepositoriesChannel => ({ - id: "get-helm-active-list-repositories", - }), - - injectionToken: requestChannelInjectionToken, -}); - -export default getActiveHelmRepositoriesChannelInjectable; diff --git a/src/common/helm/get-active-helm-repositories-channel.ts b/src/common/helm/get-active-helm-repositories-channel.ts new file mode 100644 index 0000000000..26720e9a5f --- /dev/null +++ b/src/common/helm/get-active-helm-repositories-channel.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 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 GetActiveHelmRepositoriesChannel = RequestChannel>; + +export const getActiveHelmRepositoriesChannel: GetActiveHelmRepositoriesChannel = { + id: "get-helm-active-list-repositories", +}; diff --git a/src/common/helm/remove-helm-repository-channel.injectable.ts b/src/common/helm/remove-helm-repository-channel.injectable.ts deleted file mode 100644 index eddecb1ccd..0000000000 --- a/src/common/helm/remove-helm-repository-channel.injectable.ts +++ /dev/null @@ -1,22 +0,0 @@ -/** - * 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 type { HelmRepo } from "./helm-repo"; -import type { RequestChannel } from "../utils/channel/request-channel-injection-token"; -import { requestChannelInjectionToken } from "../utils/channel/request-channel-injection-token"; - -export type RemoveHelmRepositoryChannel = RequestChannel; - -const removeHelmRepositoryChannelInjectable = getInjectable({ - id: "remove-helm-repository-channel", - - instantiate: (): RemoveHelmRepositoryChannel => ({ - id: "remove-helm-repository-channel", - }), - - injectionToken: requestChannelInjectionToken, -}); - -export default removeHelmRepositoryChannelInjectable; diff --git a/src/common/helm/remove-helm-repository-channel.ts b/src/common/helm/remove-helm-repository-channel.ts new file mode 100644 index 0000000000..7eda160159 --- /dev/null +++ b/src/common/helm/remove-helm-repository-channel.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 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>; + +export const removeHelmRepositoryChannel: RemoveHelmRepositoryChannel = { + id: "remove-helm-repository-channel", +}; diff --git a/src/common/root-frame-rendered-channel/root-frame-rendered-channel.injectable.ts b/src/common/root-frame-rendered-channel/root-frame-rendered-channel.injectable.ts deleted file mode 100644 index a7787c6cc4..0000000000 --- a/src/common/root-frame-rendered-channel/root-frame-rendered-channel.injectable.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * 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 type { MessageChannel } from "../utils/channel/message-channel-injection-token"; -import { messageChannelInjectionToken } from "../utils/channel/message-channel-injection-token"; - -export type RootFrameRenderedChannel = MessageChannel; - -const rootFrameRenderedChannelInjectable = getInjectable({ - id: "root-frame-rendered-channel", - - instantiate: (): RootFrameRenderedChannel => ({ - id: "root-frame-rendered", - }), - - injectionToken: messageChannelInjectionToken, -}); - -export default rootFrameRenderedChannelInjectable; diff --git a/src/common/root-frame/root-frame-rendered-channel.ts b/src/common/root-frame/root-frame-rendered-channel.ts new file mode 100644 index 0000000000..060ae8735c --- /dev/null +++ b/src/common/root-frame/root-frame-rendered-channel.ts @@ -0,0 +1,11 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token"; + +export type RootFrameHasRenderedChannel = MessageChannel; + +export const rootFrameHasRenderedChannel: RootFrameHasRenderedChannel = { + id: "root-frame-rendered", +}; diff --git a/src/common/utils/channel/channel.test.ts b/src/common/utils/channel/channel.test.ts index c5f52c0874..9a361b6770 100644 --- a/src/common/utils/channel/channel.test.ts +++ b/src/common/utils/channel/channel.test.ts @@ -4,31 +4,31 @@ */ import type { DiContainer } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable"; -import type { MessageToChannel } from "./message-to-channel-injection-token"; -import { messageToChannelInjectionToken } from "./message-to-channel-injection-token"; +import type { SendMessageToChannel } from "./message-to-channel-injection-token"; +import { sendMessageToChannelInjectionToken } from "./message-to-channel-injection-token"; import type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; import type { LensWindow } from "../../../main/start-main-application/lens-window/application-window/create-lens-window.injectable"; +import type { MessageChannel } from "./message-channel-listener-injection-token"; import { messageChannelListenerInjectionToken } from "./message-channel-listener-injection-token"; -import type { MessageChannel } from "./message-channel-injection-token"; import type { RequestFromChannel } from "./request-from-channel-injection-token"; import { requestFromChannelInjectionToken } from "./request-from-channel-injection-token"; -import type { RequestChannel } from "./request-channel-injection-token"; -import { requestChannelListenerInjectionToken } from "./request-channel-listener-injection-token"; +import type { RequestChannel } from "./request-channel-listener-injection-token"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; import { getPromiseStatus } from "../../test-utils/get-promise-status"; import { runInAction } from "mobx"; +import type { RequestChannelHandler } from "../../../main/utils/channel/channel-listeners/listener-tokens"; +import { getRequestChannelListenerInjectable } from "../../../main/utils/channel/channel-listeners/listener-tokens"; type TestMessageChannel = MessageChannel; type TestRequestChannel = RequestChannel; describe("channel", () => { describe("messaging from main to renderer, given listener for channel in a window and application has started", () => { - let testMessageChannel: TestMessageChannel; let messageListenerInWindowMock: jest.Mock; let mainDi: DiContainer; - let messageToChannel: MessageToChannel; + let messageToChannel: SendMessageToChannel; let builder: ApplicationBuilder; beforeEach(async () => { @@ -39,24 +39,17 @@ describe("channel", () => { const testChannelListenerInTestWindowInjectable = getInjectable({ id: "test-channel-listener-in-test-window", - instantiate: (di) => ({ - channel: di.inject(testMessageChannelInjectable), + instantiate: () => ({ + channel: testMessageChannel, handler: messageListenerInWindowMock, }), injectionToken: messageChannelListenerInjectionToken, }); - builder.beforeApplicationStart((mainDi) => { - runInAction(() => { - mainDi.register(testMessageChannelInjectable); - }); - }); - builder.beforeWindowStart((windowDi) => { runInAction(() => { windowDi.register(testChannelListenerInTestWindowInjectable); - windowDi.register(testMessageChannelInjectable); }); }); @@ -64,8 +57,7 @@ describe("channel", () => { await builder.startHidden(); - testMessageChannel = mainDi.inject(testMessageChannelInjectable); - messageToChannel = mainDi.inject(messageToChannelInjectionToken); + messageToChannel = mainDi.inject(sendMessageToChannelInjectionToken); }); describe("given window is started", () => { @@ -109,9 +101,8 @@ describe("channel", () => { }); describe("messaging from renderer to main, given listener for channel in a main and application has started", () => { - let testMessageChannel: TestMessageChannel; let messageListenerInMainMock: jest.Mock; - let messageToChannel: MessageToChannel; + let messageToChannel: SendMessageToChannel; beforeEach(async () => { const applicationBuilder = getApplicationBuilder(); @@ -121,9 +112,8 @@ describe("channel", () => { const testChannelListenerInMainInjectable = getInjectable({ id: "test-channel-listener-in-main", - instantiate: (di) => ({ - channel: di.inject(testMessageChannelInjectable), - + instantiate: () => ({ + channel: testMessageChannel, handler: messageListenerInMainMock, }), @@ -133,13 +123,6 @@ describe("channel", () => { applicationBuilder.beforeApplicationStart((mainDi) => { runInAction(() => { mainDi.register(testChannelListenerInMainInjectable); - mainDi.register(testMessageChannelInjectable); - }); - }); - - applicationBuilder.beforeWindowStart((windowDi) => { - runInAction(() => { - windowDi.register(testMessageChannelInjectable); }); }); @@ -147,8 +130,7 @@ describe("channel", () => { const windowDi = applicationBuilder.applicationWindow.only.di; - testMessageChannel = windowDi.inject(testMessageChannelInjectable); - messageToChannel = windowDi.inject(messageToChannelInjectionToken); + messageToChannel = windowDi.inject(sendMessageToChannelInjectionToken); }); it("when sending message, triggers listener in main", () => { @@ -159,8 +141,7 @@ describe("channel", () => { }); describe("requesting from main in renderer, given listener for channel in a main and application has started", () => { - let testRequestChannel: TestRequestChannel; - let requestListenerInMainMock: AsyncFnMock<(arg: string) => string>; + let requestListenerInMainMock: AsyncFnMock>; let requestFromChannel: RequestFromChannel; beforeEach(async () => { @@ -168,28 +149,14 @@ describe("channel", () => { requestListenerInMainMock = asyncFn(); - const testChannelListenerInMainInjectable = getInjectable({ - id: "test-channel-listener-in-main", - - instantiate: (di) => ({ - channel: di.inject(testRequestChannelInjectable), - - handler: requestListenerInMainMock, - }), - - injectionToken: requestChannelListenerInjectionToken, + const testChannelListenerInMainInjectable = getRequestChannelListenerInjectable({ + channel: testRequestChannel, + handler: () => requestListenerInMainMock, }); applicationBuilder.beforeApplicationStart((mainDi) => { runInAction(() => { mainDi.register(testChannelListenerInMainInjectable); - mainDi.register(testRequestChannelInjectable); - }); - }); - - applicationBuilder.beforeWindowStart((windowDi) => { - runInAction(() => { - windowDi.register(testRequestChannelInjectable); }); }); @@ -197,8 +164,6 @@ describe("channel", () => { const windowDi = applicationBuilder.applicationWindow.only.di; - testRequestChannel = windowDi.inject(testRequestChannelInjectable); - requestFromChannel = windowDi.inject( requestFromChannelInjectionToken, ); @@ -230,21 +195,37 @@ describe("channel", () => { }); }); }); + + it("when registering multiple handlers for the same channel, throws", async () => { + const applicationBuilder = getApplicationBuilder(); + + const testChannelListenerInMainInjectable = getRequestChannelListenerInjectable({ + channel: testRequestChannel, + handler: () => () => "some-value", + }); + const testChannelListenerInMain2Injectable = getRequestChannelListenerInjectable({ + channel: testRequestChannel, + handler: () => () => "some-other-value", + }); + + testChannelListenerInMain2Injectable.id += "2"; + + applicationBuilder.beforeApplicationStart((mainDi) => { + runInAction(() => { + mainDi.register(testChannelListenerInMainInjectable); + mainDi.register(testChannelListenerInMain2Injectable); + }); + }); + + await expect(applicationBuilder.render()).rejects.toThrow('Tried to register a multiple channel handlers for "some-request-channel-id", only one handler is supported for a request channel.'); + }); }); -const testMessageChannelInjectable = getInjectable({ - id: "some-message-test-channel", +const testMessageChannel: TestMessageChannel = { + id: "some-message-channel-id", +}; - instantiate: (): TestMessageChannel => ({ - id: "some-message-channel-id", - }), -}); - -const testRequestChannelInjectable = getInjectable({ - id: "some-request-test-channel", - - instantiate: (): TestRequestChannel => ({ - id: "some-request-channel-id", - }), -}); +const testRequestChannel: TestRequestChannel = { + id: "some-request-channel-id", +}; diff --git a/src/common/utils/channel/enlist-message-channel-listener-injection-token.ts b/src/common/utils/channel/enlist-message-channel-listener-injection-token.ts index fa6983e130..34f62d51d5 100644 --- a/src/common/utils/channel/enlist-message-channel-listener-injection-token.ts +++ b/src/common/utils/channel/enlist-message-channel-listener-injection-token.ts @@ -3,14 +3,11 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectionToken } from "@ogre-tools/injectable"; -import type { MessageChannel } from "./message-channel-injection-token"; -import type { MessageChannelListener } from "./message-channel-listener-injection-token"; +import type { Disposer } from "../disposer"; +import type { MessageChannel, MessageChannelListener } from "./message-channel-listener-injection-token"; -export type EnlistMessageChannelListener = < - TChannel extends MessageChannel, ->(listener: MessageChannelListener) => () => void; +export type EnlistMessageChannelListener = (listener: MessageChannelListener>) => Disposer; -export const enlistMessageChannelListenerInjectionToken = - getInjectionToken({ - id: "enlist-message-channel-listener", - }); +export const enlistMessageChannelListenerInjectionToken = getInjectionToken({ + id: "enlist-message-channel-listener", +}); diff --git a/src/common/utils/channel/enlist-request-channel-listener-injection-token.ts b/src/common/utils/channel/enlist-request-channel-listener-injection-token.ts deleted file mode 100644 index f87082c466..0000000000 --- a/src/common/utils/channel/enlist-request-channel-listener-injection-token.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectionToken } from "@ogre-tools/injectable"; -import type { RequestChannel } from "./request-channel-injection-token"; -import type { RequestChannelListener } from "./request-channel-listener-injection-token"; - -export type EnlistRequestChannelListener = < - TChannel extends RequestChannel, ->(listener: RequestChannelListener) => () => void; - -export const enlistRequestChannelListenerInjectionToken = - getInjectionToken({ - id: "enlist-request-channel-listener", - }); diff --git a/src/common/utils/channel/listening-of-channels.injectable.ts b/src/common/utils/channel/listening-of-channels.injectable.ts deleted file mode 100644 index 30fee42fb9..0000000000 --- a/src/common/utils/channel/listening-of-channels.injectable.ts +++ /dev/null @@ -1,32 +0,0 @@ -/** - * 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 { getStartableStoppable } from "../get-startable-stoppable"; -import { disposer } from "../index"; -import { messageChannelListenerInjectionToken } from "./message-channel-listener-injection-token"; -import { requestChannelListenerInjectionToken } from "./request-channel-listener-injection-token"; -import { enlistMessageChannelListenerInjectionToken } from "./enlist-message-channel-listener-injection-token"; -import { enlistRequestChannelListenerInjectionToken } from "./enlist-request-channel-listener-injection-token"; - -const listeningOfChannelsInjectable = getInjectable({ - id: "listening-of-channels", - - instantiate: (di) => { - const enlistMessageChannelListener = di.inject(enlistMessageChannelListenerInjectionToken); - const enlistRequestChannelListener = di.inject(enlistRequestChannelListenerInjectionToken); - const messageChannelListeners = di.injectMany(messageChannelListenerInjectionToken); - const requestChannelListeners = di.injectMany(requestChannelListenerInjectionToken); - - return getStartableStoppable("listening-of-channels", () => { - const messageChannelDisposers = messageChannelListeners.map(enlistMessageChannelListener); - const requestChannelDisposers = requestChannelListeners.map(enlistRequestChannelListener); - - return disposer(...messageChannelDisposers, ...requestChannelDisposers); - }); - }, -}); - - -export default listeningOfChannelsInjectable; diff --git a/src/common/utils/channel/listening-on-message-channels.injectable.ts b/src/common/utils/channel/listening-on-message-channels.injectable.ts new file mode 100644 index 0000000000..afe0c08f24 --- /dev/null +++ b/src/common/utils/channel/listening-on-message-channels.injectable.ts @@ -0,0 +1,25 @@ +/** + * 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 { getStartableStoppable } from "../get-startable-stoppable"; +import { disposer } from "../index"; +import { messageChannelListenerInjectionToken } from "./message-channel-listener-injection-token"; +import { enlistMessageChannelListenerInjectionToken } from "./enlist-message-channel-listener-injection-token"; + +const listeningOnMessageChannelsInjectable = getInjectable({ + id: "listening-on-message-channels", + + instantiate: (di) => { + const enlistMessageChannelListener = di.inject(enlistMessageChannelListenerInjectionToken); + const messageChannelListeners = di.injectMany(messageChannelListenerInjectionToken); + + return getStartableStoppable("listening-on-channels", () => ( + disposer(messageChannelListeners.map(enlistMessageChannelListener)) + )); + }, +}); + + +export default listeningOnMessageChannelsInjectable; diff --git a/src/common/utils/channel/message-channel-injection-token.ts b/src/common/utils/channel/message-channel-injection-token.ts deleted file mode 100644 index 3141acedf3..0000000000 --- a/src/common/utils/channel/message-channel-injection-token.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import { getInjectionToken } from "@ogre-tools/injectable"; -import type { JsonValue } from "type-fest"; - -export interface MessageChannel { - id: string; - _messageSignature?: Message; -} - -export const messageChannelInjectionToken = getInjectionToken>({ - id: "message-channel", -}); diff --git a/src/common/utils/channel/message-channel-listener-injection-token.ts b/src/common/utils/channel/message-channel-listener-injection-token.ts index 8879e19013..5bfc45a82d 100644 --- a/src/common/utils/channel/message-channel-listener-injection-token.ts +++ b/src/common/utils/channel/message-channel-listener-injection-token.ts @@ -2,17 +2,50 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getInjectionToken } from "@ogre-tools/injectable"; -import type { SetRequired } from "type-fest"; -import type { MessageChannel } from "./message-channel-injection-token"; +import type { DiContainerForInjection } from "@ogre-tools/injectable"; +import { getInjectable, getInjectionToken } from "@ogre-tools/injectable"; -export interface MessageChannelListener> { - channel: TChannel; - handler: (value: SetRequired["_messageSignature"]) => void; +export interface MessageChannel { + id: string; + _messageSignature?: Message; // only used to mark `Message` as used } -export const messageChannelListenerInjectionToken = getInjectionToken>>( +export type MessageChannelHandler = Channel extends MessageChannel + ? (message: Message) => void + : never; + +export interface MessageChannelListener { + channel: Channel; + handler: MessageChannelHandler; +} + +export const messageChannelListenerInjectionToken = getInjectionToken>>( { id: "message-channel-listener", }, ); + +export interface GetMessageChannelListenerInfo< + Channel extends MessageChannel, + Message, +> { + id: string; + channel: Channel; + handler: (di: DiContainerForInjection) => MessageChannelHandler; + causesSideEffects?: boolean; +} + +export function getMessageChannelListenerInjectable< + Channel extends MessageChannel, + Message, +>(info: GetMessageChannelListenerInfo) { + return getInjectable({ + id: `${info.channel.id}-listener-${info.id}`, + instantiate: (di) => ({ + channel: info.channel, + handler: info.handler(di), + }), + injectionToken: messageChannelListenerInjectionToken, + causesSideEffects: info.causesSideEffects, + }); +} diff --git a/src/common/utils/channel/message-to-channel-injection-token.ts b/src/common/utils/channel/message-to-channel-injection-token.ts index 8c5f03b9ee..d179ab9870 100644 --- a/src/common/utils/channel/message-to-channel-injection-token.ts +++ b/src/common/utils/channel/message-to-channel-injection-token.ts @@ -3,21 +3,13 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectionToken } from "@ogre-tools/injectable"; -import type { SetRequired } from "type-fest"; -import type { MessageChannel } from "./message-channel-injection-token"; +import type { MessageChannel } from "./message-channel-listener-injection-token"; -export interface MessageToChannel { - , TMessage extends void>( - channel: TChannel, - ): void; - - >( - channel: TChannel, - message: SetRequired["_messageSignature"], - ): void; +export interface SendMessageToChannel { + (channel: MessageChannel): void; + (channel: MessageChannel, message: Message): void; } -export const messageToChannelInjectionToken = - getInjectionToken({ - id: "message-to-message-channel", - }); +export const sendMessageToChannelInjectionToken = getInjectionToken({ + id: "send-message-to-message-channel", +}); diff --git a/src/common/utils/channel/request-channel-injection-token.ts b/src/common/utils/channel/request-channel-injection-token.ts deleted file mode 100644 index 67044db878..0000000000 --- a/src/common/utils/channel/request-channel-injection-token.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import { getInjectionToken } from "@ogre-tools/injectable"; -import type { JsonValue } from "type-fest"; - -export interface RequestChannel< - Request extends JsonValue | void = void, - Response extends JsonValue | void = void, -> { - id: string; - _requestSignature?: Request; - _responseSignature?: Response; -} - -export const requestChannelInjectionToken = getInjectionToken>({ - id: "request-channel", -}); diff --git a/src/common/utils/channel/request-channel-listener-injection-token.ts b/src/common/utils/channel/request-channel-listener-injection-token.ts index 690b96d9dc..2f0b84a3cc 100644 --- a/src/common/utils/channel/request-channel-listener-injection-token.ts +++ b/src/common/utils/channel/request-channel-listener-injection-token.ts @@ -2,24 +2,9 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getInjectionToken } from "@ogre-tools/injectable"; -import type { SetRequired } from "type-fest"; -import type { RequestChannel } from "./request-channel-injection-token"; -export interface RequestChannelListener> { - channel: TChannel; - - handler: ( - request: SetRequired["_requestSignature"] - ) => - | SetRequired["_responseSignature"] - | Promise< - SetRequired["_responseSignature"] - >; +export interface RequestChannel { + id: string; + _requestSignature?: Request; // used only to mark `Request` as "used" + _responseSignature?: Response; // used only to mark `Response` as "used" } - -export const requestChannelListenerInjectionToken = getInjectionToken>>( - { - id: "request-channel-listener", - }, -); diff --git a/src/common/utils/channel/request-from-channel-injection-token.ts b/src/common/utils/channel/request-from-channel-injection-token.ts index f4d4fdbe0c..14e925f190 100644 --- a/src/common/utils/channel/request-from-channel-injection-token.ts +++ b/src/common/utils/channel/request-from-channel-injection-token.ts @@ -3,19 +3,13 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectionToken } from "@ogre-tools/injectable"; -import type { SetRequired } from "type-fest"; -import type { RequestChannel } from "./request-channel-injection-token"; +import type { RequestChannel } from "./request-channel-listener-injection-token"; -export type RequestFromChannel = < - TChannel extends RequestChannel, ->( - channel: TChannel, - ...request: TChannel["_requestSignature"] extends void - ? [] - : [SetRequired["_requestSignature"]] -) => Promise["_responseSignature"]>; +export interface RequestFromChannel { + (channel: RequestChannel, request: Request): Promise; + (channel: RequestChannel): Promise; +} -export const requestFromChannelInjectionToken = - getInjectionToken({ - id: "request-from-request-channel", - }); +export const requestFromChannelInjectionToken = getInjectionToken({ + id: "request-from-request-channel", +}); diff --git a/src/common/utils/disposer.ts b/src/common/utils/disposer.ts index 05a349ab4d..2949a7ae35 100644 --- a/src/common/utils/disposer.ts +++ b/src/common/utils/disposer.ts @@ -3,6 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ +import type { SingleOrMany } from "./types"; + export interface Disposer { @@ -17,9 +19,9 @@ export interface ExtendableDisposer extends Disposer { push(...vals: (Disposer | ExtendableDisposer | Disposable)[]): void; } -export function disposer(...items: (Disposer | Disposable | undefined | null)[]): ExtendableDisposer { +export function disposer(...items: SingleOrMany[]): ExtendableDisposer { return Object.assign(() => { - for (const item of items) { + for (const item of items.flat()) { if (!item) { continue; } diff --git a/src/common/utils/resolve-system-proxy/resolve-system-proxy-channel.injectable.ts b/src/common/utils/resolve-system-proxy/resolve-system-proxy-channel.injectable.ts deleted file mode 100644 index 5dd17ddc6a..0000000000 --- a/src/common/utils/resolve-system-proxy/resolve-system-proxy-channel.injectable.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * 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 type { RequestChannel } from "../channel/request-channel-injection-token"; -import { requestChannelInjectionToken } from "../channel/request-channel-injection-token"; - -export type ResolveSystemProxyChannel = RequestChannel; - -const resolveSystemProxyChannelInjectable = getInjectable({ - id: "resolve-system-proxy-channel", - - instantiate: (): ResolveSystemProxyChannel => ({ - id: "resolve-system-proxy-channel", - }), - - injectionToken: requestChannelInjectionToken, -}); - -export default resolveSystemProxyChannelInjectable; diff --git a/src/common/utils/resolve-system-proxy/resolve-system-proxy-channel.ts b/src/common/utils/resolve-system-proxy/resolve-system-proxy-channel.ts new file mode 100644 index 0000000000..c823a8a8f9 --- /dev/null +++ b/src/common/utils/resolve-system-proxy/resolve-system-proxy-channel.ts @@ -0,0 +1,11 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { RequestChannel } from "../channel/request-channel-listener-injection-token"; + +export type ResolveSystemProxyChannel = RequestChannel; + +export const resolveSystemProxyChannel: ResolveSystemProxyChannel = { + id: "resolve-system-proxy-channel", +}; diff --git a/src/common/utils/sync-box/channel-listener.injectable.ts b/src/common/utils/sync-box/channel-listener.injectable.ts new file mode 100644 index 0000000000..a97d95d726 --- /dev/null +++ b/src/common/utils/sync-box/channel-listener.injectable.ts @@ -0,0 +1,15 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { syncBoxChannel } from "./channels"; +import { getMessageChannelListenerInjectable } from "../channel/message-channel-listener-injection-token"; +import syncBoxStateInjectable from "./sync-box-state.injectable"; + +const syncBoxChannelListenerInjectable = getMessageChannelListenerInjectable({ + id: "init", + channel: syncBoxChannel, + handler: (di) => ({ id, value }) => di.inject(syncBoxStateInjectable, id).set(value), +}); + +export default syncBoxChannelListenerInjectable; diff --git a/src/common/utils/sync-box/channels.ts b/src/common/utils/sync-box/channels.ts new file mode 100644 index 0000000000..4df0462dc3 --- /dev/null +++ b/src/common/utils/sync-box/channels.ts @@ -0,0 +1,21 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { MessageChannel } from "../channel/message-channel-listener-injection-token"; +import type { RequestChannel } from "../channel/request-channel-listener-injection-token"; + +export type SyncBoxChannel = MessageChannel<{ id: string; value: any }>; + +export const syncBoxChannel: SyncBoxChannel = { + id: "sync-box-channel", +}; + +export type SyncBoxInitialValueChannel = RequestChannel< + void, + { id: string; value: any }[] +>; + +export const syncBoxInitialValueChannel: SyncBoxInitialValueChannel = { + id: "sync-box-initial-value-channel", +}; diff --git a/src/common/utils/sync-box/create-sync-box.injectable.ts b/src/common/utils/sync-box/create-sync-box.injectable.ts index 1328106e24..4a01fe71a0 100644 --- a/src/common/utils/sync-box/create-sync-box.injectable.ts +++ b/src/common/utils/sync-box/create-sync-box.injectable.ts @@ -5,17 +5,17 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { IObservableValue } from "mobx"; import { computed } from "mobx"; -import syncBoxChannelInjectable from "./sync-box-channel.injectable"; -import { messageToChannelInjectionToken } from "../channel/message-to-channel-injection-token"; +import { syncBoxChannel } from "./channels"; +import { sendMessageToChannelInjectionToken } from "../channel/message-to-channel-injection-token"; import syncBoxStateInjectable from "./sync-box-state.injectable"; import type { SyncBox } from "./sync-box-injection-token"; +import { toJS } from "../toJS"; const createSyncBoxInjectable = getInjectable({ id: "create-sync-box", instantiate: (di) => { - const syncBoxChannel = di.inject(syncBoxChannelInjectable); - const messageToChannel = di.inject(messageToChannelInjectionToken); + const messageToChannel = di.inject(sendMessageToChannelInjectionToken); const getSyncBoxState = (id: string) => di.inject(syncBoxStateInjectable, id); return (id: string, initialValue: Value): SyncBox => { @@ -26,7 +26,7 @@ const createSyncBoxInjectable = getInjectable({ return { id, - value: computed(() => state.get()), + value: computed(() => toJS(state.get())), set: (value) => { state.set(value); diff --git a/src/common/utils/sync-box/handler.injectable.ts b/src/common/utils/sync-box/handler.injectable.ts new file mode 100644 index 0000000000..f520585474 --- /dev/null +++ b/src/common/utils/sync-box/handler.injectable.ts @@ -0,0 +1,19 @@ +/** + * 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 type { MessageChannelHandler } from "../channel/message-channel-listener-injection-token"; +import type { SyncBoxChannel } from "./channels"; +import syncBoxStateInjectable from "./sync-box-state.injectable"; + +const syncBoxChannelHandlerInjectable = getInjectable({ + id: "sync-box-channel-handler", + instantiate: (di): MessageChannelHandler => { + const getSyncBoxState = (id: string) => di.inject(syncBoxStateInjectable, id); + + return ({ id, value }) => getSyncBoxState(id)?.set(value); + }, +}); + +export default syncBoxChannelHandlerInjectable; diff --git a/src/common/utils/sync-box/sync-box-channel-listener.injectable.ts b/src/common/utils/sync-box/sync-box-channel-listener.injectable.ts deleted file mode 100644 index b603c85997..0000000000 --- a/src/common/utils/sync-box/sync-box-channel-listener.injectable.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** - * 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 type { SyncBoxChannel } from "./sync-box-channel.injectable"; -import syncBoxChannelInjectable from "./sync-box-channel.injectable"; -import syncBoxStateInjectable from "./sync-box-state.injectable"; -import type { MessageChannelListener } from "../channel/message-channel-listener-injection-token"; -import { messageChannelListenerInjectionToken } from "../channel/message-channel-listener-injection-token"; - -const syncBoxChannelListenerInjectable = getInjectable({ - id: "sync-box-channel-listener", - - instantiate: (di): MessageChannelListener => { - const getSyncBoxState = (id: string) => di.inject(syncBoxStateInjectable, id); - const channel = di.inject(syncBoxChannelInjectable); - - return { - channel, - - handler: ({ id, value }) => { - const target = getSyncBoxState(id); - - if (target) { - target.set(value); - } - }, - }; - }, - - injectionToken: messageChannelListenerInjectionToken, -}); - -export default syncBoxChannelListenerInjectable; diff --git a/src/common/utils/sync-box/sync-box-channel.injectable.ts b/src/common/utils/sync-box/sync-box-channel.injectable.ts deleted file mode 100644 index 9389a99867..0000000000 --- a/src/common/utils/sync-box/sync-box-channel.injectable.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * 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 type { MessageChannel } from "../channel/message-channel-injection-token"; -import { messageChannelInjectionToken } from "../channel/message-channel-injection-token"; - -export type SyncBoxChannel = MessageChannel<{ id: string; value: any }>; - -const syncBoxChannelInjectable = getInjectable({ - id: "sync-box-channel", - - instantiate: (): SyncBoxChannel => ({ - id: "sync-box-channel", - }), - - injectionToken: messageChannelInjectionToken, -}); - -export default syncBoxChannelInjectable; diff --git a/src/common/utils/sync-box/sync-box-initial-value-channel.injectable.ts b/src/common/utils/sync-box/sync-box-initial-value-channel.injectable.ts deleted file mode 100644 index 89374c3565..0000000000 --- a/src/common/utils/sync-box/sync-box-initial-value-channel.injectable.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * 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 type { RequestChannel } from "../channel/request-channel-injection-token"; -import { requestChannelInjectionToken } from "../channel/request-channel-injection-token"; - -export type SyncBoxInitialValueChannel = RequestChannel< - void, - { id: string; value: any }[] ->; - -const syncBoxInitialValueChannelInjectable = getInjectable({ - id: "sync-box-initial-value-channel", - - instantiate: (): SyncBoxInitialValueChannel => ({ - id: "sync-box-initial-value-channel", - }), - - injectionToken: requestChannelInjectionToken, -}); - -export default syncBoxInitialValueChannelInjectable; diff --git a/src/common/utils/tentative-parse-json.ts b/src/common/utils/tentative-parse-json.ts deleted file mode 100644 index a0cb089a74..0000000000 --- a/src/common/utils/tentative-parse-json.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { pipeline } from "@ogre-tools/fp"; -import { defaultTo } from "lodash/fp"; -import { withErrorSuppression } from "./with-error-suppression/with-error-suppression"; - -export const tentativeParseJson = (toBeParsed: any) => pipeline( - toBeParsed, - withErrorSuppression(JSON.parse), - defaultTo(toBeParsed), -); - - diff --git a/src/common/utils/tentative-stringify-json.ts b/src/common/utils/tentative-stringify-json.ts deleted file mode 100644 index dc7206be7c..0000000000 --- a/src/common/utils/tentative-stringify-json.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { pipeline } from "@ogre-tools/fp"; -import { defaultTo } from "lodash/fp"; -import { withErrorSuppression } from "./with-error-suppression/with-error-suppression"; - -export const tentativeStringifyJson = (toBeParsed: any) => pipeline( - toBeParsed, - withErrorSuppression(JSON.stringify), - defaultTo(toBeParsed), -); - - diff --git a/src/common/vars/build-semantic-version.injectable.ts b/src/common/vars/build-semantic-version.injectable.ts index a41efb0bd7..2a49327480 100644 --- a/src/common/vars/build-semantic-version.injectable.ts +++ b/src/common/vars/build-semantic-version.injectable.ts @@ -7,7 +7,7 @@ import { getInjectionToken } from "@ogre-tools/injectable"; import { SemVer } from "semver"; import type { InitializableState } from "../initializable-state/create"; import { createInitializableState } from "../initializable-state/create"; -import type { RequestChannel } from "../utils/channel/request-channel-injection-token"; +import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token"; export const buildVersionInjectionToken = getInjectionToken>({ id: "build-version-token", diff --git a/src/features/application-update/selection-of-update-stability.test.ts b/src/features/application-update/selection-of-update-stability.test.ts index d948573dcd..bfa6f0680d 100644 --- a/src/features/application-update/selection-of-update-stability.test.ts +++ b/src/features/application-update/selection-of-update-stability.test.ts @@ -222,7 +222,7 @@ describe("selection of update stability", () => { it('given user changes update channel to "alpha", when user would close the application, installs the update for being stable enough', () => { selectedUpdateChannel.setValue(updateChannels.alpha.id); - expect(setUpdateOnQuitMock).toHaveBeenLastCalledWith(false); + expect(setUpdateOnQuitMock).toHaveBeenLastCalledWith(true); }); }); }); diff --git a/src/features/cluster/delete-dialog/common/clear-as-deleting-channel.injectable.ts b/src/features/cluster/delete-dialog/common/clear-as-deleting-channel.injectable.ts deleted file mode 100644 index d45fecb3c2..0000000000 --- a/src/features/cluster/delete-dialog/common/clear-as-deleting-channel.injectable.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * 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 type { ClusterId } from "../../../../common/cluster-types"; -import type { RequestChannel } from "../../../../common/utils/channel/request-channel-injection-token"; -import { requestChannelInjectionToken } from "../../../../common/utils/channel/request-channel-injection-token"; - -export type ClearClusterAsDeletingChannel = RequestChannel; - -const clearClusterAsDeletingChannelInjectable = getInjectable({ - id: "clear-cluster-as-deleting-channel", - instantiate: (): ClearClusterAsDeletingChannel => ({ - id: "clear-cluster-as-deleting", - }), - injectionToken: requestChannelInjectionToken, -}); - -export default clearClusterAsDeletingChannelInjectable; diff --git a/src/features/cluster/delete-dialog/common/clear-as-deleting-channel.ts b/src/features/cluster/delete-dialog/common/clear-as-deleting-channel.ts new file mode 100644 index 0000000000..bf33a23165 --- /dev/null +++ b/src/features/cluster/delete-dialog/common/clear-as-deleting-channel.ts @@ -0,0 +1,12 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { ClusterId } from "../../../../common/cluster-types"; +import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; + +export type ClearClusterAsDeletingChannel = RequestChannel; + +export const clearClusterAsDeletingChannel: ClearClusterAsDeletingChannel = { + id: "clear-cluster-as-deleting", +}; diff --git a/src/features/cluster/delete-dialog/common/delete-channel.injectable.ts b/src/features/cluster/delete-dialog/common/delete-channel.injectable.ts deleted file mode 100644 index 9242b062c5..0000000000 --- a/src/features/cluster/delete-dialog/common/delete-channel.injectable.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * 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 type { ClusterId } from "../../../../common/cluster-types"; -import type { RequestChannel } from "../../../../common/utils/channel/request-channel-injection-token"; -import { requestChannelInjectionToken } from "../../../../common/utils/channel/request-channel-injection-token"; - -export type DeleteClusterChannel = RequestChannel; - -const deleteClusterChannelInjectable = getInjectable({ - id: "delete-cluster-channel", - instantiate: (): DeleteClusterChannel => ({ - id: "delete-cluster", - }), - injectionToken: requestChannelInjectionToken, -}); - -export default deleteClusterChannelInjectable; diff --git a/src/features/cluster/delete-dialog/common/delete-channel.ts b/src/features/cluster/delete-dialog/common/delete-channel.ts new file mode 100644 index 0000000000..0e9142fcd3 --- /dev/null +++ b/src/features/cluster/delete-dialog/common/delete-channel.ts @@ -0,0 +1,12 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { ClusterId } from "../../../../common/cluster-types"; +import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; + +export type DeleteClusterChannel = RequestChannel; + +export const deleteClusterChannel: DeleteClusterChannel = { + id: "delete-cluster", +}; diff --git a/src/features/cluster/delete-dialog/common/set-as-deleting-channel.injectable.ts b/src/features/cluster/delete-dialog/common/set-as-deleting-channel.injectable.ts deleted file mode 100644 index b625dfa14e..0000000000 --- a/src/features/cluster/delete-dialog/common/set-as-deleting-channel.injectable.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * 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 type { ClusterId } from "../../../../common/cluster-types"; -import type { RequestChannel } from "../../../../common/utils/channel/request-channel-injection-token"; -import { requestChannelInjectionToken } from "../../../../common/utils/channel/request-channel-injection-token"; - -export type SetClusterAsDeletingChannel = RequestChannel; - -const setClusterAsDeletingChannelInjectable = getInjectable({ - id: "set-cluster-as-deleting-channel", - instantiate: (): SetClusterAsDeletingChannel => ({ - id: "set-cluster-as-deleting", - }), - injectionToken: requestChannelInjectionToken, -}); - -export default setClusterAsDeletingChannelInjectable; diff --git a/src/features/cluster/delete-dialog/common/set-as-deleting-channel.ts b/src/features/cluster/delete-dialog/common/set-as-deleting-channel.ts new file mode 100644 index 0000000000..57ef2e3a8d --- /dev/null +++ b/src/features/cluster/delete-dialog/common/set-as-deleting-channel.ts @@ -0,0 +1,12 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { ClusterId } from "../../../../common/cluster-types"; +import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; + +export type SetClusterAsDeletingChannel = RequestChannel; + +export const setClusterAsDeletingChannel: SetClusterAsDeletingChannel = { + id: "set-cluster-as-deleting", +}; diff --git a/src/features/cluster/delete-dialog/main/clear-as-deleteing-channel-handler.injectable.ts b/src/features/cluster/delete-dialog/main/clear-as-deleteing-channel-handler.injectable.ts deleted file mode 100644 index f1b89573d8..0000000000 --- a/src/features/cluster/delete-dialog/main/clear-as-deleteing-channel-handler.injectable.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * 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 { requestChannelListenerInjectionToken } from "../../../../common/utils/channel/request-channel-listener-injection-token"; -import clustersThatAreBeingDeletedInjectable from "../../../../main/cluster/are-being-deleted.injectable"; -import clearClusterAsDeletingChannelInjectable from "../common/clear-as-deleting-channel.injectable"; - -const clearClusterAsDeletingChannelHandlerInjectable = getInjectable({ - id: "clear-cluster-as-deleting-channel-handler", - instantiate: (di) => { - const clustersThatAreBeingDeleted = di.inject(clustersThatAreBeingDeletedInjectable); - - return { - channel: di.inject(clearClusterAsDeletingChannelInjectable), - handler: (clusterId) => clustersThatAreBeingDeleted.delete(clusterId), - }; - }, - injectionToken: requestChannelListenerInjectionToken, -}); - -export default clearClusterAsDeletingChannelHandlerInjectable; diff --git a/src/features/cluster/delete-dialog/main/clear-as-deleting-channel-listener.injectable.ts b/src/features/cluster/delete-dialog/main/clear-as-deleting-channel-listener.injectable.ts new file mode 100644 index 0000000000..a8dd2a80b0 --- /dev/null +++ b/src/features/cluster/delete-dialog/main/clear-as-deleting-channel-listener.injectable.ts @@ -0,0 +1,20 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import clustersThatAreBeingDeletedInjectable from "../../../../main/cluster/are-being-deleted.injectable"; +import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens"; +import { clearClusterAsDeletingChannel } from "../common/clear-as-deleting-channel"; + +const clearClusterAsDeletingChannelListenerInjectable = getRequestChannelListenerInjectable({ + channel: clearClusterAsDeletingChannel, + handler: (di) => { + const clustersThatAreBeingDeleted = di.inject(clustersThatAreBeingDeletedInjectable); + + return (clusterId) => { + clustersThatAreBeingDeleted.delete(clusterId); + }; + }, +}); + +export default clearClusterAsDeletingChannelListenerInjectable; diff --git a/src/features/cluster/delete-dialog/main/delete-channel-handler.injectable.ts b/src/features/cluster/delete-dialog/main/delete-channel-handler.injectable.ts deleted file mode 100644 index 8945ffe625..0000000000 --- a/src/features/cluster/delete-dialog/main/delete-channel-handler.injectable.ts +++ /dev/null @@ -1,56 +0,0 @@ -/** - * 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 appEventBusInjectable from "../../../../common/app-event-bus/app-event-bus.injectable"; -import clusterFramesInjectable from "../../../../common/cluster-frames.injectable"; -import clusterStoreInjectable from "../../../../common/cluster-store/cluster-store.injectable"; -import directoryForLensLocalStorageInjectable from "../../../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable"; -import deleteFileInjectable from "../../../../common/fs/delete-file.injectable"; -import joinPathsInjectable from "../../../../common/path/join-paths.injectable"; -import { requestChannelListenerInjectionToken } from "../../../../common/utils/channel/request-channel-listener-injection-token"; -import deleteClusterChannelInjectable from "../common/delete-channel.injectable"; - -const deleteClusterChannelHandlerInjectable = getInjectable({ - id: "delete-cluster-channel-handler", - instantiate: (di) => { - const appEventBus = di.inject(appEventBusInjectable); - const clusterStore = di.inject(clusterStoreInjectable); - const clusterFrames = di.inject(clusterFramesInjectable); - const joinPaths = di.inject(joinPathsInjectable); - const directoryForLensLocalStorage = di.inject(directoryForLensLocalStorageInjectable); - const deleteFile = di.inject(deleteFileInjectable); - - return { - channel: di.inject(deleteClusterChannelInjectable), - handler: async (clusterId) =>{ - appEventBus.emit({ name: "cluster", action: "remove" }); - - const cluster = clusterStore.getById(clusterId); - - if (!cluster) { - return; - } - - cluster.disconnect(); - clusterFrames.delete(cluster.id); - - // Remove from the cluster store as well, this should clear any old settings - clusterStore.clusters.delete(cluster.id); - - try { - // remove the local storage file - const localStorageFilePath = joinPaths(directoryForLensLocalStorage, `${cluster.id}.json`); - - await deleteFile(localStorageFilePath); - } catch { - // ignore error - } - }, - }; - }, - injectionToken: requestChannelListenerInjectionToken, -}); - -export default deleteClusterChannelHandlerInjectable; diff --git a/src/features/cluster/delete-dialog/main/delete-channel-listener.injectable.ts b/src/features/cluster/delete-dialog/main/delete-channel-listener.injectable.ts new file mode 100644 index 0000000000..9b7617293a --- /dev/null +++ b/src/features/cluster/delete-dialog/main/delete-channel-listener.injectable.ts @@ -0,0 +1,51 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import appEventBusInjectable from "../../../../common/app-event-bus/app-event-bus.injectable"; +import clusterFramesInjectable from "../../../../common/cluster-frames.injectable"; +import clusterStoreInjectable from "../../../../common/cluster-store/cluster-store.injectable"; +import directoryForLensLocalStorageInjectable from "../../../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable"; +import deleteFileInjectable from "../../../../common/fs/delete-file.injectable"; +import joinPathsInjectable from "../../../../common/path/join-paths.injectable"; +import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens"; +import { deleteClusterChannel } from "../common/delete-channel"; + +const deleteClusterChannelListenerInjectable = getRequestChannelListenerInjectable({ + channel: deleteClusterChannel, + handler: (di) => { + const appEventBus = di.inject(appEventBusInjectable); + const clusterStore = di.inject(clusterStoreInjectable); + const clusterFrames = di.inject(clusterFramesInjectable); + const joinPaths = di.inject(joinPathsInjectable); + const directoryForLensLocalStorage = di.inject(directoryForLensLocalStorageInjectable); + const deleteFile = di.inject(deleteFileInjectable); + + return async (clusterId) => { + appEventBus.emit({ name: "cluster", action: "remove" }); + + const cluster = clusterStore.getById(clusterId); + + if (!cluster) { + return; + } + + cluster.disconnect(); + clusterFrames.delete(cluster.id); + + // Remove from the cluster store as well, this should clear any old settings + clusterStore.clusters.delete(cluster.id); + + try { + // remove the local storage file + const localStorageFilePath = joinPaths(directoryForLensLocalStorage, `${cluster.id}.json`); + + await deleteFile(localStorageFilePath); + } catch { + // ignore error + } + }; + }, +}); + +export default deleteClusterChannelListenerInjectable; diff --git a/src/features/cluster/delete-dialog/main/set-as-deleteing-channel-handler.injectable.ts b/src/features/cluster/delete-dialog/main/set-as-deleteing-channel-handler.injectable.ts deleted file mode 100644 index 0b8862e384..0000000000 --- a/src/features/cluster/delete-dialog/main/set-as-deleteing-channel-handler.injectable.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * 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 { requestChannelListenerInjectionToken } from "../../../../common/utils/channel/request-channel-listener-injection-token"; -import clustersThatAreBeingDeletedInjectable from "../../../../main/cluster/are-being-deleted.injectable"; -import setClusterAsDeletingChannelInjectable from "../common/set-as-deleting-channel.injectable"; - -const setClusterAsDeletingChannelHandlerInjectable = getInjectable({ - id: "set-cluster-as-deleting-channel-handler", - instantiate: (di) => { - const clustersThatAreBeingDeleted = di.inject(clustersThatAreBeingDeletedInjectable); - - return { - channel: di.inject(setClusterAsDeletingChannelInjectable), - handler: (clusterId) => clustersThatAreBeingDeleted.add(clusterId), - }; - }, - injectionToken: requestChannelListenerInjectionToken, -}); - -export default setClusterAsDeletingChannelHandlerInjectable; diff --git a/src/features/cluster/delete-dialog/main/set-as-deleteing-channel-listener.injectable.ts b/src/features/cluster/delete-dialog/main/set-as-deleteing-channel-listener.injectable.ts new file mode 100644 index 0000000000..f532b4a81f --- /dev/null +++ b/src/features/cluster/delete-dialog/main/set-as-deleteing-channel-listener.injectable.ts @@ -0,0 +1,20 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import clustersThatAreBeingDeletedInjectable from "../../../../main/cluster/are-being-deleted.injectable"; +import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens"; +import { setClusterAsDeletingChannel } from "../common/set-as-deleting-channel"; + +const setClusterAsDeletingChannelHandlerInjectable = getRequestChannelListenerInjectable({ + channel: setClusterAsDeletingChannel, + handler: (di) => { + const clustersThatAreBeingDeleted = di.inject(clustersThatAreBeingDeletedInjectable); + + return (clusterId) => { + clustersThatAreBeingDeleted.add(clusterId); + }; + }, +}); + +export default setClusterAsDeletingChannelHandlerInjectable; diff --git a/src/features/cluster/delete-dialog/renderer/request-clear-as-deleting.injectable.ts b/src/features/cluster/delete-dialog/renderer/request-clear-as-deleting.injectable.ts index b480630f6c..e476998ca0 100644 --- a/src/features/cluster/delete-dialog/renderer/request-clear-as-deleting.injectable.ts +++ b/src/features/cluster/delete-dialog/renderer/request-clear-as-deleting.injectable.ts @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { ClusterId } from "../../../../common/cluster-types"; import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable"; -import clearClusterAsDeletingChannelInjectable from "../common/clear-as-deleting-channel.injectable"; +import { clearClusterAsDeletingChannel } from "../common/clear-as-deleting-channel"; export type RequestClearClusterAsDeleting = (clusterId: ClusterId) => Promise; @@ -13,7 +13,6 @@ const requestClearClusterAsDeletingInjectable = getInjectable({ id: "request-clear-cluster-as-deleting", instantiate: (di): RequestClearClusterAsDeleting => { const requestChannel = di.inject(requestFromChannelInjectable); - const clearClusterAsDeletingChannel = di.inject(clearClusterAsDeletingChannelInjectable); return (clusterId) => requestChannel(clearClusterAsDeletingChannel, clusterId); }, diff --git a/src/features/cluster/delete-dialog/renderer/request-delete.injectable.ts b/src/features/cluster/delete-dialog/renderer/request-delete.injectable.ts index 602923e60e..c1286e3103 100644 --- a/src/features/cluster/delete-dialog/renderer/request-delete.injectable.ts +++ b/src/features/cluster/delete-dialog/renderer/request-delete.injectable.ts @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { ClusterId } from "../../../../common/cluster-types"; import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable"; -import deleteClusterChannelInjectable from "../common/delete-channel.injectable"; +import { deleteClusterChannel } from "../common/delete-channel"; export type RequestDeleteCluster = (clusterId: ClusterId) => Promise; @@ -13,7 +13,6 @@ const requestDeleteClusterInjectable = getInjectable({ id: "request-delete-cluster", instantiate: (di): RequestDeleteCluster => { const requestChannel = di.inject(requestFromChannelInjectable); - const deleteClusterChannel = di.inject(deleteClusterChannelInjectable); return (clusterId) => requestChannel(deleteClusterChannel, clusterId); }, diff --git a/src/features/cluster/delete-dialog/renderer/request-set-as-deleting.injectable.ts b/src/features/cluster/delete-dialog/renderer/request-set-as-deleting.injectable.ts index 997348d44d..de3a6393b3 100644 --- a/src/features/cluster/delete-dialog/renderer/request-set-as-deleting.injectable.ts +++ b/src/features/cluster/delete-dialog/renderer/request-set-as-deleting.injectable.ts @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { ClusterId } from "../../../../common/cluster-types"; import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable"; -import setClusterAsDeletingChannelInjectable from "../common/set-as-deleting-channel.injectable"; +import { setClusterAsDeletingChannel } from "../common/set-as-deleting-channel"; export type RequestSetClusterAsDeleting = (clusterId: ClusterId) => Promise; @@ -13,7 +13,6 @@ const requestSetClusterAsDeletingInjectable = getInjectable({ id: "request-set-cluster-as-deleting", instantiate: (di): RequestSetClusterAsDeleting => { const requestChannel = di.inject(requestFromChannelInjectable); - const setClusterAsDeletingChannel = di.inject(setClusterAsDeletingChannelInjectable); return (clusterId) => requestChannel(setClusterAsDeletingChannel, clusterId); }, diff --git a/src/features/helm-charts/add-custom-helm-repository-in-preferences.test.ts b/src/features/helm-charts/add-custom-helm-repository-in-preferences.test.ts index fb7b655dfe..6df4402130 100644 --- a/src/features/helm-charts/add-custom-helm-repository-in-preferences.test.ts +++ b/src/features/helm-charts/add-custom-helm-repository-in-preferences.test.ts @@ -8,6 +8,7 @@ import type { ApplicationBuilder } from "../../renderer/components/test-utils/ge import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; +import type { ExecFile } from "../../common/fs/exec-file.injectable"; import execFileInjectable from "../../common/fs/exec-file.injectable"; import helmBinaryPathInjectable from "../../main/helm/helm-binary-path.injectable"; import getActiveHelmRepositoriesInjectable from "../../main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable"; @@ -24,9 +25,7 @@ describe("add custom helm repository in preferences", () => { let showSuccessNotificationMock: jest.Mock; let showErrorNotificationMock: jest.Mock; let rendered: RenderResult; - let execFileMock: AsyncFnMock< - ReturnType - >; + let execFileMock: AsyncFnMock; let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise>>; beforeEach(async () => { @@ -184,9 +183,13 @@ describe("add custom helm repository in preferences", () => { describe("when activation rejects", () => { beforeEach(async () => { - await execFileMock.reject( - "Some error", - ); + await execFileMock.resolve({ + callWasSuccessful: false, + error: { + error: new Error("Some error"), + stderr: "", + }, + }); }); it("renders", () => { @@ -219,8 +222,10 @@ describe("add custom helm repository in preferences", () => { "some-helm-binary-path", ["repo", "add", "some-custom-repository", "http://some.url"], ], - - "", + { + callWasSuccessful: true, + response: "", + }, ); }); diff --git a/src/features/helm-charts/add-helm-repository-from-list-in-preferences.test.ts b/src/features/helm-charts/add-helm-repository-from-list-in-preferences.test.ts index 98e94321bd..73831bec04 100644 --- a/src/features/helm-charts/add-helm-repository-from-list-in-preferences.test.ts +++ b/src/features/helm-charts/add-helm-repository-from-list-in-preferences.test.ts @@ -7,6 +7,7 @@ import type { ApplicationBuilder } from "../../renderer/components/test-utils/ge import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; +import type { ExecFile } from "../../common/fs/exec-file.injectable"; import execFileInjectable from "../../common/fs/exec-file.injectable"; import helmBinaryPathInjectable from "../../main/helm/helm-binary-path.injectable"; import getActiveHelmRepositoriesInjectable from "../../main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable"; @@ -21,9 +22,7 @@ describe("add helm repository from list in preferences", () => { let showSuccessNotificationMock: jest.Mock; let showErrorNotificationMock: jest.Mock; let rendered: RenderResult; - let execFileMock: AsyncFnMock< - ReturnType - >; + let execFileMock: AsyncFnMock; let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise>>; let callForPublicHelmRepositoriesMock: AsyncFnMock<() => Promise>; @@ -129,9 +128,13 @@ describe("add helm repository from list in preferences", () => { describe("when adding rejects", () => { beforeEach(async () => { - await execFileMock.reject( - "Some error", - ); + await execFileMock.resolve({ + callWasSuccessful: false, + error: { + error: new Error("Some error"), + stderr: "", + }, + }); }); it("renders", () => { @@ -164,8 +167,10 @@ describe("add helm repository from list in preferences", () => { "some-helm-binary-path", ["repo", "add", "Some to be added repository", "some-other-url"], ], - - "", + { + callWasSuccessful: true, + response: "", + }, ); }); @@ -243,8 +248,10 @@ describe("add helm repository from list in preferences", () => { "some-helm-binary-path", ["repo", "remove", "Some already active repository"], ], - - "", + { + callWasSuccessful: true, + response: "", + }, ); }); diff --git a/src/features/helm-charts/listing-active-helm-repositories-in-preferences.test.ts b/src/features/helm-charts/listing-active-helm-repositories-in-preferences.test.ts index 19aaf28938..30e5bac5eb 100644 --- a/src/features/helm-charts/listing-active-helm-repositories-in-preferences.test.ts +++ b/src/features/helm-charts/listing-active-helm-repositories-in-preferences.test.ts @@ -83,7 +83,13 @@ describe("listing active helm repositories in preferences", () => { describe("when getting configuration rejects", () => { beforeEach(async () => { - await execFileMock.reject("some-error"); + await execFileMock.resolve({ + callWasSuccessful: false, + error: { + error: new Error("some error"), + stderr: "some-error", + }, + }); }); it("shows error notification", () => { @@ -115,7 +121,10 @@ describe("listing active helm repositories in preferences", () => { await execFileMock.resolveSpecific( ["some-helm-binary-path", ["env"]], - "HELM_REPOSITORY_CACHE=some-helm-repository-cache-path", + { + callWasSuccessful: true, + response: "HELM_REPOSITORY_CACHE=some-helm-repository-cache-path", + }, ); }); @@ -154,7 +163,10 @@ describe("listing active helm repositories in preferences", () => { await execFileMock.resolveSpecific( ["some-helm-binary-path", ["env"]], - "HELM_REPOSITORY_CONFIG=some-helm-repository-config-file.yaml", + { + callWasSuccessful: true, + response: "HELM_REPOSITORY_CONFIG=some-helm-repository-config-file.yaml", + }, ); }); @@ -193,11 +205,13 @@ describe("listing active helm repositories in preferences", () => { await execFileMock.resolveSpecific( ["some-helm-binary-path", ["env"]], - - [ - "HELM_REPOSITORY_CONFIG=some-helm-repository-config-file.yaml", - "HELM_REPOSITORY_CACHE=some-helm-repository-cache-path", - ].join("\n"), + { + callWasSuccessful: true, + response: [ + "HELM_REPOSITORY_CONFIG=some-helm-repository-config-file.yaml", + "HELM_REPOSITORY_CACHE=some-helm-repository-cache-path", + ].join("\n"), + }, ); }); @@ -219,7 +233,13 @@ describe("listing active helm repositories in preferences", () => { describe("when updating repositories reject with any other error", () => { beforeEach(async () => { - await execFileMock.reject("Some error"); + await execFileMock.resolve({ + callWasSuccessful: false, + error: { + error: new Error("Some error"), + stderr: "Some error", + }, + }); }); it("shows error notification", () => { @@ -249,9 +269,13 @@ describe("listing active helm repositories in preferences", () => { beforeEach(async () => { execFileMock.mockClear(); - await execFileMock.reject( - "Error: no repositories found. You must add one before updating", - ); + await execFileMock.resolve({ + callWasSuccessful: false, + error: { + error: new Error("no repositories found. You must add one before updating"), + stderr: "no repositories found. You must add one before updating", + }, + }); }); it("renders", () => { @@ -274,7 +298,13 @@ describe("listing active helm repositories in preferences", () => { describe("when adding default repository reject", () => { beforeEach(async () => { - await execFileMock.reject("Some error"); + await execFileMock.resolve({ + callWasSuccessful: false, + error: { + error: new Error("Some error"), + stderr: "Some error", + }, + }); }); it("shows error notification", () => { @@ -307,7 +337,6 @@ describe("listing active helm repositories in preferences", () => { await execFileMock.resolveSpecific( [ "some-helm-binary-path", - [ "repo", "add", @@ -315,8 +344,10 @@ describe("listing active helm repositories in preferences", () => { "https://charts.bitnami.com/bitnami", ], ], - - "", + { + callWasSuccessful: true, + response: "", + }, ); }); @@ -380,7 +411,10 @@ describe("listing active helm repositories in preferences", () => { await execFileMock.resolveSpecific( ["some-helm-binary-path", ["repo", "update"]], - "", + { + callWasSuccessful: true, + response: "", + }, ); }); diff --git a/src/features/helm-charts/remove-helm-repository-from-list-of-active-repository-in-preferences.test.ts b/src/features/helm-charts/remove-helm-repository-from-list-of-active-repository-in-preferences.test.ts index 7a3e787a53..8d029d3412 100644 --- a/src/features/helm-charts/remove-helm-repository-from-list-of-active-repository-in-preferences.test.ts +++ b/src/features/helm-charts/remove-helm-repository-from-list-of-active-repository-in-preferences.test.ts @@ -8,6 +8,7 @@ import type { ApplicationBuilder } from "../../renderer/components/test-utils/ge import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; +import type { ExecFile } from "../../common/fs/exec-file.injectable"; import execFileInjectable from "../../common/fs/exec-file.injectable"; import helmBinaryPathInjectable from "../../main/helm/helm-binary-path.injectable"; import getActiveHelmRepositoriesInjectable from "../../main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable"; @@ -19,9 +20,7 @@ describe("remove helm repository from list of active repositories in preferences let builder: ApplicationBuilder; let rendered: RenderResult; let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise>>; - let execFileMock: AsyncFnMock< - ReturnType - >; + let execFileMock: AsyncFnMock; beforeEach(async () => { builder = getApplicationBuilder(); @@ -101,8 +100,10 @@ describe("remove helm repository from list of active repositories in preferences "some-helm-binary-path", ["repo", "remove", "some-active-repository"], ], - - "", + { + callWasSuccessful: true, + response: "", + }, ); }); diff --git a/src/features/navigation/reload-page/common/channel.ts b/src/features/navigation/reload-page/common/channel.ts new file mode 100644 index 0000000000..b920067a4d --- /dev/null +++ b/src/features/navigation/reload-page/common/channel.ts @@ -0,0 +1,12 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type { MessageChannel } from "../../../../common/utils/channel/message-channel-listener-injection-token"; + +export type ReloadPageChannel = MessageChannel; + +export const reloadPageChannel: ReloadPageChannel = { + id: "reload-page-channel", +}; diff --git a/src/features/navigation/reload-page/renderer/register-listener.global-override-for-injectable.ts b/src/features/navigation/reload-page/renderer/register-listener.global-override-for-injectable.ts new file mode 100644 index 0000000000..c0a43713b7 --- /dev/null +++ b/src/features/navigation/reload-page/renderer/register-listener.global-override-for-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 { getGlobalOverride } from "../../../../common/test-utils/get-global-override"; +import { reloadPageChannel } from "../common/channel"; +import reloadPageChannelListenerInjectable from "./register-listener.injectable"; + +export default getGlobalOverride(reloadPageChannelListenerInjectable, () => ({ + channel: reloadPageChannel, + handler: () => {}, +})); diff --git a/src/features/navigation/reload-page/renderer/register-listener.injectable.ts b/src/features/navigation/reload-page/renderer/register-listener.injectable.ts new file mode 100644 index 0000000000..a42d818729 --- /dev/null +++ b/src/features/navigation/reload-page/renderer/register-listener.injectable.ts @@ -0,0 +1,15 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getMessageChannelListenerInjectable } from "../../../../common/utils/channel/message-channel-listener-injection-token"; +import { reloadPageChannel } from "../common/channel"; + +const reloadPageChannelListenerInjectable = getMessageChannelListenerInjectable({ + id: "handler", + channel: reloadPageChannel, + handler: () => () => location.reload(), + causesSideEffects: true, +}); + +export default reloadPageChannelListenerInjectable; diff --git a/src/main/app-paths/app-paths-request-channel-listener.injectable.ts b/src/main/app-paths/app-paths-request-channel-listener.injectable.ts index 3bd0c95bf7..568d63f1ea 100644 --- a/src/main/app-paths/app-paths-request-channel-listener.injectable.ts +++ b/src/main/app-paths/app-paths-request-channel-listener.injectable.ts @@ -2,26 +2,17 @@ * 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 type { RequestChannelListener } from "../../common/utils/channel/request-channel-listener-injection-token"; -import { requestChannelListenerInjectionToken } from "../../common/utils/channel/request-channel-listener-injection-token"; -import type { AppPathsChannel } from "../../common/app-paths/app-paths-channel.injectable"; -import appPathsChannelInjectable from "../../common/app-paths/app-paths-channel.injectable"; +import { appPathsChannel } from "../../common/app-paths/app-paths-channel"; import appPathsInjectable from "../../common/app-paths/app-paths.injectable"; +import { getRequestChannelListenerInjectable } from "../utils/channel/channel-listeners/listener-tokens"; -const appPathsRequestChannelListenerInjectable = getInjectable({ - id: "app-paths-request-channel-listener", - - instantiate: (di): RequestChannelListener => { - const channel = di.inject(appPathsChannelInjectable); +const appPathsRequestChannelListenerInjectable = getRequestChannelListenerInjectable({ + channel: appPathsChannel, + handler: (di) => { const appPaths = di.inject(appPathsInjectable); - return { - channel, - handler: () => appPaths, - }; + return () => appPaths; }, - injectionToken: requestChannelListenerInjectionToken, }); export default appPathsRequestChannelListenerInjectable; diff --git a/src/main/application-update/restart-and-install-update/restart-and-install-update-listener.injectable.ts b/src/main/application-update/restart-and-install-update/restart-and-install-update-listener.injectable.ts index 0580114885..87f232d9b1 100644 --- a/src/main/application-update/restart-and-install-update/restart-and-install-update-listener.injectable.ts +++ b/src/main/application-update/restart-and-install-update/restart-and-install-update-listener.injectable.ts @@ -2,25 +2,14 @@ * 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 restartAndInstallUpdateChannel from "../../../common/application-update/restart-and-install-update-channel/restart-and-install-update-channel.injectable"; -import { messageChannelListenerInjectionToken } from "../../../common/utils/channel/message-channel-listener-injection-token"; +import { restartAndInstallUpdateChannel } from "../../../common/application-update/restart-and-install-update-channel"; +import { getMessageChannelListenerInjectable } from "../../../common/utils/channel/message-channel-listener-injection-token"; import quitAndInstallUpdateInjectable from "../quit-and-install-update.injectable"; -const restartAndInstallUpdateListenerInjectable = getInjectable({ - id: "restart-and-install-update-listener", - - instantiate: (di) => { - const quitAndInstall = di.inject(quitAndInstallUpdateInjectable); - const channel = di.inject(restartAndInstallUpdateChannel); - - return { - channel, - handler: quitAndInstall, - }; - }, - - injectionToken: messageChannelListenerInjectionToken, +const restartAndInstallUpdateListenerInjectable = getMessageChannelListenerInjectable({ + id: "restart", + channel: restartAndInstallUpdateChannel, + handler: (di) => di.inject(quitAndInstallUpdateInjectable), }); export default restartAndInstallUpdateListenerInjectable; diff --git a/src/main/application-update/watch-if-update-should-happen-on-quit/watch-if-update-should-happen-on-quit.injectable.ts b/src/main/application-update/watch-if-update-should-happen-on-quit/watch-if-update-should-happen-on-quit.injectable.ts index 12ec2d7c6e..9be8fdd18f 100644 --- a/src/main/application-update/watch-if-update-should-happen-on-quit/watch-if-update-should-happen-on-quit.injectable.ts +++ b/src/main/application-update/watch-if-update-should-happen-on-quit/watch-if-update-should-happen-on-quit.injectable.ts @@ -7,7 +7,7 @@ import { autorun } from "mobx"; import { getStartableStoppable } from "../../../common/utils/get-startable-stoppable"; import setUpdateOnQuitInjectable from "../../electron-app/features/set-update-on-quit.injectable"; import selectedUpdateChannelInjectable from "../../../common/application-update/selected-update-channel/selected-update-channel.injectable"; -import type { UpdateChannel } from "../../../common/application-update/update-channels"; +import type { ReleaseChannel, UpdateChannel } from "../../../common/application-update/update-channels"; import discoveredUpdateVersionInjectable from "../../../common/application-update/discovered-update-version/discovered-update-version.injectable"; const watchIfUpdateShouldHappenOnQuitInjectable = getInjectable({ @@ -20,33 +20,26 @@ const watchIfUpdateShouldHappenOnQuitInjectable = getInjectable({ return getStartableStoppable("watch-if-update-should-happen-on-quit", () => autorun(() => { - const sufficientlyStableUpdateChannels = - getSufficientlyStableUpdateChannels(selectedUpdateChannel.value.get()); + const sufficientlyStableUpdateChannels = getSufficientlyStableUpdateChannels(selectedUpdateChannel.value.get()); + const updateIsDiscoveredFromChannel = discoveredVersionState.value.get()?.updateChannel; - const discoveredVersion = discoveredVersionState.value.get(); - - const updateIsDiscoveredFromChannel = discoveredVersion?.updateChannel; - - const updateOnQuit = updateIsDiscoveredFromChannel - ? sufficientlyStableUpdateChannels.includes( - updateIsDiscoveredFromChannel, - ) - : false; - - setUpdateOnQuit(updateOnQuit); + setUpdateOnQuit(( + updateIsDiscoveredFromChannel + ? sufficientlyStableUpdateChannels.includes(updateIsDiscoveredFromChannel.id) + : false + )); }), ); }, }); -const getSufficientlyStableUpdateChannels = (updateChannel: UpdateChannel): UpdateChannel[] => { +const getSufficientlyStableUpdateChannels = (updateChannel: UpdateChannel): ReleaseChannel[] => { if (!updateChannel.moreStableUpdateChannel) { - return [updateChannel]; + return [updateChannel.id]; } return [ - updateChannel, - + updateChannel.id, ...getSufficientlyStableUpdateChannels(updateChannel.moreStableUpdateChannel), ]; }; diff --git a/src/main/build-version/setup-channel.injectable.ts b/src/main/build-version/setup-channel.injectable.ts index a34edc0eac..05da92db6e 100644 --- a/src/main/build-version/setup-channel.injectable.ts +++ b/src/main/build-version/setup-channel.injectable.ts @@ -2,22 +2,17 @@ * 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 { requestChannelListenerInjectionToken } from "../../common/utils/channel/request-channel-listener-injection-token"; import { buildVersionChannel } from "../../common/vars/build-semantic-version.injectable"; +import { getRequestChannelListenerInjectable } from "../utils/channel/channel-listeners/listener-tokens"; import buildVersionInjectable from "../vars/build-version/build-version.injectable"; -const setupBuildVersionRequestChannelInjectable = getInjectable({ - id: "setup-build-version-request-channel", - instantiate: (di) => { +const buildVersionChannelListenerInjectable = getRequestChannelListenerInjectable({ + channel: buildVersionChannel, + handler: (di) => { const buildVersion = di.inject(buildVersionInjectable); - return { - channel: buildVersionChannel, - handler: () => buildVersion.get(), - }; + return () => buildVersion.get(); }, - injectionToken: requestChannelListenerInjectionToken, }); -export default setupBuildVersionRequestChannelInjectable; +export default buildVersionChannelListenerInjectable; diff --git a/src/main/helm/exec-helm/exec-helm.injectable.ts b/src/main/helm/exec-helm/exec-helm.injectable.ts index dbe65eda34..d81da0c8b8 100644 --- a/src/main/helm/exec-helm/exec-helm.injectable.ts +++ b/src/main/helm/exec-helm/exec-helm.injectable.ts @@ -6,9 +6,8 @@ import { getInjectable } from "@ogre-tools/injectable"; import execFileInjectable from "../../../common/fs/exec-file.injectable"; import helmBinaryPathInjectable from "../helm-binary-path.injectable"; import type { AsyncResult } from "../../../common/utils/async-result"; -import { getErrorMessage } from "../../../common/utils/get-error-message"; -export type ExecHelm = (args: string[]) => Promise>; +export type ExecHelm = (args: string[]) => Promise>; const execHelmInjectable = getInjectable({ id: "exec-helm", @@ -18,15 +17,18 @@ const execHelmInjectable = getInjectable({ const helmBinaryPath = di.inject(helmBinaryPathInjectable); return async (args) => { - try { - const response = await execFile(helmBinaryPath, args, { - maxBuffer: 32 * 1024 * 1024 * 1024, // 32 MiB - }); + const response = await execFile(helmBinaryPath, args, { + maxBuffer: 32 * 1024 * 1024 * 1024, // 32 MiB + }); - return { callWasSuccessful: true, response }; - } catch (error) { - return { callWasSuccessful: false, error: getErrorMessage(error) }; + if (response.callWasSuccessful) { + return response; } + + return { + callWasSuccessful: false, + error: response.error.stderr || response.error.error.message, + }; }; }, }); diff --git a/src/main/helm/repositories/add-helm-repository/add-helm-repository-channel-listener.injectable.ts b/src/main/helm/repositories/add-helm-repository/add-helm-repository-channel-listener.injectable.ts index f4effd1a62..1c68bf6fd7 100644 --- a/src/main/helm/repositories/add-helm-repository/add-helm-repository-channel-listener.injectable.ts +++ b/src/main/helm/repositories/add-helm-repository/add-helm-repository-channel-listener.injectable.ts @@ -2,25 +2,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"; -import addHelmRepositoryChannelInjectable from "../../../../common/helm/add-helm-repository-channel.injectable"; +import { addHelmRepositoryChannel } from "../../../../common/helm/add-helm-repository-channel"; +import { getRequestChannelListenerInjectable } from "../../../utils/channel/channel-listeners/listener-tokens"; import addHelmRepositoryInjectable from "./add-helm-repository.injectable"; -import { requestChannelListenerInjectionToken } from "../../../../common/utils/channel/request-channel-listener-injection-token"; -const addHelmRepositoryChannelListenerInjectable = getInjectable({ - id: "add-helm-repository-channel-listener", - - instantiate: (di) => { - const addHelmRepository = di.inject(addHelmRepositoryInjectable); - const channel = di.inject(addHelmRepositoryChannelInjectable); - - return { - channel, - handler: addHelmRepository, - }; - }, - - injectionToken: requestChannelListenerInjectionToken, +const addHelmRepositoryChannelListenerInjectable = getRequestChannelListenerInjectable({ + channel: addHelmRepositoryChannel, + handler: (di) => di.inject(addHelmRepositoryInjectable), }); export default addHelmRepositoryChannelListenerInjectable; diff --git a/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories-channel-listener.injectable.ts b/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories-channel-listener.injectable.ts index e48ec7665e..5ef0f2b5a4 100644 --- a/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories-channel-listener.injectable.ts +++ b/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories-channel-listener.injectable.ts @@ -2,25 +2,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"; -import { requestChannelListenerInjectionToken } from "../../../../common/utils/channel/request-channel-listener-injection-token"; -import getActiveHelmRepositoriesChannelInjectable from "../../../../common/helm/get-active-helm-repositories-channel.injectable"; +import { getActiveHelmRepositoriesChannel } from "../../../../common/helm/get-active-helm-repositories-channel"; +import { getRequestChannelListenerInjectable } from "../../../utils/channel/channel-listeners/listener-tokens"; import getActiveHelmRepositoriesInjectable from "./get-active-helm-repositories.injectable"; -const getActiveHelmRepositoriesChannelListenerInjectable = getInjectable({ - id: "get-active-helm-repositories-channel-listener", - - instantiate: (di) => { - const getActiveHelmRepositories = di.inject(getActiveHelmRepositoriesInjectable); - - return { - channel: di.inject(getActiveHelmRepositoriesChannelInjectable), - - handler: getActiveHelmRepositories, - }; - }, - - injectionToken: requestChannelListenerInjectionToken, +const getActiveHelmRepositoriesChannelListenerInjectable = getRequestChannelListenerInjectable({ + channel: getActiveHelmRepositoriesChannel, + handler: (di) => di.inject(getActiveHelmRepositoriesInjectable), }); export default getActiveHelmRepositoriesChannelListenerInjectable; diff --git a/src/main/helm/repositories/remove-helm-repository/remove-helm-repository-channel-listener.injectable.ts b/src/main/helm/repositories/remove-helm-repository/remove-helm-repository-channel-listener.injectable.ts index b9b2f11777..8a4e04b87c 100644 --- a/src/main/helm/repositories/remove-helm-repository/remove-helm-repository-channel-listener.injectable.ts +++ b/src/main/helm/repositories/remove-helm-repository/remove-helm-repository-channel-listener.injectable.ts @@ -2,25 +2,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"; -import { requestChannelListenerInjectionToken } from "../../../../common/utils/channel/request-channel-listener-injection-token"; import removeHelmRepositoryInjectable from "./remove-helm-repository.injectable"; -import removeHelmRepositoryChannelInjectable from "../../../../common/helm/remove-helm-repository-channel.injectable"; +import { removeHelmRepositoryChannel } from "../../../../common/helm/remove-helm-repository-channel"; +import { getRequestChannelListenerInjectable } from "../../../utils/channel/channel-listeners/listener-tokens"; -const removeHelmRepositoryChannelListenerInjectable = getInjectable({ - id: "remove-helm-repository-channel-listener", - - instantiate: (di) => { - const removeHelmRepository = di.inject(removeHelmRepositoryInjectable); - const channel = di.inject(removeHelmRepositoryChannelInjectable); - - return { - channel, - handler: removeHelmRepository, - }; - }, - - injectionToken: requestChannelListenerInjectionToken, +const removeHelmRepositoryChannelListenerInjectable = getRequestChannelListenerInjectable({ + channel: removeHelmRepositoryChannel, + handler: (di) => di.inject(removeHelmRepositoryInjectable), }); export default removeHelmRepositoryChannelListenerInjectable; diff --git a/src/main/start-main-application/lens-window/application-window/create-electron-window.injectable.ts b/src/main/start-main-application/lens-window/application-window/create-electron-window.injectable.ts index 252db16a1f..07f9b8fb7e 100644 --- a/src/main/start-main-application/lens-window/application-window/create-electron-window.injectable.ts +++ b/src/main/start-main-application/lens-window/application-window/create-electron-window.injectable.ts @@ -6,7 +6,6 @@ import { getInjectable } from "@ogre-tools/injectable"; import loggerInjectable from "../../../../common/logger.injectable"; import applicationWindowStateInjectable from "./application-window-state.injectable"; import { BrowserWindow } from "electron"; -import sendToChannelInElectronBrowserWindowInjectable from "./send-to-channel-in-electron-browser-window.injectable"; import type { ElectronWindow } from "./create-lens-window.injectable"; import type { RequireExactlyOne } from "type-fest"; import openLinkInBrowserInjectable from "../../../../common/utils/open-link-in-browser.injectable"; @@ -45,7 +44,6 @@ const createElectronWindowInjectable = getInjectable({ instantiate: (di): CreateElectronWindow => { const logger = di.inject(loggerInjectable); - const sendToChannelInLensWindow = di.inject(sendToChannelInElectronBrowserWindowInjectable); const openLinkInBrowser = di.inject(openLinkInBrowserInjectable); return (configuration) => { @@ -140,7 +138,17 @@ const createElectronWindowInjectable = getInjectable({ show: () => browserWindow.show(), close: () => browserWindow.close(), - send: (args) => sendToChannelInLensWindow(configuration.id, browserWindow, args), + send: ({ channel, data, frameInfo }) => { + if (frameInfo) { + browserWindow.webContents.sendToFrame( + [frameInfo.processId, frameInfo.frameId], + channel, + data, + ); + } else { + browserWindow.webContents.send(channel, data); + } + }, reload: () => { const wc = browserWindow.webContents; diff --git a/src/main/start-main-application/lens-window/application-window/create-lens-window.injectable.ts b/src/main/start-main-application/lens-window/application-window/create-lens-window.injectable.ts index 6dcf6b0174..b44e5774bd 100644 --- a/src/main/start-main-application/lens-window/application-window/create-lens-window.injectable.ts +++ b/src/main/start-main-application/lens-window/application-window/create-lens-window.injectable.ts @@ -20,7 +20,7 @@ export interface ElectronWindow { export interface SendToViewArgs { channel: string; frameInfo?: ClusterFrameInfo; - data?: unknown[]; + data?: unknown; } export interface LensWindow { diff --git a/src/main/start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable.ts b/src/main/start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable.ts deleted file mode 100644 index 08de6fec46..0000000000 --- a/src/main/start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable.ts +++ /dev/null @@ -1,33 +0,0 @@ -/** - * 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 type { BrowserWindow } from "electron"; -import type { SendToViewArgs } from "./create-lens-window.injectable"; - -const sendToChannelInElectronBrowserWindowInjectable = getInjectable({ - id: "send-to-channel-in-electron-browser-window", - - instantiate: - () => - ( - windowId: string, - browserWindow: BrowserWindow, - { channel, frameInfo, data = [] }: SendToViewArgs, - ) => { - if (frameInfo) { - browserWindow.webContents.sendToFrame( - [frameInfo.processId, frameInfo.frameId], - channel, - ...data, - ); - } else { - browserWindow.webContents.send(channel, ...data); - } - }, - - causesSideEffects: true, -}); - -export default sendToChannelInElectronBrowserWindowInjectable; diff --git a/src/main/start-main-application/lens-window/navigate.injectable.ts b/src/main/start-main-application/lens-window/navigate.injectable.ts index 1916b8205f..8b204be9b3 100644 --- a/src/main/start-main-application/lens-window/navigate.injectable.ts +++ b/src/main/start-main-application/lens-window/navigate.injectable.ts @@ -37,7 +37,7 @@ const navigateInjectable = getInjectable({ applicationWindow.send({ channel, frameInfo, - data: [url], + data: url, }); }; }, diff --git a/src/main/start-main-application/lens-window/reload-current-application-window.injectable.ts b/src/main/start-main-application/lens-window/reload-current-application-window.injectable.ts index daaf88a24c..9b0d04fe9f 100644 --- a/src/main/start-main-application/lens-window/reload-current-application-window.injectable.ts +++ b/src/main/start-main-application/lens-window/reload-current-application-window.injectable.ts @@ -3,9 +3,9 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { IpcRendererNavigationEvents } from "../../../renderer/navigation/events"; import currentClusterFrameInjectable from "./current-cluster-frame/current-cluster-frame.injectable"; import getCurrentApplicationWindowInjectable from "./application-window/get-current-application-window.injectable"; +import { reloadPageChannel } from "../../../features/navigation/reload-page/common/channel"; const reloadCurrentApplicationWindowInjectable = getInjectable({ id: "reload-current-application-window", @@ -25,7 +25,7 @@ const reloadCurrentApplicationWindowInjectable = getInjectable({ if (frameInfo) { lensWindow.send({ - channel: IpcRendererNavigationEvents.RELOAD_PAGE, + channel: reloadPageChannel.id, frameInfo, }); } else { diff --git a/src/main/start-main-application/runnables/root-frame-has-rendered/channel-listener.injectable.ts b/src/main/start-main-application/runnables/root-frame-has-rendered/channel-listener.injectable.ts new file mode 100644 index 0000000000..40f5ceb788 --- /dev/null +++ b/src/main/start-main-application/runnables/root-frame-has-rendered/channel-listener.injectable.ts @@ -0,0 +1,20 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getMessageChannelListenerInjectable } from "../../../../common/utils/channel/message-channel-listener-injection-token"; +import { rootFrameHasRenderedChannel } from "../../../../common/root-frame/root-frame-rendered-channel"; +import { runManyFor } from "../../../../common/runnable/run-many-for"; +import { afterRootFrameIsReadyInjectionToken } from "../../runnable-tokens/after-root-frame-is-ready-injection-token"; + +const rootFrameRenderedChannelListenerInjectable = getMessageChannelListenerInjectable({ + id: "action", + channel: rootFrameHasRenderedChannel, + handler: (di) => { + const runMany = runManyFor(di); + + return runMany(afterRootFrameIsReadyInjectionToken); + }, +}); + +export default rootFrameRenderedChannelListenerInjectable; diff --git a/src/main/start-main-application/runnables/root-frame-rendered-channel-listener/root-frame-rendered-channel-listener.injectable.ts b/src/main/start-main-application/runnables/root-frame-rendered-channel-listener/root-frame-rendered-channel-listener.injectable.ts deleted file mode 100644 index 83ebf7bf91..0000000000 --- a/src/main/start-main-application/runnables/root-frame-rendered-channel-listener/root-frame-rendered-channel-listener.injectable.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** - * 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 rootFrameRenderedChannelInjectable from "../../../../common/root-frame-rendered-channel/root-frame-rendered-channel.injectable"; -import { runManyFor } from "../../../../common/runnable/run-many-for"; -import { afterRootFrameIsReadyInjectionToken } from "../../runnable-tokens/after-root-frame-is-ready-injection-token"; -import { messageChannelListenerInjectionToken } from "../../../../common/utils/channel/message-channel-listener-injection-token"; - -const rootFrameRenderedChannelListenerInjectable = getInjectable({ - id: "root-frame-rendered-channel-listener", - - instantiate: (di) => { - const channel = di.inject(rootFrameRenderedChannelInjectable); - - const runMany = runManyFor(di); - - const runRunnablesAfterRootFrameIsReady = runMany( - afterRootFrameIsReadyInjectionToken, - ); - - return { - channel, - - handler: async () => { - await runRunnablesAfterRootFrameIsReady(); - }, - }; - }, - - injectionToken: messageChannelListenerInjectionToken, -}); - -export default rootFrameRenderedChannelListenerInjectable; diff --git a/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts b/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts index 6b7fa9b8df..6ace54c845 100644 --- a/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts +++ b/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts @@ -6,8 +6,6 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { IpcMainEvent } from "electron"; import ipcMainInjectable from "../ipc-main/ipc-main.injectable"; import { enlistMessageChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-message-channel-listener-injection-token"; -import { pipeline } from "@ogre-tools/fp"; -import { tentativeParseJson } from "../../../../common/utils/tentative-parse-json"; const enlistMessageChannelListenerInjectable = getInjectable({ id: "enlist-message-channel-listener-for-main", @@ -17,11 +15,7 @@ const enlistMessageChannelListenerInjectable = getInjectable({ return ({ channel, handler }) => { const nativeOnCallback = (_: IpcMainEvent, message: unknown) => { - pipeline( - message, - tentativeParseJson, - handler, - ); + handler(message); }; ipcMain.on(channel.id, nativeOnCallback); diff --git a/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.test.ts b/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.test.ts index 3bd0398d8e..407ffabd8f 100644 --- a/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.test.ts +++ b/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.test.ts @@ -88,8 +88,8 @@ describe("enlist message channel listener in main", () => { expect(handlerMock).toHaveBeenCalledWith(true); }); - it("given stringified object as message, when message arrives, calls the handler with the message", () => { - onMock.mock.calls[0][1]({} as IpcMainEvent, JSON.stringify({ some: "object" })); + it("given object as message, when message arrives, calls the handler with the message", () => { + onMock.mock.calls[0][1]({} as IpcMainEvent, { some: "object" }); expect(handlerMock).toHaveBeenCalledWith({ some: "object" }); }); diff --git a/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.injectable.ts b/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.injectable.ts index 6f118288f3..d72e4afcaf 100644 --- a/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.injectable.ts +++ b/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.injectable.ts @@ -5,20 +5,20 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { IpcMainInvokeEvent } from "electron"; import ipcMainInjectable from "../ipc-main/ipc-main.injectable"; -import { enlistRequestChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-request-channel-listener-injection-token"; -import { pipeline } from "@ogre-tools/fp"; -import { tentativeParseJson } from "../../../../common/utils/tentative-parse-json"; -import { tentativeStringifyJson } from "../../../../common/utils/tentative-stringify-json"; +import type { Disposer } from "../../../../common/utils"; +import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; +import type { RequestChannelListener } from "./listener-tokens"; + +export type EnlistRequestChannelListener = >(listener: RequestChannelListener) => Disposer; const enlistRequestChannelListenerInjectable = getInjectable({ id: "enlist-request-channel-listener-for-main", - instantiate: (di) => { + instantiate: (di): EnlistRequestChannelListener => { const ipcMain = di.inject(ipcMainInjectable); return ({ channel, handler }) => { - const nativeHandleCallback = (_: IpcMainInvokeEvent, request: unknown) => - pipeline(request, tentativeParseJson, handler, tentativeStringifyJson); + const nativeHandleCallback = (_: IpcMainInvokeEvent, request: unknown) => handler(request); ipcMain.handle(channel.id, nativeHandleCallback); @@ -27,8 +27,6 @@ const enlistRequestChannelListenerInjectable = getInjectable({ }; }; }, - - injectionToken: enlistRequestChannelListenerInjectionToken, }); export default enlistRequestChannelListenerInjectable; diff --git a/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.test.ts b/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.test.ts index 12a5e9af74..2c13bbd8f9 100644 --- a/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.test.ts +++ b/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.test.ts @@ -5,11 +5,19 @@ import { getDiForUnitTesting } from "../../../getDiForUnitTesting"; import ipcMainInjectable from "../ipc-main/ipc-main.injectable"; import type { IpcMain, IpcMainInvokeEvent } from "electron"; -import type { EnlistRequestChannelListener } from "../../../../common/utils/channel/enlist-request-channel-listener-injection-token"; -import { enlistRequestChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-request-channel-listener-injection-token"; import { getPromiseStatus } from "../../../../common/test-utils/get-promise-status"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; +import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; +import type { EnlistRequestChannelListener } from "./enlist-request-channel-listener.injectable"; +import enlistRequestChannelListenerInjectable from "./enlist-request-channel-listener.injectable"; +import type { RequestChannelHandler } from "./listener-tokens"; + +type TestRequestChannel = RequestChannel; + +const testRequestChannel: TestRequestChannel = { + id: "some-channel-id", +}; describe("enlist request channel listener in main", () => { let enlistRequestChannelListener: EnlistRequestChannelListener; @@ -30,20 +38,18 @@ describe("enlist request channel listener in main", () => { di.override(ipcMainInjectable, () => ipcMainStub); - enlistRequestChannelListener = di.inject( - enlistRequestChannelListenerInjectionToken, - ); + enlistRequestChannelListener = di.inject(enlistRequestChannelListenerInjectable); }); describe("when called", () => { - let handlerMock: AsyncFnMock<(message: any) => any>; + let handlerMock: AsyncFnMock>; let disposer: () => void; beforeEach(() => { handlerMock = asyncFn(); disposer = enlistRequestChannelListener({ - channel: { id: "some-channel-id" }, + channel: testRequestChannel, handler: handlerMock, }); }); @@ -91,7 +97,7 @@ describe("enlist request channel listener in main", () => { it("resolves with the response", async () => { const actual = await actualPromise; - expect(actual).toBe('"some-response"'); + expect(actual).toBe("some-response"); }); it("when disposing the listener, de-registers the listener", () => { @@ -106,7 +112,7 @@ describe("enlist request channel listener in main", () => { const actual = await actualPromise; - expect(actual).toBe("42"); + expect(actual).toBe(42); }); it("given boolean as response, when handler resolves with response, listener resolves with stringified response", async () => { @@ -114,15 +120,15 @@ describe("enlist request channel listener in main", () => { const actual = await actualPromise; - expect(actual).toBe("true"); + expect(actual).toBe(true); }); - it("given object as response, when handler resolves with response, listener resolves with stringified response", async () => { + it("given object as response, when handler resolves with response, listener resolves with response", async () => { await handlerMock.resolve({ some: "object" }); const actual = await actualPromise; - expect(actual).toBe(JSON.stringify({ some: "object" })); + expect(actual).toEqual({ some: "object" }); }); }); @@ -138,8 +144,8 @@ describe("enlist request channel listener in main", () => { expect(handlerMock).toHaveBeenCalledWith(true); }); - it("given stringified object as request, when request arrives, calls the handler with the request", () => { - handleMock.mock.calls[0][1]({} as IpcMainInvokeEvent, JSON.stringify({ some: "object" })); + it("given object as request, when request arrives, calls the handler with the request", () => { + handleMock.mock.calls[0][1]({} as IpcMainInvokeEvent, { some: "object" }); expect(handlerMock).toHaveBeenCalledWith({ some: "object" }); }); diff --git a/src/main/utils/channel/channel-listeners/listener-tokens.ts b/src/main/utils/channel/channel-listeners/listener-tokens.ts new file mode 100644 index 0000000000..a3cd5af4f4 --- /dev/null +++ b/src/main/utils/channel/channel-listeners/listener-tokens.ts @@ -0,0 +1,46 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type { DiContainerForInjection } from "@ogre-tools/injectable"; +import { getInjectable, getInjectionToken } from "@ogre-tools/injectable"; +import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; + +export type RequestChannelHandler = Channel extends RequestChannel + ? (req: Request) => Promise | Response + : never; + +export interface RequestChannelListener { + channel: Channel; + handler: RequestChannelHandler; +} + + +export const requestChannelListenerInjectionToken = getInjectionToken>>( { + id: "request-channel-listener", +}); + +export interface GetRequestChannelListenerInjectableInfo< + Channel extends RequestChannel, + Request, + Response, +> { + channel: Channel; + handler: (di: DiContainerForInjection) => RequestChannelHandler; +} + +export function getRequestChannelListenerInjectable< + Channel extends RequestChannel, + Request, + Response, +>(info: GetRequestChannelListenerInjectableInfo) { + return getInjectable({ + id: `${info.channel.id}-listener`, + instantiate: (di) => ({ + channel: info.channel, + handler: info.handler(di), + }), + injectionToken: requestChannelListenerInjectionToken, + }); +} diff --git a/src/main/utils/channel/channel-listeners/listening-on-request-channels.injectable.ts b/src/main/utils/channel/channel-listeners/listening-on-request-channels.injectable.ts new file mode 100644 index 0000000000..80b94fbe0e --- /dev/null +++ b/src/main/utils/channel/channel-listeners/listening-on-request-channels.injectable.ts @@ -0,0 +1,34 @@ +/** + * 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 { disposer } from "../../../../common/utils"; +import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; +import { getStartableStoppable } from "../../../../common/utils/get-startable-stoppable"; +import enlistRequestChannelListenerInjectable from "./enlist-request-channel-listener.injectable"; +import { requestChannelListenerInjectionToken } from "./listener-tokens"; + +const listeningOnRequestChannelsInjectable = getInjectable({ + id: "listening-on-request-channels", + instantiate: (di) => { + const enlistRequestChannelListener = di.inject(enlistRequestChannelListenerInjectable); + const requestChannelListeners = di.injectMany(requestChannelListenerInjectionToken); + + return getStartableStoppable("listening-on-request-channels", () => { + const seenChannels = new Set>(); + + for (const listener of requestChannelListeners) { + if (seenChannels.has(listener.channel)) { + throw new Error(`Tried to register a multiple channel handlers for "${listener.channel.id}", only one handler is supported for a request channel.`); + } + + seenChannels.add(listener.channel); + } + + return disposer(requestChannelListeners.map(enlistRequestChannelListener)); + }); + }, +}); + +export default listeningOnRequestChannelsInjectable; diff --git a/src/main/utils/channel/channel-listeners/start-listening-of-channels.injectable.ts b/src/main/utils/channel/channel-listeners/start-listening-of-channels.injectable.ts deleted file mode 100644 index 78d73044e9..0000000000 --- a/src/main/utils/channel/channel-listeners/start-listening-of-channels.injectable.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * 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 { onLoadOfApplicationInjectionToken } from "../../../start-main-application/runnable-tokens/on-load-of-application-injection-token"; -import listeningOfChannelsInjectable from "../../../../common/utils/channel/listening-of-channels.injectable"; - -const startListeningOfChannelsInjectable = getInjectable({ - id: "start-listening-of-channels-main", - - instantiate: (di) => { - const listeningOfChannels = di.inject(listeningOfChannelsInjectable); - - return { - id: "start-listening-of-channels-main", - run: async () => { - await listeningOfChannels.start(); - }, - }; - }, - - injectionToken: onLoadOfApplicationInjectionToken, -}); - -export default startListeningOfChannelsInjectable; diff --git a/src/main/utils/channel/channel-listeners/start-listening-on-channels.injectable.ts b/src/main/utils/channel/channel-listeners/start-listening-on-channels.injectable.ts new file mode 100644 index 0000000000..d1cf5d68d6 --- /dev/null +++ b/src/main/utils/channel/channel-listeners/start-listening-on-channels.injectable.ts @@ -0,0 +1,29 @@ +/** + * 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 { onLoadOfApplicationInjectionToken } from "../../../start-main-application/runnable-tokens/on-load-of-application-injection-token"; +import listeningOnMessageChannelsInjectable from "../../../../common/utils/channel/listening-on-message-channels.injectable"; +import listeningOnRequestChannelsInjectable from "./listening-on-request-channels.injectable"; + +const startListeningOnChannelsInjectable = getInjectable({ + id: "start-listening-on-channels-main", + + instantiate: (di) => { + const listeningOnMessageChannels = di.inject(listeningOnMessageChannelsInjectable); + const listeningOnRequestChannels = di.inject(listeningOnRequestChannelsInjectable); + + return { + id: "start-listening-on-channels-main", + run: async () => { + await listeningOnMessageChannels.start(); + await listeningOnRequestChannels.start(); + }, + }; + }, + + injectionToken: onLoadOfApplicationInjectionToken, +}); + +export default startListeningOnChannelsInjectable; diff --git a/src/main/utils/channel/message-to-channel.injectable.ts b/src/main/utils/channel/message-to-channel.injectable.ts index cbcdc2badd..1435ea59b5 100644 --- a/src/main/utils/channel/message-to-channel.injectable.ts +++ b/src/main/utils/channel/message-to-channel.injectable.ts @@ -3,9 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { messageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; -import type { MessageChannel } from "../../../common/utils/channel/message-channel-injection-token"; -import { tentativeStringifyJson } from "../../../common/utils/tentative-stringify-json"; +import type { SendMessageToChannel } from "../../../common/utils/channel/message-to-channel-injection-token"; +import { sendMessageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; import getVisibleWindowsInjectable from "../../start-main-application/lens-window/get-visible-windows.injectable"; const messageToChannelInjectable = getInjectable({ @@ -14,18 +13,14 @@ const messageToChannelInjectable = getInjectable({ instantiate: (di) => { const getVisibleWindows = di.inject(getVisibleWindowsInjectable); - // TODO: Figure out way to improve typing in internals - // Notice that this should be injected using "messageToChannelInjectionToken" which is typed correctly. - return (channel: MessageChannel, message?: unknown) => { - const stringifiedMessage = tentativeStringifyJson(message); - - getVisibleWindows().forEach((lensWindow) => - lensWindow.send({ channel: channel.id, data: stringifiedMessage ? [stringifiedMessage] : [] }), - ); - }; + return ((channel, data) => { + for (const window of getVisibleWindows()) { + window.send({ channel: channel.id, data }); + } + }) as SendMessageToChannel; }, - injectionToken: messageToChannelInjectionToken, + injectionToken: sendMessageToChannelInjectionToken, }); export default messageToChannelInjectable; diff --git a/src/main/utils/channel/message-to-channel.test.ts b/src/main/utils/channel/message-to-channel.test.ts deleted file mode 100644 index 6d5e83a548..0000000000 --- a/src/main/utils/channel/message-to-channel.test.ts +++ /dev/null @@ -1,148 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import type { MessageToChannel } from "../../../common/utils/channel/message-to-channel-injection-token"; -import { messageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; -import type { MessageChannel } from "../../../common/utils/channel/message-channel-injection-token"; -import type { LensWindow } from "../../start-main-application/lens-window/application-window/create-lens-window.injectable"; -import sendToChannelInElectronBrowserWindowInjectable from "../../start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable"; -import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; - -describe("message to channel from main", () => { - let messageToChannel: MessageToChannel; - let someTestWindow: LensWindow; - let someOtherTestWindow: LensWindow; - let sendToChannelInBrowserMock: jest.Mock; - - beforeEach(async () => { - const builder = getApplicationBuilder(); - - sendToChannelInBrowserMock = jest.fn(); - - builder.beforeApplicationStart(mainDi => { - mainDi.override(sendToChannelInElectronBrowserWindowInjectable, () => sendToChannelInBrowserMock); - }); - - await builder.startHidden(); - - someTestWindow = builder.applicationWindow.create("some-test-window-id"); - someOtherTestWindow = builder.applicationWindow.create("some-other-test-window-id"); - - messageToChannel = builder.mainDi.inject(messageToChannelInjectionToken); - }); - - it("given no visible windows, when messaging to channel, does not message to any window", () => { - messageToChannel(someChannel, "some-message"); - - expect(sendToChannelInBrowserMock).not.toHaveBeenCalled(); - }); - - describe("given started window", () => { - beforeEach(async () => { - await someTestWindow.start(); - }); - - it("when messaging to channel, messages to window", () => { - messageToChannel(someChannel, "some-message"); - - expect(sendToChannelInBrowserMock.mock.calls).toEqual([ - [ - "some-test-window-id", - - null, - - { - channel: "some-channel", - data: ['"some-message"'], - }, - ], - ]); - }); - - it("given boolean as message, when messaging to channel, messages to window with stringified message", () => { - messageToChannel(someChannel, true); - - expect(sendToChannelInBrowserMock.mock.calls).toEqual([ - [ - "some-test-window-id", - - null, - - { - channel: "some-channel", - data: ["true"], - }, - ], - ]); - }); - - it("given number as message, when messaging to channel, messages to window with stringified message", () => { - messageToChannel(someChannel, 42); - - expect(sendToChannelInBrowserMock.mock.calls).toEqual([ - [ - "some-test-window-id", - - null, - - { - channel: "some-channel", - data: ["42"], - }, - ], - ]); - }); - - it("given object as message, when messaging to channel, messages to window with stringified message", () => { - messageToChannel(someChannel, { some: "object" }); - - expect(sendToChannelInBrowserMock.mock.calls).toEqual([ - [ - "some-test-window-id", - - null, - - { - channel: "some-channel", - data: [JSON.stringify({ some: "object" })], - }, - ], - ]); - }); - }); - - it("given multiple started windows, when messaging to channel, messages to window", async () => { - await someTestWindow.start(); - await someOtherTestWindow.start(); - - messageToChannel(someChannel, "some-message"); - - expect(sendToChannelInBrowserMock.mock.calls).toEqual([ - [ - "some-test-window-id", - - null, - - { - channel: "some-channel", - data: ['"some-message"'], - }, - ], - - [ - "some-other-test-window-id", - - null, - - { - channel: "some-channel", - data: ['"some-message"'], - }, - ], - ]); - }); -}); - -const someChannel: MessageChannel = { id: "some-channel" }; diff --git a/src/main/utils/resolve-system-proxy/resolve-system-proxy-channel-responder.injectable.ts b/src/main/utils/resolve-system-proxy/resolve-system-proxy-channel-responder.injectable.ts index c7a1747770..a2cd605633 100644 --- a/src/main/utils/resolve-system-proxy/resolve-system-proxy-channel-responder.injectable.ts +++ b/src/main/utils/resolve-system-proxy/resolve-system-proxy-channel-responder.injectable.ts @@ -2,20 +2,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"; -import resolveSystemProxyChannelInjectable from "../../../common/utils/resolve-system-proxy/resolve-system-proxy-channel.injectable"; +import { resolveSystemProxyChannel } from "../../../common/utils/resolve-system-proxy/resolve-system-proxy-channel"; +import { getRequestChannelListenerInjectable } from "../channel/channel-listeners/listener-tokens"; import resolveSystemProxyInjectable from "./resolve-system-proxy.injectable"; -import { requestChannelListenerInjectionToken } from "../../../common/utils/channel/request-channel-listener-injection-token"; -const resolveSystemProxyChannelResponderInjectable = getInjectable({ - id: "resolve-system-proxy-channel-responder", - - instantiate: (di) => ({ - channel: di.inject(resolveSystemProxyChannelInjectable), - handler: di.inject(resolveSystemProxyInjectable), - }), - - injectionToken: requestChannelListenerInjectionToken, +const resolveSystemProxyChannelResponderInjectable = getRequestChannelListenerInjectable({ + channel: resolveSystemProxyChannel, + handler: (di) => di.inject(resolveSystemProxyInjectable), }); export default resolveSystemProxyChannelResponderInjectable; diff --git a/src/main/utils/sync-box/sync-box-initial-value-channel-listener.injectable.ts b/src/main/utils/sync-box/sync-box-initial-value-channel-listener.injectable.ts index 5eb043291a..da78d76c36 100644 --- a/src/main/utils/sync-box/sync-box-initial-value-channel-listener.injectable.ts +++ b/src/main/utils/sync-box/sync-box-initial-value-channel-listener.injectable.ts @@ -2,30 +2,20 @@ * 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 syncBoxInitialValueChannelInjectable from "../../../common/utils/sync-box/sync-box-initial-value-channel.injectable"; +import { syncBoxInitialValueChannel } from "../../../common/utils/sync-box/channels"; import { syncBoxInjectionToken } from "../../../common/utils/sync-box/sync-box-injection-token"; -import { requestChannelListenerInjectionToken } from "../../../common/utils/channel/request-channel-listener-injection-token"; +import { getRequestChannelListenerInjectable } from "../channel/channel-listeners/listener-tokens"; -const syncBoxInitialValueChannelListenerInjectable = getInjectable({ - id: "sync-box-initial-value-channel-listener", - - instantiate: (di) => { - const channel = di.inject(syncBoxInitialValueChannelInjectable); +const syncBoxInitialValueChannelListenerInjectable = getRequestChannelListenerInjectable({ + channel: syncBoxInitialValueChannel, + handler: (di) => { const syncBoxes = di.injectMany(syncBoxInjectionToken); - return { - channel, - - handler: () => - syncBoxes.map((box) => ({ - id: box.id, - value: box.value.get(), - })), - }; + return () => syncBoxes.map((box) => ({ + id: box.id, + value: box.value.get(), + })); }, - - injectionToken: requestChannelListenerInjectionToken, }); export default syncBoxInitialValueChannelListenerInjectable; diff --git a/src/renderer/app-paths/setup-app-paths.injectable.ts b/src/renderer/app-paths/setup-app-paths.injectable.ts index 3660ad9db8..50ad4df34a 100644 --- a/src/renderer/app-paths/setup-app-paths.injectable.ts +++ b/src/renderer/app-paths/setup-app-paths.injectable.ts @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import appPathsStateInjectable from "../../common/app-paths/app-paths-state.injectable"; import { beforeFrameStartsInjectionToken } from "../before-frame-starts/before-frame-starts-injection-token"; -import appPathsChannelInjectable from "../../common/app-paths/app-paths-channel.injectable"; +import { appPathsChannel } from "../../common/app-paths/app-paths-channel"; import { requestFromChannelInjectionToken } from "../../common/utils/channel/request-from-channel-injection-token"; const setupAppPathsInjectable = getInjectable({ @@ -13,15 +13,12 @@ const setupAppPathsInjectable = getInjectable({ instantiate: (di) => { const requestFromChannel = di.inject(requestFromChannelInjectionToken); - const appPathsChannel = di.inject(appPathsChannelInjectable); const appPathsState = di.inject(appPathsStateInjectable); return { id: "setup-app-paths", run: async () => { - const appPaths = await requestFromChannel( - appPathsChannel, - ); + const appPaths = await requestFromChannel(appPathsChannel); appPathsState.set(appPaths); }, diff --git a/src/renderer/components/+preferences/kubernetes/helm-charts/active-helm-repositories.injectable.ts b/src/renderer/components/+preferences/kubernetes/helm-charts/active-helm-repositories.injectable.ts index 94fdeaa393..2894e88b09 100644 --- a/src/renderer/components/+preferences/kubernetes/helm-charts/active-helm-repositories.injectable.ts +++ b/src/renderer/components/+preferences/kubernetes/helm-charts/active-helm-repositories.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { asyncComputed } from "@ogre-tools/injectable-react"; -import getActiveHelmRepositoriesChannelInjectable from "../../../../../common/helm/get-active-helm-repositories-channel.injectable"; +import { getActiveHelmRepositoriesChannel } from "../../../../../common/helm/get-active-helm-repositories-channel"; import { requestFromChannelInjectionToken } from "../../../../../common/utils/channel/request-from-channel-injection-token"; import showErrorNotificationInjectable from "../../../notifications/show-error-notification.injectable"; import helmRepositoriesErrorStateInjectable from "./helm-repositories-error-state.injectable"; @@ -15,12 +15,11 @@ const activeHelmRepositoriesInjectable = getInjectable({ instantiate: (di) => { const requestFromChannel = di.inject(requestFromChannelInjectionToken); - const getHelmRepositoriesChannel = di.inject(getActiveHelmRepositoriesChannelInjectable); const showErrorNotification = di.inject(showErrorNotificationInjectable); const helmRepositoriesErrorState = di.inject(helmRepositoriesErrorStateInjectable); return asyncComputed(async () => { - const result = await requestFromChannel(getHelmRepositoriesChannel); + const result = await requestFromChannel(getActiveHelmRepositoriesChannel); if (result.callWasSuccessful) { return result.response; diff --git a/src/renderer/components/+preferences/kubernetes/helm-charts/adding-of-public-helm-repository/select-helm-repository/add-helm-repository.injectable.ts b/src/renderer/components/+preferences/kubernetes/helm-charts/adding-of-public-helm-repository/select-helm-repository/add-helm-repository.injectable.ts index 50e02f4235..9a2370635b 100644 --- a/src/renderer/components/+preferences/kubernetes/helm-charts/adding-of-public-helm-repository/select-helm-repository/add-helm-repository.injectable.ts +++ b/src/renderer/components/+preferences/kubernetes/helm-charts/adding-of-public-helm-repository/select-helm-repository/add-helm-repository.injectable.ts @@ -3,19 +3,18 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import addHelmRepositoryChannelInjectable from "../../../../../../../common/helm/add-helm-repository-channel.injectable"; import type { HelmRepo } from "../../../../../../../common/helm/helm-repo"; import { requestFromChannelInjectionToken } from "../../../../../../../common/utils/channel/request-from-channel-injection-token"; import activeHelmRepositoriesInjectable from "../../active-helm-repositories.injectable"; import showErrorNotificationInjectable from "../../../../../notifications/show-error-notification.injectable"; import showSuccessNotificationInjectable from "../../../../../notifications/show-success-notification.injectable"; +import { addHelmRepositoryChannel } from "../../../../../../../common/helm/add-helm-repository-channel"; const addHelmRepositoryInjectable = getInjectable({ id: "add-public-helm-repository", instantiate: (di) => { const requestFromChannel = di.inject(requestFromChannelInjectionToken); - const addHelmRepositoryChannel = di.inject(addHelmRepositoryChannelInjectable); const activeHelmRepositories = di.inject(activeHelmRepositoriesInjectable); const showErrorNotification = di.inject(showErrorNotificationInjectable); const showSuccessNotification = di.inject(showSuccessNotificationInjectable); diff --git a/src/renderer/components/+preferences/kubernetes/helm-charts/remove-helm-repository.injectable.ts b/src/renderer/components/+preferences/kubernetes/helm-charts/remove-helm-repository.injectable.ts index 4f316baed0..3aa56a4b04 100644 --- a/src/renderer/components/+preferences/kubernetes/helm-charts/remove-helm-repository.injectable.ts +++ b/src/renderer/components/+preferences/kubernetes/helm-charts/remove-helm-repository.injectable.ts @@ -6,14 +6,13 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { HelmRepo } from "../../../../../common/helm/helm-repo"; import { requestFromChannelInjectionToken } from "../../../../../common/utils/channel/request-from-channel-injection-token"; import activeHelmRepositoriesInjectable from "./active-helm-repositories.injectable"; -import removeHelmRepositoryChannelInjectable from "../../../../../common/helm/remove-helm-repository-channel.injectable"; +import { removeHelmRepositoryChannel } from "../../../../../common/helm/remove-helm-repository-channel"; const removePublicHelmRepositoryInjectable = getInjectable({ id: "remove-public-helm-repository", instantiate: (di) => { const requestFromChannel = di.inject(requestFromChannelInjectionToken); - const removeHelmRepositoryChannel = di.inject(removeHelmRepositoryChannelInjectable); const activeHelmRepositories = di.inject(activeHelmRepositoriesInjectable); return async (repository: HelmRepo) => { diff --git a/src/renderer/components/test-utils/get-application-builder.tsx b/src/renderer/components/test-utils/get-application-builder.tsx index 7d6630be82..45f33bdc9e 100644 --- a/src/renderer/components/test-utils/get-application-builder.tsx +++ b/src/renderer/components/test-utils/get-application-builder.tsx @@ -61,7 +61,6 @@ import createApplicationWindowInjectable from "../../../main/start-main-applicat import type { CreateElectronWindow } from "../../../main/start-main-application/lens-window/application-window/create-electron-window.injectable"; import createElectronWindowInjectable from "../../../main/start-main-application/lens-window/application-window/create-electron-window.injectable"; import { applicationWindowInjectionToken } from "../../../main/start-main-application/lens-window/application-window/application-window-injection-token"; -import sendToChannelInElectronBrowserWindowInjectable from "../../../main/start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable"; import closeAllWindowsInjectable from "../../../main/start-main-application/lens-window/hide-all-windows/close-all-windows.injectable"; import type { LensWindow } from "../../../main/start-main-application/lens-window/application-window/create-lens-window.injectable"; import type { FakeExtensionOptions } from "./get-extension-fake"; @@ -166,7 +165,7 @@ export const getApplicationBuilder = () => { mainDi.register(mainExtensionsStateInjectable); }); - const overrideChannelsForWindow = overrideChannels(mainDi); + const { overrideForWindow, sendToWindow } = overrideChannels(mainDi); const beforeApplicationStartCallbacks: Callback[] = []; const beforeWindowStartCallbacks: Callback[] = []; @@ -208,7 +207,7 @@ export const getApplicationBuilder = () => { const windowDi = getRendererDi({ doGeneralOverrides: true }); - overrideChannelsForWindow(windowDi, windowId); + overrideForWindow(windowDi, windowId); overrideFsWithFakes(windowDi, fsState); runInAction(() => { @@ -259,9 +258,7 @@ export const getApplicationBuilder = () => { }, send: (arg) => { - const sendFake = mainDi.inject(sendToChannelInElectronBrowserWindowInjectable) as any; - - sendFake(windowId, null, arg); + sendToWindow(windowId, arg); }, reload: () => { diff --git a/src/renderer/components/update-button/restart-and-install-update.injectable.ts b/src/renderer/components/update-button/restart-and-install-update.injectable.ts index 854e0a428f..83fb3d72a3 100644 --- a/src/renderer/components/update-button/restart-and-install-update.injectable.ts +++ b/src/renderer/components/update-button/restart-and-install-update.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import restartAndInstallUpdateChannel from "../../../common/application-update/restart-and-install-update-channel/restart-and-install-update-channel.injectable"; +import { restartAndInstallUpdateChannel } from "../../../common/application-update/restart-and-install-update-channel"; import messageToChannelInjectable from "../../utils/channel/message-to-channel.injectable"; const restartAndInstallUpdateInjectable = getInjectable({ @@ -11,10 +11,9 @@ const restartAndInstallUpdateInjectable = getInjectable({ instantiate: (di) => { const messageToChannel = di.inject(messageToChannelInjectable); - const channel = di.inject(restartAndInstallUpdateChannel); return () => { - messageToChannel(channel); + messageToChannel(restartAndInstallUpdateChannel); }; }, }); diff --git a/src/renderer/frames/root-frame/broadcast-that-root-frame-is-rendered.injectable.ts b/src/renderer/frames/root-frame/broadcast-that-root-frame-is-rendered.injectable.ts index e6493e2832..841d19e002 100644 --- a/src/renderer/frames/root-frame/broadcast-that-root-frame-is-rendered.injectable.ts +++ b/src/renderer/frames/root-frame/broadcast-that-root-frame-is-rendered.injectable.ts @@ -3,18 +3,17 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { messageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; -import rootFrameIsRenderedChannelInjectable from "../../../common/root-frame-rendered-channel/root-frame-rendered-channel.injectable"; +import { sendMessageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; +import { rootFrameHasRenderedChannel } from "../../../common/root-frame/root-frame-rendered-channel"; const broadcastThatRootFrameIsRenderedInjectable = getInjectable({ id: "broadcast-that-root-frame-is-rendered", instantiate: (di) => { - const messageToChannel = di.inject(messageToChannelInjectionToken); - const rootFrameIsRenderedChannel = di.inject(rootFrameIsRenderedChannelInjectable); + const messageToChannel = di.inject(sendMessageToChannelInjectionToken); return () => { - messageToChannel(rootFrameIsRenderedChannel); + messageToChannel(rootFrameHasRenderedChannel); }; }, }); diff --git a/src/renderer/navigation/events.ts b/src/renderer/navigation/events.ts index 35021e1d72..7cacd1b313 100644 --- a/src/renderer/navigation/events.ts +++ b/src/renderer/navigation/events.ts @@ -5,14 +5,11 @@ import { ipcRenderer } from "electron"; import { reaction } from "mobx"; -import { broadcastMessage, ipcRendererOn } from "../../common/ipc"; -import { - getLegacyGlobalDiForExtensionApi, -} from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; +import { broadcastMessage } from "../../common/ipc"; +import { getLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; import matchedClusterIdInjectable from "./matched-cluster-id.injectable"; export const enum IpcRendererNavigationEvents { - RELOAD_PAGE = "renderer:page-reload", CLUSTER_VIEW_CURRENT_ID = "renderer:cluster-id-of-active-view", NAVIGATE_IN_APP = "renderer:navigate", NAVIGATE_IN_CLUSTER = "renderer:navigate-in-cluster", @@ -27,11 +24,6 @@ export function bindEvents() { if (process.isMainFrame) { bindClusterManagerRouteEvents(); } - - // Reload dashboard window - ipcRendererOn(IpcRendererNavigationEvents.RELOAD_PAGE, () => { - location.reload(); - }); } // Handle events only in main window renderer process (see also: cluster-manager.tsx) diff --git a/src/renderer/navigation/navigation-channel-listener.injectable.ts b/src/renderer/navigation/navigation-channel-listener.injectable.ts index 3a17451071..1b33b4fe2c 100644 --- a/src/renderer/navigation/navigation-channel-listener.injectable.ts +++ b/src/renderer/navigation/navigation-channel-listener.injectable.ts @@ -2,12 +2,14 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ +import type { InjectionToken } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable"; import currentlyInClusterFrameInjectable from "../routes/currently-in-cluster-frame.injectable"; -import appNavigationChannelInjectable from "../../common/front-end-routing/app-navigation-channel.injectable"; -import clusterFrameNavigationChannelInjectable from "../../common/front-end-routing/cluster-frame-navigation-channel.injectable"; +import { appNavigationChannel } from "../../common/front-end-routing/app-navigation-channel"; +import { clusterFrameNavigationChannel } from "../../common/front-end-routing/cluster-frame-navigation-channel"; import focusWindowInjectable from "./focus-window.injectable"; import { navigateToUrlInjectionToken } from "../../common/front-end-routing/navigate-to-url-injection-token"; +import type { MessageChannel, MessageChannelListener } from "../../common/utils/channel/message-channel-listener-injection-token"; import { messageChannelListenerInjectionToken } from "../../common/utils/channel/message-channel-listener-injection-token"; const navigationChannelListenerInjectable = getInjectable({ @@ -15,8 +17,6 @@ const navigationChannelListenerInjectable = getInjectable({ instantiate: (di) => { const currentlyInClusterFrame = di.inject(currentlyInClusterFrameInjectable); - const appNavigationChannel = di.inject(appNavigationChannelInjectable); - const clusterFrameNavigationChannel = di.inject(clusterFrameNavigationChannelInjectable); const focusWindow = di.inject(focusWindowInjectable); const navigateToUrl = di.inject(navigateToUrlInjectionToken); @@ -34,7 +34,7 @@ const navigationChannelListenerInjectable = getInjectable({ }, }; }, - injectionToken: messageChannelListenerInjectionToken, + injectionToken: messageChannelListenerInjectionToken as InjectionToken>, void>, }); export default navigationChannelListenerInjectable; diff --git a/src/renderer/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts b/src/renderer/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts index 6d76e35340..1e5b14bb40 100644 --- a/src/renderer/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts +++ b/src/renderer/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts @@ -6,8 +6,6 @@ import ipcRendererInjectable from "../ipc-renderer.injectable"; import { getInjectable } from "@ogre-tools/injectable"; import type { IpcRendererEvent } from "electron"; import { enlistMessageChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-message-channel-listener-injection-token"; -import { tentativeParseJson } from "../../../../common/utils/tentative-parse-json"; -import { pipeline } from "@ogre-tools/fp"; const enlistMessageChannelListenerInjectable = getInjectable({ id: "enlist-message-channel-listener-for-renderer", @@ -17,11 +15,7 @@ const enlistMessageChannelListenerInjectable = getInjectable({ return ({ channel, handler }) => { const nativeCallback = (_: IpcRendererEvent, message: unknown) => { - pipeline( - message, - tentativeParseJson, - handler, - ); + handler(message); }; ipcRenderer.on(channel.id, nativeCallback); diff --git a/src/renderer/utils/channel/channel-listeners/enlist-message-channel-listener.test.ts b/src/renderer/utils/channel/channel-listeners/enlist-message-channel-listener.test.ts index 4653dcdd5d..f5555d94f3 100644 --- a/src/renderer/utils/channel/channel-listeners/enlist-message-channel-listener.test.ts +++ b/src/renderer/utils/channel/channel-listeners/enlist-message-channel-listener.test.ts @@ -88,8 +88,8 @@ describe("enlist message channel listener in renderer", () => { expect(handlerMock).toHaveBeenCalledWith(true); }); - it("given stringified object as message, when message arrives, calls the handler with the message", () => { - onMock.mock.calls[0][1]({} as IpcRendererEvent, JSON.stringify({ some: "object" })); + it("given object as message, when message arrives, calls the handler with the message", () => { + onMock.mock.calls[0][1]({} as IpcRendererEvent, { some: "object" }); expect(handlerMock).toHaveBeenCalledWith({ some: "object" }); }); diff --git a/src/renderer/utils/channel/channel-listeners/enlist-request-channel-listener.injectable.ts b/src/renderer/utils/channel/channel-listeners/enlist-request-channel-listener.injectable.ts deleted file mode 100644 index 03253a06f2..0000000000 --- a/src/renderer/utils/channel/channel-listeners/enlist-request-channel-listener.injectable.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * 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 { enlistRequestChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-request-channel-listener-injection-token"; - -const enlistRequestChannelListenerInjectable = getInjectable({ - id: "enlist-request-channel-listener-for-renderer", - - instantiate: () => { - // Requests from main to renderer are not implemented yet. - return () => () => {}; - }, - - injectionToken: enlistRequestChannelListenerInjectionToken, -}); - -export default enlistRequestChannelListenerInjectable; diff --git a/src/renderer/utils/channel/channel-listeners/start-listening-of-channels.injectable.ts b/src/renderer/utils/channel/channel-listeners/start-listening-of-channels.injectable.ts index e423299915..3b10ef6bd9 100644 --- a/src/renderer/utils/channel/channel-listeners/start-listening-of-channels.injectable.ts +++ b/src/renderer/utils/channel/channel-listeners/start-listening-of-channels.injectable.ts @@ -4,13 +4,13 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { beforeFrameStartsInjectionToken } from "../../../before-frame-starts/before-frame-starts-injection-token"; -import listeningOfChannelsInjectable from "../../../../common/utils/channel/listening-of-channels.injectable"; +import listeningOnMessageChannelsInjectable from "../../../../common/utils/channel/listening-on-message-channels.injectable"; const startListeningOfChannelsInjectable = getInjectable({ id: "start-listening-of-channels-renderer", instantiate: (di) => { - const listeningOfChannels = di.inject(listeningOfChannelsInjectable); + const listeningOfChannels = di.inject(listeningOnMessageChannelsInjectable); return { id: "start-listening-of-channels-renderer", diff --git a/src/renderer/utils/channel/message-to-channel.injectable.ts b/src/renderer/utils/channel/message-to-channel.injectable.ts index 3e493fd322..eab7e4ec7f 100644 --- a/src/renderer/utils/channel/message-to-channel.injectable.ts +++ b/src/renderer/utils/channel/message-to-channel.injectable.ts @@ -3,9 +3,9 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { messageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; +import type { SendMessageToChannel } from "../../../common/utils/channel/message-to-channel-injection-token"; +import { sendMessageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; import sendToMainInjectable from "./send-to-main.injectable"; -import type { MessageChannel } from "../../../common/utils/channel/message-channel-injection-token"; const messageToChannelInjectable = getInjectable({ id: "message-to-channel", @@ -13,14 +13,12 @@ const messageToChannelInjectable = getInjectable({ instantiate: (di) => { const sendToMain = di.inject(sendToMainInjectable); - // TODO: Figure out way to improve typing in internals - // Notice that this should be injected using "messageToChannelInjectionToken" which is typed correctly. - return (channel: MessageChannel, message?: unknown) => { + return ((channel, message) => { sendToMain(channel.id, message); - }; + }) as SendMessageToChannel; }, - injectionToken: messageToChannelInjectionToken, + injectionToken: sendMessageToChannelInjectionToken, }); export default messageToChannelInjectable; diff --git a/src/renderer/utils/channel/message-to-channel.test.ts b/src/renderer/utils/channel/message-to-channel.test.ts deleted file mode 100644 index 443abfb0dc..0000000000 --- a/src/renderer/utils/channel/message-to-channel.test.ts +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import type { MessageToChannel } from "../../../common/utils/channel/message-to-channel-injection-token"; -import type { MessageChannel } from "../../../common/utils/channel/message-channel-injection-token"; -import { getDiForUnitTesting } from "../../getDiForUnitTesting"; -import { messageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; -import ipcRendererInjectable from "./ipc-renderer.injectable"; -import type { IpcRenderer } from "electron"; - -describe("message to channel from renderer", () => { - let messageToChannel: MessageToChannel; - let sendMock: jest.Mock; - - beforeEach(() => { - const di = getDiForUnitTesting({ doGeneralOverrides: true }); - - sendMock = jest.fn(); - - di.override(ipcRendererInjectable, () => ({ - send: sendMock, - }) as unknown as IpcRenderer); - - messageToChannel = di.inject(messageToChannelInjectionToken); - }); - - it("given string as message, when messaging to channel, sends stringified message", () => { - messageToChannel(someChannel, "some-message"); - - expect(sendMock).toHaveBeenCalledWith("some-channel-id", '"some-message"'); - }); - - it("given boolean as message, when messaging to channel, sends stringified message", () => { - messageToChannel(someChannel, true); - - expect(sendMock).toHaveBeenCalledWith("some-channel-id", "true"); - }); - - it("given number as message, when messaging to channel, sends stringified message", () => { - messageToChannel(someChannel, 42); - - expect(sendMock).toHaveBeenCalledWith("some-channel-id", "42"); - }); - - it("given object as message, when messaging to channel, sends stringified message", () => { - messageToChannel(someChannel, { some: "object" }); - - expect(sendMock).toHaveBeenCalledWith( - "some-channel-id", - JSON.stringify({ some: "object" }), - ); - }); -}); - -const someChannel: MessageChannel = { id: "some-channel-id" }; diff --git a/src/renderer/utils/channel/request-from-channel.injectable.ts b/src/renderer/utils/channel/request-from-channel.injectable.ts index f77287a2ed..fd0815b1a3 100644 --- a/src/renderer/utils/channel/request-from-channel.injectable.ts +++ b/src/renderer/utils/channel/request-from-channel.injectable.ts @@ -4,10 +4,8 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import ipcRendererInjectable from "./ipc-renderer.injectable"; +import type { RequestFromChannel } from "../../../common/utils/channel/request-from-channel-injection-token"; import { requestFromChannelInjectionToken } from "../../../common/utils/channel/request-from-channel-injection-token"; -import { pipeline } from "@ogre-tools/fp"; -import { tentativeStringifyJson } from "../../../common/utils/tentative-stringify-json"; -import { tentativeParseJson } from "../../../common/utils/tentative-parse-json"; const requestFromChannelInjectable = getInjectable({ id: "request-from-channel", @@ -15,13 +13,7 @@ const requestFromChannelInjectable = getInjectable({ instantiate: (di) => { const ipcRenderer = di.inject(ipcRendererInjectable); - return async (channel, ...[request]) => - await pipeline( - request, - tentativeStringifyJson, - (req) => ipcRenderer.invoke(channel.id, req), - tentativeParseJson, - ); + return ((channel, request) => ipcRenderer.invoke(channel.id, request)) as RequestFromChannel; }, injectionToken: requestFromChannelInjectionToken, diff --git a/src/renderer/utils/channel/request-from-channel.test.ts b/src/renderer/utils/channel/request-from-channel.test.ts deleted file mode 100644 index d7b343bf02..0000000000 --- a/src/renderer/utils/channel/request-from-channel.test.ts +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import type { MessageChannel } from "../../../common/utils/channel/message-channel-injection-token"; -import { getDiForUnitTesting } from "../../getDiForUnitTesting"; -import ipcRendererInjectable from "./ipc-renderer.injectable"; -import type { IpcRenderer } from "electron"; -import type { AsyncFnMock } from "@async-fn/jest"; -import asyncFn from "@async-fn/jest"; -import type { RequestFromChannel } from "../../../common/utils/channel/request-from-channel-injection-token"; -import { requestFromChannelInjectionToken } from "../../../common/utils/channel/request-from-channel-injection-token"; -import requestFromChannelInjectable from "./request-from-channel.injectable"; -import { getPromiseStatus } from "../../../common/test-utils/get-promise-status"; - -describe("request from channel in renderer", () => { - let requestFromChannel: RequestFromChannel; - let invokeMock: AsyncFnMock<(channelId: string, request: any) => any>; - - beforeEach(() => { - const di = getDiForUnitTesting({ doGeneralOverrides: true }); - - di.unoverride(requestFromChannelInjectable); - - invokeMock = asyncFn(); - - di.override(ipcRendererInjectable, () => ({ - invoke: invokeMock, - }) as unknown as IpcRenderer); - - requestFromChannel = di.inject(requestFromChannelInjectionToken); - }); - - describe("when messaging to channel", () => { - let actualPromise: Promise; - - beforeEach(() => { - actualPromise = requestFromChannel(someChannel, "some-message"); - }); - - it("sends stringified message", () => { - expect(invokeMock).toHaveBeenCalledWith("some-channel-id", '"some-message"'); - }); - - it("does not resolve yet", async () => { - const promiseStatus = await getPromiseStatus(actualPromise); - - expect(promiseStatus.fulfilled).toBe(false); - }); - - it("when invoking resolves, resolves", async () => { - await invokeMock.resolve("some-response"); - - const actual = await actualPromise; - - expect(actual).toBe("some-response"); - }); - - it("when invoking resolves with stringified string, resolves with string", async () => { - await invokeMock.resolve('"some-response"'); - - const actual = await actualPromise; - - expect(actual).toBe("some-response"); - }); - - it("when invoking resolves with stringified boolean, resolves with boolean", async () => { - await invokeMock.resolve("true"); - - const actual = await actualPromise; - - expect(actual).toBe(true); - }); - - it("when invoking resolves with stringified number, resolves with number", async () => { - await invokeMock.resolve("42"); - - const actual = await actualPromise; - - expect(actual).toBe(42); - }); - - it("when invoking resolves with stringified object, resolves with object", async () => { - await invokeMock.resolve(JSON.stringify({ some: "object" })); - - const actual = await actualPromise; - - expect(actual).toEqual({ some: "object" }); - }); - }); - - it("given string as message, when messaging to channel, sends stringified message", () => { - requestFromChannel(someChannel, "some-message"); - - expect(invokeMock).toHaveBeenCalledWith("some-channel-id", '"some-message"'); - }); - - it("given boolean as message, when messaging to channel, sends stringified message", () => { - requestFromChannel(someChannel, true); - - expect(invokeMock).toHaveBeenCalledWith("some-channel-id", "true"); - }); - - it("given number as message, when messaging to channel, sends stringified message", () => { - requestFromChannel(someChannel, 42); - - expect(invokeMock).toHaveBeenCalledWith("some-channel-id", "42"); - }); - - it("given object as message, when messaging to channel, sends stringified message", () => { - requestFromChannel(someChannel, { some: "object" }); - - expect(invokeMock).toHaveBeenCalledWith( - "some-channel-id", - JSON.stringify({ some: "object" }), - ); - }); -}); - -const someChannel: MessageChannel = { id: "some-channel-id" }; diff --git a/src/renderer/utils/channel/send-to-main.injectable.ts b/src/renderer/utils/channel/send-to-main.injectable.ts index 0811a78798..6eb4540062 100644 --- a/src/renderer/utils/channel/send-to-main.injectable.ts +++ b/src/renderer/utils/channel/send-to-main.injectable.ts @@ -3,9 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import type { JsonValue } from "type-fest"; import ipcRendererInjectable from "./ipc-renderer.injectable"; -import { tentativeStringifyJson } from "../../../common/utils/tentative-stringify-json"; const sendToMainInjectable = getInjectable({ id: "send-to-main", @@ -13,11 +11,8 @@ const sendToMainInjectable = getInjectable({ instantiate: (di) => { const ipcRenderer = di.inject(ipcRendererInjectable); - // TODO: Figure out way to improve typing in internals - return (channelId: string, message: JsonValue extends T ? T : never ) => { - const stringifiedMessage = tentativeStringifyJson(message); - - ipcRenderer.send(channelId, ...(stringifiedMessage ? [stringifiedMessage] : [])); + return (channelId: string, message: any) => { + ipcRenderer.send(channelId, message); }; }, }); diff --git a/src/renderer/utils/resolve-proxy/resolve-system-proxy.injectable.ts b/src/renderer/utils/resolve-proxy/resolve-system-proxy.injectable.ts index 8fcb9063d0..5468a8c7b7 100644 --- a/src/renderer/utils/resolve-proxy/resolve-system-proxy.injectable.ts +++ b/src/renderer/utils/resolve-proxy/resolve-system-proxy.injectable.ts @@ -5,14 +5,13 @@ import { getInjectable } from "@ogre-tools/injectable"; import { resolveSystemProxyInjectionToken } from "../../../common/utils/resolve-system-proxy/resolve-system-proxy-injection-token"; import requestFromChannelInjectable from "../channel/request-from-channel.injectable"; -import resolveSystemProxyChannelInjectable from "../../../common/utils/resolve-system-proxy/resolve-system-proxy-channel.injectable"; +import { resolveSystemProxyChannel } from "../../../common/utils/resolve-system-proxy/resolve-system-proxy-channel"; const resolveSystemProxyInjectable = getInjectable({ id: "resolve-system-proxy-for-renderer", instantiate: (di) => { const requestFromChannel = di.inject(requestFromChannelInjectable); - const resolveSystemProxyChannel = di.inject(resolveSystemProxyChannelInjectable); return async (url) => requestFromChannel(resolveSystemProxyChannel, url); }, diff --git a/src/renderer/utils/sync-box/provide-initial-values-for-sync-boxes.injectable.ts b/src/renderer/utils/sync-box/provide-initial-values-for-sync-boxes.injectable.ts index f7d692cdef..b356aa0b32 100644 --- a/src/renderer/utils/sync-box/provide-initial-values-for-sync-boxes.injectable.ts +++ b/src/renderer/utils/sync-box/provide-initial-values-for-sync-boxes.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { beforeFrameStartsInjectionToken } from "../../before-frame-starts/before-frame-starts-injection-token"; -import syncBoxInitialValueChannelInjectable from "../../../common/utils/sync-box/sync-box-initial-value-channel.injectable"; +import { syncBoxInitialValueChannel } from "../../../common/utils/sync-box/channels"; import createSyncBoxStateInjectable from "../../../common/utils/sync-box/sync-box-state.injectable"; import { requestFromChannelInjectionToken } from "../../../common/utils/channel/request-from-channel-injection-token"; import { runInAction } from "mobx"; @@ -17,7 +17,6 @@ const provideInitialValuesForSyncBoxesInjectable = getInjectable({ instantiate: (di) => { const requestFromChannel = di.inject(requestFromChannelInjectionToken); - const syncBoxInitialValueChannel = di.inject(syncBoxInitialValueChannelInjectable); const syncBoxes = di.injectMany(syncBoxInjectionToken); diff --git a/src/test-utils/channel-fakes/override-channels.ts b/src/test-utils/channel-fakes/override-channels.ts index 7d3a20cd75..798fcd84af 100644 --- a/src/test-utils/channel-fakes/override-channels.ts +++ b/src/test-utils/channel-fakes/override-channels.ts @@ -3,18 +3,27 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import type { DiContainer } from "@ogre-tools/injectable"; +import type { SendToViewArgs } from "../../main/start-main-application/lens-window/application-window/create-lens-window.injectable"; import { overrideMessagingFromMainToWindow } from "./override-messaging-from-main-to-window"; import { overrideMessagingFromWindowToMain } from "./override-messaging-from-window-to-main"; import { overrideRequestingFromWindowToMain } from "./override-requesting-from-window-to-main"; -export const overrideChannels = (mainDi: DiContainer) => { - const overrideMessagingFromMainToWindowForWindow = overrideMessagingFromMainToWindow(mainDi); +export interface OverrideChannels { + overrideForWindow: (windowDi: DiContainer, windowId: string) => void; + sendToWindow: (windowId: string, args: SendToViewArgs) => void; +} + +export const overrideChannels = (mainDi: DiContainer): OverrideChannels => { + const { overrideEnlistForWindow, sendToWindow } = overrideMessagingFromMainToWindow(); const overrideMessagingFromWindowToForWindow = overrideMessagingFromWindowToMain(mainDi); const overrideRequestingFromWindowToMainForWindow = overrideRequestingFromWindowToMain(mainDi); - return (windowDi: DiContainer, windowId: string) => { - overrideMessagingFromMainToWindowForWindow(windowDi, windowId); - overrideMessagingFromWindowToForWindow(windowDi); - overrideRequestingFromWindowToMainForWindow(windowDi); + return { + overrideForWindow: (windowDi, windowId) => { + overrideEnlistForWindow(windowDi, windowId); + overrideMessagingFromWindowToForWindow(windowDi); + overrideRequestingFromWindowToMainForWindow(windowDi); + }, + sendToWindow, }; }; diff --git a/src/test-utils/channel-fakes/override-messaging-from-main-to-window.ts b/src/test-utils/channel-fakes/override-messaging-from-main-to-window.ts index 852b2cfb0b..f9275c18b2 100644 --- a/src/test-utils/channel-fakes/override-messaging-from-main-to-window.ts +++ b/src/test-utils/channel-fakes/override-messaging-from-main-to-window.ts @@ -3,18 +3,22 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import type { MessageChannelListener } from "../../common/utils/channel/message-channel-listener-injection-token"; -import sendToChannelInElectronBrowserWindowInjectable from "../../main/start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable"; -import type { SendToViewArgs } from "../../main/start-main-application/lens-window/application-window/create-lens-window.injectable"; import enlistMessageChannelListenerInjectableInRenderer from "../../renderer/utils/channel/channel-listeners/enlist-message-channel-listener.injectable"; import type { DiContainer } from "@ogre-tools/injectable"; -import { tentativeParseJson } from "../../common/utils/tentative-parse-json"; -import { getOrInsert } from "../../common/utils"; +import { getOrInsert, getOrInsertSet } from "../../common/utils"; +import type { SendToViewArgs } from "../../main/start-main-application/lens-window/application-window/create-lens-window.injectable"; +import { deserialize, serialize } from "v8"; type ListenerSet = Set>; type WindowListenerMap = Map; type ListenerFakeMap = Map; -export const overrideMessagingFromMainToWindow = (mainDi: DiContainer) => { +export interface OverriddenWindowMessaging { + sendToWindow(windowId: string, args: SendToViewArgs): void; + overrideEnlistForWindow(windowDi: DiContainer, windowId: string): void; +} + +export const overrideMessagingFromMainToWindow = (): OverriddenWindowMessaging => { const messageChannelListenerFakesForRenderer: ListenerFakeMap = new Map(); const getWindowListeners = (channelId: string, windowId: string) => { @@ -24,68 +28,52 @@ export const overrideMessagingFromMainToWindow = (mainDi: DiContainer) => { new Map(), ); - return getOrInsert( - channelListeners, - windowId, - new Set(), - ); + return getOrInsertSet(channelListeners, windowId); }; - mainDi.override( - sendToChannelInElectronBrowserWindowInjectable, + return { + overrideEnlistForWindow: (windowDi, windowId) => { + windowDi.override( + enlistMessageChannelListenerInjectableInRenderer, - () => - ( - windowId: string, - browserWindow, - { channel: channelId, frameInfo, data = [] }: SendToViewArgs, - ) => { - const windowListeners = getWindowListeners(channelId, windowId); - - if (frameInfo) { - throw new Error( - `Tried to send message to frame "${frameInfo.frameId}" in process "${frameInfo.processId}" using channel "${channelId}" which isn't supported yet.`, + () => (listener) => { + const windowListeners = getWindowListeners( + listener.channel.id, + windowId, ); - } - if (data.length > 1) { - throw new Error( - `Tried to send message to channel "${channelId}" with more than one argument which is not supported in MessageChannelListener yet.`, - ); - } + windowListeners.add(listener); - if (windowListeners.size === 0) { - throw new Error( - `Tried to send message to channel "${channelId}" but there where no listeners. Current channels with listeners: "${[ - ...messageChannelListenerFakesForRenderer.keys(), - ].join('", "')}"`, - ); - } + return () => { + windowListeners.delete(listener); + }; + }, + ); + }, + sendToWindow: (windowId, { channel, data, frameInfo }) => { + try { + data = deserialize(serialize(data)); + } catch (error) { + throw new Error(`Tried to send a message to channel "${channel}" that is not compatible with StructuredClone: ${error}`); + } - const message = tentativeParseJson(data[0]); + const windowListeners = getWindowListeners(channel, windowId); - windowListeners.forEach((listener) => - listener.handler(message), + if (frameInfo) { + throw new Error( + `Tried to send message to frame "${frameInfo.frameId}" in process "${frameInfo.processId}" using channel "${channel}" which isn't supported yet.`, ); - }, - ); + } - return (windowDi: DiContainer, windowId: string) => { - windowDi.override( - enlistMessageChannelListenerInjectableInRenderer, - - () => (listener) => { - const windowListeners = getWindowListeners( - listener.channel.id, - windowId, + if (windowListeners.size === 0) { + throw new Error( + `Tried to send message to channel "${channel}" but there where no listeners. Current channels with listeners: "${[ + ...messageChannelListenerFakesForRenderer.keys(), + ].join('", "')}"`, ); + } - windowListeners.add(listener); - - return () => { - windowListeners.delete(listener); - }; - }, - ); + windowListeners.forEach((listener) => listener.handler(data)); + }, }; }; diff --git a/src/test-utils/channel-fakes/override-messaging-from-window-to-main.ts b/src/test-utils/channel-fakes/override-messaging-from-window-to-main.ts index ba6813235b..f00f4e626c 100644 --- a/src/test-utils/channel-fakes/override-messaging-from-window-to-main.ts +++ b/src/test-utils/channel-fakes/override-messaging-from-window-to-main.ts @@ -3,54 +3,36 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import type { DiContainer } from "@ogre-tools/injectable"; -import assert from "assert"; -import type { MessageChannel } from "../../common/utils/channel/message-channel-injection-token"; -import type { MessageChannelListener } from "../../common/utils/channel/message-channel-listener-injection-token"; +import type { MessageChannel, MessageChannelListener } from "../../common/utils/channel/message-channel-listener-injection-token"; import enlistMessageChannelListenerInjectableInMain from "../../main/utils/channel/channel-listeners/enlist-message-channel-listener.injectable"; +import { getOrInsertSet } from "../../renderer/utils"; import sendToMainInjectable from "../../renderer/utils/channel/send-to-main.injectable"; export const overrideMessagingFromWindowToMain = (mainDi: DiContainer) => { const messageChannelListenerFakesForMain = new Map< string, - Set>> + Set>> >(); mainDi.override( enlistMessageChannelListenerInjectableInMain, () => (listener) => { - const channelId = listener.channel.id; + const listeners = getOrInsertSet(messageChannelListenerFakesForMain, listener.channel.id); - if (!messageChannelListenerFakesForMain.has(channelId)) { - messageChannelListenerFakesForMain.set(channelId, new Set()); - } - - const listeners = messageChannelListenerFakesForMain.get( - channelId, - ); - - assert(listeners); - - // TODO: Figure out typing - listeners.add( - listener as unknown as MessageChannelListener>, - ); + listeners.add(listener); return () => { - // TODO: Figure out typing - listeners.delete( - listener as unknown as MessageChannelListener>, - ); + listeners.delete(listener); }; }, ); return (windowDi: DiContainer) => { windowDi.override(sendToMainInjectable, () => (channelId, message) => { - const listeners = - messageChannelListenerFakesForMain.get(channelId) || new Set(); + const listeners = messageChannelListenerFakesForMain.get(channelId); - if (listeners.size === 0) { + if (!listeners || listeners.size === 0) { throw new Error( `Tried to send message to channel "${channelId}" but there where no listeners. Current channels with listeners: "${[ ...messageChannelListenerFakesForMain.keys(), diff --git a/src/test-utils/channel-fakes/override-requesting-from-window-to-main.ts b/src/test-utils/channel-fakes/override-requesting-from-window-to-main.ts index 8ee4227289..ddf758f5b6 100644 --- a/src/test-utils/channel-fakes/override-requesting-from-window-to-main.ts +++ b/src/test-utils/channel-fakes/override-requesting-from-window-to-main.ts @@ -3,35 +3,29 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import type { DiContainer } from "@ogre-tools/injectable"; -import type { RequestChannel } from "../../common/utils/channel/request-channel-injection-token"; -import type { RequestChannelListener } from "../../common/utils/channel/request-channel-listener-injection-token"; +import type { RequestChannel } from "../../common/utils/channel/request-channel-listener-injection-token"; +import type { RequestFromChannel } from "../../common/utils/channel/request-from-channel-injection-token"; import enlistRequestChannelListenerInjectableInMain from "../../main/utils/channel/channel-listeners/enlist-request-channel-listener.injectable"; +import type { RequestChannelListener } from "../../main/utils/channel/channel-listeners/listener-tokens"; import requestFromChannelInjectable from "../../renderer/utils/channel/request-from-channel.injectable"; export const overrideRequestingFromWindowToMain = (mainDi: DiContainer) => { const requestChannelListenerFakesForMain = new Map< - string, - RequestChannelListener> - >(); + string, + RequestChannelListener> + >(); mainDi.override( enlistRequestChannelListenerInjectableInMain, () => (listener) => { - if (requestChannelListenerFakesForMain.get(listener.channel.id)) { + if (requestChannelListenerFakesForMain.has(listener.channel.id)) { throw new Error( `Tried to enlist listener for channel "${listener.channel.id}", but it was already enlisted`, ); } - requestChannelListenerFakesForMain.set( - listener.channel.id, - - // TODO: Figure out typing - listener as unknown as RequestChannelListener< - RequestChannel - >, - ); + requestChannelListenerFakesForMain.set(listener.channel.id, listener); return () => { requestChannelListenerFakesForMain.delete(listener.channel.id); @@ -43,7 +37,7 @@ export const overrideRequestingFromWindowToMain = (mainDi: DiContainer) => { windowDi.override( requestFromChannelInjectable, - () => async (channel, ...[request]) => { + () => (async (channel, request) => { const requestListener = requestChannelListenerFakesForMain.get(channel.id); if (!requestListener) { @@ -53,7 +47,7 @@ export const overrideRequestingFromWindowToMain = (mainDi: DiContainer) => { } return requestListener.handler(request); - }, + }) as RequestFromChannel, ); }; };