mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
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>
This commit is contained in:
parent
a7ea891458
commit
13ba8dea84
@ -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;
|
||||
13
src/common/app-paths/app-paths-channel.ts
Normal file
13
src/common/app-paths/app-paths-channel.ts
Normal 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",
|
||||
};
|
||||
|
||||
@ -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",
|
||||
};
|
||||
@ -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;
|
||||
@ -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;
|
||||
12
src/common/front-end-routing/app-navigation-channel.ts
Normal file
12
src/common/front-end-routing/app-navigation-channel.ts
Normal 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,
|
||||
};
|
||||
@ -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;
|
||||
@ -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,
|
||||
};
|
||||
@ -5,22 +5,33 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { ExecFileOptions } from "child_process";
|
||||
import { execFile } from "child_process";
|
||||
import { promisify } from "util";
|
||||
import type { AsyncResult } from "../utils/async-result";
|
||||
|
||||
export type ExecFile = (filePath: string, args: string[], options: ExecFileOptions) => Promise<string>;
|
||||
export interface ExecFile {
|
||||
(filePath: string, args: string[], options: ExecFileOptions): Promise<AsyncResult<string, { stderr: string; error: Error }>>;
|
||||
}
|
||||
|
||||
const execFileInjectable = getInjectable({
|
||||
id: "exec-file",
|
||||
|
||||
instantiate: (): ExecFile => {
|
||||
const asyncExecFile = promisify(execFile);
|
||||
|
||||
return async (filePath, args, options) => {
|
||||
const result = await asyncExecFile(filePath, args, options);
|
||||
|
||||
return result.stdout;
|
||||
};
|
||||
},
|
||||
instantiate: (): ExecFile => (filePath, args, options) => new Promise((resolve) => {
|
||||
execFile(filePath, args, options, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
resolve({
|
||||
callWasSuccessful: false,
|
||||
error: {
|
||||
error,
|
||||
stderr,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
resolve({
|
||||
callWasSuccessful: true,
|
||||
response: stdout,
|
||||
});
|
||||
}
|
||||
});
|
||||
}),
|
||||
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
@ -2,22 +2,12 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { HelmRepo } from "./helm-repo";
|
||||
import type { RequestChannel } from "../utils/channel/request-channel-injection-token";
|
||||
import { requestChannelInjectionToken } from "../utils/channel/request-channel-injection-token";
|
||||
import type { AsyncResult } from "../utils/async-result";
|
||||
import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token";
|
||||
|
||||
export type AddHelmRepositoryChannel = RequestChannel<HelmRepo, AsyncResult<string>>;
|
||||
|
||||
const addHelmRepositoryChannelInjectable = getInjectable({
|
||||
export const addHelmRepositoryChannel: AddHelmRepositoryChannel = {
|
||||
id: "add-helm-repository-channel",
|
||||
|
||||
instantiate: (): AddHelmRepositoryChannel => ({
|
||||
id: "add-helm-repository-channel",
|
||||
}),
|
||||
|
||||
injectionToken: requestChannelInjectionToken,
|
||||
});
|
||||
|
||||
export default addHelmRepositoryChannelInjectable;
|
||||
};
|
||||
@ -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;
|
||||
13
src/common/helm/get-active-helm-repositories-channel.ts
Normal file
13
src/common/helm/get-active-helm-repositories-channel.ts
Normal 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",
|
||||
};
|
||||
@ -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;
|
||||
13
src/common/helm/remove-helm-repository-channel.ts
Normal file
13
src/common/helm/remove-helm-repository-channel.ts
Normal 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",
|
||||
};
|
||||
@ -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;
|
||||
11
src/common/root-frame/root-frame-rendered-channel.ts
Normal file
11
src/common/root-frame/root-frame-rendered-channel.ts
Normal 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",
|
||||
};
|
||||
@ -4,17 +4,17 @@
|
||||
*/
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { MessageToChannel } from "./message-to-channel-injection-token";
|
||||
import { messageToChannelInjectionToken } from "./message-to-channel-injection-token";
|
||||
import type { SendMessageToChannel } from "./message-to-channel-injection-token";
|
||||
import { sendMessageToChannelInjectionToken } from "./message-to-channel-injection-token";
|
||||
import type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder";
|
||||
import type { LensWindow } from "../../../main/start-main-application/lens-window/application-window/create-lens-window.injectable";
|
||||
import type { MessageChannel } from "./message-channel-listener-injection-token";
|
||||
import { messageChannelListenerInjectionToken } from "./message-channel-listener-injection-token";
|
||||
import type { MessageChannel } from "./message-channel-injection-token";
|
||||
import type { RequestFromChannel } from "./request-from-channel-injection-token";
|
||||
import { requestFromChannelInjectionToken } from "./request-from-channel-injection-token";
|
||||
import type { RequestChannel } from "./request-channel-injection-token";
|
||||
import { requestChannelListenerInjectionToken } from "./request-channel-listener-injection-token";
|
||||
import type { RequestChannel, RequestChannelHandler } from "./request-channel-listener-injection-token";
|
||||
import { getRequestChannelListenerInjectable } from "./request-channel-listener-injection-token";
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import { getPromiseStatus } from "../../test-utils/get-promise-status";
|
||||
@ -25,10 +25,9 @@ type TestRequestChannel = RequestChannel<string, string>;
|
||||
|
||||
describe("channel", () => {
|
||||
describe("messaging from main to renderer, given listener for channel in a window and application has started", () => {
|
||||
let testMessageChannel: TestMessageChannel;
|
||||
let messageListenerInWindowMock: jest.Mock;
|
||||
let mainDi: DiContainer;
|
||||
let messageToChannel: MessageToChannel;
|
||||
let messageToChannel: SendMessageToChannel;
|
||||
let builder: ApplicationBuilder;
|
||||
|
||||
beforeEach(async () => {
|
||||
@ -39,24 +38,17 @@ describe("channel", () => {
|
||||
const testChannelListenerInTestWindowInjectable = getInjectable({
|
||||
id: "test-channel-listener-in-test-window",
|
||||
|
||||
instantiate: (di) => ({
|
||||
channel: di.inject(testMessageChannelInjectable),
|
||||
instantiate: () => ({
|
||||
channel: testMessageChannel,
|
||||
handler: messageListenerInWindowMock,
|
||||
}),
|
||||
|
||||
injectionToken: messageChannelListenerInjectionToken,
|
||||
});
|
||||
|
||||
builder.beforeApplicationStart((mainDi) => {
|
||||
runInAction(() => {
|
||||
mainDi.register(testMessageChannelInjectable);
|
||||
});
|
||||
});
|
||||
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
runInAction(() => {
|
||||
windowDi.register(testChannelListenerInTestWindowInjectable);
|
||||
windowDi.register(testMessageChannelInjectable);
|
||||
});
|
||||
});
|
||||
|
||||
@ -64,8 +56,7 @@ describe("channel", () => {
|
||||
|
||||
await builder.startHidden();
|
||||
|
||||
testMessageChannel = mainDi.inject(testMessageChannelInjectable);
|
||||
messageToChannel = mainDi.inject(messageToChannelInjectionToken);
|
||||
messageToChannel = mainDi.inject(sendMessageToChannelInjectionToken);
|
||||
});
|
||||
|
||||
describe("given window is started", () => {
|
||||
@ -109,9 +100,8 @@ describe("channel", () => {
|
||||
});
|
||||
|
||||
describe("messaging from renderer to main, given listener for channel in a main and application has started", () => {
|
||||
let testMessageChannel: TestMessageChannel;
|
||||
let messageListenerInMainMock: jest.Mock;
|
||||
let messageToChannel: MessageToChannel;
|
||||
let messageToChannel: SendMessageToChannel;
|
||||
|
||||
beforeEach(async () => {
|
||||
const applicationBuilder = getApplicationBuilder();
|
||||
@ -121,9 +111,8 @@ describe("channel", () => {
|
||||
const testChannelListenerInMainInjectable = getInjectable({
|
||||
id: "test-channel-listener-in-main",
|
||||
|
||||
instantiate: (di) => ({
|
||||
channel: di.inject(testMessageChannelInjectable),
|
||||
|
||||
instantiate: () => ({
|
||||
channel: testMessageChannel,
|
||||
handler: messageListenerInMainMock,
|
||||
}),
|
||||
|
||||
@ -133,13 +122,6 @@ describe("channel", () => {
|
||||
applicationBuilder.beforeApplicationStart((mainDi) => {
|
||||
runInAction(() => {
|
||||
mainDi.register(testChannelListenerInMainInjectable);
|
||||
mainDi.register(testMessageChannelInjectable);
|
||||
});
|
||||
});
|
||||
|
||||
applicationBuilder.beforeWindowStart((windowDi) => {
|
||||
runInAction(() => {
|
||||
windowDi.register(testMessageChannelInjectable);
|
||||
});
|
||||
});
|
||||
|
||||
@ -147,8 +129,7 @@ describe("channel", () => {
|
||||
|
||||
const windowDi = applicationBuilder.applicationWindow.only.di;
|
||||
|
||||
testMessageChannel = windowDi.inject(testMessageChannelInjectable);
|
||||
messageToChannel = windowDi.inject(messageToChannelInjectionToken);
|
||||
messageToChannel = windowDi.inject(sendMessageToChannelInjectionToken);
|
||||
});
|
||||
|
||||
it("when sending message, triggers listener in main", () => {
|
||||
@ -159,8 +140,7 @@ describe("channel", () => {
|
||||
});
|
||||
|
||||
describe("requesting from main in renderer, given listener for channel in a main and application has started", () => {
|
||||
let testRequestChannel: TestRequestChannel;
|
||||
let requestListenerInMainMock: AsyncFnMock<(arg: string) => string>;
|
||||
let requestListenerInMainMock: AsyncFnMock<RequestChannelHandler<TestRequestChannel>>;
|
||||
let requestFromChannel: RequestFromChannel;
|
||||
|
||||
beforeEach(async () => {
|
||||
@ -168,28 +148,20 @@ describe("channel", () => {
|
||||
|
||||
requestListenerInMainMock = asyncFn();
|
||||
|
||||
const testChannelListenerInMainInjectable = getInjectable({
|
||||
id: "test-channel-listener-in-main",
|
||||
const testChannelHandlerInjectable = getInjectable({
|
||||
id: "test-channel-handler",
|
||||
instantiate: (): RequestChannelHandler<TestRequestChannel> => requestListenerInMainMock,
|
||||
});
|
||||
|
||||
instantiate: (di) => ({
|
||||
channel: di.inject(testRequestChannelInjectable),
|
||||
|
||||
handler: requestListenerInMainMock,
|
||||
}),
|
||||
|
||||
injectionToken: requestChannelListenerInjectionToken,
|
||||
const testChannelListenerInMainInjectable = getRequestChannelListenerInjectable({
|
||||
channel: testRequestChannel,
|
||||
handlerInjectable: testChannelHandlerInjectable,
|
||||
});
|
||||
|
||||
applicationBuilder.beforeApplicationStart((mainDi) => {
|
||||
runInAction(() => {
|
||||
mainDi.register(testChannelHandlerInjectable);
|
||||
mainDi.register(testChannelListenerInMainInjectable);
|
||||
mainDi.register(testRequestChannelInjectable);
|
||||
});
|
||||
});
|
||||
|
||||
applicationBuilder.beforeWindowStart((windowDi) => {
|
||||
runInAction(() => {
|
||||
windowDi.register(testRequestChannelInjectable);
|
||||
});
|
||||
});
|
||||
|
||||
@ -197,8 +169,6 @@ describe("channel", () => {
|
||||
|
||||
const windowDi = applicationBuilder.applicationWindow.only.di;
|
||||
|
||||
testRequestChannel = windowDi.inject(testRequestChannelInjectable);
|
||||
|
||||
requestFromChannel = windowDi.inject(
|
||||
requestFromChannelInjectionToken,
|
||||
);
|
||||
@ -232,19 +202,11 @@ describe("channel", () => {
|
||||
});
|
||||
});
|
||||
|
||||
const testMessageChannelInjectable = getInjectable({
|
||||
id: "some-message-test-channel",
|
||||
const testMessageChannel: TestMessageChannel = {
|
||||
id: "some-message-channel-id",
|
||||
};
|
||||
|
||||
instantiate: (): TestMessageChannel => ({
|
||||
id: "some-message-channel-id",
|
||||
}),
|
||||
});
|
||||
|
||||
const testRequestChannelInjectable = getInjectable({
|
||||
id: "some-request-test-channel",
|
||||
|
||||
instantiate: (): TestRequestChannel => ({
|
||||
id: "some-request-channel-id",
|
||||
}),
|
||||
});
|
||||
const testRequestChannel: TestRequestChannel = {
|
||||
id: "some-request-channel-id",
|
||||
};
|
||||
|
||||
|
||||
@ -3,14 +3,11 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { MessageChannel } from "./message-channel-injection-token";
|
||||
import type { MessageChannelListener } from "./message-channel-listener-injection-token";
|
||||
import type { Disposer } from "../disposer";
|
||||
import type { MessageChannel, MessageChannelListener } from "./message-channel-listener-injection-token";
|
||||
|
||||
export type EnlistMessageChannelListener = <
|
||||
TChannel extends MessageChannel<any>,
|
||||
>(listener: MessageChannelListener<TChannel>) => () => void;
|
||||
export type EnlistMessageChannelListener = (listener: MessageChannelListener<MessageChannel<unknown>>) => Disposer;
|
||||
|
||||
export const enlistMessageChannelListenerInjectionToken =
|
||||
getInjectionToken<EnlistMessageChannelListener>({
|
||||
id: "enlist-message-channel-listener",
|
||||
});
|
||||
export const enlistMessageChannelListenerInjectionToken = getInjectionToken<EnlistMessageChannelListener>({
|
||||
id: "enlist-message-channel-listener",
|
||||
});
|
||||
|
||||
@ -3,14 +3,11 @@
|
||||
* 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";
|
||||
import type { Disposer } from "../disposer";
|
||||
import type { RequestChannel, RequestChannelListener } from "./request-channel-listener-injection-token";
|
||||
|
||||
export type EnlistRequestChannelListener = <
|
||||
TChannel extends RequestChannel<any, any>,
|
||||
>(listener: RequestChannelListener<TChannel>) => () => void;
|
||||
export type EnlistRequestChannelListener = <TChannel extends RequestChannel<unknown, unknown>>(listener: RequestChannelListener<TChannel>) => Disposer;
|
||||
|
||||
export const enlistRequestChannelListenerInjectionToken =
|
||||
getInjectionToken<EnlistRequestChannelListener>({
|
||||
id: "enlist-request-channel-listener",
|
||||
});
|
||||
export const enlistRequestChannelListenerInjectionToken = getInjectionToken<EnlistRequestChannelListener>({
|
||||
id: "enlist-request-channel-listener",
|
||||
});
|
||||
|
||||
@ -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",
|
||||
});
|
||||
@ -2,17 +2,47 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { SetRequired } from "type-fest";
|
||||
import type { MessageChannel } from "./message-channel-injection-token";
|
||||
import type { Injectable } from "@ogre-tools/injectable";
|
||||
import { getInjectable, getInjectionToken } from "@ogre-tools/injectable";
|
||||
|
||||
export interface MessageChannelListener<TChannel extends MessageChannel<any>> {
|
||||
channel: TChannel;
|
||||
handler: (value: SetRequired<TChannel, "_messageSignature">["_messageSignature"]) => void;
|
||||
export interface MessageChannel<Message> {
|
||||
id: string;
|
||||
_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",
|
||||
},
|
||||
);
|
||||
|
||||
export interface GetMessageChannelListenerInfo<
|
||||
Channel extends MessageChannel<Message>,
|
||||
Message,
|
||||
> {
|
||||
channel: Channel;
|
||||
handlerInjectable: Injectable<MessageChannelHandler<Channel>, unknown, void>;
|
||||
}
|
||||
|
||||
export function getMessageChannelListenerInjectable<
|
||||
Channel extends MessageChannel<Message>,
|
||||
Message,
|
||||
>(info: GetMessageChannelListenerInfo<Channel, Message>) {
|
||||
return getInjectable({
|
||||
id: `${info.channel.id}-listener`,
|
||||
instantiate: (di) => ({
|
||||
channel: info.channel,
|
||||
handler: di.inject(info.handlerInjectable),
|
||||
}),
|
||||
injectionToken: messageChannelListenerInjectionToken,
|
||||
});
|
||||
}
|
||||
|
||||
@ -3,21 +3,13 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { SetRequired } from "type-fest";
|
||||
import type { MessageChannel } from "./message-channel-injection-token";
|
||||
import type { MessageChannel } from "./message-channel-listener-injection-token";
|
||||
|
||||
export interface MessageToChannel {
|
||||
<TChannel extends MessageChannel<TMessage>, TMessage extends void>(
|
||||
channel: TChannel,
|
||||
): void;
|
||||
|
||||
<TChannel extends MessageChannel<any>>(
|
||||
channel: TChannel,
|
||||
message: SetRequired<TChannel, "_messageSignature">["_messageSignature"],
|
||||
): void;
|
||||
export interface SendMessageToChannel {
|
||||
(channel: MessageChannel<void>): void;
|
||||
<Message>(channel: MessageChannel<Message>, message: Message): void;
|
||||
}
|
||||
|
||||
export const messageToChannelInjectionToken =
|
||||
getInjectionToken<MessageToChannel>({
|
||||
id: "message-to-message-channel",
|
||||
});
|
||||
export const sendMessageToChannelInjectionToken = getInjectionToken<SendMessageToChannel>({
|
||||
id: "send-message-to-message-channel",
|
||||
});
|
||||
|
||||
@ -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",
|
||||
});
|
||||
@ -2,24 +2,48 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { SetRequired } from "type-fest";
|
||||
import type { RequestChannel } from "./request-channel-injection-token";
|
||||
import type { Injectable } from "@ogre-tools/injectable";
|
||||
import { getInjectable, getInjectionToken } from "@ogre-tools/injectable";
|
||||
|
||||
export interface RequestChannelListener<TChannel extends RequestChannel<any, any>> {
|
||||
channel: TChannel;
|
||||
export type RequestChannelHandler<Channel> = Channel extends RequestChannel<infer Request, infer Response>
|
||||
? (req: Request) => Promise<Response> | Response
|
||||
: never;
|
||||
|
||||
handler: (
|
||||
request: SetRequired<TChannel, "_requestSignature">["_requestSignature"]
|
||||
) =>
|
||||
| SetRequired<TChannel, "_responseSignature">["_responseSignature"]
|
||||
| Promise<
|
||||
SetRequired<TChannel, "_responseSignature">["_responseSignature"]
|
||||
>;
|
||||
export interface RequestChannelListener<Channel> {
|
||||
channel: Channel;
|
||||
handler: RequestChannelHandler<Channel>;
|
||||
}
|
||||
|
||||
export const requestChannelListenerInjectionToken = getInjectionToken<RequestChannelListener<RequestChannel<any, any>>>(
|
||||
{
|
||||
id: "request-channel-listener",
|
||||
},
|
||||
);
|
||||
export interface RequestChannel<Request, Response> {
|
||||
id: string;
|
||||
_requestSignature?: Request; // used only to mark `Request` as "used"
|
||||
_responseSignature?: Response; // used only to mark `Response` as "used"
|
||||
}
|
||||
|
||||
export const requestChannelListenerInjectionToken = getInjectionToken<RequestChannelListener<RequestChannel<unknown, unknown>>>( {
|
||||
id: "request-channel-listener",
|
||||
});
|
||||
|
||||
export interface GetRequestChannelListenerInjectableInfo<
|
||||
Channel extends RequestChannel<Request, Response>,
|
||||
Request,
|
||||
Response,
|
||||
> {
|
||||
channel: Channel;
|
||||
handlerInjectable: Injectable<RequestChannelHandler<Channel>, unknown, void>;
|
||||
}
|
||||
|
||||
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: di.inject(info.handlerInjectable),
|
||||
}),
|
||||
injectionToken: requestChannelListenerInjectionToken,
|
||||
});
|
||||
}
|
||||
|
||||
@ -3,19 +3,13 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { SetRequired } from "type-fest";
|
||||
import type { RequestChannel } from "./request-channel-injection-token";
|
||||
import type { RequestChannel } from "./request-channel-listener-injection-token";
|
||||
|
||||
export type RequestFromChannel = <
|
||||
TChannel extends RequestChannel<any, any>,
|
||||
>(
|
||||
channel: TChannel,
|
||||
...request: TChannel["_requestSignature"] extends void
|
||||
? []
|
||||
: [SetRequired<TChannel, "_requestSignature">["_requestSignature"]]
|
||||
) => Promise<SetRequired<TChannel, "_responseSignature">["_responseSignature"]>;
|
||||
export interface RequestFromChannel {
|
||||
<Request, Response>(channel: RequestChannel<Request, Response>, request: Request): Promise<Response>;
|
||||
<Response>(channel: RequestChannel<void, Response>): Promise<Response>;
|
||||
}
|
||||
|
||||
export const requestFromChannelInjectionToken =
|
||||
getInjectionToken<RequestFromChannel>({
|
||||
id: "request-from-request-channel",
|
||||
});
|
||||
export const requestFromChannelInjectionToken = getInjectionToken<RequestFromChannel>({
|
||||
id: "request-from-request-channel",
|
||||
});
|
||||
|
||||
@ -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;
|
||||
@ -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",
|
||||
};
|
||||
14
src/common/utils/sync-box/channel-listener.injectable.ts
Normal file
14
src/common/utils/sync-box/channel-listener.injectable.ts
Normal file
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* 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 syncBoxChannelHandlerInjectable from "./handler.injectable";
|
||||
|
||||
const syncBoxChannelListenerInjectable = getMessageChannelListenerInjectable({
|
||||
channel: syncBoxChannel,
|
||||
handlerInjectable: syncBoxChannelHandlerInjectable,
|
||||
});
|
||||
|
||||
export default syncBoxChannelListenerInjectable;
|
||||
21
src/common/utils/sync-box/channels.ts
Normal file
21
src/common/utils/sync-box/channels.ts
Normal 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",
|
||||
};
|
||||
@ -5,17 +5,17 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { IObservableValue } from "mobx";
|
||||
import { computed } from "mobx";
|
||||
import syncBoxChannelInjectable from "./sync-box-channel.injectable";
|
||||
import { messageToChannelInjectionToken } from "../channel/message-to-channel-injection-token";
|
||||
import { syncBoxChannel } from "./channels";
|
||||
import { sendMessageToChannelInjectionToken } from "../channel/message-to-channel-injection-token";
|
||||
import syncBoxStateInjectable from "./sync-box-state.injectable";
|
||||
import type { SyncBox } from "./sync-box-injection-token";
|
||||
import { toJS } from "../toJS";
|
||||
|
||||
const createSyncBoxInjectable = getInjectable({
|
||||
id: "create-sync-box",
|
||||
|
||||
instantiate: (di) => {
|
||||
const syncBoxChannel = di.inject(syncBoxChannelInjectable);
|
||||
const messageToChannel = di.inject(messageToChannelInjectionToken);
|
||||
const messageToChannel = di.inject(sendMessageToChannelInjectionToken);
|
||||
const getSyncBoxState = (id: string) => di.inject(syncBoxStateInjectable, id);
|
||||
|
||||
return <Value>(id: string, initialValue: Value): SyncBox<Value> => {
|
||||
@ -26,7 +26,7 @@ const createSyncBoxInjectable = getInjectable({
|
||||
return {
|
||||
id,
|
||||
|
||||
value: computed(() => state.get()),
|
||||
value: computed(() => toJS(state.get())),
|
||||
|
||||
set: (value) => {
|
||||
state.set(value);
|
||||
|
||||
19
src/common/utils/sync-box/handler.injectable.ts
Normal file
19
src/common/utils/sync-box/handler.injectable.ts
Normal 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;
|
||||
@ -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;
|
||||
@ -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;
|
||||
@ -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;
|
||||
@ -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),
|
||||
);
|
||||
|
||||
|
||||
@ -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),
|
||||
);
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import { SemVer } from "semver";
|
||||
import type { InitializableState } from "../initializable-state/create";
|
||||
import { createInitializableState } from "../initializable-state/create";
|
||||
import type { RequestChannel } from "../utils/channel/request-channel-injection-token";
|
||||
import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token";
|
||||
|
||||
export const buildVersionInjectionToken = getInjectionToken<InitializableState<string>>({
|
||||
id: "build-version-token",
|
||||
|
||||
@ -222,7 +222,7 @@ describe("selection of update stability", () => {
|
||||
it('given user changes update channel to "alpha", when user would close the application, installs the update for being stable enough', () => {
|
||||
selectedUpdateChannel.setValue(updateChannels.alpha.id);
|
||||
|
||||
expect(setUpdateOnQuitMock).toHaveBeenLastCalledWith(false);
|
||||
expect(setUpdateOnQuitMock).toHaveBeenLastCalledWith(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -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;
|
||||
@ -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",
|
||||
};
|
||||
@ -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;
|
||||
12
src/features/cluster/delete-dialog/common/delete-channel.ts
Normal file
12
src/features/cluster/delete-dialog/common/delete-channel.ts
Normal 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",
|
||||
};
|
||||
@ -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;
|
||||
@ -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",
|
||||
};
|
||||
@ -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;
|
||||
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getRequestChannelListenerInjectable } from "../../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import { clearClusterAsDeletingChannel } from "../common/clear-as-deleting-channel";
|
||||
import clearClusterAsDeletingHandlerInjectable from "./clear-as-deleting-handler.injectable";
|
||||
|
||||
const clearClusterAsDeletingChannelListenerInjectable = getRequestChannelListenerInjectable({
|
||||
channel: clearClusterAsDeletingChannel,
|
||||
handlerInjectable: clearClusterAsDeletingHandlerInjectable,
|
||||
});
|
||||
|
||||
export default clearClusterAsDeletingChannelListenerInjectable;
|
||||
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* 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 { RequestChannelHandler } from "../../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import clustersThatAreBeingDeletedInjectable from "../../../../main/cluster/are-being-deleted.injectable";
|
||||
import type { ClearClusterAsDeletingChannel } from "../common/clear-as-deleting-channel";
|
||||
|
||||
const clearClusterAsDeletingHandlerInjectable = getInjectable({
|
||||
id: "clear-cluster-as-deleting-handler",
|
||||
instantiate: (di): RequestChannelHandler<ClearClusterAsDeletingChannel> => {
|
||||
const clustersThatAreBeingDeleted = di.inject(clustersThatAreBeingDeletedInjectable);
|
||||
|
||||
return (clusterId) => {
|
||||
clustersThatAreBeingDeleted.delete(clusterId);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default clearClusterAsDeletingHandlerInjectable;
|
||||
@ -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;
|
||||
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getRequestChannelListenerInjectable } from "../../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import { deleteClusterChannel } from "../common/delete-channel";
|
||||
import deleteClusterHandlerInjectable from "./delete-cluster-handler.injectable";
|
||||
|
||||
const deleteClusterChannelListenerInjectable = getRequestChannelListenerInjectable({
|
||||
channel: deleteClusterChannel,
|
||||
handlerInjectable: deleteClusterHandlerInjectable,
|
||||
});
|
||||
|
||||
export default deleteClusterChannelListenerInjectable;
|
||||
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* 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 { RequestChannelHandler } from "../../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import type { DeleteClusterChannel } from "../common/delete-channel";
|
||||
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";
|
||||
|
||||
const deleteClusterHandlerInjectable = getInjectable({
|
||||
id: "delete-cluster-handler",
|
||||
instantiate: (di): RequestChannelHandler<DeleteClusterChannel> => {
|
||||
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 deleteClusterHandlerInjectable;
|
||||
@ -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;
|
||||
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getRequestChannelListenerInjectable } from "../../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import { setClusterAsDeletingChannel } from "../common/set-as-deleting-channel";
|
||||
import setClusterAsDeletingHandlerInjectable from "./set-as-deleting-handler.injectable";
|
||||
|
||||
const setClusterAsDeletingChannelHandlerInjectable = getRequestChannelListenerInjectable({
|
||||
channel: setClusterAsDeletingChannel,
|
||||
handlerInjectable: setClusterAsDeletingHandlerInjectable,
|
||||
});
|
||||
|
||||
export default setClusterAsDeletingChannelHandlerInjectable;
|
||||
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* 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 { RequestChannelHandler } from "../../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import clustersThatAreBeingDeletedInjectable from "../../../../main/cluster/are-being-deleted.injectable";
|
||||
import type { SetClusterAsDeletingChannel } from "../common/set-as-deleting-channel";
|
||||
|
||||
const setClusterAsDeletingHandlerInjectable = getInjectable({
|
||||
id: "set-cluster-as-deleting-handler",
|
||||
instantiate: (di): RequestChannelHandler<SetClusterAsDeletingChannel> => {
|
||||
const clustersThatAreBeingDeleted = di.inject(clustersThatAreBeingDeletedInjectable);
|
||||
|
||||
return (clusterId) => {
|
||||
clustersThatAreBeingDeleted.add(clusterId);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default setClusterAsDeletingHandlerInjectable;
|
||||
@ -5,7 +5,7 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { ClusterId } from "../../../../common/cluster-types";
|
||||
import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable";
|
||||
import clearClusterAsDeletingChannelInjectable from "../common/clear-as-deleting-channel.injectable";
|
||||
import { clearClusterAsDeletingChannel } from "../common/clear-as-deleting-channel";
|
||||
|
||||
export type RequestClearClusterAsDeleting = (clusterId: ClusterId) => Promise<void>;
|
||||
|
||||
@ -13,7 +13,6 @@ const requestClearClusterAsDeletingInjectable = getInjectable({
|
||||
id: "request-clear-cluster-as-deleting",
|
||||
instantiate: (di): RequestClearClusterAsDeleting => {
|
||||
const requestChannel = di.inject(requestFromChannelInjectable);
|
||||
const clearClusterAsDeletingChannel = di.inject(clearClusterAsDeletingChannelInjectable);
|
||||
|
||||
return (clusterId) => requestChannel(clearClusterAsDeletingChannel, clusterId);
|
||||
},
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { ClusterId } from "../../../../common/cluster-types";
|
||||
import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable";
|
||||
import deleteClusterChannelInjectable from "../common/delete-channel.injectable";
|
||||
import { deleteClusterChannel } from "../common/delete-channel";
|
||||
|
||||
export type RequestDeleteCluster = (clusterId: ClusterId) => Promise<void>;
|
||||
|
||||
@ -13,7 +13,6 @@ const requestDeleteClusterInjectable = getInjectable({
|
||||
id: "request-delete-cluster",
|
||||
instantiate: (di): RequestDeleteCluster => {
|
||||
const requestChannel = di.inject(requestFromChannelInjectable);
|
||||
const deleteClusterChannel = di.inject(deleteClusterChannelInjectable);
|
||||
|
||||
return (clusterId) => requestChannel(deleteClusterChannel, clusterId);
|
||||
},
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { ClusterId } from "../../../../common/cluster-types";
|
||||
import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable";
|
||||
import setClusterAsDeletingChannelInjectable from "../common/set-as-deleting-channel.injectable";
|
||||
import { setClusterAsDeletingChannel } from "../common/set-as-deleting-channel";
|
||||
|
||||
export type RequestSetClusterAsDeleting = (clusterId: ClusterId) => Promise<void>;
|
||||
|
||||
@ -13,7 +13,6 @@ const requestSetClusterAsDeletingInjectable = getInjectable({
|
||||
id: "request-set-cluster-as-deleting",
|
||||
instantiate: (di): RequestSetClusterAsDeleting => {
|
||||
const requestChannel = di.inject(requestFromChannelInjectable);
|
||||
const setClusterAsDeletingChannel = di.inject(setClusterAsDeletingChannelInjectable);
|
||||
|
||||
return (clusterId) => requestChannel(setClusterAsDeletingChannel, clusterId);
|
||||
},
|
||||
|
||||
@ -8,6 +8,7 @@ import type { ApplicationBuilder } from "../../renderer/components/test-utils/ge
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import type { ExecFile } from "../../common/fs/exec-file.injectable";
|
||||
import execFileInjectable from "../../common/fs/exec-file.injectable";
|
||||
import helmBinaryPathInjectable from "../../main/helm/helm-binary-path.injectable";
|
||||
import getActiveHelmRepositoriesInjectable from "../../main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable";
|
||||
@ -24,9 +25,7 @@ describe("add custom helm repository in preferences", () => {
|
||||
let showSuccessNotificationMock: jest.Mock;
|
||||
let showErrorNotificationMock: jest.Mock;
|
||||
let rendered: RenderResult;
|
||||
let execFileMock: AsyncFnMock<
|
||||
ReturnType<typeof execFileInjectable["instantiate"]>
|
||||
>;
|
||||
let execFileMock: AsyncFnMock<ExecFile>;
|
||||
let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise<AsyncResult<HelmRepo[]>>>;
|
||||
|
||||
beforeEach(async () => {
|
||||
@ -184,9 +183,13 @@ describe("add custom helm repository in preferences", () => {
|
||||
|
||||
describe("when activation rejects", () => {
|
||||
beforeEach(async () => {
|
||||
await execFileMock.reject(
|
||||
"Some error",
|
||||
);
|
||||
await execFileMock.resolve({
|
||||
callWasSuccessful: false,
|
||||
error: {
|
||||
error: new Error("Some error"),
|
||||
stderr: "",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -219,8 +222,10 @@ describe("add custom helm repository in preferences", () => {
|
||||
"some-helm-binary-path",
|
||||
["repo", "add", "some-custom-repository", "http://some.url"],
|
||||
],
|
||||
|
||||
"",
|
||||
{
|
||||
callWasSuccessful: true,
|
||||
response: "",
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@ import type { ApplicationBuilder } from "../../renderer/components/test-utils/ge
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import type { ExecFile } from "../../common/fs/exec-file.injectable";
|
||||
import execFileInjectable from "../../common/fs/exec-file.injectable";
|
||||
import helmBinaryPathInjectable from "../../main/helm/helm-binary-path.injectable";
|
||||
import getActiveHelmRepositoriesInjectable from "../../main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable";
|
||||
@ -21,9 +22,7 @@ describe("add helm repository from list in preferences", () => {
|
||||
let showSuccessNotificationMock: jest.Mock;
|
||||
let showErrorNotificationMock: jest.Mock;
|
||||
let rendered: RenderResult;
|
||||
let execFileMock: AsyncFnMock<
|
||||
ReturnType<typeof execFileInjectable["instantiate"]>
|
||||
>;
|
||||
let execFileMock: AsyncFnMock<ExecFile>;
|
||||
let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise<AsyncResult<HelmRepo[]>>>;
|
||||
let callForPublicHelmRepositoriesMock: AsyncFnMock<() => Promise<HelmRepo[]>>;
|
||||
|
||||
@ -129,9 +128,13 @@ describe("add helm repository from list in preferences", () => {
|
||||
|
||||
describe("when adding rejects", () => {
|
||||
beforeEach(async () => {
|
||||
await execFileMock.reject(
|
||||
"Some error",
|
||||
);
|
||||
await execFileMock.resolve({
|
||||
callWasSuccessful: false,
|
||||
error: {
|
||||
error: new Error("Some error"),
|
||||
stderr: "",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -164,8 +167,10 @@ describe("add helm repository from list in preferences", () => {
|
||||
"some-helm-binary-path",
|
||||
["repo", "add", "Some to be added repository", "some-other-url"],
|
||||
],
|
||||
|
||||
"",
|
||||
{
|
||||
callWasSuccessful: true,
|
||||
response: "",
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@ -243,8 +248,10 @@ describe("add helm repository from list in preferences", () => {
|
||||
"some-helm-binary-path",
|
||||
["repo", "remove", "Some already active repository"],
|
||||
],
|
||||
|
||||
"",
|
||||
{
|
||||
callWasSuccessful: true,
|
||||
response: "",
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@ -83,7 +83,13 @@ describe("listing active helm repositories in preferences", () => {
|
||||
|
||||
describe("when getting configuration rejects", () => {
|
||||
beforeEach(async () => {
|
||||
await execFileMock.reject("some-error");
|
||||
await execFileMock.resolve({
|
||||
callWasSuccessful: false,
|
||||
error: {
|
||||
error: new Error("some error"),
|
||||
stderr: "some-error",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("shows error notification", () => {
|
||||
@ -115,7 +121,10 @@ describe("listing active helm repositories in preferences", () => {
|
||||
|
||||
await execFileMock.resolveSpecific(
|
||||
["some-helm-binary-path", ["env"]],
|
||||
"HELM_REPOSITORY_CACHE=some-helm-repository-cache-path",
|
||||
{
|
||||
callWasSuccessful: true,
|
||||
response: "HELM_REPOSITORY_CACHE=some-helm-repository-cache-path",
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@ -154,7 +163,10 @@ describe("listing active helm repositories in preferences", () => {
|
||||
|
||||
await execFileMock.resolveSpecific(
|
||||
["some-helm-binary-path", ["env"]],
|
||||
"HELM_REPOSITORY_CONFIG=some-helm-repository-config-file.yaml",
|
||||
{
|
||||
callWasSuccessful: true,
|
||||
response: "HELM_REPOSITORY_CONFIG=some-helm-repository-config-file.yaml",
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@ -193,11 +205,13 @@ describe("listing active helm repositories in preferences", () => {
|
||||
|
||||
await execFileMock.resolveSpecific(
|
||||
["some-helm-binary-path", ["env"]],
|
||||
|
||||
[
|
||||
"HELM_REPOSITORY_CONFIG=some-helm-repository-config-file.yaml",
|
||||
"HELM_REPOSITORY_CACHE=some-helm-repository-cache-path",
|
||||
].join("\n"),
|
||||
{
|
||||
callWasSuccessful: true,
|
||||
response: [
|
||||
"HELM_REPOSITORY_CONFIG=some-helm-repository-config-file.yaml",
|
||||
"HELM_REPOSITORY_CACHE=some-helm-repository-cache-path",
|
||||
].join("\n"),
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@ -219,7 +233,13 @@ describe("listing active helm repositories in preferences", () => {
|
||||
|
||||
describe("when updating repositories reject with any other error", () => {
|
||||
beforeEach(async () => {
|
||||
await execFileMock.reject("Some error");
|
||||
await execFileMock.resolve({
|
||||
callWasSuccessful: false,
|
||||
error: {
|
||||
error: new Error("Some error"),
|
||||
stderr: "Some error",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("shows error notification", () => {
|
||||
@ -249,9 +269,13 @@ describe("listing active helm repositories in preferences", () => {
|
||||
beforeEach(async () => {
|
||||
execFileMock.mockClear();
|
||||
|
||||
await execFileMock.reject(
|
||||
"Error: no repositories found. You must add one before updating",
|
||||
);
|
||||
await execFileMock.resolve({
|
||||
callWasSuccessful: false,
|
||||
error: {
|
||||
error: new Error("no repositories found. You must add one before updating"),
|
||||
stderr: "no repositories found. You must add one before updating",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -274,7 +298,13 @@ describe("listing active helm repositories in preferences", () => {
|
||||
|
||||
describe("when adding default repository reject", () => {
|
||||
beforeEach(async () => {
|
||||
await execFileMock.reject("Some error");
|
||||
await execFileMock.resolve({
|
||||
callWasSuccessful: false,
|
||||
error: {
|
||||
error: new Error("Some error"),
|
||||
stderr: "Some error",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("shows error notification", () => {
|
||||
@ -307,7 +337,6 @@ describe("listing active helm repositories in preferences", () => {
|
||||
await execFileMock.resolveSpecific(
|
||||
[
|
||||
"some-helm-binary-path",
|
||||
|
||||
[
|
||||
"repo",
|
||||
"add",
|
||||
@ -315,8 +344,10 @@ describe("listing active helm repositories in preferences", () => {
|
||||
"https://charts.bitnami.com/bitnami",
|
||||
],
|
||||
],
|
||||
|
||||
"",
|
||||
{
|
||||
callWasSuccessful: true,
|
||||
response: "",
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@ -380,7 +411,10 @@ describe("listing active helm repositories in preferences", () => {
|
||||
|
||||
await execFileMock.resolveSpecific(
|
||||
["some-helm-binary-path", ["repo", "update"]],
|
||||
"",
|
||||
{
|
||||
callWasSuccessful: true,
|
||||
response: "",
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@ import type { ApplicationBuilder } from "../../renderer/components/test-utils/ge
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import type { ExecFile } from "../../common/fs/exec-file.injectable";
|
||||
import execFileInjectable from "../../common/fs/exec-file.injectable";
|
||||
import helmBinaryPathInjectable from "../../main/helm/helm-binary-path.injectable";
|
||||
import getActiveHelmRepositoriesInjectable from "../../main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable";
|
||||
@ -19,9 +20,7 @@ describe("remove helm repository from list of active repositories in preferences
|
||||
let builder: ApplicationBuilder;
|
||||
let rendered: RenderResult;
|
||||
let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise<AsyncResult<HelmRepo[]>>>;
|
||||
let execFileMock: AsyncFnMock<
|
||||
ReturnType<typeof execFileInjectable["instantiate"]>
|
||||
>;
|
||||
let execFileMock: AsyncFnMock<ExecFile>;
|
||||
|
||||
beforeEach(async () => {
|
||||
builder = getApplicationBuilder();
|
||||
@ -101,8 +100,10 @@ describe("remove helm repository from list of active repositories in preferences
|
||||
"some-helm-binary-path",
|
||||
["repo", "remove", "some-active-repository"],
|
||||
],
|
||||
|
||||
"",
|
||||
{
|
||||
callWasSuccessful: true,
|
||||
response: "",
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
12
src/features/navigation/reload-page/common/channel.ts
Normal file
12
src/features/navigation/reload-page/common/channel.ts
Normal 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",
|
||||
};
|
||||
@ -0,0 +1,9 @@
|
||||
/**
|
||||
* 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 reloadPageHandlerInjectable from "./handler.injectable";
|
||||
|
||||
export default getGlobalOverride(reloadPageHandlerInjectable, () => () => {});
|
||||
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* 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 "../../../../common/utils/channel/message-channel-listener-injection-token";
|
||||
import type { ReloadPageChannel } from "../common/channel";
|
||||
|
||||
const reloadPageHandlerInjectable = getInjectable({
|
||||
id: "reload-page-handler",
|
||||
instantiate: (): MessageChannelHandler<ReloadPageChannel> => {
|
||||
return () => location.reload();
|
||||
},
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
export default reloadPageHandlerInjectable;
|
||||
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* 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";
|
||||
import reloadPageHandlerInjectable from "./handler.injectable";
|
||||
|
||||
const reloadPageChannelListenerInjectable = getMessageChannelListenerInjectable({
|
||||
channel: reloadPageChannel,
|
||||
handlerInjectable: reloadPageHandlerInjectable,
|
||||
});
|
||||
|
||||
export default reloadPageChannelListenerInjectable;
|
||||
19
src/main/app-paths/app-paths-channel-handler.injectable.ts
Normal file
19
src/main/app-paths/app-paths-channel-handler.injectable.ts
Normal 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 { AppPathsChannel } from "../../common/app-paths/app-paths-channel";
|
||||
import appPathsInjectable from "../../common/app-paths/app-paths.injectable";
|
||||
import type { RequestChannelHandler } from "../../common/utils/channel/request-channel-listener-injection-token";
|
||||
|
||||
const appPathsChannelHandlerInjectable = getInjectable({
|
||||
id: "app-paths-channel-handler",
|
||||
instantiate: (di): RequestChannelHandler<AppPathsChannel> => {
|
||||
const appPaths = di.inject(appPathsInjectable);
|
||||
|
||||
return () => appPaths;
|
||||
},
|
||||
});
|
||||
|
||||
export default appPathsChannelHandlerInjectable;
|
||||
@ -2,26 +2,13 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import 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 { getRequestChannelListenerInjectable } from "../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import { appPathsChannel } from "../../common/app-paths/app-paths-channel";
|
||||
import appPathsChannelHandlerInjectable from "./app-paths-channel-handler.injectable";
|
||||
|
||||
const appPathsRequestChannelListenerInjectable = getInjectable({
|
||||
id: "app-paths-request-channel-listener",
|
||||
|
||||
instantiate: (di): RequestChannelListener<AppPathsChannel> => {
|
||||
const channel = di.inject(appPathsChannelInjectable);
|
||||
const appPaths = di.inject(appPathsInjectable);
|
||||
|
||||
return {
|
||||
channel,
|
||||
handler: () => appPaths,
|
||||
};
|
||||
},
|
||||
injectionToken: requestChannelListenerInjectionToken,
|
||||
const appPathsRequestChannelListenerInjectable = getRequestChannelListenerInjectable({
|
||||
channel: appPathsChannel,
|
||||
handlerInjectable: appPathsChannelHandlerInjectable,
|
||||
});
|
||||
|
||||
export default appPathsRequestChannelListenerInjectable;
|
||||
|
||||
@ -2,25 +2,13 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import restartAndInstallUpdateChannel from "../../../common/application-update/restart-and-install-update-channel/restart-and-install-update-channel.injectable";
|
||||
import { messageChannelListenerInjectionToken } from "../../../common/utils/channel/message-channel-listener-injection-token";
|
||||
import { restartAndInstallUpdateChannel } from "../../../common/application-update/restart-and-install-update-channel";
|
||||
import { getMessageChannelListenerInjectable } from "../../../common/utils/channel/message-channel-listener-injection-token";
|
||||
import quitAndInstallUpdateInjectable from "../quit-and-install-update.injectable";
|
||||
|
||||
const restartAndInstallUpdateListenerInjectable = getInjectable({
|
||||
id: "restart-and-install-update-listener",
|
||||
|
||||
instantiate: (di) => {
|
||||
const quitAndInstall = di.inject(quitAndInstallUpdateInjectable);
|
||||
const channel = di.inject(restartAndInstallUpdateChannel);
|
||||
|
||||
return {
|
||||
channel,
|
||||
handler: quitAndInstall,
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: messageChannelListenerInjectionToken,
|
||||
const restartAndInstallUpdateListenerInjectable = getMessageChannelListenerInjectable({
|
||||
channel: restartAndInstallUpdateChannel,
|
||||
handlerInjectable: quitAndInstallUpdateInjectable,
|
||||
});
|
||||
|
||||
export default restartAndInstallUpdateListenerInjectable;
|
||||
|
||||
@ -7,7 +7,7 @@ import { autorun } from "mobx";
|
||||
import { getStartableStoppable } from "../../../common/utils/get-startable-stoppable";
|
||||
import setUpdateOnQuitInjectable from "../../electron-app/features/set-update-on-quit.injectable";
|
||||
import selectedUpdateChannelInjectable from "../../../common/application-update/selected-update-channel/selected-update-channel.injectable";
|
||||
import type { UpdateChannel } from "../../../common/application-update/update-channels";
|
||||
import type { ReleaseChannel, UpdateChannel } from "../../../common/application-update/update-channels";
|
||||
import discoveredUpdateVersionInjectable from "../../../common/application-update/discovered-update-version/discovered-update-version.injectable";
|
||||
|
||||
const watchIfUpdateShouldHappenOnQuitInjectable = getInjectable({
|
||||
@ -20,33 +20,26 @@ const watchIfUpdateShouldHappenOnQuitInjectable = getInjectable({
|
||||
|
||||
return getStartableStoppable("watch-if-update-should-happen-on-quit", () =>
|
||||
autorun(() => {
|
||||
const sufficientlyStableUpdateChannels =
|
||||
getSufficientlyStableUpdateChannels(selectedUpdateChannel.value.get());
|
||||
const sufficientlyStableUpdateChannels = getSufficientlyStableUpdateChannels(selectedUpdateChannel.value.get());
|
||||
const updateIsDiscoveredFromChannel = discoveredVersionState.value.get()?.updateChannel;
|
||||
|
||||
const discoveredVersion = discoveredVersionState.value.get();
|
||||
|
||||
const updateIsDiscoveredFromChannel = discoveredVersion?.updateChannel;
|
||||
|
||||
const updateOnQuit = updateIsDiscoveredFromChannel
|
||||
? sufficientlyStableUpdateChannels.includes(
|
||||
updateIsDiscoveredFromChannel,
|
||||
)
|
||||
: false;
|
||||
|
||||
setUpdateOnQuit(updateOnQuit);
|
||||
setUpdateOnQuit((
|
||||
updateIsDiscoveredFromChannel
|
||||
? sufficientlyStableUpdateChannels.includes(updateIsDiscoveredFromChannel.id)
|
||||
: false
|
||||
));
|
||||
}),
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const getSufficientlyStableUpdateChannels = (updateChannel: UpdateChannel): UpdateChannel[] => {
|
||||
const getSufficientlyStableUpdateChannels = (updateChannel: UpdateChannel): ReleaseChannel[] => {
|
||||
if (!updateChannel.moreStableUpdateChannel) {
|
||||
return [updateChannel];
|
||||
return [updateChannel.id];
|
||||
}
|
||||
|
||||
return [
|
||||
updateChannel,
|
||||
|
||||
updateChannel.id,
|
||||
...getSufficientlyStableUpdateChannels(updateChannel.moreStableUpdateChannel),
|
||||
];
|
||||
};
|
||||
|
||||
@ -6,9 +6,8 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import execFileInjectable from "../../../common/fs/exec-file.injectable";
|
||||
import helmBinaryPathInjectable from "../helm-binary-path.injectable";
|
||||
import type { AsyncResult } from "../../../common/utils/async-result";
|
||||
import { getErrorMessage } from "../../../common/utils/get-error-message";
|
||||
|
||||
export type ExecHelm = (args: string[]) => Promise<AsyncResult<string>>;
|
||||
export type ExecHelm = (args: string[]) => Promise<AsyncResult<string, string>>;
|
||||
|
||||
const execHelmInjectable = getInjectable({
|
||||
id: "exec-helm",
|
||||
@ -18,15 +17,18 @@ const execHelmInjectable = getInjectable({
|
||||
const helmBinaryPath = di.inject(helmBinaryPathInjectable);
|
||||
|
||||
return async (args) => {
|
||||
try {
|
||||
const response = await execFile(helmBinaryPath, args, {
|
||||
maxBuffer: 32 * 1024 * 1024 * 1024, // 32 MiB
|
||||
});
|
||||
const response = await execFile(helmBinaryPath, args, {
|
||||
maxBuffer: 32 * 1024 * 1024 * 1024, // 32 MiB
|
||||
});
|
||||
|
||||
return { callWasSuccessful: true, response };
|
||||
} catch (error) {
|
||||
return { callWasSuccessful: false, error: getErrorMessage(error) };
|
||||
if (response.callWasSuccessful) {
|
||||
return response;
|
||||
}
|
||||
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: response.error.stderr || response.error.error.message,
|
||||
};
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@ -2,25 +2,13 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import addHelmRepositoryChannelInjectable from "../../../../common/helm/add-helm-repository-channel.injectable";
|
||||
import { addHelmRepositoryChannel } from "../../../../common/helm/add-helm-repository-channel";
|
||||
import addHelmRepositoryInjectable from "./add-helm-repository.injectable";
|
||||
import { requestChannelListenerInjectionToken } from "../../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import { getRequestChannelListenerInjectable } from "../../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
|
||||
const addHelmRepositoryChannelListenerInjectable = getInjectable({
|
||||
id: "add-helm-repository-channel-listener",
|
||||
|
||||
instantiate: (di) => {
|
||||
const addHelmRepository = di.inject(addHelmRepositoryInjectable);
|
||||
const channel = di.inject(addHelmRepositoryChannelInjectable);
|
||||
|
||||
return {
|
||||
channel,
|
||||
handler: addHelmRepository,
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: requestChannelListenerInjectionToken,
|
||||
const addHelmRepositoryChannelListenerInjectable = getRequestChannelListenerInjectable({
|
||||
channel: addHelmRepositoryChannel,
|
||||
handlerInjectable: addHelmRepositoryInjectable,
|
||||
});
|
||||
|
||||
export default addHelmRepositoryChannelListenerInjectable;
|
||||
|
||||
@ -2,25 +2,13 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { requestChannelListenerInjectionToken } from "../../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import getActiveHelmRepositoriesChannelInjectable from "../../../../common/helm/get-active-helm-repositories-channel.injectable";
|
||||
import { getRequestChannelListenerInjectable } from "../../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import { getActiveHelmRepositoriesChannel } from "../../../../common/helm/get-active-helm-repositories-channel";
|
||||
import getActiveHelmRepositoriesInjectable from "./get-active-helm-repositories.injectable";
|
||||
|
||||
const getActiveHelmRepositoriesChannelListenerInjectable = getInjectable({
|
||||
id: "get-active-helm-repositories-channel-listener",
|
||||
|
||||
instantiate: (di) => {
|
||||
const getActiveHelmRepositories = di.inject(getActiveHelmRepositoriesInjectable);
|
||||
|
||||
return {
|
||||
channel: di.inject(getActiveHelmRepositoriesChannelInjectable),
|
||||
|
||||
handler: getActiveHelmRepositories,
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: requestChannelListenerInjectionToken,
|
||||
const getActiveHelmRepositoriesChannelListenerInjectable = getRequestChannelListenerInjectable({
|
||||
channel: getActiveHelmRepositoriesChannel,
|
||||
handlerInjectable: getActiveHelmRepositoriesInjectable,
|
||||
});
|
||||
|
||||
export default getActiveHelmRepositoriesChannelListenerInjectable;
|
||||
|
||||
@ -2,25 +2,13 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { requestChannelListenerInjectionToken } from "../../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import { getRequestChannelListenerInjectable } from "../../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import removeHelmRepositoryInjectable from "./remove-helm-repository.injectable";
|
||||
import removeHelmRepositoryChannelInjectable from "../../../../common/helm/remove-helm-repository-channel.injectable";
|
||||
import { removeHelmRepositoryChannel } from "../../../../common/helm/remove-helm-repository-channel";
|
||||
|
||||
const removeHelmRepositoryChannelListenerInjectable = getInjectable({
|
||||
id: "remove-helm-repository-channel-listener",
|
||||
|
||||
instantiate: (di) => {
|
||||
const removeHelmRepository = di.inject(removeHelmRepositoryInjectable);
|
||||
const channel = di.inject(removeHelmRepositoryChannelInjectable);
|
||||
|
||||
return {
|
||||
channel,
|
||||
handler: removeHelmRepository,
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: requestChannelListenerInjectionToken,
|
||||
const removeHelmRepositoryChannelListenerInjectable = getRequestChannelListenerInjectable({
|
||||
channel: removeHelmRepositoryChannel,
|
||||
handlerInjectable: removeHelmRepositoryInjectable,
|
||||
});
|
||||
|
||||
export default removeHelmRepositoryChannelListenerInjectable;
|
||||
|
||||
@ -6,7 +6,6 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import loggerInjectable from "../../../../common/logger.injectable";
|
||||
import applicationWindowStateInjectable from "./application-window-state.injectable";
|
||||
import { BrowserWindow } from "electron";
|
||||
import sendToChannelInElectronBrowserWindowInjectable from "./send-to-channel-in-electron-browser-window.injectable";
|
||||
import type { ElectronWindow } from "./create-lens-window.injectable";
|
||||
import type { RequireExactlyOne } from "type-fest";
|
||||
import openLinkInBrowserInjectable from "../../../../common/utils/open-link-in-browser.injectable";
|
||||
@ -45,7 +44,6 @@ const createElectronWindowInjectable = getInjectable({
|
||||
|
||||
instantiate: (di): CreateElectronWindow => {
|
||||
const logger = di.inject(loggerInjectable);
|
||||
const sendToChannelInLensWindow = di.inject(sendToChannelInElectronBrowserWindowInjectable);
|
||||
const openLinkInBrowser = di.inject(openLinkInBrowserInjectable);
|
||||
|
||||
return (configuration) => {
|
||||
@ -140,7 +138,17 @@ const createElectronWindowInjectable = getInjectable({
|
||||
|
||||
show: () => browserWindow.show(),
|
||||
close: () => browserWindow.close(),
|
||||
send: (args) => sendToChannelInLensWindow(configuration.id, browserWindow, args),
|
||||
send: ({ channel, data, frameInfo }) => {
|
||||
if (frameInfo) {
|
||||
browserWindow.webContents.sendToFrame(
|
||||
[frameInfo.processId, frameInfo.frameId],
|
||||
channel,
|
||||
data,
|
||||
);
|
||||
} else {
|
||||
browserWindow.webContents.send(channel, data);
|
||||
}
|
||||
},
|
||||
|
||||
reload: () => {
|
||||
const wc = browserWindow.webContents;
|
||||
|
||||
@ -20,7 +20,7 @@ export interface ElectronWindow {
|
||||
export interface SendToViewArgs {
|
||||
channel: string;
|
||||
frameInfo?: ClusterFrameInfo;
|
||||
data?: unknown[];
|
||||
data?: unknown;
|
||||
}
|
||||
|
||||
export interface LensWindow {
|
||||
|
||||
@ -1,33 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { BrowserWindow } from "electron";
|
||||
import type { SendToViewArgs } from "./create-lens-window.injectable";
|
||||
|
||||
const sendToChannelInElectronBrowserWindowInjectable = getInjectable({
|
||||
id: "send-to-channel-in-electron-browser-window",
|
||||
|
||||
instantiate:
|
||||
() =>
|
||||
(
|
||||
windowId: string,
|
||||
browserWindow: BrowserWindow,
|
||||
{ channel, frameInfo, data = [] }: SendToViewArgs,
|
||||
) => {
|
||||
if (frameInfo) {
|
||||
browserWindow.webContents.sendToFrame(
|
||||
[frameInfo.processId, frameInfo.frameId],
|
||||
channel,
|
||||
...data,
|
||||
);
|
||||
} else {
|
||||
browserWindow.webContents.send(channel, ...data);
|
||||
}
|
||||
},
|
||||
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
export default sendToChannelInElectronBrowserWindowInjectable;
|
||||
@ -37,7 +37,7 @@ const navigateInjectable = getInjectable({
|
||||
applicationWindow.send({
|
||||
channel,
|
||||
frameInfo,
|
||||
data: [url],
|
||||
data: url,
|
||||
});
|
||||
};
|
||||
},
|
||||
|
||||
@ -3,9 +3,9 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { IpcRendererNavigationEvents } from "../../../renderer/navigation/events";
|
||||
import currentClusterFrameInjectable from "./current-cluster-frame/current-cluster-frame.injectable";
|
||||
import getCurrentApplicationWindowInjectable from "./application-window/get-current-application-window.injectable";
|
||||
import { reloadPageChannel } from "../../../features/navigation/reload-page/common/channel";
|
||||
|
||||
const reloadCurrentApplicationWindowInjectable = getInjectable({
|
||||
id: "reload-current-application-window",
|
||||
@ -25,7 +25,7 @@ const reloadCurrentApplicationWindowInjectable = getInjectable({
|
||||
|
||||
if (frameInfo) {
|
||||
lensWindow.send({
|
||||
channel: IpcRendererNavigationEvents.RELOAD_PAGE,
|
||||
channel: reloadPageChannel.id,
|
||||
frameInfo,
|
||||
});
|
||||
} else {
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* 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 rootFrameHasRenderedHandlerInjectable from "./handler.injectable";
|
||||
|
||||
const rootFrameRenderedChannelListenerInjectable = getMessageChannelListenerInjectable({
|
||||
channel: rootFrameHasRenderedChannel,
|
||||
handlerInjectable: rootFrameHasRenderedHandlerInjectable,
|
||||
});
|
||||
|
||||
export default rootFrameRenderedChannelListenerInjectable;
|
||||
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { RootFrameHasRenderedChannel } from "../../../../common/root-frame/root-frame-rendered-channel";
|
||||
import { runManyFor } from "../../../../common/runnable/run-many-for";
|
||||
import type { MessageChannelHandler } from "../../../../common/utils/channel/message-channel-listener-injection-token";
|
||||
import { afterRootFrameIsReadyInjectionToken } from "../../runnable-tokens/after-root-frame-is-ready-injection-token";
|
||||
|
||||
const rootFrameHasRenderedHandlerInjectable = getInjectable({
|
||||
id: "root-frame-has-rendered-handler",
|
||||
instantiate: (di): MessageChannelHandler<RootFrameHasRenderedChannel> => {
|
||||
const runMany = runManyFor(di);
|
||||
|
||||
return runMany(afterRootFrameIsReadyInjectionToken);
|
||||
},
|
||||
});
|
||||
|
||||
export default rootFrameHasRenderedHandlerInjectable;
|
||||
@ -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;
|
||||
@ -6,8 +6,6 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { IpcMainEvent } from "electron";
|
||||
import ipcMainInjectable from "../ipc-main/ipc-main.injectable";
|
||||
import { enlistMessageChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-message-channel-listener-injection-token";
|
||||
import { pipeline } from "@ogre-tools/fp";
|
||||
import { tentativeParseJson } from "../../../../common/utils/tentative-parse-json";
|
||||
|
||||
const enlistMessageChannelListenerInjectable = getInjectable({
|
||||
id: "enlist-message-channel-listener-for-main",
|
||||
@ -17,11 +15,7 @@ const enlistMessageChannelListenerInjectable = getInjectable({
|
||||
|
||||
return ({ channel, handler }) => {
|
||||
const nativeOnCallback = (_: IpcMainEvent, message: unknown) => {
|
||||
pipeline(
|
||||
message,
|
||||
tentativeParseJson,
|
||||
handler,
|
||||
);
|
||||
handler(message);
|
||||
};
|
||||
|
||||
ipcMain.on(channel.id, nativeOnCallback);
|
||||
|
||||
@ -88,8 +88,8 @@ describe("enlist message channel listener in main", () => {
|
||||
expect(handlerMock).toHaveBeenCalledWith(true);
|
||||
});
|
||||
|
||||
it("given stringified object as message, when message arrives, calls the handler with the message", () => {
|
||||
onMock.mock.calls[0][1]({} as IpcMainEvent, JSON.stringify({ some: "object" }));
|
||||
it("given object as message, when message arrives, calls the handler with the message", () => {
|
||||
onMock.mock.calls[0][1]({} as IpcMainEvent, { some: "object" });
|
||||
|
||||
expect(handlerMock).toHaveBeenCalledWith({ some: "object" });
|
||||
});
|
||||
|
||||
@ -6,9 +6,6 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { IpcMainInvokeEvent } from "electron";
|
||||
import ipcMainInjectable from "../ipc-main/ipc-main.injectable";
|
||||
import { enlistRequestChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-request-channel-listener-injection-token";
|
||||
import { pipeline } from "@ogre-tools/fp";
|
||||
import { tentativeParseJson } from "../../../../common/utils/tentative-parse-json";
|
||||
import { tentativeStringifyJson } from "../../../../common/utils/tentative-stringify-json";
|
||||
|
||||
const enlistRequestChannelListenerInjectable = getInjectable({
|
||||
id: "enlist-request-channel-listener-for-main",
|
||||
@ -17,8 +14,7 @@ const enlistRequestChannelListenerInjectable = getInjectable({
|
||||
const ipcMain = di.inject(ipcMainInjectable);
|
||||
|
||||
return ({ channel, handler }) => {
|
||||
const nativeHandleCallback = (_: IpcMainInvokeEvent, request: unknown) =>
|
||||
pipeline(request, tentativeParseJson, handler, tentativeStringifyJson);
|
||||
const nativeHandleCallback = (_: IpcMainInvokeEvent, request: unknown) => handler(request);
|
||||
|
||||
ipcMain.handle(channel.id, nativeHandleCallback);
|
||||
|
||||
|
||||
@ -10,6 +10,13 @@ import { enlistRequestChannelListenerInjectionToken } from "../../../../common/u
|
||||
import { getPromiseStatus } from "../../../../common/test-utils/get-promise-status";
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import type { RequestChannel, RequestChannelHandler } from "../../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
|
||||
type TestRequestChannel = RequestChannel<unknown, unknown>;
|
||||
|
||||
const testRequestChannel: TestRequestChannel = {
|
||||
id: "some-channel-id",
|
||||
};
|
||||
|
||||
describe("enlist request channel listener in main", () => {
|
||||
let enlistRequestChannelListener: EnlistRequestChannelListener;
|
||||
@ -36,14 +43,14 @@ describe("enlist request channel listener in main", () => {
|
||||
});
|
||||
|
||||
describe("when called", () => {
|
||||
let handlerMock: AsyncFnMock<(message: any) => any>;
|
||||
let handlerMock: AsyncFnMock<RequestChannelHandler<TestRequestChannel>>;
|
||||
let disposer: () => void;
|
||||
|
||||
beforeEach(() => {
|
||||
handlerMock = asyncFn();
|
||||
|
||||
disposer = enlistRequestChannelListener({
|
||||
channel: { id: "some-channel-id" },
|
||||
channel: testRequestChannel,
|
||||
handler: handlerMock,
|
||||
});
|
||||
});
|
||||
@ -91,7 +98,7 @@ describe("enlist request channel listener in main", () => {
|
||||
it("resolves with the response", async () => {
|
||||
const actual = await actualPromise;
|
||||
|
||||
expect(actual).toBe('"some-response"');
|
||||
expect(actual).toBe("some-response");
|
||||
});
|
||||
|
||||
it("when disposing the listener, de-registers the listener", () => {
|
||||
@ -106,7 +113,7 @@ describe("enlist request channel listener in main", () => {
|
||||
|
||||
const actual = await actualPromise;
|
||||
|
||||
expect(actual).toBe("42");
|
||||
expect(actual).toBe(42);
|
||||
});
|
||||
|
||||
it("given boolean as response, when handler resolves with response, listener resolves with stringified response", async () => {
|
||||
@ -114,15 +121,15 @@ describe("enlist request channel listener in main", () => {
|
||||
|
||||
const actual = await actualPromise;
|
||||
|
||||
expect(actual).toBe("true");
|
||||
expect(actual).toBe(true);
|
||||
});
|
||||
|
||||
it("given object as response, when handler resolves with response, listener resolves with stringified response", async () => {
|
||||
it("given object as response, when handler resolves with response, listener resolves with response", async () => {
|
||||
await handlerMock.resolve({ some: "object" });
|
||||
|
||||
const actual = await actualPromise;
|
||||
|
||||
expect(actual).toBe(JSON.stringify({ some: "object" }));
|
||||
expect(actual).toEqual({ some: "object" });
|
||||
});
|
||||
});
|
||||
|
||||
@ -138,8 +145,8 @@ describe("enlist request channel listener in main", () => {
|
||||
expect(handlerMock).toHaveBeenCalledWith(true);
|
||||
});
|
||||
|
||||
it("given stringified object as request, when request arrives, calls the handler with the request", () => {
|
||||
handleMock.mock.calls[0][1]({} as IpcMainInvokeEvent, JSON.stringify({ some: "object" }));
|
||||
it("given object as request, when request arrives, calls the handler with the request", () => {
|
||||
handleMock.mock.calls[0][1]({} as IpcMainInvokeEvent, { some: "object" });
|
||||
|
||||
expect(handlerMock).toHaveBeenCalledWith({ some: "object" });
|
||||
});
|
||||
|
||||
@ -3,9 +3,8 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { messageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token";
|
||||
import type { MessageChannel } from "../../../common/utils/channel/message-channel-injection-token";
|
||||
import { tentativeStringifyJson } from "../../../common/utils/tentative-stringify-json";
|
||||
import type { SendMessageToChannel } from "../../../common/utils/channel/message-to-channel-injection-token";
|
||||
import { sendMessageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token";
|
||||
import getVisibleWindowsInjectable from "../../start-main-application/lens-window/get-visible-windows.injectable";
|
||||
|
||||
const messageToChannelInjectable = getInjectable({
|
||||
@ -14,18 +13,14 @@ const messageToChannelInjectable = getInjectable({
|
||||
instantiate: (di) => {
|
||||
const getVisibleWindows = di.inject(getVisibleWindowsInjectable);
|
||||
|
||||
// TODO: Figure out way to improve typing in internals
|
||||
// Notice that this should be injected using "messageToChannelInjectionToken" which is typed correctly.
|
||||
return (channel: MessageChannel<any>, message?: unknown) => {
|
||||
const stringifiedMessage = tentativeStringifyJson(message);
|
||||
|
||||
getVisibleWindows().forEach((lensWindow) =>
|
||||
lensWindow.send({ channel: channel.id, data: stringifiedMessage ? [stringifiedMessage] : [] }),
|
||||
);
|
||||
};
|
||||
return ((channel, data) => {
|
||||
for (const window of getVisibleWindows()) {
|
||||
window.send({ channel: channel.id, data });
|
||||
}
|
||||
}) as SendMessageToChannel;
|
||||
},
|
||||
|
||||
injectionToken: messageToChannelInjectionToken,
|
||||
injectionToken: sendMessageToChannelInjectionToken,
|
||||
});
|
||||
|
||||
export default messageToChannelInjectable;
|
||||
|
||||
@ -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" };
|
||||
@ -2,20 +2,13 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import resolveSystemProxyChannelInjectable from "../../../common/utils/resolve-system-proxy/resolve-system-proxy-channel.injectable";
|
||||
import { resolveSystemProxyChannel } from "../../../common/utils/resolve-system-proxy/resolve-system-proxy-channel";
|
||||
import resolveSystemProxyInjectable from "./resolve-system-proxy.injectable";
|
||||
import { requestChannelListenerInjectionToken } from "../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import { getRequestChannelListenerInjectable } from "../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
|
||||
const resolveSystemProxyChannelResponderInjectable = getInjectable({
|
||||
id: "resolve-system-proxy-channel-responder",
|
||||
|
||||
instantiate: (di) => ({
|
||||
channel: di.inject(resolveSystemProxyChannelInjectable),
|
||||
handler: di.inject(resolveSystemProxyInjectable),
|
||||
}),
|
||||
|
||||
injectionToken: requestChannelListenerInjectionToken,
|
||||
const resolveSystemProxyChannelResponderInjectable = getRequestChannelListenerInjectable({
|
||||
channel: resolveSystemProxyChannel,
|
||||
handlerInjectable: resolveSystemProxyInjectable,
|
||||
});
|
||||
|
||||
export default resolveSystemProxyChannelResponderInjectable;
|
||||
|
||||
@ -2,30 +2,13 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import syncBoxInitialValueChannelInjectable from "../../../common/utils/sync-box/sync-box-initial-value-channel.injectable";
|
||||
import { syncBoxInjectionToken } from "../../../common/utils/sync-box/sync-box-injection-token";
|
||||
import { requestChannelListenerInjectionToken } from "../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import { syncBoxInitialValueChannel } from "../../../common/utils/sync-box/channels";
|
||||
import { getRequestChannelListenerInjectable } from "../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import syncBoxInitialValueChannelHandlerInjectable from "./sync-box-initial-value-handler.injectable";
|
||||
|
||||
const syncBoxInitialValueChannelListenerInjectable = getInjectable({
|
||||
id: "sync-box-initial-value-channel-listener",
|
||||
|
||||
instantiate: (di) => {
|
||||
const channel = di.inject(syncBoxInitialValueChannelInjectable);
|
||||
const syncBoxes = di.injectMany(syncBoxInjectionToken);
|
||||
|
||||
return {
|
||||
channel,
|
||||
|
||||
handler: () =>
|
||||
syncBoxes.map((box) => ({
|
||||
id: box.id,
|
||||
value: box.value.get(),
|
||||
})),
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: requestChannelListenerInjectionToken,
|
||||
const syncBoxInitialValueChannelListenerInjectable = getRequestChannelListenerInjectable({
|
||||
channel: syncBoxInitialValueChannel,
|
||||
handlerInjectable: syncBoxInitialValueChannelHandlerInjectable,
|
||||
});
|
||||
|
||||
export default syncBoxInitialValueChannelListenerInjectable;
|
||||
|
||||
@ -0,0 +1,22 @@
|
||||
/**
|
||||
* 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 { RequestChannelHandler } from "../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import type { SyncBoxInitialValueChannel } from "../../../common/utils/sync-box/channels";
|
||||
import { syncBoxInjectionToken } from "../../../common/utils/sync-box/sync-box-injection-token";
|
||||
|
||||
const syncBoxInitialValueChannelHandlerInjectable = getInjectable({
|
||||
id: "sync-box-initial-value-channel-handler",
|
||||
instantiate: (di): RequestChannelHandler<SyncBoxInitialValueChannel> => {
|
||||
const syncBoxes = di.injectMany(syncBoxInjectionToken);
|
||||
|
||||
return () => syncBoxes.map((box) => ({
|
||||
id: box.id,
|
||||
value: box.value.get(),
|
||||
}));
|
||||
},
|
||||
});
|
||||
|
||||
export default syncBoxInitialValueChannelHandlerInjectable;
|
||||
@ -5,7 +5,7 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import appPathsStateInjectable from "../../common/app-paths/app-paths-state.injectable";
|
||||
import { beforeFrameStartsInjectionToken } from "../before-frame-starts/before-frame-starts-injection-token";
|
||||
import appPathsChannelInjectable from "../../common/app-paths/app-paths-channel.injectable";
|
||||
import { appPathsChannel } from "../../common/app-paths/app-paths-channel";
|
||||
import { requestFromChannelInjectionToken } from "../../common/utils/channel/request-from-channel-injection-token";
|
||||
|
||||
const setupAppPathsInjectable = getInjectable({
|
||||
@ -13,15 +13,12 @@ const setupAppPathsInjectable = getInjectable({
|
||||
|
||||
instantiate: (di) => {
|
||||
const requestFromChannel = di.inject(requestFromChannelInjectionToken);
|
||||
const appPathsChannel = di.inject(appPathsChannelInjectable);
|
||||
const appPathsState = di.inject(appPathsStateInjectable);
|
||||
|
||||
return {
|
||||
id: "setup-app-paths",
|
||||
run: async () => {
|
||||
const appPaths = await requestFromChannel(
|
||||
appPathsChannel,
|
||||
);
|
||||
const appPaths = await requestFromChannel(appPathsChannel);
|
||||
|
||||
appPathsState.set(appPaths);
|
||||
},
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { asyncComputed } from "@ogre-tools/injectable-react";
|
||||
import getActiveHelmRepositoriesChannelInjectable from "../../../../../common/helm/get-active-helm-repositories-channel.injectable";
|
||||
import { getActiveHelmRepositoriesChannel } from "../../../../../common/helm/get-active-helm-repositories-channel";
|
||||
import { requestFromChannelInjectionToken } from "../../../../../common/utils/channel/request-from-channel-injection-token";
|
||||
import showErrorNotificationInjectable from "../../../notifications/show-error-notification.injectable";
|
||||
import helmRepositoriesErrorStateInjectable from "./helm-repositories-error-state.injectable";
|
||||
@ -15,12 +15,11 @@ const activeHelmRepositoriesInjectable = getInjectable({
|
||||
|
||||
instantiate: (di) => {
|
||||
const requestFromChannel = di.inject(requestFromChannelInjectionToken);
|
||||
const getHelmRepositoriesChannel = di.inject(getActiveHelmRepositoriesChannelInjectable);
|
||||
const showErrorNotification = di.inject(showErrorNotificationInjectable);
|
||||
const helmRepositoriesErrorState = di.inject(helmRepositoriesErrorStateInjectable);
|
||||
|
||||
return asyncComputed(async () => {
|
||||
const result = await requestFromChannel(getHelmRepositoriesChannel);
|
||||
const result = await requestFromChannel(getActiveHelmRepositoriesChannel);
|
||||
|
||||
if (result.callWasSuccessful) {
|
||||
return result.response;
|
||||
|
||||
@ -3,19 +3,18 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import addHelmRepositoryChannelInjectable from "../../../../../../../common/helm/add-helm-repository-channel.injectable";
|
||||
import type { HelmRepo } from "../../../../../../../common/helm/helm-repo";
|
||||
import { requestFromChannelInjectionToken } from "../../../../../../../common/utils/channel/request-from-channel-injection-token";
|
||||
import activeHelmRepositoriesInjectable from "../../active-helm-repositories.injectable";
|
||||
import showErrorNotificationInjectable from "../../../../../notifications/show-error-notification.injectable";
|
||||
import showSuccessNotificationInjectable from "../../../../../notifications/show-success-notification.injectable";
|
||||
import { addHelmRepositoryChannel } from "../../../../../../../common/helm/add-helm-repository-channel";
|
||||
|
||||
const addHelmRepositoryInjectable = getInjectable({
|
||||
id: "add-public-helm-repository",
|
||||
|
||||
instantiate: (di) => {
|
||||
const requestFromChannel = di.inject(requestFromChannelInjectionToken);
|
||||
const addHelmRepositoryChannel = di.inject(addHelmRepositoryChannelInjectable);
|
||||
const activeHelmRepositories = di.inject(activeHelmRepositoriesInjectable);
|
||||
const showErrorNotification = di.inject(showErrorNotificationInjectable);
|
||||
const showSuccessNotification = di.inject(showSuccessNotificationInjectable);
|
||||
|
||||
@ -6,14 +6,13 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { HelmRepo } from "../../../../../common/helm/helm-repo";
|
||||
import { requestFromChannelInjectionToken } from "../../../../../common/utils/channel/request-from-channel-injection-token";
|
||||
import activeHelmRepositoriesInjectable from "./active-helm-repositories.injectable";
|
||||
import removeHelmRepositoryChannelInjectable from "../../../../../common/helm/remove-helm-repository-channel.injectable";
|
||||
import { removeHelmRepositoryChannel } from "../../../../../common/helm/remove-helm-repository-channel";
|
||||
|
||||
const removePublicHelmRepositoryInjectable = getInjectable({
|
||||
id: "remove-public-helm-repository",
|
||||
|
||||
instantiate: (di) => {
|
||||
const requestFromChannel = di.inject(requestFromChannelInjectionToken);
|
||||
const removeHelmRepositoryChannel = di.inject(removeHelmRepositoryChannelInjectable);
|
||||
const activeHelmRepositories = di.inject(activeHelmRepositoriesInjectable);
|
||||
|
||||
return async (repository: HelmRepo) => {
|
||||
|
||||
@ -61,7 +61,6 @@ import createApplicationWindowInjectable from "../../../main/start-main-applicat
|
||||
import type { CreateElectronWindow } from "../../../main/start-main-application/lens-window/application-window/create-electron-window.injectable";
|
||||
import createElectronWindowInjectable from "../../../main/start-main-application/lens-window/application-window/create-electron-window.injectable";
|
||||
import { applicationWindowInjectionToken } from "../../../main/start-main-application/lens-window/application-window/application-window-injection-token";
|
||||
import sendToChannelInElectronBrowserWindowInjectable from "../../../main/start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable";
|
||||
import closeAllWindowsInjectable from "../../../main/start-main-application/lens-window/hide-all-windows/close-all-windows.injectable";
|
||||
import type { LensWindow } from "../../../main/start-main-application/lens-window/application-window/create-lens-window.injectable";
|
||||
import type { FakeExtensionOptions } from "./get-extension-fake";
|
||||
@ -166,7 +165,7 @@ export const getApplicationBuilder = () => {
|
||||
mainDi.register(mainExtensionsStateInjectable);
|
||||
});
|
||||
|
||||
const overrideChannelsForWindow = overrideChannels(mainDi);
|
||||
const { overrideForWindow, sendToWindow } = overrideChannels(mainDi);
|
||||
|
||||
const beforeApplicationStartCallbacks: Callback[] = [];
|
||||
const beforeWindowStartCallbacks: Callback[] = [];
|
||||
@ -208,7 +207,7 @@ export const getApplicationBuilder = () => {
|
||||
|
||||
const windowDi = getRendererDi({ doGeneralOverrides: true });
|
||||
|
||||
overrideChannelsForWindow(windowDi, windowId);
|
||||
overrideForWindow(windowDi, windowId);
|
||||
overrideFsWithFakes(windowDi, fsState);
|
||||
|
||||
runInAction(() => {
|
||||
@ -259,9 +258,7 @@ export const getApplicationBuilder = () => {
|
||||
},
|
||||
|
||||
send: (arg) => {
|
||||
const sendFake = mainDi.inject(sendToChannelInElectronBrowserWindowInjectable) as any;
|
||||
|
||||
sendFake(windowId, null, arg);
|
||||
sendToWindow(windowId, arg);
|
||||
},
|
||||
|
||||
reload: () => {
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import restartAndInstallUpdateChannel from "../../../common/application-update/restart-and-install-update-channel/restart-and-install-update-channel.injectable";
|
||||
import { restartAndInstallUpdateChannel } from "../../../common/application-update/restart-and-install-update-channel";
|
||||
import messageToChannelInjectable from "../../utils/channel/message-to-channel.injectable";
|
||||
|
||||
const restartAndInstallUpdateInjectable = getInjectable({
|
||||
@ -11,10 +11,9 @@ const restartAndInstallUpdateInjectable = getInjectable({
|
||||
|
||||
instantiate: (di) => {
|
||||
const messageToChannel = di.inject(messageToChannelInjectable);
|
||||
const channel = di.inject(restartAndInstallUpdateChannel);
|
||||
|
||||
return () => {
|
||||
messageToChannel(channel);
|
||||
messageToChannel(restartAndInstallUpdateChannel);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@ -3,18 +3,17 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { messageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token";
|
||||
import rootFrameIsRenderedChannelInjectable from "../../../common/root-frame-rendered-channel/root-frame-rendered-channel.injectable";
|
||||
import { sendMessageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token";
|
||||
import { rootFrameHasRenderedChannel } from "../../../common/root-frame/root-frame-rendered-channel";
|
||||
|
||||
const broadcastThatRootFrameIsRenderedInjectable = getInjectable({
|
||||
id: "broadcast-that-root-frame-is-rendered",
|
||||
|
||||
instantiate: (di) => {
|
||||
const messageToChannel = di.inject(messageToChannelInjectionToken);
|
||||
const rootFrameIsRenderedChannel = di.inject(rootFrameIsRenderedChannelInjectable);
|
||||
const messageToChannel = di.inject(sendMessageToChannelInjectionToken);
|
||||
|
||||
return () => {
|
||||
messageToChannel(rootFrameIsRenderedChannel);
|
||||
messageToChannel(rootFrameHasRenderedChannel);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@ -5,14 +5,11 @@
|
||||
|
||||
import { ipcRenderer } from "electron";
|
||||
import { reaction } from "mobx";
|
||||
import { broadcastMessage, ipcRendererOn } from "../../common/ipc";
|
||||
import {
|
||||
getLegacyGlobalDiForExtensionApi,
|
||||
} from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
||||
import { broadcastMessage } from "../../common/ipc";
|
||||
import { getLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
||||
import matchedClusterIdInjectable from "./matched-cluster-id.injectable";
|
||||
|
||||
export const enum IpcRendererNavigationEvents {
|
||||
RELOAD_PAGE = "renderer:page-reload",
|
||||
CLUSTER_VIEW_CURRENT_ID = "renderer:cluster-id-of-active-view",
|
||||
NAVIGATE_IN_APP = "renderer:navigate",
|
||||
NAVIGATE_IN_CLUSTER = "renderer:navigate-in-cluster",
|
||||
@ -27,11 +24,6 @@ export function bindEvents() {
|
||||
if (process.isMainFrame) {
|
||||
bindClusterManagerRouteEvents();
|
||||
}
|
||||
|
||||
// Reload dashboard window
|
||||
ipcRendererOn(IpcRendererNavigationEvents.RELOAD_PAGE, () => {
|
||||
location.reload();
|
||||
});
|
||||
}
|
||||
|
||||
// Handle events only in main window renderer process (see also: cluster-manager.tsx)
|
||||
|
||||
@ -2,12 +2,14 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { InjectionToken } from "@ogre-tools/injectable";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import currentlyInClusterFrameInjectable from "../routes/currently-in-cluster-frame.injectable";
|
||||
import appNavigationChannelInjectable from "../../common/front-end-routing/app-navigation-channel.injectable";
|
||||
import clusterFrameNavigationChannelInjectable from "../../common/front-end-routing/cluster-frame-navigation-channel.injectable";
|
||||
import { appNavigationChannel } from "../../common/front-end-routing/app-navigation-channel";
|
||||
import { clusterFrameNavigationChannel } from "../../common/front-end-routing/cluster-frame-navigation-channel";
|
||||
import focusWindowInjectable from "./focus-window.injectable";
|
||||
import { navigateToUrlInjectionToken } from "../../common/front-end-routing/navigate-to-url-injection-token";
|
||||
import type { MessageChannel, MessageChannelListener } from "../../common/utils/channel/message-channel-listener-injection-token";
|
||||
import { messageChannelListenerInjectionToken } from "../../common/utils/channel/message-channel-listener-injection-token";
|
||||
|
||||
const navigationChannelListenerInjectable = getInjectable({
|
||||
@ -15,8 +17,6 @@ const navigationChannelListenerInjectable = getInjectable({
|
||||
|
||||
instantiate: (di) => {
|
||||
const currentlyInClusterFrame = di.inject(currentlyInClusterFrameInjectable);
|
||||
const appNavigationChannel = di.inject(appNavigationChannelInjectable);
|
||||
const clusterFrameNavigationChannel = di.inject(clusterFrameNavigationChannelInjectable);
|
||||
const focusWindow = di.inject(focusWindowInjectable);
|
||||
const navigateToUrl = di.inject(navigateToUrlInjectionToken);
|
||||
|
||||
@ -34,7 +34,7 @@ const navigationChannelListenerInjectable = getInjectable({
|
||||
},
|
||||
};
|
||||
},
|
||||
injectionToken: messageChannelListenerInjectionToken,
|
||||
injectionToken: messageChannelListenerInjectionToken as InjectionToken<MessageChannelListener<MessageChannel<string>>, void>,
|
||||
});
|
||||
|
||||
export default navigationChannelListenerInjectable;
|
||||
|
||||
@ -6,8 +6,6 @@ import ipcRendererInjectable from "../ipc-renderer.injectable";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { IpcRendererEvent } from "electron";
|
||||
import { enlistMessageChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-message-channel-listener-injection-token";
|
||||
import { tentativeParseJson } from "../../../../common/utils/tentative-parse-json";
|
||||
import { pipeline } from "@ogre-tools/fp";
|
||||
|
||||
const enlistMessageChannelListenerInjectable = getInjectable({
|
||||
id: "enlist-message-channel-listener-for-renderer",
|
||||
@ -17,11 +15,7 @@ const enlistMessageChannelListenerInjectable = getInjectable({
|
||||
|
||||
return ({ channel, handler }) => {
|
||||
const nativeCallback = (_: IpcRendererEvent, message: unknown) => {
|
||||
pipeline(
|
||||
message,
|
||||
tentativeParseJson,
|
||||
handler,
|
||||
);
|
||||
handler(message);
|
||||
};
|
||||
|
||||
ipcRenderer.on(channel.id, nativeCallback);
|
||||
|
||||
@ -88,8 +88,8 @@ describe("enlist message channel listener in renderer", () => {
|
||||
expect(handlerMock).toHaveBeenCalledWith(true);
|
||||
});
|
||||
|
||||
it("given stringified object as message, when message arrives, calls the handler with the message", () => {
|
||||
onMock.mock.calls[0][1]({} as IpcRendererEvent, JSON.stringify({ some: "object" }));
|
||||
it("given object as message, when message arrives, calls the handler with the message", () => {
|
||||
onMock.mock.calls[0][1]({} as IpcRendererEvent, { some: "object" });
|
||||
|
||||
expect(handlerMock).toHaveBeenCalledWith({ some: "object" });
|
||||
});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user