mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Add better type safety around Channels (#6133)
* Add better type safety around Channels - Reallow non-JSON serializable complex types - Remove unnecessary JSON serialization step to IPC - Remove unnecesary injectable-ization of MessageChannel and RequestChannel declarations - Add channel listener injectable getter function to remove general need for type casting and improve type safety Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add check to verify data in IPC related tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix implementation in light of new safety check in tests Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix listener ID clash potential Signed-off-by: Sebastian Malton <sebastian@malton.name> * Switch to not forcing split of request channel handlers being seperate from the listener decl Signed-off-by: Sebastian Malton <sebastian@malton.name> * Move message channels to changed signature too Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix not registering listener Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix test imports Signed-off-by: Sebastian Malton <sebastian@malton.name> * Fix type errors Signed-off-by: Sebastian Malton <sebastian@malton.name> * Refactor listening of different channel kinds Signed-off-by: Sebastian Malton <sebastian@malton.name> * Add test covering new checking code for request channel handlers Signed-off-by: Sebastian Malton <sebastian@malton.name> Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
1 parent
d96918c966
commit
5a5eda935b
115 files changed
+949
-1568
No files matched your search
@@ -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);
|
||||
},
|
||||
|
||||
+2
-3
@@ -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;
|
||||
|
||||
+1
-2
@@ -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);
|
||||
|
||||
+1
-2
@@ -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) => {
|
||||
|
||||
@@ -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: () => {
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<MessageChannelListener<MessageChannel<string>>, void>,
|
||||
});
|
||||
|
||||
export default navigationChannelListenerInjectable;
|
||||
+1
-7
@@ -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);
|
||||
|
||||
+2
-2
@@ -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" });
|
||||
});
|
||||
|
||||
-19
@@ -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;
|
||||
+2
-2
@@ -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",
|
||||
|
||||
@@ -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<any>, message?: unknown) => {
|
||||
return ((channel, message) => {
|
||||
sendToMain(channel.id, message);
|
||||
};
|
||||
}) as SendMessageToChannel;
|
||||
},
|
||||
|
||||
injectionToken: messageToChannelInjectionToken,
|
||||
injectionToken: sendMessageToChannelInjectionToken,
|
||||
});
|
||||
|
||||
export default messageToChannelInjectable;
|
||||
@@ -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<any> = { id: "some-channel-id" };
|
||||
@@ -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,
|
||||
|
||||
@@ -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<any>;
|
||||
|
||||
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<any> = { id: "some-channel-id" };
|
||||
@@ -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 <T>(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);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
},
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in new issue
Block a user