1
0
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:
Sebastian Malton 2022-10-13 07:50:19 -04:00 committed by GitHub
parent d96918c966
commit 5a5eda935b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
115 changed files with 949 additions and 1568 deletions

View File

@ -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<void, AppPaths>;
const appPathsChannelInjectable = getInjectable({
id: "app-paths-channel",
instantiate: (): AppPathsChannel => ({
id: "app-paths",
}),
injectionToken: messageChannelInjectionToken,
});
export default appPathsChannelInjectable;

View File

@ -0,0 +1,13 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { AppPaths } from "./app-path-injection-token";
import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token";
export type AppPathsChannel = RequestChannel<void, AppPaths>;
export const appPathsChannel: AppPathsChannel = {
id: "app-paths",
};

View File

@ -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<void>;
export const restartAndInstallUpdateChannel: RestartAndInstallUpdateChannel = {
id: "restart-and-install-update-channel",
};

View File

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

View File

@ -19,7 +19,7 @@ const selectedUpdateChannelInjectable = getInjectable({
instantiate: (di): SelectedUpdateChannel => { instantiate: (di): SelectedUpdateChannel => {
const defaultUpdateChannel = di.inject(defaultUpdateChannelInjectable); const defaultUpdateChannel = di.inject(defaultUpdateChannelInjectable);
const state = observable.box<UpdateChannel>(); const state = observable.box<UpdateChannel>(undefined, { deep: false });
return { return {
value: computed(() => state.get() ?? defaultUpdateChannel.get()), value: computed(() => state.get() ?? defaultUpdateChannel.get()),

View File

@ -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<string>;
const appNavigationChannelInjectable = getInjectable({
id: "app-navigation-channel",
instantiate: (): AppNavigationChannel => ({
id: IpcRendererNavigationEvents.NAVIGATE_IN_APP,
}),
injectionToken: messageChannelInjectionToken,
});
export default appNavigationChannelInjectable;

View File

@ -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<string>;
export const appNavigationChannel: AppNavigationChannel = {
id: IpcRendererNavigationEvents.NAVIGATE_IN_APP,
};

View File

@ -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<string>;
const clusterFrameNavigationChannelInjectable = getInjectable({
id: "cluster-frame-navigation-channel",
instantiate: (): ClusterFrameNavigationChannel => ({
id: IpcRendererNavigationEvents.NAVIGATE_IN_CLUSTER,
}),
injectionToken: messageChannelInjectionToken,
});
export default clusterFrameNavigationChannelInjectable;

View File

@ -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<string>;
export const clusterFrameNavigationChannel: ClusterFrameNavigationChannel = {
id: IpcRendererNavigationEvents.NAVIGATE_IN_CLUSTER,
};

View File

@ -5,22 +5,33 @@
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import type { ExecFileOptions } from "child_process"; import type { ExecFileOptions } from "child_process";
import { execFile } 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<string>; export interface ExecFile {
(filePath: string, args: string[], options: ExecFileOptions): Promise<AsyncResult<string, { stderr: string; error: Error }>>;
}
const execFileInjectable = getInjectable({ const execFileInjectable = getInjectable({
id: "exec-file", id: "exec-file",
instantiate: (): ExecFile => { instantiate: (): ExecFile => (filePath, args, options) => new Promise((resolve) => {
const asyncExecFile = promisify(execFile); execFile(filePath, args, options, (error, stdout, stderr) => {
if (error) {
return async (filePath, args, options) => { resolve({
const result = await asyncExecFile(filePath, args, options); callWasSuccessful: false,
error: {
return result.stdout; error,
}; stderr,
}, },
});
} else {
resolve({
callWasSuccessful: true,
response: stdout,
});
}
});
}),
causesSideEffects: true, causesSideEffects: true,
}); });

View File

@ -2,22 +2,12 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import type { HelmRepo } from "./helm-repo"; 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 { AsyncResult } from "../utils/async-result";
import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token";
export type AddHelmRepositoryChannel = RequestChannel<HelmRepo, AsyncResult<string>>; export type AddHelmRepositoryChannel = RequestChannel<HelmRepo, AsyncResult<string>>;
const addHelmRepositoryChannelInjectable = getInjectable({ export const addHelmRepositoryChannel: AddHelmRepositoryChannel = {
id: "add-helm-repository-channel", id: "add-helm-repository-channel",
};
instantiate: (): AddHelmRepositoryChannel => ({
id: "add-helm-repository-channel",
}),
injectionToken: requestChannelInjectionToken,
});
export default addHelmRepositoryChannelInjectable;

View File

@ -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<void, AsyncResult<HelmRepo[]>>;
const getActiveHelmRepositoriesChannelInjectable = getInjectable({
id: "get-active-helm-repositories-channel",
instantiate: (): GetHelmRepositoriesChannel => ({
id: "get-helm-active-list-repositories",
}),
injectionToken: requestChannelInjectionToken,
});
export default getActiveHelmRepositoriesChannelInjectable;

View File

@ -0,0 +1,13 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import 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<void, AsyncResult<HelmRepo[]>>;
export const getActiveHelmRepositoriesChannel: GetActiveHelmRepositoriesChannel = {
id: "get-helm-active-list-repositories",
};

View File

@ -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<HelmRepo>;
const removeHelmRepositoryChannelInjectable = getInjectable({
id: "remove-helm-repository-channel",
instantiate: (): RemoveHelmRepositoryChannel => ({
id: "remove-helm-repository-channel",
}),
injectionToken: requestChannelInjectionToken,
});
export default removeHelmRepositoryChannelInjectable;

View File

@ -0,0 +1,13 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { AsyncResult } from "../utils/async-result";
import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token";
import type { HelmRepo } from "./helm-repo";
export type RemoveHelmRepositoryChannel = RequestChannel<HelmRepo, AsyncResult<string, string>>;
export const removeHelmRepositoryChannel: RemoveHelmRepositoryChannel = {
id: "remove-helm-repository-channel",
};

View File

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

View File

@ -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<void>;
export const rootFrameHasRenderedChannel: RootFrameHasRenderedChannel = {
id: "root-frame-rendered",
};

View File

@ -4,31 +4,31 @@
*/ */
import type { DiContainer } from "@ogre-tools/injectable"; import type { DiContainer } from "@ogre-tools/injectable";
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import type { MessageToChannel } from "./message-to-channel-injection-token"; import type { SendMessageToChannel } from "./message-to-channel-injection-token";
import { messageToChannelInjectionToken } 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 type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder";
import { getApplicationBuilder } 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 { 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 { 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 type { RequestFromChannel } from "./request-from-channel-injection-token";
import { requestFromChannelInjectionToken } from "./request-from-channel-injection-token"; import { requestFromChannelInjectionToken } from "./request-from-channel-injection-token";
import type { RequestChannel } from "./request-channel-injection-token"; import type { RequestChannel } from "./request-channel-listener-injection-token";
import { requestChannelListenerInjectionToken } from "./request-channel-listener-injection-token";
import type { AsyncFnMock } from "@async-fn/jest"; import type { AsyncFnMock } from "@async-fn/jest";
import asyncFn from "@async-fn/jest"; import asyncFn from "@async-fn/jest";
import { getPromiseStatus } from "../../test-utils/get-promise-status"; import { getPromiseStatus } from "../../test-utils/get-promise-status";
import { runInAction } from "mobx"; 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<string>; type TestMessageChannel = MessageChannel<string>;
type TestRequestChannel = RequestChannel<string, string>; type TestRequestChannel = RequestChannel<string, string>;
describe("channel", () => { describe("channel", () => {
describe("messaging from main to renderer, given listener for channel in a window and application has started", () => { 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 messageListenerInWindowMock: jest.Mock;
let mainDi: DiContainer; let mainDi: DiContainer;
let messageToChannel: MessageToChannel; let messageToChannel: SendMessageToChannel;
let builder: ApplicationBuilder; let builder: ApplicationBuilder;
beforeEach(async () => { beforeEach(async () => {
@ -39,24 +39,17 @@ describe("channel", () => {
const testChannelListenerInTestWindowInjectable = getInjectable({ const testChannelListenerInTestWindowInjectable = getInjectable({
id: "test-channel-listener-in-test-window", id: "test-channel-listener-in-test-window",
instantiate: (di) => ({ instantiate: () => ({
channel: di.inject(testMessageChannelInjectable), channel: testMessageChannel,
handler: messageListenerInWindowMock, handler: messageListenerInWindowMock,
}), }),
injectionToken: messageChannelListenerInjectionToken, injectionToken: messageChannelListenerInjectionToken,
}); });
builder.beforeApplicationStart((mainDi) => {
runInAction(() => {
mainDi.register(testMessageChannelInjectable);
});
});
builder.beforeWindowStart((windowDi) => { builder.beforeWindowStart((windowDi) => {
runInAction(() => { runInAction(() => {
windowDi.register(testChannelListenerInTestWindowInjectable); windowDi.register(testChannelListenerInTestWindowInjectable);
windowDi.register(testMessageChannelInjectable);
}); });
}); });
@ -64,8 +57,7 @@ describe("channel", () => {
await builder.startHidden(); await builder.startHidden();
testMessageChannel = mainDi.inject(testMessageChannelInjectable); messageToChannel = mainDi.inject(sendMessageToChannelInjectionToken);
messageToChannel = mainDi.inject(messageToChannelInjectionToken);
}); });
describe("given window is started", () => { 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", () => { 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 messageListenerInMainMock: jest.Mock;
let messageToChannel: MessageToChannel; let messageToChannel: SendMessageToChannel;
beforeEach(async () => { beforeEach(async () => {
const applicationBuilder = getApplicationBuilder(); const applicationBuilder = getApplicationBuilder();
@ -121,9 +112,8 @@ describe("channel", () => {
const testChannelListenerInMainInjectable = getInjectable({ const testChannelListenerInMainInjectable = getInjectable({
id: "test-channel-listener-in-main", id: "test-channel-listener-in-main",
instantiate: (di) => ({ instantiate: () => ({
channel: di.inject(testMessageChannelInjectable), channel: testMessageChannel,
handler: messageListenerInMainMock, handler: messageListenerInMainMock,
}), }),
@ -133,13 +123,6 @@ describe("channel", () => {
applicationBuilder.beforeApplicationStart((mainDi) => { applicationBuilder.beforeApplicationStart((mainDi) => {
runInAction(() => { runInAction(() => {
mainDi.register(testChannelListenerInMainInjectable); 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; const windowDi = applicationBuilder.applicationWindow.only.di;
testMessageChannel = windowDi.inject(testMessageChannelInjectable); messageToChannel = windowDi.inject(sendMessageToChannelInjectionToken);
messageToChannel = windowDi.inject(messageToChannelInjectionToken);
}); });
it("when sending message, triggers listener in main", () => { 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", () => { describe("requesting from main in renderer, given listener for channel in a main and application has started", () => {
let testRequestChannel: TestRequestChannel; let requestListenerInMainMock: AsyncFnMock<RequestChannelHandler<TestRequestChannel>>;
let requestListenerInMainMock: AsyncFnMock<(arg: string) => string>;
let requestFromChannel: RequestFromChannel; let requestFromChannel: RequestFromChannel;
beforeEach(async () => { beforeEach(async () => {
@ -168,28 +149,14 @@ describe("channel", () => {
requestListenerInMainMock = asyncFn(); requestListenerInMainMock = asyncFn();
const testChannelListenerInMainInjectable = getInjectable({ const testChannelListenerInMainInjectable = getRequestChannelListenerInjectable({
id: "test-channel-listener-in-main", channel: testRequestChannel,
handler: () => requestListenerInMainMock,
instantiate: (di) => ({
channel: di.inject(testRequestChannelInjectable),
handler: requestListenerInMainMock,
}),
injectionToken: requestChannelListenerInjectionToken,
}); });
applicationBuilder.beforeApplicationStart((mainDi) => { applicationBuilder.beforeApplicationStart((mainDi) => {
runInAction(() => { runInAction(() => {
mainDi.register(testChannelListenerInMainInjectable); 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; const windowDi = applicationBuilder.applicationWindow.only.di;
testRequestChannel = windowDi.inject(testRequestChannelInjectable);
requestFromChannel = windowDi.inject( requestFromChannel = windowDi.inject(
requestFromChannelInjectionToken, 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({ const testMessageChannel: TestMessageChannel = {
id: "some-message-test-channel",
instantiate: (): TestMessageChannel => ({
id: "some-message-channel-id", id: "some-message-channel-id",
}), };
});
const testRequestChannelInjectable = getInjectable({ const testRequestChannel: TestRequestChannel = {
id: "some-request-test-channel",
instantiate: (): TestRequestChannel => ({
id: "some-request-channel-id", id: "some-request-channel-id",
}), };
});

View File

@ -3,14 +3,11 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectionToken } from "@ogre-tools/injectable"; import { getInjectionToken } from "@ogre-tools/injectable";
import type { MessageChannel } from "./message-channel-injection-token"; import type { Disposer } from "../disposer";
import type { MessageChannelListener } from "./message-channel-listener-injection-token"; import type { MessageChannel, MessageChannelListener } from "./message-channel-listener-injection-token";
export type EnlistMessageChannelListener = < export type EnlistMessageChannelListener = (listener: MessageChannelListener<MessageChannel<unknown>>) => Disposer;
TChannel extends MessageChannel<any>,
>(listener: MessageChannelListener<TChannel>) => () => void;
export const enlistMessageChannelListenerInjectionToken = export const enlistMessageChannelListenerInjectionToken = getInjectionToken<EnlistMessageChannelListener>({
getInjectionToken<EnlistMessageChannelListener>({
id: "enlist-message-channel-listener", id: "enlist-message-channel-listener",
}); });

View File

@ -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<any, any>,
>(listener: RequestChannelListener<TChannel>) => () => void;
export const enlistRequestChannelListenerInjectionToken =
getInjectionToken<EnlistRequestChannelListener>({
id: "enlist-request-channel-listener",
});

View File

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

View File

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

View File

@ -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<Message extends JsonValue | void = void> {
id: string;
_messageSignature?: Message;
}
export const messageChannelInjectionToken = getInjectionToken<MessageChannel<any>>({
id: "message-channel",
});

View File

@ -2,17 +2,50 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectionToken } from "@ogre-tools/injectable"; import type { DiContainerForInjection } from "@ogre-tools/injectable";
import type { SetRequired } from "type-fest"; import { getInjectable, getInjectionToken } from "@ogre-tools/injectable";
import type { MessageChannel } from "./message-channel-injection-token";
export interface MessageChannelListener<TChannel extends MessageChannel<any>> { export interface MessageChannel<Message> {
channel: TChannel; id: string;
handler: (value: SetRequired<TChannel, "_messageSignature">["_messageSignature"]) => void; _messageSignature?: Message; // only used to mark `Message` as used
} }
export const messageChannelListenerInjectionToken = getInjectionToken<MessageChannelListener<MessageChannel<any>>>( export type MessageChannelHandler<Channel> = Channel extends MessageChannel<infer Message>
? (message: Message) => void
: never;
export interface MessageChannelListener<Channel> {
channel: Channel;
handler: MessageChannelHandler<Channel>;
}
export const messageChannelListenerInjectionToken = getInjectionToken<MessageChannelListener<MessageChannel<unknown>>>(
{ {
id: "message-channel-listener", id: "message-channel-listener",
}, },
); );
export interface GetMessageChannelListenerInfo<
Channel extends MessageChannel<Message>,
Message,
> {
id: string;
channel: Channel;
handler: (di: DiContainerForInjection) => MessageChannelHandler<Channel>;
causesSideEffects?: boolean;
}
export function getMessageChannelListenerInjectable<
Channel extends MessageChannel<Message>,
Message,
>(info: GetMessageChannelListenerInfo<Channel, Message>) {
return getInjectable({
id: `${info.channel.id}-listener-${info.id}`,
instantiate: (di) => ({
channel: info.channel,
handler: info.handler(di),
}),
injectionToken: messageChannelListenerInjectionToken,
causesSideEffects: info.causesSideEffects,
});
}

View File

@ -3,21 +3,13 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectionToken } from "@ogre-tools/injectable"; import { getInjectionToken } from "@ogre-tools/injectable";
import type { SetRequired } from "type-fest"; import type { MessageChannel } from "./message-channel-listener-injection-token";
import type { MessageChannel } from "./message-channel-injection-token";
export interface MessageToChannel { export interface SendMessageToChannel {
<TChannel extends MessageChannel<TMessage>, TMessage extends void>( (channel: MessageChannel<void>): void;
channel: TChannel, <Message>(channel: MessageChannel<Message>, message: Message): void;
): void;
<TChannel extends MessageChannel<any>>(
channel: TChannel,
message: SetRequired<TChannel, "_messageSignature">["_messageSignature"],
): void;
} }
export const messageToChannelInjectionToken = export const sendMessageToChannelInjectionToken = getInjectionToken<SendMessageToChannel>({
getInjectionToken<MessageToChannel>({ id: "send-message-to-message-channel",
id: "message-to-message-channel", });
});

View File

@ -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<RequestChannel<any, any>>({
id: "request-channel",
});

View File

@ -2,24 +2,9 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectionToken } from "@ogre-tools/injectable";
import type { SetRequired } from "type-fest";
import type { RequestChannel } from "./request-channel-injection-token";
export interface RequestChannelListener<TChannel extends RequestChannel<any, any>> { export interface RequestChannel<Request, Response> {
channel: TChannel; id: string;
_requestSignature?: Request; // used only to mark `Request` as "used"
handler: ( _responseSignature?: Response; // used only to mark `Response` as "used"
request: SetRequired<TChannel, "_requestSignature">["_requestSignature"]
) =>
| SetRequired<TChannel, "_responseSignature">["_responseSignature"]
| Promise<
SetRequired<TChannel, "_responseSignature">["_responseSignature"]
>;
} }
export const requestChannelListenerInjectionToken = getInjectionToken<RequestChannelListener<RequestChannel<any, any>>>(
{
id: "request-channel-listener",
},
);

View File

@ -3,19 +3,13 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectionToken } from "@ogre-tools/injectable"; import { getInjectionToken } from "@ogre-tools/injectable";
import type { SetRequired } from "type-fest"; import type { RequestChannel } from "./request-channel-listener-injection-token";
import type { RequestChannel } from "./request-channel-injection-token";
export type RequestFromChannel = < export interface RequestFromChannel {
TChannel extends RequestChannel<any, any>, <Request, Response>(channel: RequestChannel<Request, Response>, request: Request): Promise<Response>;
>( <Response>(channel: RequestChannel<void, Response>): Promise<Response>;
channel: TChannel, }
...request: TChannel["_requestSignature"] extends void
? []
: [SetRequired<TChannel, "_requestSignature">["_requestSignature"]]
) => Promise<SetRequired<TChannel, "_responseSignature">["_responseSignature"]>;
export const requestFromChannelInjectionToken = export const requestFromChannelInjectionToken = getInjectionToken<RequestFromChannel>({
getInjectionToken<RequestFromChannel>({
id: "request-from-request-channel", id: "request-from-request-channel",
}); });

View File

@ -3,6 +3,8 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import type { SingleOrMany } from "./types";
export interface Disposer { export interface Disposer {
@ -17,9 +19,9 @@ export interface ExtendableDisposer extends Disposer {
push(...vals: (Disposer | ExtendableDisposer | Disposable)[]): void; push(...vals: (Disposer | ExtendableDisposer | Disposable)[]): void;
} }
export function disposer(...items: (Disposer | Disposable | undefined | null)[]): ExtendableDisposer { export function disposer(...items: SingleOrMany<Disposer | Disposable | undefined | null>[]): ExtendableDisposer {
return Object.assign(() => { return Object.assign(() => {
for (const item of items) { for (const item of items.flat()) {
if (!item) { if (!item) {
continue; continue;
} }

View File

@ -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<string, string>;
const resolveSystemProxyChannelInjectable = getInjectable({
id: "resolve-system-proxy-channel",
instantiate: (): ResolveSystemProxyChannel => ({
id: "resolve-system-proxy-channel",
}),
injectionToken: requestChannelInjectionToken,
});
export default resolveSystemProxyChannelInjectable;

View File

@ -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<string, string>;
export const resolveSystemProxyChannel: ResolveSystemProxyChannel = {
id: "resolve-system-proxy-channel",
};

View File

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

View File

@ -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",
};

View File

@ -5,17 +5,17 @@
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import type { IObservableValue } from "mobx"; import type { IObservableValue } from "mobx";
import { computed } from "mobx"; import { computed } from "mobx";
import syncBoxChannelInjectable from "./sync-box-channel.injectable"; import { syncBoxChannel } from "./channels";
import { messageToChannelInjectionToken } from "../channel/message-to-channel-injection-token"; import { sendMessageToChannelInjectionToken } from "../channel/message-to-channel-injection-token";
import syncBoxStateInjectable from "./sync-box-state.injectable"; import syncBoxStateInjectable from "./sync-box-state.injectable";
import type { SyncBox } from "./sync-box-injection-token"; import type { SyncBox } from "./sync-box-injection-token";
import { toJS } from "../toJS";
const createSyncBoxInjectable = getInjectable({ const createSyncBoxInjectable = getInjectable({
id: "create-sync-box", id: "create-sync-box",
instantiate: (di) => { instantiate: (di) => {
const syncBoxChannel = di.inject(syncBoxChannelInjectable); const messageToChannel = di.inject(sendMessageToChannelInjectionToken);
const messageToChannel = di.inject(messageToChannelInjectionToken);
const getSyncBoxState = (id: string) => di.inject(syncBoxStateInjectable, id); const getSyncBoxState = (id: string) => di.inject(syncBoxStateInjectable, id);
return <Value>(id: string, initialValue: Value): SyncBox<Value> => { return <Value>(id: string, initialValue: Value): SyncBox<Value> => {
@ -26,7 +26,7 @@ const createSyncBoxInjectable = getInjectable({
return { return {
id, id,
value: computed(() => state.get()), value: computed(() => toJS(state.get())),
set: (value) => { set: (value) => {
state.set(value); state.set(value);

View File

@ -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<SyncBoxChannel> => {
const getSyncBoxState = (id: string) => di.inject(syncBoxStateInjectable, id);
return ({ id, value }) => getSyncBoxState(id)?.set(value);
},
});
export default syncBoxChannelHandlerInjectable;

View File

@ -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<SyncBoxChannel> => {
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;

View File

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

View File

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

View File

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

View File

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

View File

@ -7,7 +7,7 @@ import { getInjectionToken } from "@ogre-tools/injectable";
import { SemVer } from "semver"; import { SemVer } from "semver";
import type { InitializableState } from "../initializable-state/create"; import type { InitializableState } from "../initializable-state/create";
import { createInitializableState } 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<InitializableState<string>>({ export const buildVersionInjectionToken = getInjectionToken<InitializableState<string>>({
id: "build-version-token", id: "build-version-token",

View File

@ -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', () => { 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); selectedUpdateChannel.setValue(updateChannels.alpha.id);
expect(setUpdateOnQuitMock).toHaveBeenLastCalledWith(false); expect(setUpdateOnQuitMock).toHaveBeenLastCalledWith(true);
}); });
}); });
}); });

View File

@ -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<ClusterId, void>;
const clearClusterAsDeletingChannelInjectable = getInjectable({
id: "clear-cluster-as-deleting-channel",
instantiate: (): ClearClusterAsDeletingChannel => ({
id: "clear-cluster-as-deleting",
}),
injectionToken: requestChannelInjectionToken,
});
export default clearClusterAsDeletingChannelInjectable;

View File

@ -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<ClusterId, void>;
export const clearClusterAsDeletingChannel: ClearClusterAsDeletingChannel = {
id: "clear-cluster-as-deleting",
};

View File

@ -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<ClusterId, void>;
const deleteClusterChannelInjectable = getInjectable({
id: "delete-cluster-channel",
instantiate: (): DeleteClusterChannel => ({
id: "delete-cluster",
}),
injectionToken: requestChannelInjectionToken,
});
export default deleteClusterChannelInjectable;

View File

@ -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<ClusterId, void>;
export const deleteClusterChannel: DeleteClusterChannel = {
id: "delete-cluster",
};

View File

@ -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<ClusterId, void>;
const setClusterAsDeletingChannelInjectable = getInjectable({
id: "set-cluster-as-deleting-channel",
instantiate: (): SetClusterAsDeletingChannel => ({
id: "set-cluster-as-deleting",
}),
injectionToken: requestChannelInjectionToken,
});
export default setClusterAsDeletingChannelInjectable;

View File

@ -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<ClusterId, void>;
export const setClusterAsDeletingChannel: SetClusterAsDeletingChannel = {
id: "set-cluster-as-deleting",
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,7 +5,7 @@
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import type { ClusterId } from "../../../../common/cluster-types"; import type { ClusterId } from "../../../../common/cluster-types";
import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable"; 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<void>; export type RequestClearClusterAsDeleting = (clusterId: ClusterId) => Promise<void>;
@ -13,7 +13,6 @@ const requestClearClusterAsDeletingInjectable = getInjectable({
id: "request-clear-cluster-as-deleting", id: "request-clear-cluster-as-deleting",
instantiate: (di): RequestClearClusterAsDeleting => { instantiate: (di): RequestClearClusterAsDeleting => {
const requestChannel = di.inject(requestFromChannelInjectable); const requestChannel = di.inject(requestFromChannelInjectable);
const clearClusterAsDeletingChannel = di.inject(clearClusterAsDeletingChannelInjectable);
return (clusterId) => requestChannel(clearClusterAsDeletingChannel, clusterId); return (clusterId) => requestChannel(clearClusterAsDeletingChannel, clusterId);
}, },

View File

@ -5,7 +5,7 @@
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import type { ClusterId } from "../../../../common/cluster-types"; import type { ClusterId } from "../../../../common/cluster-types";
import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable"; 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<void>; export type RequestDeleteCluster = (clusterId: ClusterId) => Promise<void>;
@ -13,7 +13,6 @@ const requestDeleteClusterInjectable = getInjectable({
id: "request-delete-cluster", id: "request-delete-cluster",
instantiate: (di): RequestDeleteCluster => { instantiate: (di): RequestDeleteCluster => {
const requestChannel = di.inject(requestFromChannelInjectable); const requestChannel = di.inject(requestFromChannelInjectable);
const deleteClusterChannel = di.inject(deleteClusterChannelInjectable);
return (clusterId) => requestChannel(deleteClusterChannel, clusterId); return (clusterId) => requestChannel(deleteClusterChannel, clusterId);
}, },

View File

@ -5,7 +5,7 @@
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import type { ClusterId } from "../../../../common/cluster-types"; import type { ClusterId } from "../../../../common/cluster-types";
import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable"; 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<void>; export type RequestSetClusterAsDeleting = (clusterId: ClusterId) => Promise<void>;
@ -13,7 +13,6 @@ const requestSetClusterAsDeletingInjectable = getInjectable({
id: "request-set-cluster-as-deleting", id: "request-set-cluster-as-deleting",
instantiate: (di): RequestSetClusterAsDeleting => { instantiate: (di): RequestSetClusterAsDeleting => {
const requestChannel = di.inject(requestFromChannelInjectable); const requestChannel = di.inject(requestFromChannelInjectable);
const setClusterAsDeletingChannel = di.inject(setClusterAsDeletingChannelInjectable);
return (clusterId) => requestChannel(setClusterAsDeletingChannel, clusterId); return (clusterId) => requestChannel(setClusterAsDeletingChannel, clusterId);
}, },

View File

@ -8,6 +8,7 @@ import type { ApplicationBuilder } from "../../renderer/components/test-utils/ge
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
import type { AsyncFnMock } from "@async-fn/jest"; import type { AsyncFnMock } from "@async-fn/jest";
import asyncFn 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 execFileInjectable from "../../common/fs/exec-file.injectable";
import helmBinaryPathInjectable from "../../main/helm/helm-binary-path.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"; 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 showSuccessNotificationMock: jest.Mock;
let showErrorNotificationMock: jest.Mock; let showErrorNotificationMock: jest.Mock;
let rendered: RenderResult; let rendered: RenderResult;
let execFileMock: AsyncFnMock< let execFileMock: AsyncFnMock<ExecFile>;
ReturnType<typeof execFileInjectable["instantiate"]>
>;
let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise<AsyncResult<HelmRepo[]>>>; let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise<AsyncResult<HelmRepo[]>>>;
beforeEach(async () => { beforeEach(async () => {
@ -184,9 +183,13 @@ describe("add custom helm repository in preferences", () => {
describe("when activation rejects", () => { describe("when activation rejects", () => {
beforeEach(async () => { beforeEach(async () => {
await execFileMock.reject( await execFileMock.resolve({
"Some error", callWasSuccessful: false,
); error: {
error: new Error("Some error"),
stderr: "",
},
});
}); });
it("renders", () => { it("renders", () => {
@ -219,8 +222,10 @@ describe("add custom helm repository in preferences", () => {
"some-helm-binary-path", "some-helm-binary-path",
["repo", "add", "some-custom-repository", "http://some.url"], ["repo", "add", "some-custom-repository", "http://some.url"],
], ],
{
"", callWasSuccessful: true,
response: "",
},
); );
}); });

View File

@ -7,6 +7,7 @@ import type { ApplicationBuilder } from "../../renderer/components/test-utils/ge
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
import type { AsyncFnMock } from "@async-fn/jest"; import type { AsyncFnMock } from "@async-fn/jest";
import asyncFn 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 execFileInjectable from "../../common/fs/exec-file.injectable";
import helmBinaryPathInjectable from "../../main/helm/helm-binary-path.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"; 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 showSuccessNotificationMock: jest.Mock;
let showErrorNotificationMock: jest.Mock; let showErrorNotificationMock: jest.Mock;
let rendered: RenderResult; let rendered: RenderResult;
let execFileMock: AsyncFnMock< let execFileMock: AsyncFnMock<ExecFile>;
ReturnType<typeof execFileInjectable["instantiate"]>
>;
let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise<AsyncResult<HelmRepo[]>>>; let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise<AsyncResult<HelmRepo[]>>>;
let callForPublicHelmRepositoriesMock: AsyncFnMock<() => Promise<HelmRepo[]>>; let callForPublicHelmRepositoriesMock: AsyncFnMock<() => Promise<HelmRepo[]>>;
@ -129,9 +128,13 @@ describe("add helm repository from list in preferences", () => {
describe("when adding rejects", () => { describe("when adding rejects", () => {
beforeEach(async () => { beforeEach(async () => {
await execFileMock.reject( await execFileMock.resolve({
"Some error", callWasSuccessful: false,
); error: {
error: new Error("Some error"),
stderr: "",
},
});
}); });
it("renders", () => { it("renders", () => {
@ -164,8 +167,10 @@ describe("add helm repository from list in preferences", () => {
"some-helm-binary-path", "some-helm-binary-path",
["repo", "add", "Some to be added repository", "some-other-url"], ["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", "some-helm-binary-path",
["repo", "remove", "Some already active repository"], ["repo", "remove", "Some already active repository"],
], ],
{
"", callWasSuccessful: true,
response: "",
},
); );
}); });

View File

@ -83,7 +83,13 @@ describe("listing active helm repositories in preferences", () => {
describe("when getting configuration rejects", () => { describe("when getting configuration rejects", () => {
beforeEach(async () => { 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", () => { it("shows error notification", () => {
@ -115,7 +121,10 @@ describe("listing active helm repositories in preferences", () => {
await execFileMock.resolveSpecific( await execFileMock.resolveSpecific(
["some-helm-binary-path", ["env"]], ["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( await execFileMock.resolveSpecific(
["some-helm-binary-path", ["env"]], ["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( await execFileMock.resolveSpecific(
["some-helm-binary-path", ["env"]], ["some-helm-binary-path", ["env"]],
{
[ callWasSuccessful: true,
response: [
"HELM_REPOSITORY_CONFIG=some-helm-repository-config-file.yaml", "HELM_REPOSITORY_CONFIG=some-helm-repository-config-file.yaml",
"HELM_REPOSITORY_CACHE=some-helm-repository-cache-path", "HELM_REPOSITORY_CACHE=some-helm-repository-cache-path",
].join("\n"), ].join("\n"),
},
); );
}); });
@ -219,7 +233,13 @@ describe("listing active helm repositories in preferences", () => {
describe("when updating repositories reject with any other error", () => { describe("when updating repositories reject with any other error", () => {
beforeEach(async () => { 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", () => { it("shows error notification", () => {
@ -249,9 +269,13 @@ describe("listing active helm repositories in preferences", () => {
beforeEach(async () => { beforeEach(async () => {
execFileMock.mockClear(); execFileMock.mockClear();
await execFileMock.reject( await execFileMock.resolve({
"Error: no repositories found. You must add one before updating", 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", () => { it("renders", () => {
@ -274,7 +298,13 @@ describe("listing active helm repositories in preferences", () => {
describe("when adding default repository reject", () => { describe("when adding default repository reject", () => {
beforeEach(async () => { 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", () => { it("shows error notification", () => {
@ -307,7 +337,6 @@ describe("listing active helm repositories in preferences", () => {
await execFileMock.resolveSpecific( await execFileMock.resolveSpecific(
[ [
"some-helm-binary-path", "some-helm-binary-path",
[ [
"repo", "repo",
"add", "add",
@ -315,8 +344,10 @@ describe("listing active helm repositories in preferences", () => {
"https://charts.bitnami.com/bitnami", "https://charts.bitnami.com/bitnami",
], ],
], ],
{
"", callWasSuccessful: true,
response: "",
},
); );
}); });
@ -380,7 +411,10 @@ describe("listing active helm repositories in preferences", () => {
await execFileMock.resolveSpecific( await execFileMock.resolveSpecific(
["some-helm-binary-path", ["repo", "update"]], ["some-helm-binary-path", ["repo", "update"]],
"", {
callWasSuccessful: true,
response: "",
},
); );
}); });

View File

@ -8,6 +8,7 @@ import type { ApplicationBuilder } from "../../renderer/components/test-utils/ge
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
import type { AsyncFnMock } from "@async-fn/jest"; import type { AsyncFnMock } from "@async-fn/jest";
import asyncFn 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 execFileInjectable from "../../common/fs/exec-file.injectable";
import helmBinaryPathInjectable from "../../main/helm/helm-binary-path.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"; 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 builder: ApplicationBuilder;
let rendered: RenderResult; let rendered: RenderResult;
let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise<AsyncResult<HelmRepo[]>>>; let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise<AsyncResult<HelmRepo[]>>>;
let execFileMock: AsyncFnMock< let execFileMock: AsyncFnMock<ExecFile>;
ReturnType<typeof execFileInjectable["instantiate"]>
>;
beforeEach(async () => { beforeEach(async () => {
builder = getApplicationBuilder(); builder = getApplicationBuilder();
@ -101,8 +100,10 @@ describe("remove helm repository from list of active repositories in preferences
"some-helm-binary-path", "some-helm-binary-path",
["repo", "remove", "some-active-repository"], ["repo", "remove", "some-active-repository"],
], ],
{
"", callWasSuccessful: true,
response: "",
},
); );
}); });

View File

@ -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<void>;
export const reloadPageChannel: ReloadPageChannel = {
id: "reload-page-channel",
};

View File

@ -0,0 +1,13 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { 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: () => {},
}));

View File

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

View File

@ -2,26 +2,17 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { appPathsChannel } from "../../common/app-paths/app-paths-channel";
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 appPathsInjectable from "../../common/app-paths/app-paths.injectable"; import appPathsInjectable from "../../common/app-paths/app-paths.injectable";
import { getRequestChannelListenerInjectable } from "../utils/channel/channel-listeners/listener-tokens";
const appPathsRequestChannelListenerInjectable = getInjectable({ const appPathsRequestChannelListenerInjectable = getRequestChannelListenerInjectable({
id: "app-paths-request-channel-listener", channel: appPathsChannel,
handler: (di) => {
instantiate: (di): RequestChannelListener<AppPathsChannel> => {
const channel = di.inject(appPathsChannelInjectable);
const appPaths = di.inject(appPathsInjectable); const appPaths = di.inject(appPathsInjectable);
return { return () => appPaths;
channel,
handler: () => appPaths,
};
}, },
injectionToken: requestChannelListenerInjectionToken,
}); });
export default appPathsRequestChannelListenerInjectable; export default appPathsRequestChannelListenerInjectable;

View File

@ -2,25 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { restartAndInstallUpdateChannel } from "../../../common/application-update/restart-and-install-update-channel";
import restartAndInstallUpdateChannel from "../../../common/application-update/restart-and-install-update-channel/restart-and-install-update-channel.injectable"; import { getMessageChannelListenerInjectable } from "../../../common/utils/channel/message-channel-listener-injection-token";
import { messageChannelListenerInjectionToken } from "../../../common/utils/channel/message-channel-listener-injection-token";
import quitAndInstallUpdateInjectable from "../quit-and-install-update.injectable"; import quitAndInstallUpdateInjectable from "../quit-and-install-update.injectable";
const restartAndInstallUpdateListenerInjectable = getInjectable({ const restartAndInstallUpdateListenerInjectable = getMessageChannelListenerInjectable({
id: "restart-and-install-update-listener", id: "restart",
channel: restartAndInstallUpdateChannel,
instantiate: (di) => { handler: (di) => di.inject(quitAndInstallUpdateInjectable),
const quitAndInstall = di.inject(quitAndInstallUpdateInjectable);
const channel = di.inject(restartAndInstallUpdateChannel);
return {
channel,
handler: quitAndInstall,
};
},
injectionToken: messageChannelListenerInjectionToken,
}); });
export default restartAndInstallUpdateListenerInjectable; export default restartAndInstallUpdateListenerInjectable;

View File

@ -7,7 +7,7 @@ import { autorun } from "mobx";
import { getStartableStoppable } from "../../../common/utils/get-startable-stoppable"; import { getStartableStoppable } from "../../../common/utils/get-startable-stoppable";
import setUpdateOnQuitInjectable from "../../electron-app/features/set-update-on-quit.injectable"; 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 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"; import discoveredUpdateVersionInjectable from "../../../common/application-update/discovered-update-version/discovered-update-version.injectable";
const watchIfUpdateShouldHappenOnQuitInjectable = getInjectable({ const watchIfUpdateShouldHappenOnQuitInjectable = getInjectable({
@ -20,33 +20,26 @@ const watchIfUpdateShouldHappenOnQuitInjectable = getInjectable({
return getStartableStoppable("watch-if-update-should-happen-on-quit", () => return getStartableStoppable("watch-if-update-should-happen-on-quit", () =>
autorun(() => { autorun(() => {
const sufficientlyStableUpdateChannels = const sufficientlyStableUpdateChannels = getSufficientlyStableUpdateChannels(selectedUpdateChannel.value.get());
getSufficientlyStableUpdateChannels(selectedUpdateChannel.value.get()); const updateIsDiscoveredFromChannel = discoveredVersionState.value.get()?.updateChannel;
const discoveredVersion = discoveredVersionState.value.get(); setUpdateOnQuit((
updateIsDiscoveredFromChannel
const updateIsDiscoveredFromChannel = discoveredVersion?.updateChannel; ? sufficientlyStableUpdateChannels.includes(updateIsDiscoveredFromChannel.id)
: false
const updateOnQuit = updateIsDiscoveredFromChannel ));
? sufficientlyStableUpdateChannels.includes(
updateIsDiscoveredFromChannel,
)
: false;
setUpdateOnQuit(updateOnQuit);
}), }),
); );
}, },
}); });
const getSufficientlyStableUpdateChannels = (updateChannel: UpdateChannel): UpdateChannel[] => { const getSufficientlyStableUpdateChannels = (updateChannel: UpdateChannel): ReleaseChannel[] => {
if (!updateChannel.moreStableUpdateChannel) { if (!updateChannel.moreStableUpdateChannel) {
return [updateChannel]; return [updateChannel.id];
} }
return [ return [
updateChannel, updateChannel.id,
...getSufficientlyStableUpdateChannels(updateChannel.moreStableUpdateChannel), ...getSufficientlyStableUpdateChannels(updateChannel.moreStableUpdateChannel),
]; ];
}; };

View File

@ -2,22 +2,17 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import { requestChannelListenerInjectionToken } from "../../common/utils/channel/request-channel-listener-injection-token";
import { buildVersionChannel } from "../../common/vars/build-semantic-version.injectable"; 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"; import buildVersionInjectable from "../vars/build-version/build-version.injectable";
const setupBuildVersionRequestChannelInjectable = getInjectable({ const buildVersionChannelListenerInjectable = getRequestChannelListenerInjectable({
id: "setup-build-version-request-channel", channel: buildVersionChannel,
instantiate: (di) => { handler: (di) => {
const buildVersion = di.inject(buildVersionInjectable); const buildVersion = di.inject(buildVersionInjectable);
return { return () => buildVersion.get();
channel: buildVersionChannel,
handler: () => buildVersion.get(),
};
}, },
injectionToken: requestChannelListenerInjectionToken,
}); });
export default setupBuildVersionRequestChannelInjectable; export default buildVersionChannelListenerInjectable;

View File

@ -6,9 +6,8 @@ import { getInjectable } from "@ogre-tools/injectable";
import execFileInjectable from "../../../common/fs/exec-file.injectable"; import execFileInjectable from "../../../common/fs/exec-file.injectable";
import helmBinaryPathInjectable from "../helm-binary-path.injectable"; import helmBinaryPathInjectable from "../helm-binary-path.injectable";
import type { AsyncResult } from "../../../common/utils/async-result"; import type { AsyncResult } from "../../../common/utils/async-result";
import { getErrorMessage } from "../../../common/utils/get-error-message";
export type ExecHelm = (args: string[]) => Promise<AsyncResult<string>>; export type ExecHelm = (args: string[]) => Promise<AsyncResult<string, string>>;
const execHelmInjectable = getInjectable({ const execHelmInjectable = getInjectable({
id: "exec-helm", id: "exec-helm",
@ -18,15 +17,18 @@ const execHelmInjectable = getInjectable({
const helmBinaryPath = di.inject(helmBinaryPathInjectable); const helmBinaryPath = di.inject(helmBinaryPathInjectable);
return async (args) => { return async (args) => {
try {
const response = await execFile(helmBinaryPath, args, { const response = await execFile(helmBinaryPath, args, {
maxBuffer: 32 * 1024 * 1024 * 1024, // 32 MiB maxBuffer: 32 * 1024 * 1024 * 1024, // 32 MiB
}); });
return { callWasSuccessful: true, response }; if (response.callWasSuccessful) {
} catch (error) { return response;
return { callWasSuccessful: false, error: getErrorMessage(error) };
} }
return {
callWasSuccessful: false,
error: response.error.stderr || response.error.error.message,
};
}; };
}, },
}); });

View File

@ -2,25 +2,13 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { addHelmRepositoryChannel } from "../../../../common/helm/add-helm-repository-channel";
import addHelmRepositoryChannelInjectable from "../../../../common/helm/add-helm-repository-channel.injectable"; import { getRequestChannelListenerInjectable } from "../../../utils/channel/channel-listeners/listener-tokens";
import addHelmRepositoryInjectable from "./add-helm-repository.injectable"; import addHelmRepositoryInjectable from "./add-helm-repository.injectable";
import { requestChannelListenerInjectionToken } from "../../../../common/utils/channel/request-channel-listener-injection-token";
const addHelmRepositoryChannelListenerInjectable = getInjectable({ const addHelmRepositoryChannelListenerInjectable = getRequestChannelListenerInjectable({
id: "add-helm-repository-channel-listener", channel: addHelmRepositoryChannel,
handler: (di) => di.inject(addHelmRepositoryInjectable),
instantiate: (di) => {
const addHelmRepository = di.inject(addHelmRepositoryInjectable);
const channel = di.inject(addHelmRepositoryChannelInjectable);
return {
channel,
handler: addHelmRepository,
};
},
injectionToken: requestChannelListenerInjectionToken,
}); });
export default addHelmRepositoryChannelListenerInjectable; export default addHelmRepositoryChannelListenerInjectable;

View File

@ -2,25 +2,13 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getActiveHelmRepositoriesChannel } from "../../../../common/helm/get-active-helm-repositories-channel";
import { requestChannelListenerInjectionToken } from "../../../../common/utils/channel/request-channel-listener-injection-token"; import { getRequestChannelListenerInjectable } from "../../../utils/channel/channel-listeners/listener-tokens";
import getActiveHelmRepositoriesChannelInjectable from "../../../../common/helm/get-active-helm-repositories-channel.injectable";
import getActiveHelmRepositoriesInjectable from "./get-active-helm-repositories.injectable"; import getActiveHelmRepositoriesInjectable from "./get-active-helm-repositories.injectable";
const getActiveHelmRepositoriesChannelListenerInjectable = getInjectable({ const getActiveHelmRepositoriesChannelListenerInjectable = getRequestChannelListenerInjectable({
id: "get-active-helm-repositories-channel-listener", channel: getActiveHelmRepositoriesChannel,
handler: (di) => di.inject(getActiveHelmRepositoriesInjectable),
instantiate: (di) => {
const getActiveHelmRepositories = di.inject(getActiveHelmRepositoriesInjectable);
return {
channel: di.inject(getActiveHelmRepositoriesChannelInjectable),
handler: getActiveHelmRepositories,
};
},
injectionToken: requestChannelListenerInjectionToken,
}); });
export default getActiveHelmRepositoriesChannelListenerInjectable; export default getActiveHelmRepositoriesChannelListenerInjectable;

View File

@ -2,25 +2,13 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import { requestChannelListenerInjectionToken } from "../../../../common/utils/channel/request-channel-listener-injection-token";
import removeHelmRepositoryInjectable from "./remove-helm-repository.injectable"; 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({ const removeHelmRepositoryChannelListenerInjectable = getRequestChannelListenerInjectable({
id: "remove-helm-repository-channel-listener", channel: removeHelmRepositoryChannel,
handler: (di) => di.inject(removeHelmRepositoryInjectable),
instantiate: (di) => {
const removeHelmRepository = di.inject(removeHelmRepositoryInjectable);
const channel = di.inject(removeHelmRepositoryChannelInjectable);
return {
channel,
handler: removeHelmRepository,
};
},
injectionToken: requestChannelListenerInjectionToken,
}); });
export default removeHelmRepositoryChannelListenerInjectable; export default removeHelmRepositoryChannelListenerInjectable;

View File

@ -6,7 +6,6 @@ import { getInjectable } from "@ogre-tools/injectable";
import loggerInjectable from "../../../../common/logger.injectable"; import loggerInjectable from "../../../../common/logger.injectable";
import applicationWindowStateInjectable from "./application-window-state.injectable"; import applicationWindowStateInjectable from "./application-window-state.injectable";
import { BrowserWindow } from "electron"; 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 { ElectronWindow } from "./create-lens-window.injectable";
import type { RequireExactlyOne } from "type-fest"; import type { RequireExactlyOne } from "type-fest";
import openLinkInBrowserInjectable from "../../../../common/utils/open-link-in-browser.injectable"; import openLinkInBrowserInjectable from "../../../../common/utils/open-link-in-browser.injectable";
@ -45,7 +44,6 @@ const createElectronWindowInjectable = getInjectable({
instantiate: (di): CreateElectronWindow => { instantiate: (di): CreateElectronWindow => {
const logger = di.inject(loggerInjectable); const logger = di.inject(loggerInjectable);
const sendToChannelInLensWindow = di.inject(sendToChannelInElectronBrowserWindowInjectable);
const openLinkInBrowser = di.inject(openLinkInBrowserInjectable); const openLinkInBrowser = di.inject(openLinkInBrowserInjectable);
return (configuration) => { return (configuration) => {
@ -140,7 +138,17 @@ const createElectronWindowInjectable = getInjectable({
show: () => browserWindow.show(), show: () => browserWindow.show(),
close: () => browserWindow.close(), 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: () => { reload: () => {
const wc = browserWindow.webContents; const wc = browserWindow.webContents;

View File

@ -20,7 +20,7 @@ export interface ElectronWindow {
export interface SendToViewArgs { export interface SendToViewArgs {
channel: string; channel: string;
frameInfo?: ClusterFrameInfo; frameInfo?: ClusterFrameInfo;
data?: unknown[]; data?: unknown;
} }
export interface LensWindow { export interface LensWindow {

View File

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

View File

@ -37,7 +37,7 @@ const navigateInjectable = getInjectable({
applicationWindow.send({ applicationWindow.send({
channel, channel,
frameInfo, frameInfo,
data: [url], data: url,
}); });
}; };
}, },

View File

@ -3,9 +3,9 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { IpcRendererNavigationEvents } from "../../../renderer/navigation/events";
import currentClusterFrameInjectable from "./current-cluster-frame/current-cluster-frame.injectable"; import currentClusterFrameInjectable from "./current-cluster-frame/current-cluster-frame.injectable";
import getCurrentApplicationWindowInjectable from "./application-window/get-current-application-window.injectable"; import getCurrentApplicationWindowInjectable from "./application-window/get-current-application-window.injectable";
import { reloadPageChannel } from "../../../features/navigation/reload-page/common/channel";
const reloadCurrentApplicationWindowInjectable = getInjectable({ const reloadCurrentApplicationWindowInjectable = getInjectable({
id: "reload-current-application-window", id: "reload-current-application-window",
@ -25,7 +25,7 @@ const reloadCurrentApplicationWindowInjectable = getInjectable({
if (frameInfo) { if (frameInfo) {
lensWindow.send({ lensWindow.send({
channel: IpcRendererNavigationEvents.RELOAD_PAGE, channel: reloadPageChannel.id,
frameInfo, frameInfo,
}); });
} else { } else {

View File

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

View File

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

View File

@ -6,8 +6,6 @@ import { getInjectable } from "@ogre-tools/injectable";
import type { IpcMainEvent } from "electron"; import type { IpcMainEvent } from "electron";
import ipcMainInjectable from "../ipc-main/ipc-main.injectable"; import ipcMainInjectable from "../ipc-main/ipc-main.injectable";
import { enlistMessageChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-message-channel-listener-injection-token"; 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({ const enlistMessageChannelListenerInjectable = getInjectable({
id: "enlist-message-channel-listener-for-main", id: "enlist-message-channel-listener-for-main",
@ -17,11 +15,7 @@ const enlistMessageChannelListenerInjectable = getInjectable({
return ({ channel, handler }) => { return ({ channel, handler }) => {
const nativeOnCallback = (_: IpcMainEvent, message: unknown) => { const nativeOnCallback = (_: IpcMainEvent, message: unknown) => {
pipeline( handler(message);
message,
tentativeParseJson,
handler,
);
}; };
ipcMain.on(channel.id, nativeOnCallback); ipcMain.on(channel.id, nativeOnCallback);

View File

@ -88,8 +88,8 @@ describe("enlist message channel listener in main", () => {
expect(handlerMock).toHaveBeenCalledWith(true); expect(handlerMock).toHaveBeenCalledWith(true);
}); });
it("given stringified object as message, when message arrives, calls the handler with the message", () => { it("given object as message, when message arrives, calls the handler with the message", () => {
onMock.mock.calls[0][1]({} as IpcMainEvent, JSON.stringify({ some: "object" })); onMock.mock.calls[0][1]({} as IpcMainEvent, { some: "object" });
expect(handlerMock).toHaveBeenCalledWith({ some: "object" }); expect(handlerMock).toHaveBeenCalledWith({ some: "object" });
}); });

View File

@ -5,20 +5,20 @@
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import type { IpcMainInvokeEvent } from "electron"; import type { IpcMainInvokeEvent } from "electron";
import ipcMainInjectable from "../ipc-main/ipc-main.injectable"; import ipcMainInjectable from "../ipc-main/ipc-main.injectable";
import { enlistRequestChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-request-channel-listener-injection-token"; import type { Disposer } from "../../../../common/utils";
import { pipeline } from "@ogre-tools/fp"; import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token";
import { tentativeParseJson } from "../../../../common/utils/tentative-parse-json"; import type { RequestChannelListener } from "./listener-tokens";
import { tentativeStringifyJson } from "../../../../common/utils/tentative-stringify-json";
export type EnlistRequestChannelListener = <TChannel extends RequestChannel<unknown, unknown>>(listener: RequestChannelListener<TChannel>) => Disposer;
const enlistRequestChannelListenerInjectable = getInjectable({ const enlistRequestChannelListenerInjectable = getInjectable({
id: "enlist-request-channel-listener-for-main", id: "enlist-request-channel-listener-for-main",
instantiate: (di) => { instantiate: (di): EnlistRequestChannelListener => {
const ipcMain = di.inject(ipcMainInjectable); const ipcMain = di.inject(ipcMainInjectable);
return ({ channel, handler }) => { return ({ channel, handler }) => {
const nativeHandleCallback = (_: IpcMainInvokeEvent, request: unknown) => const nativeHandleCallback = (_: IpcMainInvokeEvent, request: unknown) => handler(request);
pipeline(request, tentativeParseJson, handler, tentativeStringifyJson);
ipcMain.handle(channel.id, nativeHandleCallback); ipcMain.handle(channel.id, nativeHandleCallback);
@ -27,8 +27,6 @@ const enlistRequestChannelListenerInjectable = getInjectable({
}; };
}; };
}, },
injectionToken: enlistRequestChannelListenerInjectionToken,
}); });
export default enlistRequestChannelListenerInjectable; export default enlistRequestChannelListenerInjectable;

View File

@ -5,11 +5,19 @@
import { getDiForUnitTesting } from "../../../getDiForUnitTesting"; import { getDiForUnitTesting } from "../../../getDiForUnitTesting";
import ipcMainInjectable from "../ipc-main/ipc-main.injectable"; import ipcMainInjectable from "../ipc-main/ipc-main.injectable";
import type { IpcMain, IpcMainInvokeEvent } from "electron"; 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 { getPromiseStatus } from "../../../../common/test-utils/get-promise-status";
import type { AsyncFnMock } from "@async-fn/jest"; import type { AsyncFnMock } from "@async-fn/jest";
import asyncFn 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<unknown, unknown>;
const testRequestChannel: TestRequestChannel = {
id: "some-channel-id",
};
describe("enlist request channel listener in main", () => { describe("enlist request channel listener in main", () => {
let enlistRequestChannelListener: EnlistRequestChannelListener; let enlistRequestChannelListener: EnlistRequestChannelListener;
@ -30,20 +38,18 @@ describe("enlist request channel listener in main", () => {
di.override(ipcMainInjectable, () => ipcMainStub); di.override(ipcMainInjectable, () => ipcMainStub);
enlistRequestChannelListener = di.inject( enlistRequestChannelListener = di.inject(enlistRequestChannelListenerInjectable);
enlistRequestChannelListenerInjectionToken,
);
}); });
describe("when called", () => { describe("when called", () => {
let handlerMock: AsyncFnMock<(message: any) => any>; let handlerMock: AsyncFnMock<RequestChannelHandler<TestRequestChannel>>;
let disposer: () => void; let disposer: () => void;
beforeEach(() => { beforeEach(() => {
handlerMock = asyncFn(); handlerMock = asyncFn();
disposer = enlistRequestChannelListener({ disposer = enlistRequestChannelListener({
channel: { id: "some-channel-id" }, channel: testRequestChannel,
handler: handlerMock, handler: handlerMock,
}); });
}); });
@ -91,7 +97,7 @@ describe("enlist request channel listener in main", () => {
it("resolves with the response", async () => { it("resolves with the response", async () => {
const actual = await actualPromise; const actual = await actualPromise;
expect(actual).toBe('"some-response"'); expect(actual).toBe("some-response");
}); });
it("when disposing the listener, de-registers the listener", () => { it("when disposing the listener, de-registers the listener", () => {
@ -106,7 +112,7 @@ describe("enlist request channel listener in main", () => {
const actual = await actualPromise; 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 () => { 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; 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" }); await handlerMock.resolve({ some: "object" });
const actual = await actualPromise; 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); expect(handlerMock).toHaveBeenCalledWith(true);
}); });
it("given stringified object as request, when request arrives, calls the handler with the request", () => { it("given object as request, when request arrives, calls the handler with the request", () => {
handleMock.mock.calls[0][1]({} as IpcMainInvokeEvent, JSON.stringify({ some: "object" })); handleMock.mock.calls[0][1]({} as IpcMainInvokeEvent, { some: "object" });
expect(handlerMock).toHaveBeenCalledWith({ some: "object" }); expect(handlerMock).toHaveBeenCalledWith({ some: "object" });
}); });

View File

@ -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> = Channel extends RequestChannel<infer Request, infer Response>
? (req: Request) => Promise<Response> | Response
: never;
export interface RequestChannelListener<Channel> {
channel: Channel;
handler: RequestChannelHandler<Channel>;
}
export const requestChannelListenerInjectionToken = getInjectionToken<RequestChannelListener<RequestChannel<unknown, unknown>>>( {
id: "request-channel-listener",
});
export interface GetRequestChannelListenerInjectableInfo<
Channel extends RequestChannel<Request, Response>,
Request,
Response,
> {
channel: Channel;
handler: (di: DiContainerForInjection) => RequestChannelHandler<Channel>;
}
export function getRequestChannelListenerInjectable<
Channel extends RequestChannel<Request, Response>,
Request,
Response,
>(info: GetRequestChannelListenerInjectableInfo<Channel, Request, Response>) {
return getInjectable({
id: `${info.channel.id}-listener`,
instantiate: (di) => ({
channel: info.channel,
handler: info.handler(di),
}),
injectionToken: requestChannelListenerInjectionToken,
});
}

View File

@ -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<RequestChannel<unknown, unknown>>();
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;

View File

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

View File

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

View File

@ -3,9 +3,8 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { messageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; import type { SendMessageToChannel } from "../../../common/utils/channel/message-to-channel-injection-token";
import type { MessageChannel } from "../../../common/utils/channel/message-channel-injection-token"; import { sendMessageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token";
import { tentativeStringifyJson } from "../../../common/utils/tentative-stringify-json";
import getVisibleWindowsInjectable from "../../start-main-application/lens-window/get-visible-windows.injectable"; import getVisibleWindowsInjectable from "../../start-main-application/lens-window/get-visible-windows.injectable";
const messageToChannelInjectable = getInjectable({ const messageToChannelInjectable = getInjectable({
@ -14,18 +13,14 @@ const messageToChannelInjectable = getInjectable({
instantiate: (di) => { instantiate: (di) => {
const getVisibleWindows = di.inject(getVisibleWindowsInjectable); const getVisibleWindows = di.inject(getVisibleWindowsInjectable);
// TODO: Figure out way to improve typing in internals return ((channel, data) => {
// Notice that this should be injected using "messageToChannelInjectionToken" which is typed correctly. for (const window of getVisibleWindows()) {
return (channel: MessageChannel<any>, message?: unknown) => { window.send({ channel: channel.id, data });
const stringifiedMessage = tentativeStringifyJson(message); }
}) as SendMessageToChannel;
getVisibleWindows().forEach((lensWindow) =>
lensWindow.send({ channel: channel.id, data: stringifiedMessage ? [stringifiedMessage] : [] }),
);
};
}, },
injectionToken: messageToChannelInjectionToken, injectionToken: sendMessageToChannelInjectionToken,
}); });
export default messageToChannelInjectable; export default messageToChannelInjectable;

View File

@ -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<any> = { id: "some-channel" };

View File

@ -2,20 +2,13 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { resolveSystemProxyChannel } from "../../../common/utils/resolve-system-proxy/resolve-system-proxy-channel";
import resolveSystemProxyChannelInjectable from "../../../common/utils/resolve-system-proxy/resolve-system-proxy-channel.injectable"; import { getRequestChannelListenerInjectable } from "../channel/channel-listeners/listener-tokens";
import resolveSystemProxyInjectable from "./resolve-system-proxy.injectable"; import resolveSystemProxyInjectable from "./resolve-system-proxy.injectable";
import { requestChannelListenerInjectionToken } from "../../../common/utils/channel/request-channel-listener-injection-token";
const resolveSystemProxyChannelResponderInjectable = getInjectable({ const resolveSystemProxyChannelResponderInjectable = getRequestChannelListenerInjectable({
id: "resolve-system-proxy-channel-responder", channel: resolveSystemProxyChannel,
handler: (di) => di.inject(resolveSystemProxyInjectable),
instantiate: (di) => ({
channel: di.inject(resolveSystemProxyChannelInjectable),
handler: di.inject(resolveSystemProxyInjectable),
}),
injectionToken: requestChannelListenerInjectionToken,
}); });
export default resolveSystemProxyChannelResponderInjectable; export default resolveSystemProxyChannelResponderInjectable;

View File

@ -2,30 +2,20 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { syncBoxInitialValueChannel } from "../../../common/utils/sync-box/channels";
import syncBoxInitialValueChannelInjectable from "../../../common/utils/sync-box/sync-box-initial-value-channel.injectable";
import { syncBoxInjectionToken } from "../../../common/utils/sync-box/sync-box-injection-token"; 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({ const syncBoxInitialValueChannelListenerInjectable = getRequestChannelListenerInjectable({
id: "sync-box-initial-value-channel-listener", channel: syncBoxInitialValueChannel,
handler: (di) => {
instantiate: (di) => {
const channel = di.inject(syncBoxInitialValueChannelInjectable);
const syncBoxes = di.injectMany(syncBoxInjectionToken); const syncBoxes = di.injectMany(syncBoxInjectionToken);
return { return () => syncBoxes.map((box) => ({
channel,
handler: () =>
syncBoxes.map((box) => ({
id: box.id, id: box.id,
value: box.value.get(), value: box.value.get(),
})), }));
};
}, },
injectionToken: requestChannelListenerInjectionToken,
}); });
export default syncBoxInitialValueChannelListenerInjectable; export default syncBoxInitialValueChannelListenerInjectable;

View File

@ -5,7 +5,7 @@
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import appPathsStateInjectable from "../../common/app-paths/app-paths-state.injectable"; import appPathsStateInjectable from "../../common/app-paths/app-paths-state.injectable";
import { beforeFrameStartsInjectionToken } from "../before-frame-starts/before-frame-starts-injection-token"; 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"; import { requestFromChannelInjectionToken } from "../../common/utils/channel/request-from-channel-injection-token";
const setupAppPathsInjectable = getInjectable({ const setupAppPathsInjectable = getInjectable({
@ -13,15 +13,12 @@ const setupAppPathsInjectable = getInjectable({
instantiate: (di) => { instantiate: (di) => {
const requestFromChannel = di.inject(requestFromChannelInjectionToken); const requestFromChannel = di.inject(requestFromChannelInjectionToken);
const appPathsChannel = di.inject(appPathsChannelInjectable);
const appPathsState = di.inject(appPathsStateInjectable); const appPathsState = di.inject(appPathsStateInjectable);
return { return {
id: "setup-app-paths", id: "setup-app-paths",
run: async () => { run: async () => {
const appPaths = await requestFromChannel( const appPaths = await requestFromChannel(appPathsChannel);
appPathsChannel,
);
appPathsState.set(appPaths); appPathsState.set(appPaths);
}, },

View File

@ -4,7 +4,7 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { asyncComputed } from "@ogre-tools/injectable-react"; 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 { requestFromChannelInjectionToken } from "../../../../../common/utils/channel/request-from-channel-injection-token";
import showErrorNotificationInjectable from "../../../notifications/show-error-notification.injectable"; import showErrorNotificationInjectable from "../../../notifications/show-error-notification.injectable";
import helmRepositoriesErrorStateInjectable from "./helm-repositories-error-state.injectable"; import helmRepositoriesErrorStateInjectable from "./helm-repositories-error-state.injectable";
@ -15,12 +15,11 @@ const activeHelmRepositoriesInjectable = getInjectable({
instantiate: (di) => { instantiate: (di) => {
const requestFromChannel = di.inject(requestFromChannelInjectionToken); const requestFromChannel = di.inject(requestFromChannelInjectionToken);
const getHelmRepositoriesChannel = di.inject(getActiveHelmRepositoriesChannelInjectable);
const showErrorNotification = di.inject(showErrorNotificationInjectable); const showErrorNotification = di.inject(showErrorNotificationInjectable);
const helmRepositoriesErrorState = di.inject(helmRepositoriesErrorStateInjectable); const helmRepositoriesErrorState = di.inject(helmRepositoriesErrorStateInjectable);
return asyncComputed(async () => { return asyncComputed(async () => {
const result = await requestFromChannel(getHelmRepositoriesChannel); const result = await requestFromChannel(getActiveHelmRepositoriesChannel);
if (result.callWasSuccessful) { if (result.callWasSuccessful) {
return result.response; return result.response;

View File

@ -3,19 +3,18 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import addHelmRepositoryChannelInjectable from "../../../../../../../common/helm/add-helm-repository-channel.injectable";
import type { HelmRepo } from "../../../../../../../common/helm/helm-repo"; import type { HelmRepo } from "../../../../../../../common/helm/helm-repo";
import { requestFromChannelInjectionToken } from "../../../../../../../common/utils/channel/request-from-channel-injection-token"; import { requestFromChannelInjectionToken } from "../../../../../../../common/utils/channel/request-from-channel-injection-token";
import activeHelmRepositoriesInjectable from "../../active-helm-repositories.injectable"; import activeHelmRepositoriesInjectable from "../../active-helm-repositories.injectable";
import showErrorNotificationInjectable from "../../../../../notifications/show-error-notification.injectable"; import showErrorNotificationInjectable from "../../../../../notifications/show-error-notification.injectable";
import showSuccessNotificationInjectable from "../../../../../notifications/show-success-notification.injectable"; import showSuccessNotificationInjectable from "../../../../../notifications/show-success-notification.injectable";
import { addHelmRepositoryChannel } from "../../../../../../../common/helm/add-helm-repository-channel";
const addHelmRepositoryInjectable = getInjectable({ const addHelmRepositoryInjectable = getInjectable({
id: "add-public-helm-repository", id: "add-public-helm-repository",
instantiate: (di) => { instantiate: (di) => {
const requestFromChannel = di.inject(requestFromChannelInjectionToken); const requestFromChannel = di.inject(requestFromChannelInjectionToken);
const addHelmRepositoryChannel = di.inject(addHelmRepositoryChannelInjectable);
const activeHelmRepositories = di.inject(activeHelmRepositoriesInjectable); const activeHelmRepositories = di.inject(activeHelmRepositoriesInjectable);
const showErrorNotification = di.inject(showErrorNotificationInjectable); const showErrorNotification = di.inject(showErrorNotificationInjectable);
const showSuccessNotification = di.inject(showSuccessNotificationInjectable); const showSuccessNotification = di.inject(showSuccessNotificationInjectable);

View File

@ -6,14 +6,13 @@ import { getInjectable } from "@ogre-tools/injectable";
import type { HelmRepo } from "../../../../../common/helm/helm-repo"; import type { HelmRepo } from "../../../../../common/helm/helm-repo";
import { requestFromChannelInjectionToken } from "../../../../../common/utils/channel/request-from-channel-injection-token"; import { requestFromChannelInjectionToken } from "../../../../../common/utils/channel/request-from-channel-injection-token";
import activeHelmRepositoriesInjectable from "./active-helm-repositories.injectable"; 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({ const removePublicHelmRepositoryInjectable = getInjectable({
id: "remove-public-helm-repository", id: "remove-public-helm-repository",
instantiate: (di) => { instantiate: (di) => {
const requestFromChannel = di.inject(requestFromChannelInjectionToken); const requestFromChannel = di.inject(requestFromChannelInjectionToken);
const removeHelmRepositoryChannel = di.inject(removeHelmRepositoryChannelInjectable);
const activeHelmRepositories = di.inject(activeHelmRepositoriesInjectable); const activeHelmRepositories = di.inject(activeHelmRepositoriesInjectable);
return async (repository: HelmRepo) => { return async (repository: HelmRepo) => {

View File

@ -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 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 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 { 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 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 { LensWindow } from "../../../main/start-main-application/lens-window/application-window/create-lens-window.injectable";
import type { FakeExtensionOptions } from "./get-extension-fake"; import type { FakeExtensionOptions } from "./get-extension-fake";
@ -166,7 +165,7 @@ export const getApplicationBuilder = () => {
mainDi.register(mainExtensionsStateInjectable); mainDi.register(mainExtensionsStateInjectable);
}); });
const overrideChannelsForWindow = overrideChannels(mainDi); const { overrideForWindow, sendToWindow } = overrideChannels(mainDi);
const beforeApplicationStartCallbacks: Callback[] = []; const beforeApplicationStartCallbacks: Callback[] = [];
const beforeWindowStartCallbacks: Callback[] = []; const beforeWindowStartCallbacks: Callback[] = [];
@ -208,7 +207,7 @@ export const getApplicationBuilder = () => {
const windowDi = getRendererDi({ doGeneralOverrides: true }); const windowDi = getRendererDi({ doGeneralOverrides: true });
overrideChannelsForWindow(windowDi, windowId); overrideForWindow(windowDi, windowId);
overrideFsWithFakes(windowDi, fsState); overrideFsWithFakes(windowDi, fsState);
runInAction(() => { runInAction(() => {
@ -259,9 +258,7 @@ export const getApplicationBuilder = () => {
}, },
send: (arg) => { send: (arg) => {
const sendFake = mainDi.inject(sendToChannelInElectronBrowserWindowInjectable) as any; sendToWindow(windowId, arg);
sendFake(windowId, null, arg);
}, },
reload: () => { reload: () => {

View File

@ -3,7 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import 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"; import messageToChannelInjectable from "../../utils/channel/message-to-channel.injectable";
const restartAndInstallUpdateInjectable = getInjectable({ const restartAndInstallUpdateInjectable = getInjectable({
@ -11,10 +11,9 @@ const restartAndInstallUpdateInjectable = getInjectable({
instantiate: (di) => { instantiate: (di) => {
const messageToChannel = di.inject(messageToChannelInjectable); const messageToChannel = di.inject(messageToChannelInjectable);
const channel = di.inject(restartAndInstallUpdateChannel);
return () => { return () => {
messageToChannel(channel); messageToChannel(restartAndInstallUpdateChannel);
}; };
}, },
}); });

View File

@ -3,18 +3,17 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { messageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; import { sendMessageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token";
import rootFrameIsRenderedChannelInjectable from "../../../common/root-frame-rendered-channel/root-frame-rendered-channel.injectable"; import { rootFrameHasRenderedChannel } from "../../../common/root-frame/root-frame-rendered-channel";
const broadcastThatRootFrameIsRenderedInjectable = getInjectable({ const broadcastThatRootFrameIsRenderedInjectable = getInjectable({
id: "broadcast-that-root-frame-is-rendered", id: "broadcast-that-root-frame-is-rendered",
instantiate: (di) => { instantiate: (di) => {
const messageToChannel = di.inject(messageToChannelInjectionToken); const messageToChannel = di.inject(sendMessageToChannelInjectionToken);
const rootFrameIsRenderedChannel = di.inject(rootFrameIsRenderedChannelInjectable);
return () => { return () => {
messageToChannel(rootFrameIsRenderedChannel); messageToChannel(rootFrameHasRenderedChannel);
}; };
}, },
}); });

View File

@ -5,14 +5,11 @@
import { ipcRenderer } from "electron"; import { ipcRenderer } from "electron";
import { reaction } from "mobx"; import { reaction } from "mobx";
import { broadcastMessage, ipcRendererOn } from "../../common/ipc"; import { broadcastMessage } from "../../common/ipc";
import { import { getLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
getLegacyGlobalDiForExtensionApi,
} from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
import matchedClusterIdInjectable from "./matched-cluster-id.injectable"; import matchedClusterIdInjectable from "./matched-cluster-id.injectable";
export const enum IpcRendererNavigationEvents { export const enum IpcRendererNavigationEvents {
RELOAD_PAGE = "renderer:page-reload",
CLUSTER_VIEW_CURRENT_ID = "renderer:cluster-id-of-active-view", CLUSTER_VIEW_CURRENT_ID = "renderer:cluster-id-of-active-view",
NAVIGATE_IN_APP = "renderer:navigate", NAVIGATE_IN_APP = "renderer:navigate",
NAVIGATE_IN_CLUSTER = "renderer:navigate-in-cluster", NAVIGATE_IN_CLUSTER = "renderer:navigate-in-cluster",
@ -27,11 +24,6 @@ export function bindEvents() {
if (process.isMainFrame) { if (process.isMainFrame) {
bindClusterManagerRouteEvents(); bindClusterManagerRouteEvents();
} }
// Reload dashboard window
ipcRendererOn(IpcRendererNavigationEvents.RELOAD_PAGE, () => {
location.reload();
});
} }
// Handle events only in main window renderer process (see also: cluster-manager.tsx) // Handle events only in main window renderer process (see also: cluster-manager.tsx)

View File

@ -2,12 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import type { InjectionToken } from "@ogre-tools/injectable";
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import currentlyInClusterFrameInjectable from "../routes/currently-in-cluster-frame.injectable"; import currentlyInClusterFrameInjectable from "../routes/currently-in-cluster-frame.injectable";
import appNavigationChannelInjectable from "../../common/front-end-routing/app-navigation-channel.injectable"; import { appNavigationChannel } from "../../common/front-end-routing/app-navigation-channel";
import clusterFrameNavigationChannelInjectable from "../../common/front-end-routing/cluster-frame-navigation-channel.injectable"; import { clusterFrameNavigationChannel } from "../../common/front-end-routing/cluster-frame-navigation-channel";
import focusWindowInjectable from "./focus-window.injectable"; import focusWindowInjectable from "./focus-window.injectable";
import { navigateToUrlInjectionToken } from "../../common/front-end-routing/navigate-to-url-injection-token"; 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"; import { messageChannelListenerInjectionToken } from "../../common/utils/channel/message-channel-listener-injection-token";
const navigationChannelListenerInjectable = getInjectable({ const navigationChannelListenerInjectable = getInjectable({
@ -15,8 +17,6 @@ const navigationChannelListenerInjectable = getInjectable({
instantiate: (di) => { instantiate: (di) => {
const currentlyInClusterFrame = di.inject(currentlyInClusterFrameInjectable); const currentlyInClusterFrame = di.inject(currentlyInClusterFrameInjectable);
const appNavigationChannel = di.inject(appNavigationChannelInjectable);
const clusterFrameNavigationChannel = di.inject(clusterFrameNavigationChannelInjectable);
const focusWindow = di.inject(focusWindowInjectable); const focusWindow = di.inject(focusWindowInjectable);
const navigateToUrl = di.inject(navigateToUrlInjectionToken); 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; export default navigationChannelListenerInjectable;

Some files were not shown because too many files have changed in this diff Show More