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:
Sebastian Malton authored and GitHub committed 2022-10-13 07:50:19 -04:00
1 parent d96918c966
commit 5a5eda935b
115 files changed
+949 -1568

No files matched your search

@@ -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;
@@ -20,7 +20,7 @@ export interface ElectronWindow {
export interface SendToViewArgs {
channel: string;
frameInfo?: ClusterFrameInfo;
data?: unknown[];
data?: unknown;
}
export interface LensWindow {
@@ -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;
@@ -37,7 +37,7 @@ const navigateInjectable = getInjectable({
applicationWindow.send({
channel,
frameInfo,
data: [url],
data: url,
});
};
},
@@ -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 {
@@ -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;
@@ -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;