From d96918c966e1bd36166f62faac7fb155db188dc2 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Thu, 13 Oct 2022 07:49:58 -0400 Subject: [PATCH 1/7] Fix windows shell not having all environment variables (#6402) * Fix windows shell not having all environment variables Signed-off-by: Sebastian Malton * Fix startup due to buildVersion dependency Signed-off-by: Sebastian Malton * Call cleanup in computeShellEnvironment Signed-off-by: Sebastian Malton Signed-off-by: Sebastian Malton --- .../user-store/resolved-shell.injectable.ts | 13 ++ src/main/__test__/shell-session.test.ts | 6 +- .../local-shell-session.ts | 5 +- .../local-shell-session/open.injectable.ts | 12 +- .../local-shell-session/techincal.test.ts | 90 +++++++++++++ .../node-shell-session/open.injectable.ts | 10 ++ src/main/shell-session/shell-session.ts | 41 +++--- ...pawn-pty.global-override-for-injectable.ts | 10 ++ .../shell-session/spawn-pty.injectable.ts | 21 ++++ .../runnables/setup-shell.injectable.ts | 17 ++- src/main/utils/clear-kube-env-vars.ts | 2 +- src/main/utils/shell-env.ts | 118 ------------------ .../compute-shell-environment.injectable.ts | 62 +++++++++ ...ironment.global-override-for-injectable.ts | 11 ++ ...mpute-unix-shell-environment.injectable.ts | 93 ++++++++++++++ 15 files changed, 367 insertions(+), 144 deletions(-) create mode 100644 src/common/user-store/resolved-shell.injectable.ts create mode 100644 src/main/shell-session/local-shell-session/techincal.test.ts create mode 100644 src/main/shell-session/spawn-pty.global-override-for-injectable.ts create mode 100644 src/main/shell-session/spawn-pty.injectable.ts delete mode 100644 src/main/utils/shell-env.ts create mode 100644 src/main/utils/shell-env/compute-shell-environment.injectable.ts create mode 100644 src/main/utils/shell-env/compute-unix-shell-environment.global-override-for-injectable.ts create mode 100644 src/main/utils/shell-env/compute-unix-shell-environment.injectable.ts diff --git a/src/common/user-store/resolved-shell.injectable.ts b/src/common/user-store/resolved-shell.injectable.ts new file mode 100644 index 0000000000..98c219feff --- /dev/null +++ b/src/common/user-store/resolved-shell.injectable.ts @@ -0,0 +1,13 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import userStoreInjectable from "./user-store.injectable"; + +const resolvedShellInjectable = getInjectable({ + id: "resolved-shell", + instantiate: (di) => di.inject(userStoreInjectable).resolvedShell, +}); + +export default resolvedShellInjectable; diff --git a/src/main/__test__/shell-session.test.ts b/src/main/__test__/shell-session.test.ts index 1fe8915e26..c8c0f1c8df 100644 --- a/src/main/__test__/shell-session.test.ts +++ b/src/main/__test__/shell-session.test.ts @@ -7,14 +7,14 @@ import { clearKubeconfigEnvVars } from "../utils/clear-kube-env-vars"; describe("clearKubeconfigEnvVars tests", () => { it("should not touch non kubeconfig keys", () => { - expect(clearKubeconfigEnvVars({ a: 1 })).toStrictEqual({ a: 1 }); + expect(clearKubeconfigEnvVars({ a: "22" })).toStrictEqual({ a: "22" }); }); it("should remove a single kubeconfig key", () => { - expect(clearKubeconfigEnvVars({ a: 1, kubeconfig: "1" })).toStrictEqual({ a: 1 }); + expect(clearKubeconfigEnvVars({ a: "22", kubeconfig: "1" })).toStrictEqual({ a: "22" }); }); it("should remove a two kubeconfig key", () => { - expect(clearKubeconfigEnvVars({ a: 1, kubeconfig: "1", kUbeconfig: "1" })).toStrictEqual({ a: 1 }); + expect(clearKubeconfigEnvVars({ a: "22", kubeconfig: "1", kUbeconfig: "1" })).toStrictEqual({ a: "22" }); }); }); diff --git a/src/main/shell-session/local-shell-session/local-shell-session.ts b/src/main/shell-session/local-shell-session/local-shell-session.ts index c13bbeb5a2..49e6dd059f 100644 --- a/src/main/shell-session/local-shell-session/local-shell-session.ts +++ b/src/main/shell-session/local-shell-session/local-shell-session.ts @@ -36,11 +36,8 @@ export class LocalShellSession extends ShellSession { } public async open() { - let env = await this.getCachedShellEnv(); - // extensions can modify the env - env = this.dependencies.modifyTerminalShellEnv(this.cluster.id, env); - + const env = this.dependencies.modifyTerminalShellEnv(this.cluster.id, await this.getCachedShellEnv()); const shell = env.PTYSHELL; if (!shell) { diff --git a/src/main/shell-session/local-shell-session/open.injectable.ts b/src/main/shell-session/local-shell-session/open.injectable.ts index 0187ba97e7..bfb72911ec 100644 --- a/src/main/shell-session/local-shell-session/open.injectable.ts +++ b/src/main/shell-session/local-shell-session/open.injectable.ts @@ -17,6 +17,11 @@ import type WebSocket from "ws"; import getDirnameOfPathInjectable from "../../../common/path/get-dirname.injectable"; import joinPathsInjectable from "../../../common/path/join-paths.injectable"; import getBasenameOfPathInjectable from "../../../common/path/get-basename.injectable"; +import computeShellEnvironmentInjectable from "../../utils/shell-env/compute-shell-environment.injectable"; +import spawnPtyInjectable from "../spawn-pty.injectable"; +import resolvedShellInjectable from "../../../common/user-store/resolved-shell.injectable"; +import appNameInjectable from "../../../common/vars/app-name.injectable"; +import buildVersionInjectable from "../../vars/build-version/build-version.injectable"; export interface OpenLocalShellSessionArgs { websocket: WebSocket; @@ -34,13 +39,18 @@ const openLocalShellSessionInjectable = getInjectable({ const dependencies: LocalShellSessionDependencies = { directoryForBinaries: di.inject(directoryForBinariesInjectable), isMac: di.inject(isMacInjectable), - modifyTerminalShellEnv: di.inject(modifyTerminalShellEnvInjectable), isWindows: di.inject(isWindowsInjectable), logger: di.inject(loggerInjectable), userStore: di.inject(userStoreInjectable), + resolvedShell: di.inject(resolvedShellInjectable), + appName: di.inject(appNameInjectable), + buildVersion: di.inject(buildVersionInjectable), + modifyTerminalShellEnv: di.inject(modifyTerminalShellEnvInjectable), getDirnameOfPath: di.inject(getDirnameOfPathInjectable), joinPaths: di.inject(joinPathsInjectable), getBasenameOfPath: di.inject(getBasenameOfPathInjectable), + computeShellEnvironment: di.inject(computeShellEnvironmentInjectable), + spawnPty: di.inject(spawnPtyInjectable), }; return (args) => { diff --git a/src/main/shell-session/local-shell-session/techincal.test.ts b/src/main/shell-session/local-shell-session/techincal.test.ts new file mode 100644 index 0000000000..fbe2ccaea3 --- /dev/null +++ b/src/main/shell-session/local-shell-session/techincal.test.ts @@ -0,0 +1,90 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type { DiContainer } from "@ogre-tools/injectable"; +import { WebSocket } from "ws"; +import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; +import type { Cluster } from "../../../common/cluster/cluster"; +import platformInjectable from "../../../common/vars/platform.injectable"; +import { getDiForUnitTesting } from "../../getDiForUnitTesting"; +import createKubectlInjectable from "../../kubectl/create-kubectl.injectable"; +import type { Kubectl } from "../../kubectl/kubectl"; +import buildVersionInjectable from "../../vars/build-version/build-version.injectable"; +import type { OpenShellSession } from "../create-shell-session.injectable"; +import type { SpawnPty } from "../spawn-pty.injectable"; +import spawnPtyInjectable from "../spawn-pty.injectable"; +import openLocalShellSessionInjectable from "./open.injectable"; + +describe("technical unit tests for local shell sessions", () => { + let di: DiContainer; + + beforeEach(() => { + di = getDiForUnitTesting({ + doGeneralOverrides: true, + }); + + di.override(directoryForUserDataInjectable, () => "/some-directory-for-user-data"); + di.override(buildVersionInjectable, () => ({ + get: () => "1.1.1", + })); + }); + + describe("when on windows", () => { + let openLocalShellSession: OpenShellSession; + let spawnPtyMock: jest.MockedFunction; + + beforeEach(() => { + di.override(platformInjectable, () => "win32"); + + spawnPtyMock = jest.fn(); + di.override(spawnPtyInjectable, () => spawnPtyMock); + + di.override(createKubectlInjectable, () => () => ({ + binDir: async () => "/some-kubectl-binary-dir", + getBundledPath: () => "/some-bundled-kubectl-path", + }) as Partial as Kubectl); + + openLocalShellSession = di.inject(openLocalShellSessionInjectable); + }); + + describe("when opening a local shell session", () => { + it("should pass through all environment variables to shell", async () => { + process.env.MY_TEST_ENV_VAR = "true"; + + spawnPtyMock.mockImplementationOnce((file, args, options) => { + expect(options.env).toMatchObject({ + MY_TEST_ENV_VAR: "true", + }); + + return { + cols: 80, + rows: 40, + pid: 12343, + handleFlowControl: false, + kill: jest.fn(), + onData: jest.fn(), + onExit: jest.fn(), + pause: jest.fn(), + process: "my-pty", + resize: jest.fn(), + resume: jest.fn(), + write: jest.fn(), + on: jest.fn(), + + }; + }); + + await openLocalShellSession({ + cluster: { + getProxyKubeconfigPath: async () => "/some-proxy-kubeconfig", + preferences: {}, + } as Partial as Cluster, + tabId: "my-tab-id", + websocket: new WebSocket(null), + }); + }); + }); + }); +}); diff --git a/src/main/shell-session/node-shell-session/open.injectable.ts b/src/main/shell-session/node-shell-session/open.injectable.ts index 9bc418d812..6080129d6a 100644 --- a/src/main/shell-session/node-shell-session/open.injectable.ts +++ b/src/main/shell-session/node-shell-session/open.injectable.ts @@ -12,6 +12,11 @@ import isMacInjectable from "../../../common/vars/is-mac.injectable"; import isWindowsInjectable from "../../../common/vars/is-windows.injectable"; import loggerInjectable from "../../../common/logger.injectable"; import createKubeJsonApiForClusterInjectable from "../../../common/k8s-api/create-kube-json-api-for-cluster.injectable"; +import computeShellEnvironmentInjectable from "../../utils/shell-env/compute-shell-environment.injectable"; +import spawnPtyInjectable from "../spawn-pty.injectable"; +import resolvedShellInjectable from "../../../common/user-store/resolved-shell.injectable"; +import appNameInjectable from "../../../common/vars/app-name.injectable"; +import buildVersionInjectable from "../../vars/build-version/build-version.injectable"; export interface NodeShellSessionArgs { websocket: WebSocket; @@ -28,7 +33,12 @@ const openNodeShellSessionInjectable = getInjectable({ isMac: di.inject(isMacInjectable), isWindows: di.inject(isWindowsInjectable), logger: di.inject(loggerInjectable), + resolvedShell: di.inject(resolvedShellInjectable), + appName: di.inject(appNameInjectable), + buildVersion: di.inject(buildVersionInjectable), createKubeJsonApiForCluster: di.inject(createKubeJsonApiForClusterInjectable), + computeShellEnvironment: di.inject(computeShellEnvironmentInjectable), + spawnPty: di.inject(spawnPtyInjectable), }; const kubectl = createKubectl(params.cluster.version); const session = new NodeShellSession(dependencies, { kubectl, ...params }); diff --git a/src/main/shell-session/shell-session.ts b/src/main/shell-session/shell-session.ts index 6514b0cf85..e17f533ccb 100644 --- a/src/main/shell-session/shell-session.ts +++ b/src/main/shell-session/shell-session.ts @@ -6,18 +6,18 @@ import type { Cluster } from "../../common/cluster/cluster"; import type { Kubectl } from "../kubectl/kubectl"; import type WebSocket from "ws"; -import { shellEnv } from "../utils/shell-env"; -import { app } from "electron"; import { clearKubeconfigEnvVars } from "../utils/clear-kube-env-vars"; import path from "path"; import os, { userInfo } from "os"; -import { UserStore } from "../../common/user-store"; -import * as pty from "node-pty"; +import type * as pty from "node-pty"; import { appEventBus } from "../../common/app-event-bus/event-bus"; import { stat } from "fs/promises"; import { getOrInsertWith } from "../../common/utils"; import { type TerminalMessage, TerminalChannels } from "../../common/terminal/channels"; import type { Logger } from "../../common/logger"; +import type { ComputeShellEnvironment } from "../utils/shell-env/compute-shell-environment.injectable"; +import type { SpawnPty } from "./spawn-pty.injectable"; +import type { InitializableState } from "../../common/initializable-state/create"; export class ShellOpenError extends Error { constructor(message: string, options?: ErrorOptions) { @@ -107,6 +107,11 @@ export interface ShellSessionDependencies { readonly isWindows: boolean; readonly isMac: boolean; readonly logger: Logger; + readonly resolvedShell: string | undefined; + readonly appName: string; + readonly buildVersion: InitializableState; + computeShellEnvironment: ComputeShellEnvironment; + spawnPty: SpawnPty; } export interface ShellSessionArgs { @@ -148,14 +153,14 @@ export abstract class ShellSession { protected abstract get cwd(): string | undefined; - protected ensureShellProcess(shell: string, args: string[], env: Record, cwd: string): { shellProcess: pty.IPty; resume: boolean } { + protected ensureShellProcess(shell: string, args: string[], env: Partial>, cwd: string): { shellProcess: pty.IPty; resume: boolean } { const resume = ShellSession.processes.has(this.terminalId); const shellProcess = getOrInsertWith(ShellSession.processes, this.terminalId, () => ( - pty.spawn(shell, args, { + this.dependencies.spawnPty(shell, args, { rows: 30, cols: 80, cwd, - env: env as Record, + env, name: "xterm-256color", // TODO: Something else is broken here so we need to force the use of winPty on windows useConpty: false, @@ -331,19 +336,27 @@ export abstract class ShellSession { } protected async getShellEnv() { - const shell = UserStore.getInstance().resolvedShell; - const env = clearKubeconfigEnvVars(JSON.parse(JSON.stringify(await shellEnv(shell || userInfo().shell)))); - const pathStr = [await this.kubectlBinDirP, ...this.getPathEntries(), process.env.PATH].join(path.delimiter); + const shell = this.dependencies.resolvedShell || userInfo().shell; + const result = await this.dependencies.computeShellEnvironment(shell); + const rawEnv = (() => { + if (result.callWasSuccessful) { + return result.response ?? process.env; + } + + return process.env; + })(); + + const env = clearKubeconfigEnvVars(JSON.parse(JSON.stringify(rawEnv))); + const pathStr = [await this.kubectlBinDirP, ...this.getPathEntries(), env.PATH].join(path.delimiter); delete env.DEBUG; // don't pass DEBUG into shells if (this.dependencies.isWindows) { - env.SystemRoot = process.env.SystemRoot; env.PTYSHELL = shell || "powershell.exe"; env.PATH = pathStr; env.LENS_SESSION = "true"; env.WSLENV = [ - process.env.WSLENV, + env.WSLENV, "KUBECONFIG/up:LENS_SESSION/u", ] .filter(Boolean) @@ -363,8 +376,8 @@ export abstract class ShellSession { env.PTYPID = process.pid.toString(); env.KUBECONFIG = await this.kubeconfigPathP; - env.TERM_PROGRAM = app.getName(); - env.TERM_PROGRAM_VERSION = app.getVersion(); + env.TERM_PROGRAM = this.dependencies.appName; + env.TERM_PROGRAM_VERSION = this.dependencies.buildVersion.get(); if (this.cluster.preferences.httpsProxy) { env.HTTPS_PROXY = this.cluster.preferences.httpsProxy; diff --git a/src/main/shell-session/spawn-pty.global-override-for-injectable.ts b/src/main/shell-session/spawn-pty.global-override-for-injectable.ts new file mode 100644 index 0000000000..239f7c5e47 --- /dev/null +++ b/src/main/shell-session/spawn-pty.global-override-for-injectable.ts @@ -0,0 +1,10 @@ +/** + * 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 spawnPtyInjectable from "./spawn-pty.injectable"; + +export default getGlobalOverride(spawnPtyInjectable, () => () => { + throw new Error("Tried to spawn a PTY without an override"); +}); diff --git a/src/main/shell-session/spawn-pty.injectable.ts b/src/main/shell-session/spawn-pty.injectable.ts new file mode 100644 index 0000000000..0639c7307b --- /dev/null +++ b/src/main/shell-session/spawn-pty.injectable.ts @@ -0,0 +1,21 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import type { IPty, IPtyForkOptions, IWindowsPtyForkOptions } from "node-pty"; +import { spawn } from "node-pty"; + +export type WindowsSpawnPtyOptions = Omit & { env?: Partial> }; +export type UnixSpawnPtyOptions = Omit & { env?: Partial> }; +export type SpawnPtyOptions = UnixSpawnPtyOptions | WindowsSpawnPtyOptions; + +export type SpawnPty = (file: string, args: string[], options: SpawnPtyOptions) => IPty; + +const spawnPtyInjectable = getInjectable({ + id: "spawn-pty", + instantiate: () => spawn as SpawnPty, + causesSideEffects: true, +}); + +export default spawnPtyInjectable; diff --git a/src/main/start-main-application/runnables/setup-shell.injectable.ts b/src/main/start-main-application/runnables/setup-shell.injectable.ts index 147d2f24ab..9eb736b2db 100644 --- a/src/main/start-main-application/runnables/setup-shell.injectable.ts +++ b/src/main/start-main-application/runnables/setup-shell.injectable.ts @@ -5,11 +5,11 @@ import { getInjectable } from "@ogre-tools/injectable"; import loggerInjectable from "../../../common/logger.injectable"; import { onLoadOfApplicationInjectionToken } from "../runnable-tokens/on-load-of-application-injection-token"; -import { shellEnv } from "../../utils/shell-env"; import os from "os"; import { unionPATHs } from "../../../common/utils/union-env-path"; import isSnapPackageInjectable from "../../../common/vars/is-snap-package.injectable"; import electronAppInjectable from "../../electron-app/electron-app.injectable"; +import computeShellEnvironmentInjectable from "../../utils/shell-env/compute-shell-environment.injectable"; const setupShellInjectable = getInjectable({ id: "setup-shell", @@ -18,13 +18,24 @@ const setupShellInjectable = getInjectable({ const logger = di.inject(loggerInjectable); const isSnapPackage = di.inject(isSnapPackageInjectable); const electronApp = di.inject(electronAppInjectable); + const computeShellEnvironment = di.inject(computeShellEnvironmentInjectable); return { id: "setup-shell", - run: async () => { + run: async (): Promise => { logger.info("🐚 Syncing shell environment"); - const env = await shellEnv(os.userInfo().shell); + const result = await computeShellEnvironment(os.userInfo().shell); + + if (!result.callWasSuccessful) { + return void logger.error(`[SHELL-SYNC]: ${result.error}`); + } + + const env = result.response; + + if (!env) { + return void logger.debug("[SHELL-SYNC]: nothing to do, env not special in shells"); + } if (!env.LANG) { // the LANG env var expects an underscore instead of electron's dash diff --git a/src/main/utils/clear-kube-env-vars.ts b/src/main/utils/clear-kube-env-vars.ts index fab11be4e1..f678f44807 100644 --- a/src/main/utils/clear-kube-env-vars.ts +++ b/src/main/utils/clear-kube-env-vars.ts @@ -13,7 +13,7 @@ const anyKubeconfig = /^kubeconfig$/i; * before KUBECONFIG and we only set KUBECONFIG. * @param env The current copy of env */ -export function clearKubeconfigEnvVars(env: Record): Record { +export function clearKubeconfigEnvVars(env: Partial>): Partial> { return Object.fromEntries( Object.entries(env) .filter(([key]) => anyKubeconfig.exec(key) === null), diff --git a/src/main/utils/shell-env.ts b/src/main/utils/shell-env.ts deleted file mode 100644 index 6f4cce0be8..0000000000 --- a/src/main/utils/shell-env.ts +++ /dev/null @@ -1,118 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import { spawn } from "child_process"; -import { randomUUID } from "crypto"; -import { basename } from "path"; -import { isWindows } from "../../common/vars"; -import logger from "../logger"; - -export type EnvironmentVariables = Partial>; - - -async function unixShellEnvironment(shell: string): Promise { - const runAsNode = process.env["ELECTRON_RUN_AS_NODE"]; - const noAttach = process.env["ELECTRON_NO_ATTACH_CONSOLE"]; - const env = { - ...process.env, - ELECTRON_RUN_AS_NODE: "1", - ELECTRON_NO_ATTACH_CONSOLE: "1", - }; - const mark = randomUUID().replace(/-/g, ""); - const regex = new RegExp(`${mark}(.*)${mark}`); - const shellName = basename(shell); - let command: string; - let shellArgs: string[]; - - if (/^pwsh(-preview)?$/.test(shellName)) { - // Older versions of PowerShell removes double quotes sometimes so we use "double single quotes" which is how - // you escape single quotes inside of a single quoted string. - command = `& '${process.execPath}' -p '''${mark}'' + JSON.stringify(process.env) + ''${mark}'''`; - shellArgs = ["-Login", "-Command"]; - } else { - command = `'${process.execPath}' -p '"${mark}" + JSON.stringify(process.env) + "${mark}"'`; - - if (shellName === "tcsh") { - shellArgs = ["-ic"]; - } else { - shellArgs = ["-ilc"]; - } - } - - return new Promise((resolve, reject) => { - const shellProcess = spawn(shell, [...shellArgs, command], { - detached: true, - stdio: ["ignore", "pipe", "pipe"], - env, - }); - const stdout: Buffer[] = []; - - shellProcess.on("error", (err) => reject(err)); - shellProcess.stdout.on("data", b => stdout.push(b)); - shellProcess.on("close", (code, signal) => { - if (code || signal) { - return reject(new Error(`Unexpected return code from spawned shell (code: ${code}, signal: ${signal})`)); - } - - try { - const rawOutput = Buffer.concat(stdout).toString("utf-8"); - const match = regex.exec(rawOutput); - const strippedRawOutput = match ? match[1] : "{}"; - const resolvedEnv = JSON.parse(strippedRawOutput); - - if (runAsNode) { - resolvedEnv["ELECTRON_RUN_AS_NODE"] = runAsNode; - } else { - delete resolvedEnv["ELECTRON_RUN_AS_NODE"]; - } - - if (noAttach) { - resolvedEnv["ELECTRON_NO_ATTACH_CONSOLE"] = noAttach; - } else { - delete resolvedEnv["ELECTRON_NO_ATTACH_CONSOLE"]; - } - - resolve(resolvedEnv); - } catch(err) { - reject(err); - } - }); - }); -} - -let shellSyncFailed = false; - -/** - * Attempts to get the shell environment per the user's existing startup scripts. - * If the environment can't be retrieved after 5 seconds an error message is logged. - * Subsequent calls after such a timeout simply log an error message without trying - * to get the environment, unless forceRetry is true. - * @param shell the shell to get the environment from - * @returns object containing the shell's environment variables. An empty object is - * returned if the call fails. - */ -export async function shellEnv(shell: string) : Promise { - if (isWindows) { - return {}; - } - - if (!shellSyncFailed) { - try { - return await Promise.race([ - unixShellEnvironment(shell), - new Promise((_resolve, reject) => setTimeout(() => { - reject(new Error("Resolving shell environment is taking very long. Please review your shell configuration.")); - }, 30_000)), - ]); - } catch (error) { - logger.error(`shellEnv: ${error}`); - shellSyncFailed = true; - } - } else { - logger.error("shellSync(): Resolving shell environment took too long. Please review your shell configuration."); - } - - return {}; -} diff --git a/src/main/utils/shell-env/compute-shell-environment.injectable.ts b/src/main/utils/shell-env/compute-shell-environment.injectable.ts new file mode 100644 index 0000000000..e3a60fcd03 --- /dev/null +++ b/src/main/utils/shell-env/compute-shell-environment.injectable.ts @@ -0,0 +1,62 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type { AsyncResult } from "../../../common/utils/async-result"; +import { getInjectable } from "@ogre-tools/injectable"; +import isWindowsInjectable from "../../../common/vars/is-windows.injectable"; +import { disposer } from "../../../common/utils"; +import computeUnixShellEnvironmentInjectable from "./compute-unix-shell-environment.injectable"; + +export type EnvironmentVariables = Partial>; +export type ComputeShellEnvironment = (shell: string) => Promise>; + +const computeShellEnvironmentInjectable = getInjectable({ + id: "compute-shell-environment", + instantiate: (di): ComputeShellEnvironment => { + const isWindows = di.inject(isWindowsInjectable); + const computeUnixShellEnvironment = di.inject(computeUnixShellEnvironmentInjectable); + + if (isWindows) { + return async () => ({ + callWasSuccessful: true, + response: undefined, + }); + } + + return async (shell) => { + const controller = new AbortController(); + const shellEnv = computeUnixShellEnvironment(shell, { signal: controller.signal }); + const cleanup = disposer(); + + const timeoutHandle = setTimeout(() => controller.abort(), 30_000); + + cleanup.push(() => clearTimeout(timeoutHandle)); + + try { + return { + callWasSuccessful: true, + response: await shellEnv, + }; + } catch (error) { + if (controller.signal.aborted) { + return { + callWasSuccessful: false, + error: "Resolving shell environment is taking very long. Please review your shell configuration.", + }; + } + + return { + callWasSuccessful: false, + error: String(error), + }; + } finally { + cleanup(); + } + }; + }, +}); + +export default computeShellEnvironmentInjectable; + diff --git a/src/main/utils/shell-env/compute-unix-shell-environment.global-override-for-injectable.ts b/src/main/utils/shell-env/compute-unix-shell-environment.global-override-for-injectable.ts new file mode 100644 index 0000000000..aac810aa62 --- /dev/null +++ b/src/main/utils/shell-env/compute-unix-shell-environment.global-override-for-injectable.ts @@ -0,0 +1,11 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { getGlobalOverride } from "../../../common/test-utils/get-global-override"; +import computeUnixShellEnvironmentInjectable from "./compute-unix-shell-environment.injectable"; + +export default getGlobalOverride(computeUnixShellEnvironmentInjectable, () => async () => { + throw new Error("Tried to get unix shell env without override"); +}); diff --git a/src/main/utils/shell-env/compute-unix-shell-environment.injectable.ts b/src/main/utils/shell-env/compute-unix-shell-environment.injectable.ts new file mode 100644 index 0000000000..7186e96a88 --- /dev/null +++ b/src/main/utils/shell-env/compute-unix-shell-environment.injectable.ts @@ -0,0 +1,93 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { spawn } from "child_process"; +import { randomUUID } from "crypto"; +import { basename } from "path"; +import type { EnvironmentVariables } from "./compute-shell-environment.injectable"; +import { getInjectable } from "@ogre-tools/injectable"; + +interface UnixShellEnvOptions { + signal?: AbortSignal; +} + +export type ComputeUnixShellEnvironment = (shell: string, opts?: UnixShellEnvOptions) => Promise; + +const computeUnixShellEnvironmentInjectable = getInjectable({ + id: "compute-unix-shell-environment", + instantiate: (): ComputeUnixShellEnvironment => async (shell, opts) => { + const runAsNode = process.env["ELECTRON_RUN_AS_NODE"]; + const noAttach = process.env["ELECTRON_NO_ATTACH_CONSOLE"]; + const env = { + ...process.env, + ELECTRON_RUN_AS_NODE: "1", + ELECTRON_NO_ATTACH_CONSOLE: "1", + }; + const mark = randomUUID().replace(/-/g, ""); + const regex = new RegExp(`${mark}(.*)${mark}`); + const shellName = basename(shell); + let command: string; + let shellArgs: string[]; + + if (/^pwsh(-preview)?$/.test(shellName)) { + // Older versions of PowerShell removes double quotes sometimes so we use "double single quotes" which is how + // you escape single quotes inside of a single quoted string. + command = `& '${process.execPath}' -p '''${mark}'' + JSON.stringify(process.env) + ''${mark}'''`; + shellArgs = ["-Login", "-Command"]; + } else { + command = `'${process.execPath}' -p '"${mark}" + JSON.stringify(process.env) + "${mark}"'`; + + if (shellName === "tcsh") { + shellArgs = ["-ic"]; + } else { + shellArgs = ["-ilc"]; + } + } + + return new Promise((resolve, reject) => { + const shellProcess = spawn(shell, [...shellArgs, command], { + detached: true, + stdio: ["ignore", "pipe", "pipe"], + env, + }); + const stdout: Buffer[] = []; + + opts?.signal?.addEventListener("abort", () => shellProcess.kill()); + + shellProcess.on("error", (err) => reject(err)); + shellProcess.stdout.on("data", b => stdout.push(b)); + shellProcess.on("close", (code, signal) => { + if (code || signal) { + return reject(new Error(`Unexpected return code from spawned shell (code: ${code}, signal: ${signal})`)); + } + + try { + const rawOutput = Buffer.concat(stdout).toString("utf-8"); + const match = regex.exec(rawOutput); + const strippedRawOutput = match ? match[1] : "{}"; + const resolvedEnv = JSON.parse(strippedRawOutput); + + if (runAsNode) { + resolvedEnv["ELECTRON_RUN_AS_NODE"] = runAsNode; + } else { + delete resolvedEnv["ELECTRON_RUN_AS_NODE"]; + } + + if (noAttach) { + resolvedEnv["ELECTRON_NO_ATTACH_CONSOLE"] = noAttach; + } else { + delete resolvedEnv["ELECTRON_NO_ATTACH_CONSOLE"]; + } + + resolve(resolvedEnv); + } catch(err) { + reject(err); + } + }); + }); + }, + causesSideEffects: true, +}); + +export default computeUnixShellEnvironmentInjectable; From 5a5eda935bf4d2270262c56467d23089f5d14a43 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Thu, 13 Oct 2022 07:50:19 -0400 Subject: [PATCH 2/7] Add better type safety around Channels (#6133) * Add better type safety around Channels - Reallow non-JSON serializable complex types - Remove unnecessary JSON serialization step to IPC - Remove unnecesary injectable-ization of MessageChannel and RequestChannel declarations - Add channel listener injectable getter function to remove general need for type casting and improve type safety Signed-off-by: Sebastian Malton * Add check to verify data in IPC related tests Signed-off-by: Sebastian Malton * Fix implementation in light of new safety check in tests Signed-off-by: Sebastian Malton * Fix listener ID clash potential Signed-off-by: Sebastian Malton * Switch to not forcing split of request channel handlers being seperate from the listener decl Signed-off-by: Sebastian Malton * Move message channels to changed signature too Signed-off-by: Sebastian Malton * Fix not registering listener Signed-off-by: Sebastian Malton * Fix test imports Signed-off-by: Sebastian Malton * Fix type errors Signed-off-by: Sebastian Malton * Refactor listening of different channel kinds Signed-off-by: Sebastian Malton * Add test covering new checking code for request channel handlers Signed-off-by: Sebastian Malton Signed-off-by: Sebastian Malton --- .../app-paths/app-paths-channel.injectable.ts | 22 --- src/common/app-paths/app-paths-channel.ts | 13 ++ .../restart-and-install-update-channel.ts | 11 ++ ...t-and-install-update-channel.injectable.ts | 21 --- .../selected-update-channel.injectable.ts | 2 +- .../app-navigation-channel.injectable.ts | 22 --- .../app-navigation-channel.ts | 12 ++ ...ter-frame-navigation-channel.injectable.ts | 22 --- .../cluster-frame-navigation-channel.ts | 12 ++ src/common/fs/exec-file.injectable.ts | 33 ++-- ...able.ts => add-helm-repository-channel.ts} | 16 +- ...ve-helm-repositories-channel.injectable.ts | 23 --- .../get-active-helm-repositories-channel.ts | 13 ++ ...move-helm-repository-channel.injectable.ts | 22 --- .../helm/remove-helm-repository-channel.ts | 13 ++ .../root-frame-rendered-channel.injectable.ts | 21 --- .../root-frame/root-frame-rendered-channel.ts | 11 ++ src/common/utils/channel/channel.test.ts | 115 ++++++-------- ...essage-channel-listener-injection-token.ts | 15 +- ...equest-channel-listener-injection-token.ts | 16 -- .../listening-of-channels.injectable.ts | 32 ---- ...istening-on-message-channels.injectable.ts | 25 +++ .../message-channel-injection-token.ts | 16 -- ...essage-channel-listener-injection-token.ts | 47 +++++- .../message-to-channel-injection-token.ts | 22 +-- .../request-channel-injection-token.ts | 20 --- ...equest-channel-listener-injection-token.ts | 23 +-- .../request-from-channel-injection-token.ts | 22 +-- src/common/utils/disposer.ts | 6 +- ...resolve-system-proxy-channel.injectable.ts | 21 --- .../resolve-system-proxy-channel.ts | 11 ++ .../sync-box/channel-listener.injectable.ts | 15 ++ src/common/utils/sync-box/channels.ts | 21 +++ .../sync-box/create-sync-box.injectable.ts | 10 +- .../utils/sync-box/handler.injectable.ts | 19 +++ .../sync-box-channel-listener.injectable.ts | 35 ----- .../sync-box/sync-box-channel.injectable.ts | 21 --- ...nc-box-initial-value-channel.injectable.ts | 24 --- src/common/utils/tentative-parse-json.ts | 15 -- src/common/utils/tentative-stringify-json.ts | 15 -- .../vars/build-semantic-version.injectable.ts | 2 +- .../selection-of-update-stability.test.ts | 2 +- .../clear-as-deleting-channel.injectable.ts | 20 --- .../common/clear-as-deleting-channel.ts | 12 ++ .../common/delete-channel.injectable.ts | 20 --- .../delete-dialog/common/delete-channel.ts | 12 ++ .../set-as-deleting-channel.injectable.ts | 20 --- .../common/set-as-deleting-channel.ts | 12 ++ ...as-deleteing-channel-handler.injectable.ts | 23 --- ...as-deleting-channel-listener.injectable.ts | 20 +++ .../main/delete-channel-handler.injectable.ts | 56 ------- .../delete-channel-listener.injectable.ts | 51 ++++++ ...as-deleteing-channel-handler.injectable.ts | 23 --- ...s-deleteing-channel-listener.injectable.ts | 20 +++ .../request-clear-as-deleting.injectable.ts | 3 +- .../renderer/request-delete.injectable.ts | 3 +- .../request-set-as-deleting.injectable.ts | 3 +- ...tom-helm-repository-in-preferences.test.ts | 21 ++- ...epository-from-list-in-preferences.test.ts | 27 ++-- ...e-helm-repositories-in-preferences.test.ts | 68 ++++++-- ...f-active-repository-in-preferences.test.ts | 11 +- .../navigation/reload-page/common/channel.ts | 12 ++ ...listener.global-override-for-injectable.ts | 13 ++ .../renderer/register-listener.injectable.ts | 15 ++ ...ths-request-channel-listener.injectable.ts | 21 +-- ...-and-install-update-listener.injectable.ts | 23 +-- ...update-should-happen-on-quit.injectable.ts | 29 ++-- .../build-version/setup-channel.injectable.ts | 17 +- .../helm/exec-helm/exec-helm.injectable.ts | 20 +-- ...-repository-channel-listener.injectable.ts | 22 +-- ...epositories-channel-listener.injectable.ts | 22 +-- ...-repository-channel-listener.injectable.ts | 22 +-- .../create-electron-window.injectable.ts | 14 +- .../create-lens-window.injectable.ts | 2 +- ...l-in-electron-browser-window.injectable.ts | 33 ---- .../lens-window/navigate.injectable.ts | 2 +- ...d-current-application-window.injectable.ts | 4 +- .../channel-listener.injectable.ts | 20 +++ ...me-rendered-channel-listener.injectable.ts | 35 ----- ...ist-message-channel-listener.injectable.ts | 8 +- .../enlist-message-channel-listener.test.ts | 4 +- ...ist-request-channel-listener.injectable.ts | 16 +- .../enlist-request-channel-listener.test.ts | 34 ++-- .../channel-listeners/listener-tokens.ts | 46 ++++++ ...istening-on-request-channels.injectable.ts | 34 ++++ .../start-listening-of-channels.injectable.ts | 26 --- .../start-listening-on-channels.injectable.ts | 29 ++++ .../channel/message-to-channel.injectable.ts | 21 +-- .../utils/channel/message-to-channel.test.ts | 148 ------------------ ...stem-proxy-channel-responder.injectable.ts | 17 +- ...itial-value-channel-listener.injectable.ts | 28 ++-- .../app-paths/setup-app-paths.injectable.ts | 7 +- .../active-helm-repositories.injectable.ts | 5 +- .../add-helm-repository.injectable.ts | 3 +- .../remove-helm-repository.injectable.ts | 3 +- .../test-utils/get-application-builder.tsx | 9 +- .../restart-and-install-update.injectable.ts | 5 +- ...-that-root-frame-is-rendered.injectable.ts | 9 +- src/renderer/navigation/events.ts | 12 +- .../navigation-channel-listener.injectable.ts | 10 +- ...ist-message-channel-listener.injectable.ts | 8 +- .../enlist-message-channel-listener.test.ts | 4 +- ...ist-request-channel-listener.injectable.ts | 19 --- .../start-listening-of-channels.injectable.ts | 4 +- .../channel/message-to-channel.injectable.ts | 12 +- .../utils/channel/message-to-channel.test.ts | 57 ------- .../request-from-channel.injectable.ts | 12 +- .../channel/request-from-channel.test.ts | 121 -------------- .../utils/channel/send-to-main.injectable.ts | 9 +- .../resolve-system-proxy.injectable.ts | 3 +- ...nitial-values-for-sync-boxes.injectable.ts | 3 +- .../channel-fakes/override-channels.ts | 21 ++- .../override-messaging-from-main-to-window.ts | 100 ++++++------ .../override-messaging-from-window-to-main.ts | 34 +--- ...override-requesting-from-window-to-main.ts | 26 ++- 115 files changed, 949 insertions(+), 1568 deletions(-) delete mode 100644 src/common/app-paths/app-paths-channel.injectable.ts create mode 100644 src/common/app-paths/app-paths-channel.ts create mode 100644 src/common/application-update/restart-and-install-update-channel.ts delete mode 100644 src/common/application-update/restart-and-install-update-channel/restart-and-install-update-channel.injectable.ts delete mode 100644 src/common/front-end-routing/app-navigation-channel.injectable.ts create mode 100644 src/common/front-end-routing/app-navigation-channel.ts delete mode 100644 src/common/front-end-routing/cluster-frame-navigation-channel.injectable.ts create mode 100644 src/common/front-end-routing/cluster-frame-navigation-channel.ts rename src/common/helm/{add-helm-repository-channel.injectable.ts => add-helm-repository-channel.ts} (50%) delete mode 100644 src/common/helm/get-active-helm-repositories-channel.injectable.ts create mode 100644 src/common/helm/get-active-helm-repositories-channel.ts delete mode 100644 src/common/helm/remove-helm-repository-channel.injectable.ts create mode 100644 src/common/helm/remove-helm-repository-channel.ts delete mode 100644 src/common/root-frame-rendered-channel/root-frame-rendered-channel.injectable.ts create mode 100644 src/common/root-frame/root-frame-rendered-channel.ts delete mode 100644 src/common/utils/channel/enlist-request-channel-listener-injection-token.ts delete mode 100644 src/common/utils/channel/listening-of-channels.injectable.ts create mode 100644 src/common/utils/channel/listening-on-message-channels.injectable.ts delete mode 100644 src/common/utils/channel/message-channel-injection-token.ts delete mode 100644 src/common/utils/channel/request-channel-injection-token.ts delete mode 100644 src/common/utils/resolve-system-proxy/resolve-system-proxy-channel.injectable.ts create mode 100644 src/common/utils/resolve-system-proxy/resolve-system-proxy-channel.ts create mode 100644 src/common/utils/sync-box/channel-listener.injectable.ts create mode 100644 src/common/utils/sync-box/channels.ts create mode 100644 src/common/utils/sync-box/handler.injectable.ts delete mode 100644 src/common/utils/sync-box/sync-box-channel-listener.injectable.ts delete mode 100644 src/common/utils/sync-box/sync-box-channel.injectable.ts delete mode 100644 src/common/utils/sync-box/sync-box-initial-value-channel.injectable.ts delete mode 100644 src/common/utils/tentative-parse-json.ts delete mode 100644 src/common/utils/tentative-stringify-json.ts delete mode 100644 src/features/cluster/delete-dialog/common/clear-as-deleting-channel.injectable.ts create mode 100644 src/features/cluster/delete-dialog/common/clear-as-deleting-channel.ts delete mode 100644 src/features/cluster/delete-dialog/common/delete-channel.injectable.ts create mode 100644 src/features/cluster/delete-dialog/common/delete-channel.ts delete mode 100644 src/features/cluster/delete-dialog/common/set-as-deleting-channel.injectable.ts create mode 100644 src/features/cluster/delete-dialog/common/set-as-deleting-channel.ts delete mode 100644 src/features/cluster/delete-dialog/main/clear-as-deleteing-channel-handler.injectable.ts create mode 100644 src/features/cluster/delete-dialog/main/clear-as-deleting-channel-listener.injectable.ts delete mode 100644 src/features/cluster/delete-dialog/main/delete-channel-handler.injectable.ts create mode 100644 src/features/cluster/delete-dialog/main/delete-channel-listener.injectable.ts delete mode 100644 src/features/cluster/delete-dialog/main/set-as-deleteing-channel-handler.injectable.ts create mode 100644 src/features/cluster/delete-dialog/main/set-as-deleteing-channel-listener.injectable.ts create mode 100644 src/features/navigation/reload-page/common/channel.ts create mode 100644 src/features/navigation/reload-page/renderer/register-listener.global-override-for-injectable.ts create mode 100644 src/features/navigation/reload-page/renderer/register-listener.injectable.ts delete mode 100644 src/main/start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable.ts create mode 100644 src/main/start-main-application/runnables/root-frame-has-rendered/channel-listener.injectable.ts delete mode 100644 src/main/start-main-application/runnables/root-frame-rendered-channel-listener/root-frame-rendered-channel-listener.injectable.ts create mode 100644 src/main/utils/channel/channel-listeners/listener-tokens.ts create mode 100644 src/main/utils/channel/channel-listeners/listening-on-request-channels.injectable.ts delete mode 100644 src/main/utils/channel/channel-listeners/start-listening-of-channels.injectable.ts create mode 100644 src/main/utils/channel/channel-listeners/start-listening-on-channels.injectable.ts delete mode 100644 src/main/utils/channel/message-to-channel.test.ts delete mode 100644 src/renderer/utils/channel/channel-listeners/enlist-request-channel-listener.injectable.ts delete mode 100644 src/renderer/utils/channel/message-to-channel.test.ts delete mode 100644 src/renderer/utils/channel/request-from-channel.test.ts diff --git a/src/common/app-paths/app-paths-channel.injectable.ts b/src/common/app-paths/app-paths-channel.injectable.ts deleted file mode 100644 index 99fc738b41..0000000000 --- a/src/common/app-paths/app-paths-channel.injectable.ts +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import type { AppPaths } from "./app-path-injection-token"; -import type { RequestChannel } from "../utils/channel/request-channel-injection-token"; -import { messageChannelInjectionToken } from "../utils/channel/message-channel-injection-token"; - -export type AppPathsChannel = RequestChannel; - -const appPathsChannelInjectable = getInjectable({ - id: "app-paths-channel", - - instantiate: (): AppPathsChannel => ({ - id: "app-paths", - }), - - injectionToken: messageChannelInjectionToken, -}); - -export default appPathsChannelInjectable; diff --git a/src/common/app-paths/app-paths-channel.ts b/src/common/app-paths/app-paths-channel.ts new file mode 100644 index 0000000000..4502569d3b --- /dev/null +++ b/src/common/app-paths/app-paths-channel.ts @@ -0,0 +1,13 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { AppPaths } from "./app-path-injection-token"; +import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token"; + +export type AppPathsChannel = RequestChannel; + +export const appPathsChannel: AppPathsChannel = { + id: "app-paths", +}; + diff --git a/src/common/application-update/restart-and-install-update-channel.ts b/src/common/application-update/restart-and-install-update-channel.ts new file mode 100644 index 0000000000..1d45d6330f --- /dev/null +++ b/src/common/application-update/restart-and-install-update-channel.ts @@ -0,0 +1,11 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token"; + +export type RestartAndInstallUpdateChannel = MessageChannel; + +export const restartAndInstallUpdateChannel: RestartAndInstallUpdateChannel = { + id: "restart-and-install-update-channel", +}; diff --git a/src/common/application-update/restart-and-install-update-channel/restart-and-install-update-channel.injectable.ts b/src/common/application-update/restart-and-install-update-channel/restart-and-install-update-channel.injectable.ts deleted file mode 100644 index b6d811e101..0000000000 --- a/src/common/application-update/restart-and-install-update-channel/restart-and-install-update-channel.injectable.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import type { MessageChannel } from "../../utils/channel/message-channel-injection-token"; -import { messageChannelInjectionToken } from "../../utils/channel/message-channel-injection-token"; - -export type RestartAndInstallUpdateChannel = MessageChannel; - -const restartAndInstallUpdateChannel = getInjectable({ - id: "restart-and-install-update-channel", - - instantiate: (): RestartAndInstallUpdateChannel => ({ - id: "restart-and-install-update-channel", - }), - - injectionToken: messageChannelInjectionToken, -}); - -export default restartAndInstallUpdateChannel; diff --git a/src/common/application-update/selected-update-channel/selected-update-channel.injectable.ts b/src/common/application-update/selected-update-channel/selected-update-channel.injectable.ts index 8ca31e00aa..d11778b9bd 100644 --- a/src/common/application-update/selected-update-channel/selected-update-channel.injectable.ts +++ b/src/common/application-update/selected-update-channel/selected-update-channel.injectable.ts @@ -19,7 +19,7 @@ const selectedUpdateChannelInjectable = getInjectable({ instantiate: (di): SelectedUpdateChannel => { const defaultUpdateChannel = di.inject(defaultUpdateChannelInjectable); - const state = observable.box(); + const state = observable.box(undefined, { deep: false }); return { value: computed(() => state.get() ?? defaultUpdateChannel.get()), diff --git a/src/common/front-end-routing/app-navigation-channel.injectable.ts b/src/common/front-end-routing/app-navigation-channel.injectable.ts deleted file mode 100644 index 869fbfdecd..0000000000 --- a/src/common/front-end-routing/app-navigation-channel.injectable.ts +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import { IpcRendererNavigationEvents } from "../../renderer/navigation/events"; -import type { MessageChannel } from "../utils/channel/message-channel-injection-token"; -import { messageChannelInjectionToken } from "../utils/channel/message-channel-injection-token"; - -export type AppNavigationChannel = MessageChannel; - -const appNavigationChannelInjectable = getInjectable({ - id: "app-navigation-channel", - - instantiate: (): AppNavigationChannel => ({ - id: IpcRendererNavigationEvents.NAVIGATE_IN_APP, - }), - - injectionToken: messageChannelInjectionToken, -}); - -export default appNavigationChannelInjectable; diff --git a/src/common/front-end-routing/app-navigation-channel.ts b/src/common/front-end-routing/app-navigation-channel.ts new file mode 100644 index 0000000000..e0b881eff9 --- /dev/null +++ b/src/common/front-end-routing/app-navigation-channel.ts @@ -0,0 +1,12 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { IpcRendererNavigationEvents } from "../../renderer/navigation/events"; +import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token"; + +export type AppNavigationChannel = MessageChannel; + +export const appNavigationChannel: AppNavigationChannel = { + id: IpcRendererNavigationEvents.NAVIGATE_IN_APP, +}; diff --git a/src/common/front-end-routing/cluster-frame-navigation-channel.injectable.ts b/src/common/front-end-routing/cluster-frame-navigation-channel.injectable.ts deleted file mode 100644 index 596bd6d351..0000000000 --- a/src/common/front-end-routing/cluster-frame-navigation-channel.injectable.ts +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import { IpcRendererNavigationEvents } from "../../renderer/navigation/events"; -import type { MessageChannel } from "../utils/channel/message-channel-injection-token"; -import { messageChannelInjectionToken } from "../utils/channel/message-channel-injection-token"; - -export type ClusterFrameNavigationChannel = MessageChannel; - -const clusterFrameNavigationChannelInjectable = getInjectable({ - id: "cluster-frame-navigation-channel", - - instantiate: (): ClusterFrameNavigationChannel => ({ - id: IpcRendererNavigationEvents.NAVIGATE_IN_CLUSTER, - }), - - injectionToken: messageChannelInjectionToken, -}); - -export default clusterFrameNavigationChannelInjectable; diff --git a/src/common/front-end-routing/cluster-frame-navigation-channel.ts b/src/common/front-end-routing/cluster-frame-navigation-channel.ts new file mode 100644 index 0000000000..9d9a1904af --- /dev/null +++ b/src/common/front-end-routing/cluster-frame-navigation-channel.ts @@ -0,0 +1,12 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { IpcRendererNavigationEvents } from "../../renderer/navigation/events"; +import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token"; + +export type ClusterFrameNavigationChannel = MessageChannel; + +export const clusterFrameNavigationChannel: ClusterFrameNavigationChannel = { + id: IpcRendererNavigationEvents.NAVIGATE_IN_CLUSTER, +}; diff --git a/src/common/fs/exec-file.injectable.ts b/src/common/fs/exec-file.injectable.ts index 15d0ad48dc..8db31c602f 100644 --- a/src/common/fs/exec-file.injectable.ts +++ b/src/common/fs/exec-file.injectable.ts @@ -5,22 +5,33 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { ExecFileOptions } from "child_process"; import { execFile } from "child_process"; -import { promisify } from "util"; +import type { AsyncResult } from "../utils/async-result"; -export type ExecFile = (filePath: string, args: string[], options: ExecFileOptions) => Promise; +export interface ExecFile { + (filePath: string, args: string[], options: ExecFileOptions): Promise>; +} const execFileInjectable = getInjectable({ id: "exec-file", - instantiate: (): ExecFile => { - const asyncExecFile = promisify(execFile); - - return async (filePath, args, options) => { - const result = await asyncExecFile(filePath, args, options); - - return result.stdout; - }; - }, + instantiate: (): ExecFile => (filePath, args, options) => new Promise((resolve) => { + execFile(filePath, args, options, (error, stdout, stderr) => { + if (error) { + resolve({ + callWasSuccessful: false, + error: { + error, + stderr, + }, + }); + } else { + resolve({ + callWasSuccessful: true, + response: stdout, + }); + } + }); + }), causesSideEffects: true, }); diff --git a/src/common/helm/add-helm-repository-channel.injectable.ts b/src/common/helm/add-helm-repository-channel.ts similarity index 50% rename from src/common/helm/add-helm-repository-channel.injectable.ts rename to src/common/helm/add-helm-repository-channel.ts index 0bc10564ad..44471fe426 100644 --- a/src/common/helm/add-helm-repository-channel.injectable.ts +++ b/src/common/helm/add-helm-repository-channel.ts @@ -2,22 +2,12 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getInjectable } from "@ogre-tools/injectable"; import type { HelmRepo } from "./helm-repo"; -import type { RequestChannel } from "../utils/channel/request-channel-injection-token"; -import { requestChannelInjectionToken } from "../utils/channel/request-channel-injection-token"; import type { AsyncResult } from "../utils/async-result"; +import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token"; export type AddHelmRepositoryChannel = RequestChannel>; -const addHelmRepositoryChannelInjectable = getInjectable({ +export const addHelmRepositoryChannel: AddHelmRepositoryChannel = { id: "add-helm-repository-channel", - - instantiate: (): AddHelmRepositoryChannel => ({ - id: "add-helm-repository-channel", - }), - - injectionToken: requestChannelInjectionToken, -}); - -export default addHelmRepositoryChannelInjectable; +}; diff --git a/src/common/helm/get-active-helm-repositories-channel.injectable.ts b/src/common/helm/get-active-helm-repositories-channel.injectable.ts deleted file mode 100644 index ac7355ace7..0000000000 --- a/src/common/helm/get-active-helm-repositories-channel.injectable.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import type { RequestChannel } from "../utils/channel/request-channel-injection-token"; -import type { HelmRepo } from "./helm-repo"; -import { requestChannelInjectionToken } from "../utils/channel/request-channel-injection-token"; -import type { AsyncResult } from "../utils/async-result"; - -export type GetHelmRepositoriesChannel = RequestChannel>; - -const getActiveHelmRepositoriesChannelInjectable = getInjectable({ - id: "get-active-helm-repositories-channel", - - instantiate: (): GetHelmRepositoriesChannel => ({ - id: "get-helm-active-list-repositories", - }), - - injectionToken: requestChannelInjectionToken, -}); - -export default getActiveHelmRepositoriesChannelInjectable; diff --git a/src/common/helm/get-active-helm-repositories-channel.ts b/src/common/helm/get-active-helm-repositories-channel.ts new file mode 100644 index 0000000000..26720e9a5f --- /dev/null +++ b/src/common/helm/get-active-helm-repositories-channel.ts @@ -0,0 +1,13 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { HelmRepo } from "./helm-repo"; +import type { AsyncResult } from "../utils/async-result"; +import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token"; + +export type GetActiveHelmRepositoriesChannel = RequestChannel>; + +export const getActiveHelmRepositoriesChannel: GetActiveHelmRepositoriesChannel = { + id: "get-helm-active-list-repositories", +}; diff --git a/src/common/helm/remove-helm-repository-channel.injectable.ts b/src/common/helm/remove-helm-repository-channel.injectable.ts deleted file mode 100644 index eddecb1ccd..0000000000 --- a/src/common/helm/remove-helm-repository-channel.injectable.ts +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import type { HelmRepo } from "./helm-repo"; -import type { RequestChannel } from "../utils/channel/request-channel-injection-token"; -import { requestChannelInjectionToken } from "../utils/channel/request-channel-injection-token"; - -export type RemoveHelmRepositoryChannel = RequestChannel; - -const removeHelmRepositoryChannelInjectable = getInjectable({ - id: "remove-helm-repository-channel", - - instantiate: (): RemoveHelmRepositoryChannel => ({ - id: "remove-helm-repository-channel", - }), - - injectionToken: requestChannelInjectionToken, -}); - -export default removeHelmRepositoryChannelInjectable; diff --git a/src/common/helm/remove-helm-repository-channel.ts b/src/common/helm/remove-helm-repository-channel.ts new file mode 100644 index 0000000000..7eda160159 --- /dev/null +++ b/src/common/helm/remove-helm-repository-channel.ts @@ -0,0 +1,13 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { AsyncResult } from "../utils/async-result"; +import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token"; +import type { HelmRepo } from "./helm-repo"; + +export type RemoveHelmRepositoryChannel = RequestChannel>; + +export const removeHelmRepositoryChannel: RemoveHelmRepositoryChannel = { + id: "remove-helm-repository-channel", +}; diff --git a/src/common/root-frame-rendered-channel/root-frame-rendered-channel.injectable.ts b/src/common/root-frame-rendered-channel/root-frame-rendered-channel.injectable.ts deleted file mode 100644 index a7787c6cc4..0000000000 --- a/src/common/root-frame-rendered-channel/root-frame-rendered-channel.injectable.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import type { MessageChannel } from "../utils/channel/message-channel-injection-token"; -import { messageChannelInjectionToken } from "../utils/channel/message-channel-injection-token"; - -export type RootFrameRenderedChannel = MessageChannel; - -const rootFrameRenderedChannelInjectable = getInjectable({ - id: "root-frame-rendered-channel", - - instantiate: (): RootFrameRenderedChannel => ({ - id: "root-frame-rendered", - }), - - injectionToken: messageChannelInjectionToken, -}); - -export default rootFrameRenderedChannelInjectable; diff --git a/src/common/root-frame/root-frame-rendered-channel.ts b/src/common/root-frame/root-frame-rendered-channel.ts new file mode 100644 index 0000000000..060ae8735c --- /dev/null +++ b/src/common/root-frame/root-frame-rendered-channel.ts @@ -0,0 +1,11 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token"; + +export type RootFrameHasRenderedChannel = MessageChannel; + +export const rootFrameHasRenderedChannel: RootFrameHasRenderedChannel = { + id: "root-frame-rendered", +}; diff --git a/src/common/utils/channel/channel.test.ts b/src/common/utils/channel/channel.test.ts index c5f52c0874..9a361b6770 100644 --- a/src/common/utils/channel/channel.test.ts +++ b/src/common/utils/channel/channel.test.ts @@ -4,31 +4,31 @@ */ import type { DiContainer } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable"; -import type { MessageToChannel } from "./message-to-channel-injection-token"; -import { messageToChannelInjectionToken } from "./message-to-channel-injection-token"; +import type { SendMessageToChannel } from "./message-to-channel-injection-token"; +import { sendMessageToChannelInjectionToken } from "./message-to-channel-injection-token"; import type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; import type { LensWindow } from "../../../main/start-main-application/lens-window/application-window/create-lens-window.injectable"; +import type { MessageChannel } from "./message-channel-listener-injection-token"; import { messageChannelListenerInjectionToken } from "./message-channel-listener-injection-token"; -import type { MessageChannel } from "./message-channel-injection-token"; import type { RequestFromChannel } from "./request-from-channel-injection-token"; import { requestFromChannelInjectionToken } from "./request-from-channel-injection-token"; -import type { RequestChannel } from "./request-channel-injection-token"; -import { requestChannelListenerInjectionToken } from "./request-channel-listener-injection-token"; +import type { RequestChannel } from "./request-channel-listener-injection-token"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; import { getPromiseStatus } from "../../test-utils/get-promise-status"; import { runInAction } from "mobx"; +import type { RequestChannelHandler } from "../../../main/utils/channel/channel-listeners/listener-tokens"; +import { getRequestChannelListenerInjectable } from "../../../main/utils/channel/channel-listeners/listener-tokens"; type TestMessageChannel = MessageChannel; type TestRequestChannel = RequestChannel; describe("channel", () => { describe("messaging from main to renderer, given listener for channel in a window and application has started", () => { - let testMessageChannel: TestMessageChannel; let messageListenerInWindowMock: jest.Mock; let mainDi: DiContainer; - let messageToChannel: MessageToChannel; + let messageToChannel: SendMessageToChannel; let builder: ApplicationBuilder; beforeEach(async () => { @@ -39,24 +39,17 @@ describe("channel", () => { const testChannelListenerInTestWindowInjectable = getInjectable({ id: "test-channel-listener-in-test-window", - instantiate: (di) => ({ - channel: di.inject(testMessageChannelInjectable), + instantiate: () => ({ + channel: testMessageChannel, handler: messageListenerInWindowMock, }), injectionToken: messageChannelListenerInjectionToken, }); - builder.beforeApplicationStart((mainDi) => { - runInAction(() => { - mainDi.register(testMessageChannelInjectable); - }); - }); - builder.beforeWindowStart((windowDi) => { runInAction(() => { windowDi.register(testChannelListenerInTestWindowInjectable); - windowDi.register(testMessageChannelInjectable); }); }); @@ -64,8 +57,7 @@ describe("channel", () => { await builder.startHidden(); - testMessageChannel = mainDi.inject(testMessageChannelInjectable); - messageToChannel = mainDi.inject(messageToChannelInjectionToken); + messageToChannel = mainDi.inject(sendMessageToChannelInjectionToken); }); describe("given window is started", () => { @@ -109,9 +101,8 @@ describe("channel", () => { }); describe("messaging from renderer to main, given listener for channel in a main and application has started", () => { - let testMessageChannel: TestMessageChannel; let messageListenerInMainMock: jest.Mock; - let messageToChannel: MessageToChannel; + let messageToChannel: SendMessageToChannel; beforeEach(async () => { const applicationBuilder = getApplicationBuilder(); @@ -121,9 +112,8 @@ describe("channel", () => { const testChannelListenerInMainInjectable = getInjectable({ id: "test-channel-listener-in-main", - instantiate: (di) => ({ - channel: di.inject(testMessageChannelInjectable), - + instantiate: () => ({ + channel: testMessageChannel, handler: messageListenerInMainMock, }), @@ -133,13 +123,6 @@ describe("channel", () => { applicationBuilder.beforeApplicationStart((mainDi) => { runInAction(() => { mainDi.register(testChannelListenerInMainInjectable); - mainDi.register(testMessageChannelInjectable); - }); - }); - - applicationBuilder.beforeWindowStart((windowDi) => { - runInAction(() => { - windowDi.register(testMessageChannelInjectable); }); }); @@ -147,8 +130,7 @@ describe("channel", () => { const windowDi = applicationBuilder.applicationWindow.only.di; - testMessageChannel = windowDi.inject(testMessageChannelInjectable); - messageToChannel = windowDi.inject(messageToChannelInjectionToken); + messageToChannel = windowDi.inject(sendMessageToChannelInjectionToken); }); it("when sending message, triggers listener in main", () => { @@ -159,8 +141,7 @@ describe("channel", () => { }); describe("requesting from main in renderer, given listener for channel in a main and application has started", () => { - let testRequestChannel: TestRequestChannel; - let requestListenerInMainMock: AsyncFnMock<(arg: string) => string>; + let requestListenerInMainMock: AsyncFnMock>; let requestFromChannel: RequestFromChannel; beforeEach(async () => { @@ -168,28 +149,14 @@ describe("channel", () => { requestListenerInMainMock = asyncFn(); - const testChannelListenerInMainInjectable = getInjectable({ - id: "test-channel-listener-in-main", - - instantiate: (di) => ({ - channel: di.inject(testRequestChannelInjectable), - - handler: requestListenerInMainMock, - }), - - injectionToken: requestChannelListenerInjectionToken, + const testChannelListenerInMainInjectable = getRequestChannelListenerInjectable({ + channel: testRequestChannel, + handler: () => requestListenerInMainMock, }); applicationBuilder.beforeApplicationStart((mainDi) => { runInAction(() => { mainDi.register(testChannelListenerInMainInjectable); - mainDi.register(testRequestChannelInjectable); - }); - }); - - applicationBuilder.beforeWindowStart((windowDi) => { - runInAction(() => { - windowDi.register(testRequestChannelInjectable); }); }); @@ -197,8 +164,6 @@ describe("channel", () => { const windowDi = applicationBuilder.applicationWindow.only.di; - testRequestChannel = windowDi.inject(testRequestChannelInjectable); - requestFromChannel = windowDi.inject( requestFromChannelInjectionToken, ); @@ -230,21 +195,37 @@ describe("channel", () => { }); }); }); + + it("when registering multiple handlers for the same channel, throws", async () => { + const applicationBuilder = getApplicationBuilder(); + + const testChannelListenerInMainInjectable = getRequestChannelListenerInjectable({ + channel: testRequestChannel, + handler: () => () => "some-value", + }); + const testChannelListenerInMain2Injectable = getRequestChannelListenerInjectable({ + channel: testRequestChannel, + handler: () => () => "some-other-value", + }); + + testChannelListenerInMain2Injectable.id += "2"; + + applicationBuilder.beforeApplicationStart((mainDi) => { + runInAction(() => { + mainDi.register(testChannelListenerInMainInjectable); + mainDi.register(testChannelListenerInMain2Injectable); + }); + }); + + await expect(applicationBuilder.render()).rejects.toThrow('Tried to register a multiple channel handlers for "some-request-channel-id", only one handler is supported for a request channel.'); + }); }); -const testMessageChannelInjectable = getInjectable({ - id: "some-message-test-channel", +const testMessageChannel: TestMessageChannel = { + id: "some-message-channel-id", +}; - instantiate: (): TestMessageChannel => ({ - id: "some-message-channel-id", - }), -}); - -const testRequestChannelInjectable = getInjectable({ - id: "some-request-test-channel", - - instantiate: (): TestRequestChannel => ({ - id: "some-request-channel-id", - }), -}); +const testRequestChannel: TestRequestChannel = { + id: "some-request-channel-id", +}; diff --git a/src/common/utils/channel/enlist-message-channel-listener-injection-token.ts b/src/common/utils/channel/enlist-message-channel-listener-injection-token.ts index fa6983e130..34f62d51d5 100644 --- a/src/common/utils/channel/enlist-message-channel-listener-injection-token.ts +++ b/src/common/utils/channel/enlist-message-channel-listener-injection-token.ts @@ -3,14 +3,11 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectionToken } from "@ogre-tools/injectable"; -import type { MessageChannel } from "./message-channel-injection-token"; -import type { MessageChannelListener } from "./message-channel-listener-injection-token"; +import type { Disposer } from "../disposer"; +import type { MessageChannel, MessageChannelListener } from "./message-channel-listener-injection-token"; -export type EnlistMessageChannelListener = < - TChannel extends MessageChannel, ->(listener: MessageChannelListener) => () => void; +export type EnlistMessageChannelListener = (listener: MessageChannelListener>) => Disposer; -export const enlistMessageChannelListenerInjectionToken = - getInjectionToken({ - id: "enlist-message-channel-listener", - }); +export const enlistMessageChannelListenerInjectionToken = getInjectionToken({ + id: "enlist-message-channel-listener", +}); diff --git a/src/common/utils/channel/enlist-request-channel-listener-injection-token.ts b/src/common/utils/channel/enlist-request-channel-listener-injection-token.ts deleted file mode 100644 index f87082c466..0000000000 --- a/src/common/utils/channel/enlist-request-channel-listener-injection-token.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectionToken } from "@ogre-tools/injectable"; -import type { RequestChannel } from "./request-channel-injection-token"; -import type { RequestChannelListener } from "./request-channel-listener-injection-token"; - -export type EnlistRequestChannelListener = < - TChannel extends RequestChannel, ->(listener: RequestChannelListener) => () => void; - -export const enlistRequestChannelListenerInjectionToken = - getInjectionToken({ - id: "enlist-request-channel-listener", - }); diff --git a/src/common/utils/channel/listening-of-channels.injectable.ts b/src/common/utils/channel/listening-of-channels.injectable.ts deleted file mode 100644 index 30fee42fb9..0000000000 --- a/src/common/utils/channel/listening-of-channels.injectable.ts +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import { getStartableStoppable } from "../get-startable-stoppable"; -import { disposer } from "../index"; -import { messageChannelListenerInjectionToken } from "./message-channel-listener-injection-token"; -import { requestChannelListenerInjectionToken } from "./request-channel-listener-injection-token"; -import { enlistMessageChannelListenerInjectionToken } from "./enlist-message-channel-listener-injection-token"; -import { enlistRequestChannelListenerInjectionToken } from "./enlist-request-channel-listener-injection-token"; - -const listeningOfChannelsInjectable = getInjectable({ - id: "listening-of-channels", - - instantiate: (di) => { - const enlistMessageChannelListener = di.inject(enlistMessageChannelListenerInjectionToken); - const enlistRequestChannelListener = di.inject(enlistRequestChannelListenerInjectionToken); - const messageChannelListeners = di.injectMany(messageChannelListenerInjectionToken); - const requestChannelListeners = di.injectMany(requestChannelListenerInjectionToken); - - return getStartableStoppable("listening-of-channels", () => { - const messageChannelDisposers = messageChannelListeners.map(enlistMessageChannelListener); - const requestChannelDisposers = requestChannelListeners.map(enlistRequestChannelListener); - - return disposer(...messageChannelDisposers, ...requestChannelDisposers); - }); - }, -}); - - -export default listeningOfChannelsInjectable; diff --git a/src/common/utils/channel/listening-on-message-channels.injectable.ts b/src/common/utils/channel/listening-on-message-channels.injectable.ts new file mode 100644 index 0000000000..afe0c08f24 --- /dev/null +++ b/src/common/utils/channel/listening-on-message-channels.injectable.ts @@ -0,0 +1,25 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { getStartableStoppable } from "../get-startable-stoppable"; +import { disposer } from "../index"; +import { messageChannelListenerInjectionToken } from "./message-channel-listener-injection-token"; +import { enlistMessageChannelListenerInjectionToken } from "./enlist-message-channel-listener-injection-token"; + +const listeningOnMessageChannelsInjectable = getInjectable({ + id: "listening-on-message-channels", + + instantiate: (di) => { + const enlistMessageChannelListener = di.inject(enlistMessageChannelListenerInjectionToken); + const messageChannelListeners = di.injectMany(messageChannelListenerInjectionToken); + + return getStartableStoppable("listening-on-channels", () => ( + disposer(messageChannelListeners.map(enlistMessageChannelListener)) + )); + }, +}); + + +export default listeningOnMessageChannelsInjectable; diff --git a/src/common/utils/channel/message-channel-injection-token.ts b/src/common/utils/channel/message-channel-injection-token.ts deleted file mode 100644 index 3141acedf3..0000000000 --- a/src/common/utils/channel/message-channel-injection-token.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import { getInjectionToken } from "@ogre-tools/injectable"; -import type { JsonValue } from "type-fest"; - -export interface MessageChannel { - id: string; - _messageSignature?: Message; -} - -export const messageChannelInjectionToken = getInjectionToken>({ - id: "message-channel", -}); diff --git a/src/common/utils/channel/message-channel-listener-injection-token.ts b/src/common/utils/channel/message-channel-listener-injection-token.ts index 8879e19013..5bfc45a82d 100644 --- a/src/common/utils/channel/message-channel-listener-injection-token.ts +++ b/src/common/utils/channel/message-channel-listener-injection-token.ts @@ -2,17 +2,50 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getInjectionToken } from "@ogre-tools/injectable"; -import type { SetRequired } from "type-fest"; -import type { MessageChannel } from "./message-channel-injection-token"; +import type { DiContainerForInjection } from "@ogre-tools/injectable"; +import { getInjectable, getInjectionToken } from "@ogre-tools/injectable"; -export interface MessageChannelListener> { - channel: TChannel; - handler: (value: SetRequired["_messageSignature"]) => void; +export interface MessageChannel { + id: string; + _messageSignature?: Message; // only used to mark `Message` as used } -export const messageChannelListenerInjectionToken = getInjectionToken>>( +export type MessageChannelHandler = Channel extends MessageChannel + ? (message: Message) => void + : never; + +export interface MessageChannelListener { + channel: Channel; + handler: MessageChannelHandler; +} + +export const messageChannelListenerInjectionToken = getInjectionToken>>( { id: "message-channel-listener", }, ); + +export interface GetMessageChannelListenerInfo< + Channel extends MessageChannel, + Message, +> { + id: string; + channel: Channel; + handler: (di: DiContainerForInjection) => MessageChannelHandler; + causesSideEffects?: boolean; +} + +export function getMessageChannelListenerInjectable< + Channel extends MessageChannel, + Message, +>(info: GetMessageChannelListenerInfo) { + return getInjectable({ + id: `${info.channel.id}-listener-${info.id}`, + instantiate: (di) => ({ + channel: info.channel, + handler: info.handler(di), + }), + injectionToken: messageChannelListenerInjectionToken, + causesSideEffects: info.causesSideEffects, + }); +} diff --git a/src/common/utils/channel/message-to-channel-injection-token.ts b/src/common/utils/channel/message-to-channel-injection-token.ts index 8c5f03b9ee..d179ab9870 100644 --- a/src/common/utils/channel/message-to-channel-injection-token.ts +++ b/src/common/utils/channel/message-to-channel-injection-token.ts @@ -3,21 +3,13 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectionToken } from "@ogre-tools/injectable"; -import type { SetRequired } from "type-fest"; -import type { MessageChannel } from "./message-channel-injection-token"; +import type { MessageChannel } from "./message-channel-listener-injection-token"; -export interface MessageToChannel { - , TMessage extends void>( - channel: TChannel, - ): void; - - >( - channel: TChannel, - message: SetRequired["_messageSignature"], - ): void; +export interface SendMessageToChannel { + (channel: MessageChannel): void; + (channel: MessageChannel, message: Message): void; } -export const messageToChannelInjectionToken = - getInjectionToken({ - id: "message-to-message-channel", - }); +export const sendMessageToChannelInjectionToken = getInjectionToken({ + id: "send-message-to-message-channel", +}); diff --git a/src/common/utils/channel/request-channel-injection-token.ts b/src/common/utils/channel/request-channel-injection-token.ts deleted file mode 100644 index 67044db878..0000000000 --- a/src/common/utils/channel/request-channel-injection-token.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import { getInjectionToken } from "@ogre-tools/injectable"; -import type { JsonValue } from "type-fest"; - -export interface RequestChannel< - Request extends JsonValue | void = void, - Response extends JsonValue | void = void, -> { - id: string; - _requestSignature?: Request; - _responseSignature?: Response; -} - -export const requestChannelInjectionToken = getInjectionToken>({ - id: "request-channel", -}); diff --git a/src/common/utils/channel/request-channel-listener-injection-token.ts b/src/common/utils/channel/request-channel-listener-injection-token.ts index 690b96d9dc..2f0b84a3cc 100644 --- a/src/common/utils/channel/request-channel-listener-injection-token.ts +++ b/src/common/utils/channel/request-channel-listener-injection-token.ts @@ -2,24 +2,9 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getInjectionToken } from "@ogre-tools/injectable"; -import type { SetRequired } from "type-fest"; -import type { RequestChannel } from "./request-channel-injection-token"; -export interface RequestChannelListener> { - channel: TChannel; - - handler: ( - request: SetRequired["_requestSignature"] - ) => - | SetRequired["_responseSignature"] - | Promise< - SetRequired["_responseSignature"] - >; +export interface RequestChannel { + id: string; + _requestSignature?: Request; // used only to mark `Request` as "used" + _responseSignature?: Response; // used only to mark `Response` as "used" } - -export const requestChannelListenerInjectionToken = getInjectionToken>>( - { - id: "request-channel-listener", - }, -); diff --git a/src/common/utils/channel/request-from-channel-injection-token.ts b/src/common/utils/channel/request-from-channel-injection-token.ts index f4d4fdbe0c..14e925f190 100644 --- a/src/common/utils/channel/request-from-channel-injection-token.ts +++ b/src/common/utils/channel/request-from-channel-injection-token.ts @@ -3,19 +3,13 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectionToken } from "@ogre-tools/injectable"; -import type { SetRequired } from "type-fest"; -import type { RequestChannel } from "./request-channel-injection-token"; +import type { RequestChannel } from "./request-channel-listener-injection-token"; -export type RequestFromChannel = < - TChannel extends RequestChannel, ->( - channel: TChannel, - ...request: TChannel["_requestSignature"] extends void - ? [] - : [SetRequired["_requestSignature"]] -) => Promise["_responseSignature"]>; +export interface RequestFromChannel { + (channel: RequestChannel, request: Request): Promise; + (channel: RequestChannel): Promise; +} -export const requestFromChannelInjectionToken = - getInjectionToken({ - id: "request-from-request-channel", - }); +export const requestFromChannelInjectionToken = getInjectionToken({ + id: "request-from-request-channel", +}); diff --git a/src/common/utils/disposer.ts b/src/common/utils/disposer.ts index 05a349ab4d..2949a7ae35 100644 --- a/src/common/utils/disposer.ts +++ b/src/common/utils/disposer.ts @@ -3,6 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ +import type { SingleOrMany } from "./types"; + export interface Disposer { @@ -17,9 +19,9 @@ export interface ExtendableDisposer extends Disposer { push(...vals: (Disposer | ExtendableDisposer | Disposable)[]): void; } -export function disposer(...items: (Disposer | Disposable | undefined | null)[]): ExtendableDisposer { +export function disposer(...items: SingleOrMany[]): ExtendableDisposer { return Object.assign(() => { - for (const item of items) { + for (const item of items.flat()) { if (!item) { continue; } diff --git a/src/common/utils/resolve-system-proxy/resolve-system-proxy-channel.injectable.ts b/src/common/utils/resolve-system-proxy/resolve-system-proxy-channel.injectable.ts deleted file mode 100644 index 5dd17ddc6a..0000000000 --- a/src/common/utils/resolve-system-proxy/resolve-system-proxy-channel.injectable.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import type { RequestChannel } from "../channel/request-channel-injection-token"; -import { requestChannelInjectionToken } from "../channel/request-channel-injection-token"; - -export type ResolveSystemProxyChannel = RequestChannel; - -const resolveSystemProxyChannelInjectable = getInjectable({ - id: "resolve-system-proxy-channel", - - instantiate: (): ResolveSystemProxyChannel => ({ - id: "resolve-system-proxy-channel", - }), - - injectionToken: requestChannelInjectionToken, -}); - -export default resolveSystemProxyChannelInjectable; diff --git a/src/common/utils/resolve-system-proxy/resolve-system-proxy-channel.ts b/src/common/utils/resolve-system-proxy/resolve-system-proxy-channel.ts new file mode 100644 index 0000000000..c823a8a8f9 --- /dev/null +++ b/src/common/utils/resolve-system-proxy/resolve-system-proxy-channel.ts @@ -0,0 +1,11 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { RequestChannel } from "../channel/request-channel-listener-injection-token"; + +export type ResolveSystemProxyChannel = RequestChannel; + +export const resolveSystemProxyChannel: ResolveSystemProxyChannel = { + id: "resolve-system-proxy-channel", +}; diff --git a/src/common/utils/sync-box/channel-listener.injectable.ts b/src/common/utils/sync-box/channel-listener.injectable.ts new file mode 100644 index 0000000000..a97d95d726 --- /dev/null +++ b/src/common/utils/sync-box/channel-listener.injectable.ts @@ -0,0 +1,15 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { syncBoxChannel } from "./channels"; +import { getMessageChannelListenerInjectable } from "../channel/message-channel-listener-injection-token"; +import syncBoxStateInjectable from "./sync-box-state.injectable"; + +const syncBoxChannelListenerInjectable = getMessageChannelListenerInjectable({ + id: "init", + channel: syncBoxChannel, + handler: (di) => ({ id, value }) => di.inject(syncBoxStateInjectable, id).set(value), +}); + +export default syncBoxChannelListenerInjectable; diff --git a/src/common/utils/sync-box/channels.ts b/src/common/utils/sync-box/channels.ts new file mode 100644 index 0000000000..4df0462dc3 --- /dev/null +++ b/src/common/utils/sync-box/channels.ts @@ -0,0 +1,21 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { MessageChannel } from "../channel/message-channel-listener-injection-token"; +import type { RequestChannel } from "../channel/request-channel-listener-injection-token"; + +export type SyncBoxChannel = MessageChannel<{ id: string; value: any }>; + +export const syncBoxChannel: SyncBoxChannel = { + id: "sync-box-channel", +}; + +export type SyncBoxInitialValueChannel = RequestChannel< + void, + { id: string; value: any }[] +>; + +export const syncBoxInitialValueChannel: SyncBoxInitialValueChannel = { + id: "sync-box-initial-value-channel", +}; diff --git a/src/common/utils/sync-box/create-sync-box.injectable.ts b/src/common/utils/sync-box/create-sync-box.injectable.ts index 1328106e24..4a01fe71a0 100644 --- a/src/common/utils/sync-box/create-sync-box.injectable.ts +++ b/src/common/utils/sync-box/create-sync-box.injectable.ts @@ -5,17 +5,17 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { IObservableValue } from "mobx"; import { computed } from "mobx"; -import syncBoxChannelInjectable from "./sync-box-channel.injectable"; -import { messageToChannelInjectionToken } from "../channel/message-to-channel-injection-token"; +import { syncBoxChannel } from "./channels"; +import { sendMessageToChannelInjectionToken } from "../channel/message-to-channel-injection-token"; import syncBoxStateInjectable from "./sync-box-state.injectable"; import type { SyncBox } from "./sync-box-injection-token"; +import { toJS } from "../toJS"; const createSyncBoxInjectable = getInjectable({ id: "create-sync-box", instantiate: (di) => { - const syncBoxChannel = di.inject(syncBoxChannelInjectable); - const messageToChannel = di.inject(messageToChannelInjectionToken); + const messageToChannel = di.inject(sendMessageToChannelInjectionToken); const getSyncBoxState = (id: string) => di.inject(syncBoxStateInjectable, id); return (id: string, initialValue: Value): SyncBox => { @@ -26,7 +26,7 @@ const createSyncBoxInjectable = getInjectable({ return { id, - value: computed(() => state.get()), + value: computed(() => toJS(state.get())), set: (value) => { state.set(value); diff --git a/src/common/utils/sync-box/handler.injectable.ts b/src/common/utils/sync-box/handler.injectable.ts new file mode 100644 index 0000000000..f520585474 --- /dev/null +++ b/src/common/utils/sync-box/handler.injectable.ts @@ -0,0 +1,19 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import type { MessageChannelHandler } from "../channel/message-channel-listener-injection-token"; +import type { SyncBoxChannel } from "./channels"; +import syncBoxStateInjectable from "./sync-box-state.injectable"; + +const syncBoxChannelHandlerInjectable = getInjectable({ + id: "sync-box-channel-handler", + instantiate: (di): MessageChannelHandler => { + const getSyncBoxState = (id: string) => di.inject(syncBoxStateInjectable, id); + + return ({ id, value }) => getSyncBoxState(id)?.set(value); + }, +}); + +export default syncBoxChannelHandlerInjectable; diff --git a/src/common/utils/sync-box/sync-box-channel-listener.injectable.ts b/src/common/utils/sync-box/sync-box-channel-listener.injectable.ts deleted file mode 100644 index b603c85997..0000000000 --- a/src/common/utils/sync-box/sync-box-channel-listener.injectable.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import type { SyncBoxChannel } from "./sync-box-channel.injectable"; -import syncBoxChannelInjectable from "./sync-box-channel.injectable"; -import syncBoxStateInjectable from "./sync-box-state.injectable"; -import type { MessageChannelListener } from "../channel/message-channel-listener-injection-token"; -import { messageChannelListenerInjectionToken } from "../channel/message-channel-listener-injection-token"; - -const syncBoxChannelListenerInjectable = getInjectable({ - id: "sync-box-channel-listener", - - instantiate: (di): MessageChannelListener => { - const getSyncBoxState = (id: string) => di.inject(syncBoxStateInjectable, id); - const channel = di.inject(syncBoxChannelInjectable); - - return { - channel, - - handler: ({ id, value }) => { - const target = getSyncBoxState(id); - - if (target) { - target.set(value); - } - }, - }; - }, - - injectionToken: messageChannelListenerInjectionToken, -}); - -export default syncBoxChannelListenerInjectable; diff --git a/src/common/utils/sync-box/sync-box-channel.injectable.ts b/src/common/utils/sync-box/sync-box-channel.injectable.ts deleted file mode 100644 index 9389a99867..0000000000 --- a/src/common/utils/sync-box/sync-box-channel.injectable.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import type { MessageChannel } from "../channel/message-channel-injection-token"; -import { messageChannelInjectionToken } from "../channel/message-channel-injection-token"; - -export type SyncBoxChannel = MessageChannel<{ id: string; value: any }>; - -const syncBoxChannelInjectable = getInjectable({ - id: "sync-box-channel", - - instantiate: (): SyncBoxChannel => ({ - id: "sync-box-channel", - }), - - injectionToken: messageChannelInjectionToken, -}); - -export default syncBoxChannelInjectable; diff --git a/src/common/utils/sync-box/sync-box-initial-value-channel.injectable.ts b/src/common/utils/sync-box/sync-box-initial-value-channel.injectable.ts deleted file mode 100644 index 89374c3565..0000000000 --- a/src/common/utils/sync-box/sync-box-initial-value-channel.injectable.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import type { RequestChannel } from "../channel/request-channel-injection-token"; -import { requestChannelInjectionToken } from "../channel/request-channel-injection-token"; - -export type SyncBoxInitialValueChannel = RequestChannel< - void, - { id: string; value: any }[] ->; - -const syncBoxInitialValueChannelInjectable = getInjectable({ - id: "sync-box-initial-value-channel", - - instantiate: (): SyncBoxInitialValueChannel => ({ - id: "sync-box-initial-value-channel", - }), - - injectionToken: requestChannelInjectionToken, -}); - -export default syncBoxInitialValueChannelInjectable; diff --git a/src/common/utils/tentative-parse-json.ts b/src/common/utils/tentative-parse-json.ts deleted file mode 100644 index a0cb089a74..0000000000 --- a/src/common/utils/tentative-parse-json.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { pipeline } from "@ogre-tools/fp"; -import { defaultTo } from "lodash/fp"; -import { withErrorSuppression } from "./with-error-suppression/with-error-suppression"; - -export const tentativeParseJson = (toBeParsed: any) => pipeline( - toBeParsed, - withErrorSuppression(JSON.parse), - defaultTo(toBeParsed), -); - - diff --git a/src/common/utils/tentative-stringify-json.ts b/src/common/utils/tentative-stringify-json.ts deleted file mode 100644 index dc7206be7c..0000000000 --- a/src/common/utils/tentative-stringify-json.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { pipeline } from "@ogre-tools/fp"; -import { defaultTo } from "lodash/fp"; -import { withErrorSuppression } from "./with-error-suppression/with-error-suppression"; - -export const tentativeStringifyJson = (toBeParsed: any) => pipeline( - toBeParsed, - withErrorSuppression(JSON.stringify), - defaultTo(toBeParsed), -); - - diff --git a/src/common/vars/build-semantic-version.injectable.ts b/src/common/vars/build-semantic-version.injectable.ts index a41efb0bd7..2a49327480 100644 --- a/src/common/vars/build-semantic-version.injectable.ts +++ b/src/common/vars/build-semantic-version.injectable.ts @@ -7,7 +7,7 @@ import { getInjectionToken } from "@ogre-tools/injectable"; import { SemVer } from "semver"; import type { InitializableState } from "../initializable-state/create"; import { createInitializableState } from "../initializable-state/create"; -import type { RequestChannel } from "../utils/channel/request-channel-injection-token"; +import type { RequestChannel } from "../utils/channel/request-channel-listener-injection-token"; export const buildVersionInjectionToken = getInjectionToken>({ id: "build-version-token", diff --git a/src/features/application-update/selection-of-update-stability.test.ts b/src/features/application-update/selection-of-update-stability.test.ts index d948573dcd..bfa6f0680d 100644 --- a/src/features/application-update/selection-of-update-stability.test.ts +++ b/src/features/application-update/selection-of-update-stability.test.ts @@ -222,7 +222,7 @@ describe("selection of update stability", () => { it('given user changes update channel to "alpha", when user would close the application, installs the update for being stable enough', () => { selectedUpdateChannel.setValue(updateChannels.alpha.id); - expect(setUpdateOnQuitMock).toHaveBeenLastCalledWith(false); + expect(setUpdateOnQuitMock).toHaveBeenLastCalledWith(true); }); }); }); diff --git a/src/features/cluster/delete-dialog/common/clear-as-deleting-channel.injectable.ts b/src/features/cluster/delete-dialog/common/clear-as-deleting-channel.injectable.ts deleted file mode 100644 index d45fecb3c2..0000000000 --- a/src/features/cluster/delete-dialog/common/clear-as-deleting-channel.injectable.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import type { ClusterId } from "../../../../common/cluster-types"; -import type { RequestChannel } from "../../../../common/utils/channel/request-channel-injection-token"; -import { requestChannelInjectionToken } from "../../../../common/utils/channel/request-channel-injection-token"; - -export type ClearClusterAsDeletingChannel = RequestChannel; - -const clearClusterAsDeletingChannelInjectable = getInjectable({ - id: "clear-cluster-as-deleting-channel", - instantiate: (): ClearClusterAsDeletingChannel => ({ - id: "clear-cluster-as-deleting", - }), - injectionToken: requestChannelInjectionToken, -}); - -export default clearClusterAsDeletingChannelInjectable; diff --git a/src/features/cluster/delete-dialog/common/clear-as-deleting-channel.ts b/src/features/cluster/delete-dialog/common/clear-as-deleting-channel.ts new file mode 100644 index 0000000000..bf33a23165 --- /dev/null +++ b/src/features/cluster/delete-dialog/common/clear-as-deleting-channel.ts @@ -0,0 +1,12 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { ClusterId } from "../../../../common/cluster-types"; +import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; + +export type ClearClusterAsDeletingChannel = RequestChannel; + +export const clearClusterAsDeletingChannel: ClearClusterAsDeletingChannel = { + id: "clear-cluster-as-deleting", +}; diff --git a/src/features/cluster/delete-dialog/common/delete-channel.injectable.ts b/src/features/cluster/delete-dialog/common/delete-channel.injectable.ts deleted file mode 100644 index 9242b062c5..0000000000 --- a/src/features/cluster/delete-dialog/common/delete-channel.injectable.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import type { ClusterId } from "../../../../common/cluster-types"; -import type { RequestChannel } from "../../../../common/utils/channel/request-channel-injection-token"; -import { requestChannelInjectionToken } from "../../../../common/utils/channel/request-channel-injection-token"; - -export type DeleteClusterChannel = RequestChannel; - -const deleteClusterChannelInjectable = getInjectable({ - id: "delete-cluster-channel", - instantiate: (): DeleteClusterChannel => ({ - id: "delete-cluster", - }), - injectionToken: requestChannelInjectionToken, -}); - -export default deleteClusterChannelInjectable; diff --git a/src/features/cluster/delete-dialog/common/delete-channel.ts b/src/features/cluster/delete-dialog/common/delete-channel.ts new file mode 100644 index 0000000000..0e9142fcd3 --- /dev/null +++ b/src/features/cluster/delete-dialog/common/delete-channel.ts @@ -0,0 +1,12 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { ClusterId } from "../../../../common/cluster-types"; +import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; + +export type DeleteClusterChannel = RequestChannel; + +export const deleteClusterChannel: DeleteClusterChannel = { + id: "delete-cluster", +}; diff --git a/src/features/cluster/delete-dialog/common/set-as-deleting-channel.injectable.ts b/src/features/cluster/delete-dialog/common/set-as-deleting-channel.injectable.ts deleted file mode 100644 index b625dfa14e..0000000000 --- a/src/features/cluster/delete-dialog/common/set-as-deleting-channel.injectable.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import type { ClusterId } from "../../../../common/cluster-types"; -import type { RequestChannel } from "../../../../common/utils/channel/request-channel-injection-token"; -import { requestChannelInjectionToken } from "../../../../common/utils/channel/request-channel-injection-token"; - -export type SetClusterAsDeletingChannel = RequestChannel; - -const setClusterAsDeletingChannelInjectable = getInjectable({ - id: "set-cluster-as-deleting-channel", - instantiate: (): SetClusterAsDeletingChannel => ({ - id: "set-cluster-as-deleting", - }), - injectionToken: requestChannelInjectionToken, -}); - -export default setClusterAsDeletingChannelInjectable; diff --git a/src/features/cluster/delete-dialog/common/set-as-deleting-channel.ts b/src/features/cluster/delete-dialog/common/set-as-deleting-channel.ts new file mode 100644 index 0000000000..57ef2e3a8d --- /dev/null +++ b/src/features/cluster/delete-dialog/common/set-as-deleting-channel.ts @@ -0,0 +1,12 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { ClusterId } from "../../../../common/cluster-types"; +import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; + +export type SetClusterAsDeletingChannel = RequestChannel; + +export const setClusterAsDeletingChannel: SetClusterAsDeletingChannel = { + id: "set-cluster-as-deleting", +}; diff --git a/src/features/cluster/delete-dialog/main/clear-as-deleteing-channel-handler.injectable.ts b/src/features/cluster/delete-dialog/main/clear-as-deleteing-channel-handler.injectable.ts deleted file mode 100644 index f1b89573d8..0000000000 --- a/src/features/cluster/delete-dialog/main/clear-as-deleteing-channel-handler.injectable.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import { requestChannelListenerInjectionToken } from "../../../../common/utils/channel/request-channel-listener-injection-token"; -import clustersThatAreBeingDeletedInjectable from "../../../../main/cluster/are-being-deleted.injectable"; -import clearClusterAsDeletingChannelInjectable from "../common/clear-as-deleting-channel.injectable"; - -const clearClusterAsDeletingChannelHandlerInjectable = getInjectable({ - id: "clear-cluster-as-deleting-channel-handler", - instantiate: (di) => { - const clustersThatAreBeingDeleted = di.inject(clustersThatAreBeingDeletedInjectable); - - return { - channel: di.inject(clearClusterAsDeletingChannelInjectable), - handler: (clusterId) => clustersThatAreBeingDeleted.delete(clusterId), - }; - }, - injectionToken: requestChannelListenerInjectionToken, -}); - -export default clearClusterAsDeletingChannelHandlerInjectable; diff --git a/src/features/cluster/delete-dialog/main/clear-as-deleting-channel-listener.injectable.ts b/src/features/cluster/delete-dialog/main/clear-as-deleting-channel-listener.injectable.ts new file mode 100644 index 0000000000..a8dd2a80b0 --- /dev/null +++ b/src/features/cluster/delete-dialog/main/clear-as-deleting-channel-listener.injectable.ts @@ -0,0 +1,20 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import clustersThatAreBeingDeletedInjectable from "../../../../main/cluster/are-being-deleted.injectable"; +import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens"; +import { clearClusterAsDeletingChannel } from "../common/clear-as-deleting-channel"; + +const clearClusterAsDeletingChannelListenerInjectable = getRequestChannelListenerInjectable({ + channel: clearClusterAsDeletingChannel, + handler: (di) => { + const clustersThatAreBeingDeleted = di.inject(clustersThatAreBeingDeletedInjectable); + + return (clusterId) => { + clustersThatAreBeingDeleted.delete(clusterId); + }; + }, +}); + +export default clearClusterAsDeletingChannelListenerInjectable; diff --git a/src/features/cluster/delete-dialog/main/delete-channel-handler.injectable.ts b/src/features/cluster/delete-dialog/main/delete-channel-handler.injectable.ts deleted file mode 100644 index 8945ffe625..0000000000 --- a/src/features/cluster/delete-dialog/main/delete-channel-handler.injectable.ts +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import appEventBusInjectable from "../../../../common/app-event-bus/app-event-bus.injectable"; -import clusterFramesInjectable from "../../../../common/cluster-frames.injectable"; -import clusterStoreInjectable from "../../../../common/cluster-store/cluster-store.injectable"; -import directoryForLensLocalStorageInjectable from "../../../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable"; -import deleteFileInjectable from "../../../../common/fs/delete-file.injectable"; -import joinPathsInjectable from "../../../../common/path/join-paths.injectable"; -import { requestChannelListenerInjectionToken } from "../../../../common/utils/channel/request-channel-listener-injection-token"; -import deleteClusterChannelInjectable from "../common/delete-channel.injectable"; - -const deleteClusterChannelHandlerInjectable = getInjectable({ - id: "delete-cluster-channel-handler", - instantiate: (di) => { - const appEventBus = di.inject(appEventBusInjectable); - const clusterStore = di.inject(clusterStoreInjectable); - const clusterFrames = di.inject(clusterFramesInjectable); - const joinPaths = di.inject(joinPathsInjectable); - const directoryForLensLocalStorage = di.inject(directoryForLensLocalStorageInjectable); - const deleteFile = di.inject(deleteFileInjectable); - - return { - channel: di.inject(deleteClusterChannelInjectable), - handler: async (clusterId) =>{ - appEventBus.emit({ name: "cluster", action: "remove" }); - - const cluster = clusterStore.getById(clusterId); - - if (!cluster) { - return; - } - - cluster.disconnect(); - clusterFrames.delete(cluster.id); - - // Remove from the cluster store as well, this should clear any old settings - clusterStore.clusters.delete(cluster.id); - - try { - // remove the local storage file - const localStorageFilePath = joinPaths(directoryForLensLocalStorage, `${cluster.id}.json`); - - await deleteFile(localStorageFilePath); - } catch { - // ignore error - } - }, - }; - }, - injectionToken: requestChannelListenerInjectionToken, -}); - -export default deleteClusterChannelHandlerInjectable; diff --git a/src/features/cluster/delete-dialog/main/delete-channel-listener.injectable.ts b/src/features/cluster/delete-dialog/main/delete-channel-listener.injectable.ts new file mode 100644 index 0000000000..9b7617293a --- /dev/null +++ b/src/features/cluster/delete-dialog/main/delete-channel-listener.injectable.ts @@ -0,0 +1,51 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import appEventBusInjectable from "../../../../common/app-event-bus/app-event-bus.injectable"; +import clusterFramesInjectable from "../../../../common/cluster-frames.injectable"; +import clusterStoreInjectable from "../../../../common/cluster-store/cluster-store.injectable"; +import directoryForLensLocalStorageInjectable from "../../../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable"; +import deleteFileInjectable from "../../../../common/fs/delete-file.injectable"; +import joinPathsInjectable from "../../../../common/path/join-paths.injectable"; +import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens"; +import { deleteClusterChannel } from "../common/delete-channel"; + +const deleteClusterChannelListenerInjectable = getRequestChannelListenerInjectable({ + channel: deleteClusterChannel, + handler: (di) => { + const appEventBus = di.inject(appEventBusInjectable); + const clusterStore = di.inject(clusterStoreInjectable); + const clusterFrames = di.inject(clusterFramesInjectable); + const joinPaths = di.inject(joinPathsInjectable); + const directoryForLensLocalStorage = di.inject(directoryForLensLocalStorageInjectable); + const deleteFile = di.inject(deleteFileInjectable); + + return async (clusterId) => { + appEventBus.emit({ name: "cluster", action: "remove" }); + + const cluster = clusterStore.getById(clusterId); + + if (!cluster) { + return; + } + + cluster.disconnect(); + clusterFrames.delete(cluster.id); + + // Remove from the cluster store as well, this should clear any old settings + clusterStore.clusters.delete(cluster.id); + + try { + // remove the local storage file + const localStorageFilePath = joinPaths(directoryForLensLocalStorage, `${cluster.id}.json`); + + await deleteFile(localStorageFilePath); + } catch { + // ignore error + } + }; + }, +}); + +export default deleteClusterChannelListenerInjectable; diff --git a/src/features/cluster/delete-dialog/main/set-as-deleteing-channel-handler.injectable.ts b/src/features/cluster/delete-dialog/main/set-as-deleteing-channel-handler.injectable.ts deleted file mode 100644 index 0b8862e384..0000000000 --- a/src/features/cluster/delete-dialog/main/set-as-deleteing-channel-handler.injectable.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import { requestChannelListenerInjectionToken } from "../../../../common/utils/channel/request-channel-listener-injection-token"; -import clustersThatAreBeingDeletedInjectable from "../../../../main/cluster/are-being-deleted.injectable"; -import setClusterAsDeletingChannelInjectable from "../common/set-as-deleting-channel.injectable"; - -const setClusterAsDeletingChannelHandlerInjectable = getInjectable({ - id: "set-cluster-as-deleting-channel-handler", - instantiate: (di) => { - const clustersThatAreBeingDeleted = di.inject(clustersThatAreBeingDeletedInjectable); - - return { - channel: di.inject(setClusterAsDeletingChannelInjectable), - handler: (clusterId) => clustersThatAreBeingDeleted.add(clusterId), - }; - }, - injectionToken: requestChannelListenerInjectionToken, -}); - -export default setClusterAsDeletingChannelHandlerInjectable; diff --git a/src/features/cluster/delete-dialog/main/set-as-deleteing-channel-listener.injectable.ts b/src/features/cluster/delete-dialog/main/set-as-deleteing-channel-listener.injectable.ts new file mode 100644 index 0000000000..f532b4a81f --- /dev/null +++ b/src/features/cluster/delete-dialog/main/set-as-deleteing-channel-listener.injectable.ts @@ -0,0 +1,20 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import clustersThatAreBeingDeletedInjectable from "../../../../main/cluster/are-being-deleted.injectable"; +import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens"; +import { setClusterAsDeletingChannel } from "../common/set-as-deleting-channel"; + +const setClusterAsDeletingChannelHandlerInjectable = getRequestChannelListenerInjectable({ + channel: setClusterAsDeletingChannel, + handler: (di) => { + const clustersThatAreBeingDeleted = di.inject(clustersThatAreBeingDeletedInjectable); + + return (clusterId) => { + clustersThatAreBeingDeleted.add(clusterId); + }; + }, +}); + +export default setClusterAsDeletingChannelHandlerInjectable; diff --git a/src/features/cluster/delete-dialog/renderer/request-clear-as-deleting.injectable.ts b/src/features/cluster/delete-dialog/renderer/request-clear-as-deleting.injectable.ts index b480630f6c..e476998ca0 100644 --- a/src/features/cluster/delete-dialog/renderer/request-clear-as-deleting.injectable.ts +++ b/src/features/cluster/delete-dialog/renderer/request-clear-as-deleting.injectable.ts @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { ClusterId } from "../../../../common/cluster-types"; import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable"; -import clearClusterAsDeletingChannelInjectable from "../common/clear-as-deleting-channel.injectable"; +import { clearClusterAsDeletingChannel } from "../common/clear-as-deleting-channel"; export type RequestClearClusterAsDeleting = (clusterId: ClusterId) => Promise; @@ -13,7 +13,6 @@ const requestClearClusterAsDeletingInjectable = getInjectable({ id: "request-clear-cluster-as-deleting", instantiate: (di): RequestClearClusterAsDeleting => { const requestChannel = di.inject(requestFromChannelInjectable); - const clearClusterAsDeletingChannel = di.inject(clearClusterAsDeletingChannelInjectable); return (clusterId) => requestChannel(clearClusterAsDeletingChannel, clusterId); }, diff --git a/src/features/cluster/delete-dialog/renderer/request-delete.injectable.ts b/src/features/cluster/delete-dialog/renderer/request-delete.injectable.ts index 602923e60e..c1286e3103 100644 --- a/src/features/cluster/delete-dialog/renderer/request-delete.injectable.ts +++ b/src/features/cluster/delete-dialog/renderer/request-delete.injectable.ts @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { ClusterId } from "../../../../common/cluster-types"; import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable"; -import deleteClusterChannelInjectable from "../common/delete-channel.injectable"; +import { deleteClusterChannel } from "../common/delete-channel"; export type RequestDeleteCluster = (clusterId: ClusterId) => Promise; @@ -13,7 +13,6 @@ const requestDeleteClusterInjectable = getInjectable({ id: "request-delete-cluster", instantiate: (di): RequestDeleteCluster => { const requestChannel = di.inject(requestFromChannelInjectable); - const deleteClusterChannel = di.inject(deleteClusterChannelInjectable); return (clusterId) => requestChannel(deleteClusterChannel, clusterId); }, diff --git a/src/features/cluster/delete-dialog/renderer/request-set-as-deleting.injectable.ts b/src/features/cluster/delete-dialog/renderer/request-set-as-deleting.injectable.ts index 997348d44d..de3a6393b3 100644 --- a/src/features/cluster/delete-dialog/renderer/request-set-as-deleting.injectable.ts +++ b/src/features/cluster/delete-dialog/renderer/request-set-as-deleting.injectable.ts @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { ClusterId } from "../../../../common/cluster-types"; import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable"; -import setClusterAsDeletingChannelInjectable from "../common/set-as-deleting-channel.injectable"; +import { setClusterAsDeletingChannel } from "../common/set-as-deleting-channel"; export type RequestSetClusterAsDeleting = (clusterId: ClusterId) => Promise; @@ -13,7 +13,6 @@ const requestSetClusterAsDeletingInjectable = getInjectable({ id: "request-set-cluster-as-deleting", instantiate: (di): RequestSetClusterAsDeleting => { const requestChannel = di.inject(requestFromChannelInjectable); - const setClusterAsDeletingChannel = di.inject(setClusterAsDeletingChannelInjectable); return (clusterId) => requestChannel(setClusterAsDeletingChannel, clusterId); }, diff --git a/src/features/helm-charts/add-custom-helm-repository-in-preferences.test.ts b/src/features/helm-charts/add-custom-helm-repository-in-preferences.test.ts index fb7b655dfe..6df4402130 100644 --- a/src/features/helm-charts/add-custom-helm-repository-in-preferences.test.ts +++ b/src/features/helm-charts/add-custom-helm-repository-in-preferences.test.ts @@ -8,6 +8,7 @@ import type { ApplicationBuilder } from "../../renderer/components/test-utils/ge import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; +import type { ExecFile } from "../../common/fs/exec-file.injectable"; import execFileInjectable from "../../common/fs/exec-file.injectable"; import helmBinaryPathInjectable from "../../main/helm/helm-binary-path.injectable"; import getActiveHelmRepositoriesInjectable from "../../main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable"; @@ -24,9 +25,7 @@ describe("add custom helm repository in preferences", () => { let showSuccessNotificationMock: jest.Mock; let showErrorNotificationMock: jest.Mock; let rendered: RenderResult; - let execFileMock: AsyncFnMock< - ReturnType - >; + let execFileMock: AsyncFnMock; let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise>>; beforeEach(async () => { @@ -184,9 +183,13 @@ describe("add custom helm repository in preferences", () => { describe("when activation rejects", () => { beforeEach(async () => { - await execFileMock.reject( - "Some error", - ); + await execFileMock.resolve({ + callWasSuccessful: false, + error: { + error: new Error("Some error"), + stderr: "", + }, + }); }); it("renders", () => { @@ -219,8 +222,10 @@ describe("add custom helm repository in preferences", () => { "some-helm-binary-path", ["repo", "add", "some-custom-repository", "http://some.url"], ], - - "", + { + callWasSuccessful: true, + response: "", + }, ); }); diff --git a/src/features/helm-charts/add-helm-repository-from-list-in-preferences.test.ts b/src/features/helm-charts/add-helm-repository-from-list-in-preferences.test.ts index 98e94321bd..73831bec04 100644 --- a/src/features/helm-charts/add-helm-repository-from-list-in-preferences.test.ts +++ b/src/features/helm-charts/add-helm-repository-from-list-in-preferences.test.ts @@ -7,6 +7,7 @@ import type { ApplicationBuilder } from "../../renderer/components/test-utils/ge import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; +import type { ExecFile } from "../../common/fs/exec-file.injectable"; import execFileInjectable from "../../common/fs/exec-file.injectable"; import helmBinaryPathInjectable from "../../main/helm/helm-binary-path.injectable"; import getActiveHelmRepositoriesInjectable from "../../main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable"; @@ -21,9 +22,7 @@ describe("add helm repository from list in preferences", () => { let showSuccessNotificationMock: jest.Mock; let showErrorNotificationMock: jest.Mock; let rendered: RenderResult; - let execFileMock: AsyncFnMock< - ReturnType - >; + let execFileMock: AsyncFnMock; let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise>>; let callForPublicHelmRepositoriesMock: AsyncFnMock<() => Promise>; @@ -129,9 +128,13 @@ describe("add helm repository from list in preferences", () => { describe("when adding rejects", () => { beforeEach(async () => { - await execFileMock.reject( - "Some error", - ); + await execFileMock.resolve({ + callWasSuccessful: false, + error: { + error: new Error("Some error"), + stderr: "", + }, + }); }); it("renders", () => { @@ -164,8 +167,10 @@ describe("add helm repository from list in preferences", () => { "some-helm-binary-path", ["repo", "add", "Some to be added repository", "some-other-url"], ], - - "", + { + callWasSuccessful: true, + response: "", + }, ); }); @@ -243,8 +248,10 @@ describe("add helm repository from list in preferences", () => { "some-helm-binary-path", ["repo", "remove", "Some already active repository"], ], - - "", + { + callWasSuccessful: true, + response: "", + }, ); }); diff --git a/src/features/helm-charts/listing-active-helm-repositories-in-preferences.test.ts b/src/features/helm-charts/listing-active-helm-repositories-in-preferences.test.ts index 19aaf28938..30e5bac5eb 100644 --- a/src/features/helm-charts/listing-active-helm-repositories-in-preferences.test.ts +++ b/src/features/helm-charts/listing-active-helm-repositories-in-preferences.test.ts @@ -83,7 +83,13 @@ describe("listing active helm repositories in preferences", () => { describe("when getting configuration rejects", () => { beforeEach(async () => { - await execFileMock.reject("some-error"); + await execFileMock.resolve({ + callWasSuccessful: false, + error: { + error: new Error("some error"), + stderr: "some-error", + }, + }); }); it("shows error notification", () => { @@ -115,7 +121,10 @@ describe("listing active helm repositories in preferences", () => { await execFileMock.resolveSpecific( ["some-helm-binary-path", ["env"]], - "HELM_REPOSITORY_CACHE=some-helm-repository-cache-path", + { + callWasSuccessful: true, + response: "HELM_REPOSITORY_CACHE=some-helm-repository-cache-path", + }, ); }); @@ -154,7 +163,10 @@ describe("listing active helm repositories in preferences", () => { await execFileMock.resolveSpecific( ["some-helm-binary-path", ["env"]], - "HELM_REPOSITORY_CONFIG=some-helm-repository-config-file.yaml", + { + callWasSuccessful: true, + response: "HELM_REPOSITORY_CONFIG=some-helm-repository-config-file.yaml", + }, ); }); @@ -193,11 +205,13 @@ describe("listing active helm repositories in preferences", () => { await execFileMock.resolveSpecific( ["some-helm-binary-path", ["env"]], - - [ - "HELM_REPOSITORY_CONFIG=some-helm-repository-config-file.yaml", - "HELM_REPOSITORY_CACHE=some-helm-repository-cache-path", - ].join("\n"), + { + callWasSuccessful: true, + response: [ + "HELM_REPOSITORY_CONFIG=some-helm-repository-config-file.yaml", + "HELM_REPOSITORY_CACHE=some-helm-repository-cache-path", + ].join("\n"), + }, ); }); @@ -219,7 +233,13 @@ describe("listing active helm repositories in preferences", () => { describe("when updating repositories reject with any other error", () => { beforeEach(async () => { - await execFileMock.reject("Some error"); + await execFileMock.resolve({ + callWasSuccessful: false, + error: { + error: new Error("Some error"), + stderr: "Some error", + }, + }); }); it("shows error notification", () => { @@ -249,9 +269,13 @@ describe("listing active helm repositories in preferences", () => { beforeEach(async () => { execFileMock.mockClear(); - await execFileMock.reject( - "Error: no repositories found. You must add one before updating", - ); + await execFileMock.resolve({ + callWasSuccessful: false, + error: { + error: new Error("no repositories found. You must add one before updating"), + stderr: "no repositories found. You must add one before updating", + }, + }); }); it("renders", () => { @@ -274,7 +298,13 @@ describe("listing active helm repositories in preferences", () => { describe("when adding default repository reject", () => { beforeEach(async () => { - await execFileMock.reject("Some error"); + await execFileMock.resolve({ + callWasSuccessful: false, + error: { + error: new Error("Some error"), + stderr: "Some error", + }, + }); }); it("shows error notification", () => { @@ -307,7 +337,6 @@ describe("listing active helm repositories in preferences", () => { await execFileMock.resolveSpecific( [ "some-helm-binary-path", - [ "repo", "add", @@ -315,8 +344,10 @@ describe("listing active helm repositories in preferences", () => { "https://charts.bitnami.com/bitnami", ], ], - - "", + { + callWasSuccessful: true, + response: "", + }, ); }); @@ -380,7 +411,10 @@ describe("listing active helm repositories in preferences", () => { await execFileMock.resolveSpecific( ["some-helm-binary-path", ["repo", "update"]], - "", + { + callWasSuccessful: true, + response: "", + }, ); }); diff --git a/src/features/helm-charts/remove-helm-repository-from-list-of-active-repository-in-preferences.test.ts b/src/features/helm-charts/remove-helm-repository-from-list-of-active-repository-in-preferences.test.ts index 7a3e787a53..8d029d3412 100644 --- a/src/features/helm-charts/remove-helm-repository-from-list-of-active-repository-in-preferences.test.ts +++ b/src/features/helm-charts/remove-helm-repository-from-list-of-active-repository-in-preferences.test.ts @@ -8,6 +8,7 @@ import type { ApplicationBuilder } from "../../renderer/components/test-utils/ge import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; +import type { ExecFile } from "../../common/fs/exec-file.injectable"; import execFileInjectable from "../../common/fs/exec-file.injectable"; import helmBinaryPathInjectable from "../../main/helm/helm-binary-path.injectable"; import getActiveHelmRepositoriesInjectable from "../../main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories.injectable"; @@ -19,9 +20,7 @@ describe("remove helm repository from list of active repositories in preferences let builder: ApplicationBuilder; let rendered: RenderResult; let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise>>; - let execFileMock: AsyncFnMock< - ReturnType - >; + let execFileMock: AsyncFnMock; beforeEach(async () => { builder = getApplicationBuilder(); @@ -101,8 +100,10 @@ describe("remove helm repository from list of active repositories in preferences "some-helm-binary-path", ["repo", "remove", "some-active-repository"], ], - - "", + { + callWasSuccessful: true, + response: "", + }, ); }); diff --git a/src/features/navigation/reload-page/common/channel.ts b/src/features/navigation/reload-page/common/channel.ts new file mode 100644 index 0000000000..b920067a4d --- /dev/null +++ b/src/features/navigation/reload-page/common/channel.ts @@ -0,0 +1,12 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type { MessageChannel } from "../../../../common/utils/channel/message-channel-listener-injection-token"; + +export type ReloadPageChannel = MessageChannel; + +export const reloadPageChannel: ReloadPageChannel = { + id: "reload-page-channel", +}; diff --git a/src/features/navigation/reload-page/renderer/register-listener.global-override-for-injectable.ts b/src/features/navigation/reload-page/renderer/register-listener.global-override-for-injectable.ts new file mode 100644 index 0000000000..c0a43713b7 --- /dev/null +++ b/src/features/navigation/reload-page/renderer/register-listener.global-override-for-injectable.ts @@ -0,0 +1,13 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { getGlobalOverride } from "../../../../common/test-utils/get-global-override"; +import { reloadPageChannel } from "../common/channel"; +import reloadPageChannelListenerInjectable from "./register-listener.injectable"; + +export default getGlobalOverride(reloadPageChannelListenerInjectable, () => ({ + channel: reloadPageChannel, + handler: () => {}, +})); diff --git a/src/features/navigation/reload-page/renderer/register-listener.injectable.ts b/src/features/navigation/reload-page/renderer/register-listener.injectable.ts new file mode 100644 index 0000000000..a42d818729 --- /dev/null +++ b/src/features/navigation/reload-page/renderer/register-listener.injectable.ts @@ -0,0 +1,15 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getMessageChannelListenerInjectable } from "../../../../common/utils/channel/message-channel-listener-injection-token"; +import { reloadPageChannel } from "../common/channel"; + +const reloadPageChannelListenerInjectable = getMessageChannelListenerInjectable({ + id: "handler", + channel: reloadPageChannel, + handler: () => () => location.reload(), + causesSideEffects: true, +}); + +export default reloadPageChannelListenerInjectable; diff --git a/src/main/app-paths/app-paths-request-channel-listener.injectable.ts b/src/main/app-paths/app-paths-request-channel-listener.injectable.ts index 3bd0c95bf7..568d63f1ea 100644 --- a/src/main/app-paths/app-paths-request-channel-listener.injectable.ts +++ b/src/main/app-paths/app-paths-request-channel-listener.injectable.ts @@ -2,26 +2,17 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getInjectable } from "@ogre-tools/injectable"; -import type { RequestChannelListener } from "../../common/utils/channel/request-channel-listener-injection-token"; -import { requestChannelListenerInjectionToken } from "../../common/utils/channel/request-channel-listener-injection-token"; -import type { AppPathsChannel } from "../../common/app-paths/app-paths-channel.injectable"; -import appPathsChannelInjectable from "../../common/app-paths/app-paths-channel.injectable"; +import { appPathsChannel } from "../../common/app-paths/app-paths-channel"; import appPathsInjectable from "../../common/app-paths/app-paths.injectable"; +import { getRequestChannelListenerInjectable } from "../utils/channel/channel-listeners/listener-tokens"; -const appPathsRequestChannelListenerInjectable = getInjectable({ - id: "app-paths-request-channel-listener", - - instantiate: (di): RequestChannelListener => { - const channel = di.inject(appPathsChannelInjectable); +const appPathsRequestChannelListenerInjectable = getRequestChannelListenerInjectable({ + channel: appPathsChannel, + handler: (di) => { const appPaths = di.inject(appPathsInjectable); - return { - channel, - handler: () => appPaths, - }; + return () => appPaths; }, - injectionToken: requestChannelListenerInjectionToken, }); export default appPathsRequestChannelListenerInjectable; diff --git a/src/main/application-update/restart-and-install-update/restart-and-install-update-listener.injectable.ts b/src/main/application-update/restart-and-install-update/restart-and-install-update-listener.injectable.ts index 0580114885..87f232d9b1 100644 --- a/src/main/application-update/restart-and-install-update/restart-and-install-update-listener.injectable.ts +++ b/src/main/application-update/restart-and-install-update/restart-and-install-update-listener.injectable.ts @@ -2,25 +2,14 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getInjectable } from "@ogre-tools/injectable"; -import restartAndInstallUpdateChannel from "../../../common/application-update/restart-and-install-update-channel/restart-and-install-update-channel.injectable"; -import { messageChannelListenerInjectionToken } from "../../../common/utils/channel/message-channel-listener-injection-token"; +import { restartAndInstallUpdateChannel } from "../../../common/application-update/restart-and-install-update-channel"; +import { getMessageChannelListenerInjectable } from "../../../common/utils/channel/message-channel-listener-injection-token"; import quitAndInstallUpdateInjectable from "../quit-and-install-update.injectable"; -const restartAndInstallUpdateListenerInjectable = getInjectable({ - id: "restart-and-install-update-listener", - - instantiate: (di) => { - const quitAndInstall = di.inject(quitAndInstallUpdateInjectable); - const channel = di.inject(restartAndInstallUpdateChannel); - - return { - channel, - handler: quitAndInstall, - }; - }, - - injectionToken: messageChannelListenerInjectionToken, +const restartAndInstallUpdateListenerInjectable = getMessageChannelListenerInjectable({ + id: "restart", + channel: restartAndInstallUpdateChannel, + handler: (di) => di.inject(quitAndInstallUpdateInjectable), }); export default restartAndInstallUpdateListenerInjectable; diff --git a/src/main/application-update/watch-if-update-should-happen-on-quit/watch-if-update-should-happen-on-quit.injectable.ts b/src/main/application-update/watch-if-update-should-happen-on-quit/watch-if-update-should-happen-on-quit.injectable.ts index 12ec2d7c6e..9be8fdd18f 100644 --- a/src/main/application-update/watch-if-update-should-happen-on-quit/watch-if-update-should-happen-on-quit.injectable.ts +++ b/src/main/application-update/watch-if-update-should-happen-on-quit/watch-if-update-should-happen-on-quit.injectable.ts @@ -7,7 +7,7 @@ import { autorun } from "mobx"; import { getStartableStoppable } from "../../../common/utils/get-startable-stoppable"; import setUpdateOnQuitInjectable from "../../electron-app/features/set-update-on-quit.injectable"; import selectedUpdateChannelInjectable from "../../../common/application-update/selected-update-channel/selected-update-channel.injectable"; -import type { UpdateChannel } from "../../../common/application-update/update-channels"; +import type { ReleaseChannel, UpdateChannel } from "../../../common/application-update/update-channels"; import discoveredUpdateVersionInjectable from "../../../common/application-update/discovered-update-version/discovered-update-version.injectable"; const watchIfUpdateShouldHappenOnQuitInjectable = getInjectable({ @@ -20,33 +20,26 @@ const watchIfUpdateShouldHappenOnQuitInjectable = getInjectable({ return getStartableStoppable("watch-if-update-should-happen-on-quit", () => autorun(() => { - const sufficientlyStableUpdateChannels = - getSufficientlyStableUpdateChannels(selectedUpdateChannel.value.get()); + const sufficientlyStableUpdateChannels = getSufficientlyStableUpdateChannels(selectedUpdateChannel.value.get()); + const updateIsDiscoveredFromChannel = discoveredVersionState.value.get()?.updateChannel; - const discoveredVersion = discoveredVersionState.value.get(); - - const updateIsDiscoveredFromChannel = discoveredVersion?.updateChannel; - - const updateOnQuit = updateIsDiscoveredFromChannel - ? sufficientlyStableUpdateChannels.includes( - updateIsDiscoveredFromChannel, - ) - : false; - - setUpdateOnQuit(updateOnQuit); + setUpdateOnQuit(( + updateIsDiscoveredFromChannel + ? sufficientlyStableUpdateChannels.includes(updateIsDiscoveredFromChannel.id) + : false + )); }), ); }, }); -const getSufficientlyStableUpdateChannels = (updateChannel: UpdateChannel): UpdateChannel[] => { +const getSufficientlyStableUpdateChannels = (updateChannel: UpdateChannel): ReleaseChannel[] => { if (!updateChannel.moreStableUpdateChannel) { - return [updateChannel]; + return [updateChannel.id]; } return [ - updateChannel, - + updateChannel.id, ...getSufficientlyStableUpdateChannels(updateChannel.moreStableUpdateChannel), ]; }; diff --git a/src/main/build-version/setup-channel.injectable.ts b/src/main/build-version/setup-channel.injectable.ts index a34edc0eac..05da92db6e 100644 --- a/src/main/build-version/setup-channel.injectable.ts +++ b/src/main/build-version/setup-channel.injectable.ts @@ -2,22 +2,17 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getInjectable } from "@ogre-tools/injectable"; -import { requestChannelListenerInjectionToken } from "../../common/utils/channel/request-channel-listener-injection-token"; import { buildVersionChannel } from "../../common/vars/build-semantic-version.injectable"; +import { getRequestChannelListenerInjectable } from "../utils/channel/channel-listeners/listener-tokens"; import buildVersionInjectable from "../vars/build-version/build-version.injectable"; -const setupBuildVersionRequestChannelInjectable = getInjectable({ - id: "setup-build-version-request-channel", - instantiate: (di) => { +const buildVersionChannelListenerInjectable = getRequestChannelListenerInjectable({ + channel: buildVersionChannel, + handler: (di) => { const buildVersion = di.inject(buildVersionInjectable); - return { - channel: buildVersionChannel, - handler: () => buildVersion.get(), - }; + return () => buildVersion.get(); }, - injectionToken: requestChannelListenerInjectionToken, }); -export default setupBuildVersionRequestChannelInjectable; +export default buildVersionChannelListenerInjectable; diff --git a/src/main/helm/exec-helm/exec-helm.injectable.ts b/src/main/helm/exec-helm/exec-helm.injectable.ts index dbe65eda34..d81da0c8b8 100644 --- a/src/main/helm/exec-helm/exec-helm.injectable.ts +++ b/src/main/helm/exec-helm/exec-helm.injectable.ts @@ -6,9 +6,8 @@ import { getInjectable } from "@ogre-tools/injectable"; import execFileInjectable from "../../../common/fs/exec-file.injectable"; import helmBinaryPathInjectable from "../helm-binary-path.injectable"; import type { AsyncResult } from "../../../common/utils/async-result"; -import { getErrorMessage } from "../../../common/utils/get-error-message"; -export type ExecHelm = (args: string[]) => Promise>; +export type ExecHelm = (args: string[]) => Promise>; const execHelmInjectable = getInjectable({ id: "exec-helm", @@ -18,15 +17,18 @@ const execHelmInjectable = getInjectable({ const helmBinaryPath = di.inject(helmBinaryPathInjectable); return async (args) => { - try { - const response = await execFile(helmBinaryPath, args, { - maxBuffer: 32 * 1024 * 1024 * 1024, // 32 MiB - }); + const response = await execFile(helmBinaryPath, args, { + maxBuffer: 32 * 1024 * 1024 * 1024, // 32 MiB + }); - return { callWasSuccessful: true, response }; - } catch (error) { - return { callWasSuccessful: false, error: getErrorMessage(error) }; + if (response.callWasSuccessful) { + return response; } + + return { + callWasSuccessful: false, + error: response.error.stderr || response.error.error.message, + }; }; }, }); diff --git a/src/main/helm/repositories/add-helm-repository/add-helm-repository-channel-listener.injectable.ts b/src/main/helm/repositories/add-helm-repository/add-helm-repository-channel-listener.injectable.ts index f4effd1a62..1c68bf6fd7 100644 --- a/src/main/helm/repositories/add-helm-repository/add-helm-repository-channel-listener.injectable.ts +++ b/src/main/helm/repositories/add-helm-repository/add-helm-repository-channel-listener.injectable.ts @@ -2,25 +2,13 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getInjectable } from "@ogre-tools/injectable"; -import addHelmRepositoryChannelInjectable from "../../../../common/helm/add-helm-repository-channel.injectable"; +import { addHelmRepositoryChannel } from "../../../../common/helm/add-helm-repository-channel"; +import { getRequestChannelListenerInjectable } from "../../../utils/channel/channel-listeners/listener-tokens"; import addHelmRepositoryInjectable from "./add-helm-repository.injectable"; -import { requestChannelListenerInjectionToken } from "../../../../common/utils/channel/request-channel-listener-injection-token"; -const addHelmRepositoryChannelListenerInjectable = getInjectable({ - id: "add-helm-repository-channel-listener", - - instantiate: (di) => { - const addHelmRepository = di.inject(addHelmRepositoryInjectable); - const channel = di.inject(addHelmRepositoryChannelInjectable); - - return { - channel, - handler: addHelmRepository, - }; - }, - - injectionToken: requestChannelListenerInjectionToken, +const addHelmRepositoryChannelListenerInjectable = getRequestChannelListenerInjectable({ + channel: addHelmRepositoryChannel, + handler: (di) => di.inject(addHelmRepositoryInjectable), }); export default addHelmRepositoryChannelListenerInjectable; diff --git a/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories-channel-listener.injectable.ts b/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories-channel-listener.injectable.ts index e48ec7665e..5ef0f2b5a4 100644 --- a/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories-channel-listener.injectable.ts +++ b/src/main/helm/repositories/get-active-helm-repositories/get-active-helm-repositories-channel-listener.injectable.ts @@ -2,25 +2,13 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getInjectable } from "@ogre-tools/injectable"; -import { requestChannelListenerInjectionToken } from "../../../../common/utils/channel/request-channel-listener-injection-token"; -import getActiveHelmRepositoriesChannelInjectable from "../../../../common/helm/get-active-helm-repositories-channel.injectable"; +import { getActiveHelmRepositoriesChannel } from "../../../../common/helm/get-active-helm-repositories-channel"; +import { getRequestChannelListenerInjectable } from "../../../utils/channel/channel-listeners/listener-tokens"; import getActiveHelmRepositoriesInjectable from "./get-active-helm-repositories.injectable"; -const getActiveHelmRepositoriesChannelListenerInjectable = getInjectable({ - id: "get-active-helm-repositories-channel-listener", - - instantiate: (di) => { - const getActiveHelmRepositories = di.inject(getActiveHelmRepositoriesInjectable); - - return { - channel: di.inject(getActiveHelmRepositoriesChannelInjectable), - - handler: getActiveHelmRepositories, - }; - }, - - injectionToken: requestChannelListenerInjectionToken, +const getActiveHelmRepositoriesChannelListenerInjectable = getRequestChannelListenerInjectable({ + channel: getActiveHelmRepositoriesChannel, + handler: (di) => di.inject(getActiveHelmRepositoriesInjectable), }); export default getActiveHelmRepositoriesChannelListenerInjectable; diff --git a/src/main/helm/repositories/remove-helm-repository/remove-helm-repository-channel-listener.injectable.ts b/src/main/helm/repositories/remove-helm-repository/remove-helm-repository-channel-listener.injectable.ts index b9b2f11777..8a4e04b87c 100644 --- a/src/main/helm/repositories/remove-helm-repository/remove-helm-repository-channel-listener.injectable.ts +++ b/src/main/helm/repositories/remove-helm-repository/remove-helm-repository-channel-listener.injectable.ts @@ -2,25 +2,13 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getInjectable } from "@ogre-tools/injectable"; -import { requestChannelListenerInjectionToken } from "../../../../common/utils/channel/request-channel-listener-injection-token"; import removeHelmRepositoryInjectable from "./remove-helm-repository.injectable"; -import removeHelmRepositoryChannelInjectable from "../../../../common/helm/remove-helm-repository-channel.injectable"; +import { removeHelmRepositoryChannel } from "../../../../common/helm/remove-helm-repository-channel"; +import { getRequestChannelListenerInjectable } from "../../../utils/channel/channel-listeners/listener-tokens"; -const removeHelmRepositoryChannelListenerInjectable = getInjectable({ - id: "remove-helm-repository-channel-listener", - - instantiate: (di) => { - const removeHelmRepository = di.inject(removeHelmRepositoryInjectable); - const channel = di.inject(removeHelmRepositoryChannelInjectable); - - return { - channel, - handler: removeHelmRepository, - }; - }, - - injectionToken: requestChannelListenerInjectionToken, +const removeHelmRepositoryChannelListenerInjectable = getRequestChannelListenerInjectable({ + channel: removeHelmRepositoryChannel, + handler: (di) => di.inject(removeHelmRepositoryInjectable), }); export default removeHelmRepositoryChannelListenerInjectable; diff --git a/src/main/start-main-application/lens-window/application-window/create-electron-window.injectable.ts b/src/main/start-main-application/lens-window/application-window/create-electron-window.injectable.ts index 252db16a1f..07f9b8fb7e 100644 --- a/src/main/start-main-application/lens-window/application-window/create-electron-window.injectable.ts +++ b/src/main/start-main-application/lens-window/application-window/create-electron-window.injectable.ts @@ -6,7 +6,6 @@ import { getInjectable } from "@ogre-tools/injectable"; import loggerInjectable from "../../../../common/logger.injectable"; import applicationWindowStateInjectable from "./application-window-state.injectable"; import { BrowserWindow } from "electron"; -import sendToChannelInElectronBrowserWindowInjectable from "./send-to-channel-in-electron-browser-window.injectable"; import type { ElectronWindow } from "./create-lens-window.injectable"; import type { RequireExactlyOne } from "type-fest"; import openLinkInBrowserInjectable from "../../../../common/utils/open-link-in-browser.injectable"; @@ -45,7 +44,6 @@ const createElectronWindowInjectable = getInjectable({ instantiate: (di): CreateElectronWindow => { const logger = di.inject(loggerInjectable); - const sendToChannelInLensWindow = di.inject(sendToChannelInElectronBrowserWindowInjectable); const openLinkInBrowser = di.inject(openLinkInBrowserInjectable); return (configuration) => { @@ -140,7 +138,17 @@ const createElectronWindowInjectable = getInjectable({ show: () => browserWindow.show(), close: () => browserWindow.close(), - send: (args) => sendToChannelInLensWindow(configuration.id, browserWindow, args), + send: ({ channel, data, frameInfo }) => { + if (frameInfo) { + browserWindow.webContents.sendToFrame( + [frameInfo.processId, frameInfo.frameId], + channel, + data, + ); + } else { + browserWindow.webContents.send(channel, data); + } + }, reload: () => { const wc = browserWindow.webContents; diff --git a/src/main/start-main-application/lens-window/application-window/create-lens-window.injectable.ts b/src/main/start-main-application/lens-window/application-window/create-lens-window.injectable.ts index 6dcf6b0174..b44e5774bd 100644 --- a/src/main/start-main-application/lens-window/application-window/create-lens-window.injectable.ts +++ b/src/main/start-main-application/lens-window/application-window/create-lens-window.injectable.ts @@ -20,7 +20,7 @@ export interface ElectronWindow { export interface SendToViewArgs { channel: string; frameInfo?: ClusterFrameInfo; - data?: unknown[]; + data?: unknown; } export interface LensWindow { diff --git a/src/main/start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable.ts b/src/main/start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable.ts deleted file mode 100644 index 08de6fec46..0000000000 --- a/src/main/start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable.ts +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import type { BrowserWindow } from "electron"; -import type { SendToViewArgs } from "./create-lens-window.injectable"; - -const sendToChannelInElectronBrowserWindowInjectable = getInjectable({ - id: "send-to-channel-in-electron-browser-window", - - instantiate: - () => - ( - windowId: string, - browserWindow: BrowserWindow, - { channel, frameInfo, data = [] }: SendToViewArgs, - ) => { - if (frameInfo) { - browserWindow.webContents.sendToFrame( - [frameInfo.processId, frameInfo.frameId], - channel, - ...data, - ); - } else { - browserWindow.webContents.send(channel, ...data); - } - }, - - causesSideEffects: true, -}); - -export default sendToChannelInElectronBrowserWindowInjectable; diff --git a/src/main/start-main-application/lens-window/navigate.injectable.ts b/src/main/start-main-application/lens-window/navigate.injectable.ts index 1916b8205f..8b204be9b3 100644 --- a/src/main/start-main-application/lens-window/navigate.injectable.ts +++ b/src/main/start-main-application/lens-window/navigate.injectable.ts @@ -37,7 +37,7 @@ const navigateInjectable = getInjectable({ applicationWindow.send({ channel, frameInfo, - data: [url], + data: url, }); }; }, diff --git a/src/main/start-main-application/lens-window/reload-current-application-window.injectable.ts b/src/main/start-main-application/lens-window/reload-current-application-window.injectable.ts index daaf88a24c..9b0d04fe9f 100644 --- a/src/main/start-main-application/lens-window/reload-current-application-window.injectable.ts +++ b/src/main/start-main-application/lens-window/reload-current-application-window.injectable.ts @@ -3,9 +3,9 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { IpcRendererNavigationEvents } from "../../../renderer/navigation/events"; import currentClusterFrameInjectable from "./current-cluster-frame/current-cluster-frame.injectable"; import getCurrentApplicationWindowInjectable from "./application-window/get-current-application-window.injectable"; +import { reloadPageChannel } from "../../../features/navigation/reload-page/common/channel"; const reloadCurrentApplicationWindowInjectable = getInjectable({ id: "reload-current-application-window", @@ -25,7 +25,7 @@ const reloadCurrentApplicationWindowInjectable = getInjectable({ if (frameInfo) { lensWindow.send({ - channel: IpcRendererNavigationEvents.RELOAD_PAGE, + channel: reloadPageChannel.id, frameInfo, }); } else { diff --git a/src/main/start-main-application/runnables/root-frame-has-rendered/channel-listener.injectable.ts b/src/main/start-main-application/runnables/root-frame-has-rendered/channel-listener.injectable.ts new file mode 100644 index 0000000000..40f5ceb788 --- /dev/null +++ b/src/main/start-main-application/runnables/root-frame-has-rendered/channel-listener.injectable.ts @@ -0,0 +1,20 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getMessageChannelListenerInjectable } from "../../../../common/utils/channel/message-channel-listener-injection-token"; +import { rootFrameHasRenderedChannel } from "../../../../common/root-frame/root-frame-rendered-channel"; +import { runManyFor } from "../../../../common/runnable/run-many-for"; +import { afterRootFrameIsReadyInjectionToken } from "../../runnable-tokens/after-root-frame-is-ready-injection-token"; + +const rootFrameRenderedChannelListenerInjectable = getMessageChannelListenerInjectable({ + id: "action", + channel: rootFrameHasRenderedChannel, + handler: (di) => { + const runMany = runManyFor(di); + + return runMany(afterRootFrameIsReadyInjectionToken); + }, +}); + +export default rootFrameRenderedChannelListenerInjectable; diff --git a/src/main/start-main-application/runnables/root-frame-rendered-channel-listener/root-frame-rendered-channel-listener.injectable.ts b/src/main/start-main-application/runnables/root-frame-rendered-channel-listener/root-frame-rendered-channel-listener.injectable.ts deleted file mode 100644 index 83ebf7bf91..0000000000 --- a/src/main/start-main-application/runnables/root-frame-rendered-channel-listener/root-frame-rendered-channel-listener.injectable.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import rootFrameRenderedChannelInjectable from "../../../../common/root-frame-rendered-channel/root-frame-rendered-channel.injectable"; -import { runManyFor } from "../../../../common/runnable/run-many-for"; -import { afterRootFrameIsReadyInjectionToken } from "../../runnable-tokens/after-root-frame-is-ready-injection-token"; -import { messageChannelListenerInjectionToken } from "../../../../common/utils/channel/message-channel-listener-injection-token"; - -const rootFrameRenderedChannelListenerInjectable = getInjectable({ - id: "root-frame-rendered-channel-listener", - - instantiate: (di) => { - const channel = di.inject(rootFrameRenderedChannelInjectable); - - const runMany = runManyFor(di); - - const runRunnablesAfterRootFrameIsReady = runMany( - afterRootFrameIsReadyInjectionToken, - ); - - return { - channel, - - handler: async () => { - await runRunnablesAfterRootFrameIsReady(); - }, - }; - }, - - injectionToken: messageChannelListenerInjectionToken, -}); - -export default rootFrameRenderedChannelListenerInjectable; diff --git a/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts b/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts index 6b7fa9b8df..6ace54c845 100644 --- a/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts +++ b/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts @@ -6,8 +6,6 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { IpcMainEvent } from "electron"; import ipcMainInjectable from "../ipc-main/ipc-main.injectable"; import { enlistMessageChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-message-channel-listener-injection-token"; -import { pipeline } from "@ogre-tools/fp"; -import { tentativeParseJson } from "../../../../common/utils/tentative-parse-json"; const enlistMessageChannelListenerInjectable = getInjectable({ id: "enlist-message-channel-listener-for-main", @@ -17,11 +15,7 @@ const enlistMessageChannelListenerInjectable = getInjectable({ return ({ channel, handler }) => { const nativeOnCallback = (_: IpcMainEvent, message: unknown) => { - pipeline( - message, - tentativeParseJson, - handler, - ); + handler(message); }; ipcMain.on(channel.id, nativeOnCallback); diff --git a/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.test.ts b/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.test.ts index 3bd0398d8e..407ffabd8f 100644 --- a/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.test.ts +++ b/src/main/utils/channel/channel-listeners/enlist-message-channel-listener.test.ts @@ -88,8 +88,8 @@ describe("enlist message channel listener in main", () => { expect(handlerMock).toHaveBeenCalledWith(true); }); - it("given stringified object as message, when message arrives, calls the handler with the message", () => { - onMock.mock.calls[0][1]({} as IpcMainEvent, JSON.stringify({ some: "object" })); + it("given object as message, when message arrives, calls the handler with the message", () => { + onMock.mock.calls[0][1]({} as IpcMainEvent, { some: "object" }); expect(handlerMock).toHaveBeenCalledWith({ some: "object" }); }); diff --git a/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.injectable.ts b/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.injectable.ts index 6f118288f3..d72e4afcaf 100644 --- a/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.injectable.ts +++ b/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.injectable.ts @@ -5,20 +5,20 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { IpcMainInvokeEvent } from "electron"; import ipcMainInjectable from "../ipc-main/ipc-main.injectable"; -import { enlistRequestChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-request-channel-listener-injection-token"; -import { pipeline } from "@ogre-tools/fp"; -import { tentativeParseJson } from "../../../../common/utils/tentative-parse-json"; -import { tentativeStringifyJson } from "../../../../common/utils/tentative-stringify-json"; +import type { Disposer } from "../../../../common/utils"; +import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; +import type { RequestChannelListener } from "./listener-tokens"; + +export type EnlistRequestChannelListener = >(listener: RequestChannelListener) => Disposer; const enlistRequestChannelListenerInjectable = getInjectable({ id: "enlist-request-channel-listener-for-main", - instantiate: (di) => { + instantiate: (di): EnlistRequestChannelListener => { const ipcMain = di.inject(ipcMainInjectable); return ({ channel, handler }) => { - const nativeHandleCallback = (_: IpcMainInvokeEvent, request: unknown) => - pipeline(request, tentativeParseJson, handler, tentativeStringifyJson); + const nativeHandleCallback = (_: IpcMainInvokeEvent, request: unknown) => handler(request); ipcMain.handle(channel.id, nativeHandleCallback); @@ -27,8 +27,6 @@ const enlistRequestChannelListenerInjectable = getInjectable({ }; }; }, - - injectionToken: enlistRequestChannelListenerInjectionToken, }); export default enlistRequestChannelListenerInjectable; diff --git a/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.test.ts b/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.test.ts index 12a5e9af74..2c13bbd8f9 100644 --- a/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.test.ts +++ b/src/main/utils/channel/channel-listeners/enlist-request-channel-listener.test.ts @@ -5,11 +5,19 @@ import { getDiForUnitTesting } from "../../../getDiForUnitTesting"; import ipcMainInjectable from "../ipc-main/ipc-main.injectable"; import type { IpcMain, IpcMainInvokeEvent } from "electron"; -import type { EnlistRequestChannelListener } from "../../../../common/utils/channel/enlist-request-channel-listener-injection-token"; -import { enlistRequestChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-request-channel-listener-injection-token"; import { getPromiseStatus } from "../../../../common/test-utils/get-promise-status"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; +import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; +import type { EnlistRequestChannelListener } from "./enlist-request-channel-listener.injectable"; +import enlistRequestChannelListenerInjectable from "./enlist-request-channel-listener.injectable"; +import type { RequestChannelHandler } from "./listener-tokens"; + +type TestRequestChannel = RequestChannel; + +const testRequestChannel: TestRequestChannel = { + id: "some-channel-id", +}; describe("enlist request channel listener in main", () => { let enlistRequestChannelListener: EnlistRequestChannelListener; @@ -30,20 +38,18 @@ describe("enlist request channel listener in main", () => { di.override(ipcMainInjectable, () => ipcMainStub); - enlistRequestChannelListener = di.inject( - enlistRequestChannelListenerInjectionToken, - ); + enlistRequestChannelListener = di.inject(enlistRequestChannelListenerInjectable); }); describe("when called", () => { - let handlerMock: AsyncFnMock<(message: any) => any>; + let handlerMock: AsyncFnMock>; let disposer: () => void; beforeEach(() => { handlerMock = asyncFn(); disposer = enlistRequestChannelListener({ - channel: { id: "some-channel-id" }, + channel: testRequestChannel, handler: handlerMock, }); }); @@ -91,7 +97,7 @@ describe("enlist request channel listener in main", () => { it("resolves with the response", async () => { const actual = await actualPromise; - expect(actual).toBe('"some-response"'); + expect(actual).toBe("some-response"); }); it("when disposing the listener, de-registers the listener", () => { @@ -106,7 +112,7 @@ describe("enlist request channel listener in main", () => { const actual = await actualPromise; - expect(actual).toBe("42"); + expect(actual).toBe(42); }); it("given boolean as response, when handler resolves with response, listener resolves with stringified response", async () => { @@ -114,15 +120,15 @@ describe("enlist request channel listener in main", () => { const actual = await actualPromise; - expect(actual).toBe("true"); + expect(actual).toBe(true); }); - it("given object as response, when handler resolves with response, listener resolves with stringified response", async () => { + it("given object as response, when handler resolves with response, listener resolves with response", async () => { await handlerMock.resolve({ some: "object" }); const actual = await actualPromise; - expect(actual).toBe(JSON.stringify({ some: "object" })); + expect(actual).toEqual({ some: "object" }); }); }); @@ -138,8 +144,8 @@ describe("enlist request channel listener in main", () => { expect(handlerMock).toHaveBeenCalledWith(true); }); - it("given stringified object as request, when request arrives, calls the handler with the request", () => { - handleMock.mock.calls[0][1]({} as IpcMainInvokeEvent, JSON.stringify({ some: "object" })); + it("given object as request, when request arrives, calls the handler with the request", () => { + handleMock.mock.calls[0][1]({} as IpcMainInvokeEvent, { some: "object" }); expect(handlerMock).toHaveBeenCalledWith({ some: "object" }); }); diff --git a/src/main/utils/channel/channel-listeners/listener-tokens.ts b/src/main/utils/channel/channel-listeners/listener-tokens.ts new file mode 100644 index 0000000000..a3cd5af4f4 --- /dev/null +++ b/src/main/utils/channel/channel-listeners/listener-tokens.ts @@ -0,0 +1,46 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type { DiContainerForInjection } from "@ogre-tools/injectable"; +import { getInjectable, getInjectionToken } from "@ogre-tools/injectable"; +import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; + +export type RequestChannelHandler = Channel extends RequestChannel + ? (req: Request) => Promise | Response + : never; + +export interface RequestChannelListener { + channel: Channel; + handler: RequestChannelHandler; +} + + +export const requestChannelListenerInjectionToken = getInjectionToken>>( { + id: "request-channel-listener", +}); + +export interface GetRequestChannelListenerInjectableInfo< + Channel extends RequestChannel, + Request, + Response, +> { + channel: Channel; + handler: (di: DiContainerForInjection) => RequestChannelHandler; +} + +export function getRequestChannelListenerInjectable< + Channel extends RequestChannel, + Request, + Response, +>(info: GetRequestChannelListenerInjectableInfo) { + return getInjectable({ + id: `${info.channel.id}-listener`, + instantiate: (di) => ({ + channel: info.channel, + handler: info.handler(di), + }), + injectionToken: requestChannelListenerInjectionToken, + }); +} diff --git a/src/main/utils/channel/channel-listeners/listening-on-request-channels.injectable.ts b/src/main/utils/channel/channel-listeners/listening-on-request-channels.injectable.ts new file mode 100644 index 0000000000..80b94fbe0e --- /dev/null +++ b/src/main/utils/channel/channel-listeners/listening-on-request-channels.injectable.ts @@ -0,0 +1,34 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { disposer } from "../../../../common/utils"; +import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; +import { getStartableStoppable } from "../../../../common/utils/get-startable-stoppable"; +import enlistRequestChannelListenerInjectable from "./enlist-request-channel-listener.injectable"; +import { requestChannelListenerInjectionToken } from "./listener-tokens"; + +const listeningOnRequestChannelsInjectable = getInjectable({ + id: "listening-on-request-channels", + instantiate: (di) => { + const enlistRequestChannelListener = di.inject(enlistRequestChannelListenerInjectable); + const requestChannelListeners = di.injectMany(requestChannelListenerInjectionToken); + + return getStartableStoppable("listening-on-request-channels", () => { + const seenChannels = new Set>(); + + for (const listener of requestChannelListeners) { + if (seenChannels.has(listener.channel)) { + throw new Error(`Tried to register a multiple channel handlers for "${listener.channel.id}", only one handler is supported for a request channel.`); + } + + seenChannels.add(listener.channel); + } + + return disposer(requestChannelListeners.map(enlistRequestChannelListener)); + }); + }, +}); + +export default listeningOnRequestChannelsInjectable; diff --git a/src/main/utils/channel/channel-listeners/start-listening-of-channels.injectable.ts b/src/main/utils/channel/channel-listeners/start-listening-of-channels.injectable.ts deleted file mode 100644 index 78d73044e9..0000000000 --- a/src/main/utils/channel/channel-listeners/start-listening-of-channels.injectable.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import { onLoadOfApplicationInjectionToken } from "../../../start-main-application/runnable-tokens/on-load-of-application-injection-token"; -import listeningOfChannelsInjectable from "../../../../common/utils/channel/listening-of-channels.injectable"; - -const startListeningOfChannelsInjectable = getInjectable({ - id: "start-listening-of-channels-main", - - instantiate: (di) => { - const listeningOfChannels = di.inject(listeningOfChannelsInjectable); - - return { - id: "start-listening-of-channels-main", - run: async () => { - await listeningOfChannels.start(); - }, - }; - }, - - injectionToken: onLoadOfApplicationInjectionToken, -}); - -export default startListeningOfChannelsInjectable; diff --git a/src/main/utils/channel/channel-listeners/start-listening-on-channels.injectable.ts b/src/main/utils/channel/channel-listeners/start-listening-on-channels.injectable.ts new file mode 100644 index 0000000000..d1cf5d68d6 --- /dev/null +++ b/src/main/utils/channel/channel-listeners/start-listening-on-channels.injectable.ts @@ -0,0 +1,29 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { onLoadOfApplicationInjectionToken } from "../../../start-main-application/runnable-tokens/on-load-of-application-injection-token"; +import listeningOnMessageChannelsInjectable from "../../../../common/utils/channel/listening-on-message-channels.injectable"; +import listeningOnRequestChannelsInjectable from "./listening-on-request-channels.injectable"; + +const startListeningOnChannelsInjectable = getInjectable({ + id: "start-listening-on-channels-main", + + instantiate: (di) => { + const listeningOnMessageChannels = di.inject(listeningOnMessageChannelsInjectable); + const listeningOnRequestChannels = di.inject(listeningOnRequestChannelsInjectable); + + return { + id: "start-listening-on-channels-main", + run: async () => { + await listeningOnMessageChannels.start(); + await listeningOnRequestChannels.start(); + }, + }; + }, + + injectionToken: onLoadOfApplicationInjectionToken, +}); + +export default startListeningOnChannelsInjectable; diff --git a/src/main/utils/channel/message-to-channel.injectable.ts b/src/main/utils/channel/message-to-channel.injectable.ts index cbcdc2badd..1435ea59b5 100644 --- a/src/main/utils/channel/message-to-channel.injectable.ts +++ b/src/main/utils/channel/message-to-channel.injectable.ts @@ -3,9 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { messageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; -import type { MessageChannel } from "../../../common/utils/channel/message-channel-injection-token"; -import { tentativeStringifyJson } from "../../../common/utils/tentative-stringify-json"; +import type { SendMessageToChannel } from "../../../common/utils/channel/message-to-channel-injection-token"; +import { sendMessageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; import getVisibleWindowsInjectable from "../../start-main-application/lens-window/get-visible-windows.injectable"; const messageToChannelInjectable = getInjectable({ @@ -14,18 +13,14 @@ const messageToChannelInjectable = getInjectable({ instantiate: (di) => { const getVisibleWindows = di.inject(getVisibleWindowsInjectable); - // TODO: Figure out way to improve typing in internals - // Notice that this should be injected using "messageToChannelInjectionToken" which is typed correctly. - return (channel: MessageChannel, message?: unknown) => { - const stringifiedMessage = tentativeStringifyJson(message); - - getVisibleWindows().forEach((lensWindow) => - lensWindow.send({ channel: channel.id, data: stringifiedMessage ? [stringifiedMessage] : [] }), - ); - }; + return ((channel, data) => { + for (const window of getVisibleWindows()) { + window.send({ channel: channel.id, data }); + } + }) as SendMessageToChannel; }, - injectionToken: messageToChannelInjectionToken, + injectionToken: sendMessageToChannelInjectionToken, }); export default messageToChannelInjectable; diff --git a/src/main/utils/channel/message-to-channel.test.ts b/src/main/utils/channel/message-to-channel.test.ts deleted file mode 100644 index 6d5e83a548..0000000000 --- a/src/main/utils/channel/message-to-channel.test.ts +++ /dev/null @@ -1,148 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import type { MessageToChannel } from "../../../common/utils/channel/message-to-channel-injection-token"; -import { messageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; -import type { MessageChannel } from "../../../common/utils/channel/message-channel-injection-token"; -import type { LensWindow } from "../../start-main-application/lens-window/application-window/create-lens-window.injectable"; -import sendToChannelInElectronBrowserWindowInjectable from "../../start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable"; -import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; - -describe("message to channel from main", () => { - let messageToChannel: MessageToChannel; - let someTestWindow: LensWindow; - let someOtherTestWindow: LensWindow; - let sendToChannelInBrowserMock: jest.Mock; - - beforeEach(async () => { - const builder = getApplicationBuilder(); - - sendToChannelInBrowserMock = jest.fn(); - - builder.beforeApplicationStart(mainDi => { - mainDi.override(sendToChannelInElectronBrowserWindowInjectable, () => sendToChannelInBrowserMock); - }); - - await builder.startHidden(); - - someTestWindow = builder.applicationWindow.create("some-test-window-id"); - someOtherTestWindow = builder.applicationWindow.create("some-other-test-window-id"); - - messageToChannel = builder.mainDi.inject(messageToChannelInjectionToken); - }); - - it("given no visible windows, when messaging to channel, does not message to any window", () => { - messageToChannel(someChannel, "some-message"); - - expect(sendToChannelInBrowserMock).not.toHaveBeenCalled(); - }); - - describe("given started window", () => { - beforeEach(async () => { - await someTestWindow.start(); - }); - - it("when messaging to channel, messages to window", () => { - messageToChannel(someChannel, "some-message"); - - expect(sendToChannelInBrowserMock.mock.calls).toEqual([ - [ - "some-test-window-id", - - null, - - { - channel: "some-channel", - data: ['"some-message"'], - }, - ], - ]); - }); - - it("given boolean as message, when messaging to channel, messages to window with stringified message", () => { - messageToChannel(someChannel, true); - - expect(sendToChannelInBrowserMock.mock.calls).toEqual([ - [ - "some-test-window-id", - - null, - - { - channel: "some-channel", - data: ["true"], - }, - ], - ]); - }); - - it("given number as message, when messaging to channel, messages to window with stringified message", () => { - messageToChannel(someChannel, 42); - - expect(sendToChannelInBrowserMock.mock.calls).toEqual([ - [ - "some-test-window-id", - - null, - - { - channel: "some-channel", - data: ["42"], - }, - ], - ]); - }); - - it("given object as message, when messaging to channel, messages to window with stringified message", () => { - messageToChannel(someChannel, { some: "object" }); - - expect(sendToChannelInBrowserMock.mock.calls).toEqual([ - [ - "some-test-window-id", - - null, - - { - channel: "some-channel", - data: [JSON.stringify({ some: "object" })], - }, - ], - ]); - }); - }); - - it("given multiple started windows, when messaging to channel, messages to window", async () => { - await someTestWindow.start(); - await someOtherTestWindow.start(); - - messageToChannel(someChannel, "some-message"); - - expect(sendToChannelInBrowserMock.mock.calls).toEqual([ - [ - "some-test-window-id", - - null, - - { - channel: "some-channel", - data: ['"some-message"'], - }, - ], - - [ - "some-other-test-window-id", - - null, - - { - channel: "some-channel", - data: ['"some-message"'], - }, - ], - ]); - }); -}); - -const someChannel: MessageChannel = { id: "some-channel" }; diff --git a/src/main/utils/resolve-system-proxy/resolve-system-proxy-channel-responder.injectable.ts b/src/main/utils/resolve-system-proxy/resolve-system-proxy-channel-responder.injectable.ts index c7a1747770..a2cd605633 100644 --- a/src/main/utils/resolve-system-proxy/resolve-system-proxy-channel-responder.injectable.ts +++ b/src/main/utils/resolve-system-proxy/resolve-system-proxy-channel-responder.injectable.ts @@ -2,20 +2,13 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getInjectable } from "@ogre-tools/injectable"; -import resolveSystemProxyChannelInjectable from "../../../common/utils/resolve-system-proxy/resolve-system-proxy-channel.injectable"; +import { resolveSystemProxyChannel } from "../../../common/utils/resolve-system-proxy/resolve-system-proxy-channel"; +import { getRequestChannelListenerInjectable } from "../channel/channel-listeners/listener-tokens"; import resolveSystemProxyInjectable from "./resolve-system-proxy.injectable"; -import { requestChannelListenerInjectionToken } from "../../../common/utils/channel/request-channel-listener-injection-token"; -const resolveSystemProxyChannelResponderInjectable = getInjectable({ - id: "resolve-system-proxy-channel-responder", - - instantiate: (di) => ({ - channel: di.inject(resolveSystemProxyChannelInjectable), - handler: di.inject(resolveSystemProxyInjectable), - }), - - injectionToken: requestChannelListenerInjectionToken, +const resolveSystemProxyChannelResponderInjectable = getRequestChannelListenerInjectable({ + channel: resolveSystemProxyChannel, + handler: (di) => di.inject(resolveSystemProxyInjectable), }); export default resolveSystemProxyChannelResponderInjectable; diff --git a/src/main/utils/sync-box/sync-box-initial-value-channel-listener.injectable.ts b/src/main/utils/sync-box/sync-box-initial-value-channel-listener.injectable.ts index 5eb043291a..da78d76c36 100644 --- a/src/main/utils/sync-box/sync-box-initial-value-channel-listener.injectable.ts +++ b/src/main/utils/sync-box/sync-box-initial-value-channel-listener.injectable.ts @@ -2,30 +2,20 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getInjectable } from "@ogre-tools/injectable"; -import syncBoxInitialValueChannelInjectable from "../../../common/utils/sync-box/sync-box-initial-value-channel.injectable"; +import { syncBoxInitialValueChannel } from "../../../common/utils/sync-box/channels"; import { syncBoxInjectionToken } from "../../../common/utils/sync-box/sync-box-injection-token"; -import { requestChannelListenerInjectionToken } from "../../../common/utils/channel/request-channel-listener-injection-token"; +import { getRequestChannelListenerInjectable } from "../channel/channel-listeners/listener-tokens"; -const syncBoxInitialValueChannelListenerInjectable = getInjectable({ - id: "sync-box-initial-value-channel-listener", - - instantiate: (di) => { - const channel = di.inject(syncBoxInitialValueChannelInjectable); +const syncBoxInitialValueChannelListenerInjectable = getRequestChannelListenerInjectable({ + channel: syncBoxInitialValueChannel, + handler: (di) => { const syncBoxes = di.injectMany(syncBoxInjectionToken); - return { - channel, - - handler: () => - syncBoxes.map((box) => ({ - id: box.id, - value: box.value.get(), - })), - }; + return () => syncBoxes.map((box) => ({ + id: box.id, + value: box.value.get(), + })); }, - - injectionToken: requestChannelListenerInjectionToken, }); export default syncBoxInitialValueChannelListenerInjectable; diff --git a/src/renderer/app-paths/setup-app-paths.injectable.ts b/src/renderer/app-paths/setup-app-paths.injectable.ts index 3660ad9db8..50ad4df34a 100644 --- a/src/renderer/app-paths/setup-app-paths.injectable.ts +++ b/src/renderer/app-paths/setup-app-paths.injectable.ts @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import appPathsStateInjectable from "../../common/app-paths/app-paths-state.injectable"; import { beforeFrameStartsInjectionToken } from "../before-frame-starts/before-frame-starts-injection-token"; -import appPathsChannelInjectable from "../../common/app-paths/app-paths-channel.injectable"; +import { appPathsChannel } from "../../common/app-paths/app-paths-channel"; import { requestFromChannelInjectionToken } from "../../common/utils/channel/request-from-channel-injection-token"; const setupAppPathsInjectable = getInjectable({ @@ -13,15 +13,12 @@ const setupAppPathsInjectable = getInjectable({ instantiate: (di) => { const requestFromChannel = di.inject(requestFromChannelInjectionToken); - const appPathsChannel = di.inject(appPathsChannelInjectable); const appPathsState = di.inject(appPathsStateInjectable); return { id: "setup-app-paths", run: async () => { - const appPaths = await requestFromChannel( - appPathsChannel, - ); + const appPaths = await requestFromChannel(appPathsChannel); appPathsState.set(appPaths); }, diff --git a/src/renderer/components/+preferences/kubernetes/helm-charts/active-helm-repositories.injectable.ts b/src/renderer/components/+preferences/kubernetes/helm-charts/active-helm-repositories.injectable.ts index 94fdeaa393..2894e88b09 100644 --- a/src/renderer/components/+preferences/kubernetes/helm-charts/active-helm-repositories.injectable.ts +++ b/src/renderer/components/+preferences/kubernetes/helm-charts/active-helm-repositories.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { asyncComputed } from "@ogre-tools/injectable-react"; -import getActiveHelmRepositoriesChannelInjectable from "../../../../../common/helm/get-active-helm-repositories-channel.injectable"; +import { getActiveHelmRepositoriesChannel } from "../../../../../common/helm/get-active-helm-repositories-channel"; import { requestFromChannelInjectionToken } from "../../../../../common/utils/channel/request-from-channel-injection-token"; import showErrorNotificationInjectable from "../../../notifications/show-error-notification.injectable"; import helmRepositoriesErrorStateInjectable from "./helm-repositories-error-state.injectable"; @@ -15,12 +15,11 @@ const activeHelmRepositoriesInjectable = getInjectable({ instantiate: (di) => { const requestFromChannel = di.inject(requestFromChannelInjectionToken); - const getHelmRepositoriesChannel = di.inject(getActiveHelmRepositoriesChannelInjectable); const showErrorNotification = di.inject(showErrorNotificationInjectable); const helmRepositoriesErrorState = di.inject(helmRepositoriesErrorStateInjectable); return asyncComputed(async () => { - const result = await requestFromChannel(getHelmRepositoriesChannel); + const result = await requestFromChannel(getActiveHelmRepositoriesChannel); if (result.callWasSuccessful) { return result.response; diff --git a/src/renderer/components/+preferences/kubernetes/helm-charts/adding-of-public-helm-repository/select-helm-repository/add-helm-repository.injectable.ts b/src/renderer/components/+preferences/kubernetes/helm-charts/adding-of-public-helm-repository/select-helm-repository/add-helm-repository.injectable.ts index 50e02f4235..9a2370635b 100644 --- a/src/renderer/components/+preferences/kubernetes/helm-charts/adding-of-public-helm-repository/select-helm-repository/add-helm-repository.injectable.ts +++ b/src/renderer/components/+preferences/kubernetes/helm-charts/adding-of-public-helm-repository/select-helm-repository/add-helm-repository.injectable.ts @@ -3,19 +3,18 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import addHelmRepositoryChannelInjectable from "../../../../../../../common/helm/add-helm-repository-channel.injectable"; import type { HelmRepo } from "../../../../../../../common/helm/helm-repo"; import { requestFromChannelInjectionToken } from "../../../../../../../common/utils/channel/request-from-channel-injection-token"; import activeHelmRepositoriesInjectable from "../../active-helm-repositories.injectable"; import showErrorNotificationInjectable from "../../../../../notifications/show-error-notification.injectable"; import showSuccessNotificationInjectable from "../../../../../notifications/show-success-notification.injectable"; +import { addHelmRepositoryChannel } from "../../../../../../../common/helm/add-helm-repository-channel"; const addHelmRepositoryInjectable = getInjectable({ id: "add-public-helm-repository", instantiate: (di) => { const requestFromChannel = di.inject(requestFromChannelInjectionToken); - const addHelmRepositoryChannel = di.inject(addHelmRepositoryChannelInjectable); const activeHelmRepositories = di.inject(activeHelmRepositoriesInjectable); const showErrorNotification = di.inject(showErrorNotificationInjectable); const showSuccessNotification = di.inject(showSuccessNotificationInjectable); diff --git a/src/renderer/components/+preferences/kubernetes/helm-charts/remove-helm-repository.injectable.ts b/src/renderer/components/+preferences/kubernetes/helm-charts/remove-helm-repository.injectable.ts index 4f316baed0..3aa56a4b04 100644 --- a/src/renderer/components/+preferences/kubernetes/helm-charts/remove-helm-repository.injectable.ts +++ b/src/renderer/components/+preferences/kubernetes/helm-charts/remove-helm-repository.injectable.ts @@ -6,14 +6,13 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { HelmRepo } from "../../../../../common/helm/helm-repo"; import { requestFromChannelInjectionToken } from "../../../../../common/utils/channel/request-from-channel-injection-token"; import activeHelmRepositoriesInjectable from "./active-helm-repositories.injectable"; -import removeHelmRepositoryChannelInjectable from "../../../../../common/helm/remove-helm-repository-channel.injectable"; +import { removeHelmRepositoryChannel } from "../../../../../common/helm/remove-helm-repository-channel"; const removePublicHelmRepositoryInjectable = getInjectable({ id: "remove-public-helm-repository", instantiate: (di) => { const requestFromChannel = di.inject(requestFromChannelInjectionToken); - const removeHelmRepositoryChannel = di.inject(removeHelmRepositoryChannelInjectable); const activeHelmRepositories = di.inject(activeHelmRepositoriesInjectable); return async (repository: HelmRepo) => { diff --git a/src/renderer/components/test-utils/get-application-builder.tsx b/src/renderer/components/test-utils/get-application-builder.tsx index 7d6630be82..45f33bdc9e 100644 --- a/src/renderer/components/test-utils/get-application-builder.tsx +++ b/src/renderer/components/test-utils/get-application-builder.tsx @@ -61,7 +61,6 @@ import createApplicationWindowInjectable from "../../../main/start-main-applicat import type { CreateElectronWindow } from "../../../main/start-main-application/lens-window/application-window/create-electron-window.injectable"; import createElectronWindowInjectable from "../../../main/start-main-application/lens-window/application-window/create-electron-window.injectable"; import { applicationWindowInjectionToken } from "../../../main/start-main-application/lens-window/application-window/application-window-injection-token"; -import sendToChannelInElectronBrowserWindowInjectable from "../../../main/start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable"; import closeAllWindowsInjectable from "../../../main/start-main-application/lens-window/hide-all-windows/close-all-windows.injectable"; import type { LensWindow } from "../../../main/start-main-application/lens-window/application-window/create-lens-window.injectable"; import type { FakeExtensionOptions } from "./get-extension-fake"; @@ -166,7 +165,7 @@ export const getApplicationBuilder = () => { mainDi.register(mainExtensionsStateInjectable); }); - const overrideChannelsForWindow = overrideChannels(mainDi); + const { overrideForWindow, sendToWindow } = overrideChannels(mainDi); const beforeApplicationStartCallbacks: Callback[] = []; const beforeWindowStartCallbacks: Callback[] = []; @@ -208,7 +207,7 @@ export const getApplicationBuilder = () => { const windowDi = getRendererDi({ doGeneralOverrides: true }); - overrideChannelsForWindow(windowDi, windowId); + overrideForWindow(windowDi, windowId); overrideFsWithFakes(windowDi, fsState); runInAction(() => { @@ -259,9 +258,7 @@ export const getApplicationBuilder = () => { }, send: (arg) => { - const sendFake = mainDi.inject(sendToChannelInElectronBrowserWindowInjectable) as any; - - sendFake(windowId, null, arg); + sendToWindow(windowId, arg); }, reload: () => { diff --git a/src/renderer/components/update-button/restart-and-install-update.injectable.ts b/src/renderer/components/update-button/restart-and-install-update.injectable.ts index 854e0a428f..83fb3d72a3 100644 --- a/src/renderer/components/update-button/restart-and-install-update.injectable.ts +++ b/src/renderer/components/update-button/restart-and-install-update.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import restartAndInstallUpdateChannel from "../../../common/application-update/restart-and-install-update-channel/restart-and-install-update-channel.injectable"; +import { restartAndInstallUpdateChannel } from "../../../common/application-update/restart-and-install-update-channel"; import messageToChannelInjectable from "../../utils/channel/message-to-channel.injectable"; const restartAndInstallUpdateInjectable = getInjectable({ @@ -11,10 +11,9 @@ const restartAndInstallUpdateInjectable = getInjectable({ instantiate: (di) => { const messageToChannel = di.inject(messageToChannelInjectable); - const channel = di.inject(restartAndInstallUpdateChannel); return () => { - messageToChannel(channel); + messageToChannel(restartAndInstallUpdateChannel); }; }, }); diff --git a/src/renderer/frames/root-frame/broadcast-that-root-frame-is-rendered.injectable.ts b/src/renderer/frames/root-frame/broadcast-that-root-frame-is-rendered.injectable.ts index e6493e2832..841d19e002 100644 --- a/src/renderer/frames/root-frame/broadcast-that-root-frame-is-rendered.injectable.ts +++ b/src/renderer/frames/root-frame/broadcast-that-root-frame-is-rendered.injectable.ts @@ -3,18 +3,17 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { messageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; -import rootFrameIsRenderedChannelInjectable from "../../../common/root-frame-rendered-channel/root-frame-rendered-channel.injectable"; +import { sendMessageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; +import { rootFrameHasRenderedChannel } from "../../../common/root-frame/root-frame-rendered-channel"; const broadcastThatRootFrameIsRenderedInjectable = getInjectable({ id: "broadcast-that-root-frame-is-rendered", instantiate: (di) => { - const messageToChannel = di.inject(messageToChannelInjectionToken); - const rootFrameIsRenderedChannel = di.inject(rootFrameIsRenderedChannelInjectable); + const messageToChannel = di.inject(sendMessageToChannelInjectionToken); return () => { - messageToChannel(rootFrameIsRenderedChannel); + messageToChannel(rootFrameHasRenderedChannel); }; }, }); diff --git a/src/renderer/navigation/events.ts b/src/renderer/navigation/events.ts index 35021e1d72..7cacd1b313 100644 --- a/src/renderer/navigation/events.ts +++ b/src/renderer/navigation/events.ts @@ -5,14 +5,11 @@ import { ipcRenderer } from "electron"; import { reaction } from "mobx"; -import { broadcastMessage, ipcRendererOn } from "../../common/ipc"; -import { - getLegacyGlobalDiForExtensionApi, -} from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; +import { broadcastMessage } from "../../common/ipc"; +import { getLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; import matchedClusterIdInjectable from "./matched-cluster-id.injectable"; export const enum IpcRendererNavigationEvents { - RELOAD_PAGE = "renderer:page-reload", CLUSTER_VIEW_CURRENT_ID = "renderer:cluster-id-of-active-view", NAVIGATE_IN_APP = "renderer:navigate", NAVIGATE_IN_CLUSTER = "renderer:navigate-in-cluster", @@ -27,11 +24,6 @@ export function bindEvents() { if (process.isMainFrame) { bindClusterManagerRouteEvents(); } - - // Reload dashboard window - ipcRendererOn(IpcRendererNavigationEvents.RELOAD_PAGE, () => { - location.reload(); - }); } // Handle events only in main window renderer process (see also: cluster-manager.tsx) diff --git a/src/renderer/navigation/navigation-channel-listener.injectable.ts b/src/renderer/navigation/navigation-channel-listener.injectable.ts index 3a17451071..1b33b4fe2c 100644 --- a/src/renderer/navigation/navigation-channel-listener.injectable.ts +++ b/src/renderer/navigation/navigation-channel-listener.injectable.ts @@ -2,12 +2,14 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ +import type { InjectionToken } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable"; import currentlyInClusterFrameInjectable from "../routes/currently-in-cluster-frame.injectable"; -import appNavigationChannelInjectable from "../../common/front-end-routing/app-navigation-channel.injectable"; -import clusterFrameNavigationChannelInjectable from "../../common/front-end-routing/cluster-frame-navigation-channel.injectable"; +import { appNavigationChannel } from "../../common/front-end-routing/app-navigation-channel"; +import { clusterFrameNavigationChannel } from "../../common/front-end-routing/cluster-frame-navigation-channel"; import focusWindowInjectable from "./focus-window.injectable"; import { navigateToUrlInjectionToken } from "../../common/front-end-routing/navigate-to-url-injection-token"; +import type { MessageChannel, MessageChannelListener } from "../../common/utils/channel/message-channel-listener-injection-token"; import { messageChannelListenerInjectionToken } from "../../common/utils/channel/message-channel-listener-injection-token"; const navigationChannelListenerInjectable = getInjectable({ @@ -15,8 +17,6 @@ const navigationChannelListenerInjectable = getInjectable({ instantiate: (di) => { const currentlyInClusterFrame = di.inject(currentlyInClusterFrameInjectable); - const appNavigationChannel = di.inject(appNavigationChannelInjectable); - const clusterFrameNavigationChannel = di.inject(clusterFrameNavigationChannelInjectable); const focusWindow = di.inject(focusWindowInjectable); const navigateToUrl = di.inject(navigateToUrlInjectionToken); @@ -34,7 +34,7 @@ const navigationChannelListenerInjectable = getInjectable({ }, }; }, - injectionToken: messageChannelListenerInjectionToken, + injectionToken: messageChannelListenerInjectionToken as InjectionToken>, void>, }); export default navigationChannelListenerInjectable; diff --git a/src/renderer/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts b/src/renderer/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts index 6d76e35340..1e5b14bb40 100644 --- a/src/renderer/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts +++ b/src/renderer/utils/channel/channel-listeners/enlist-message-channel-listener.injectable.ts @@ -6,8 +6,6 @@ import ipcRendererInjectable from "../ipc-renderer.injectable"; import { getInjectable } from "@ogre-tools/injectable"; import type { IpcRendererEvent } from "electron"; import { enlistMessageChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-message-channel-listener-injection-token"; -import { tentativeParseJson } from "../../../../common/utils/tentative-parse-json"; -import { pipeline } from "@ogre-tools/fp"; const enlistMessageChannelListenerInjectable = getInjectable({ id: "enlist-message-channel-listener-for-renderer", @@ -17,11 +15,7 @@ const enlistMessageChannelListenerInjectable = getInjectable({ return ({ channel, handler }) => { const nativeCallback = (_: IpcRendererEvent, message: unknown) => { - pipeline( - message, - tentativeParseJson, - handler, - ); + handler(message); }; ipcRenderer.on(channel.id, nativeCallback); diff --git a/src/renderer/utils/channel/channel-listeners/enlist-message-channel-listener.test.ts b/src/renderer/utils/channel/channel-listeners/enlist-message-channel-listener.test.ts index 4653dcdd5d..f5555d94f3 100644 --- a/src/renderer/utils/channel/channel-listeners/enlist-message-channel-listener.test.ts +++ b/src/renderer/utils/channel/channel-listeners/enlist-message-channel-listener.test.ts @@ -88,8 +88,8 @@ describe("enlist message channel listener in renderer", () => { expect(handlerMock).toHaveBeenCalledWith(true); }); - it("given stringified object as message, when message arrives, calls the handler with the message", () => { - onMock.mock.calls[0][1]({} as IpcRendererEvent, JSON.stringify({ some: "object" })); + it("given object as message, when message arrives, calls the handler with the message", () => { + onMock.mock.calls[0][1]({} as IpcRendererEvent, { some: "object" }); expect(handlerMock).toHaveBeenCalledWith({ some: "object" }); }); diff --git a/src/renderer/utils/channel/channel-listeners/enlist-request-channel-listener.injectable.ts b/src/renderer/utils/channel/channel-listeners/enlist-request-channel-listener.injectable.ts deleted file mode 100644 index 03253a06f2..0000000000 --- a/src/renderer/utils/channel/channel-listeners/enlist-request-channel-listener.injectable.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import { enlistRequestChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-request-channel-listener-injection-token"; - -const enlistRequestChannelListenerInjectable = getInjectable({ - id: "enlist-request-channel-listener-for-renderer", - - instantiate: () => { - // Requests from main to renderer are not implemented yet. - return () => () => {}; - }, - - injectionToken: enlistRequestChannelListenerInjectionToken, -}); - -export default enlistRequestChannelListenerInjectable; diff --git a/src/renderer/utils/channel/channel-listeners/start-listening-of-channels.injectable.ts b/src/renderer/utils/channel/channel-listeners/start-listening-of-channels.injectable.ts index e423299915..3b10ef6bd9 100644 --- a/src/renderer/utils/channel/channel-listeners/start-listening-of-channels.injectable.ts +++ b/src/renderer/utils/channel/channel-listeners/start-listening-of-channels.injectable.ts @@ -4,13 +4,13 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { beforeFrameStartsInjectionToken } from "../../../before-frame-starts/before-frame-starts-injection-token"; -import listeningOfChannelsInjectable from "../../../../common/utils/channel/listening-of-channels.injectable"; +import listeningOnMessageChannelsInjectable from "../../../../common/utils/channel/listening-on-message-channels.injectable"; const startListeningOfChannelsInjectable = getInjectable({ id: "start-listening-of-channels-renderer", instantiate: (di) => { - const listeningOfChannels = di.inject(listeningOfChannelsInjectable); + const listeningOfChannels = di.inject(listeningOnMessageChannelsInjectable); return { id: "start-listening-of-channels-renderer", diff --git a/src/renderer/utils/channel/message-to-channel.injectable.ts b/src/renderer/utils/channel/message-to-channel.injectable.ts index 3e493fd322..eab7e4ec7f 100644 --- a/src/renderer/utils/channel/message-to-channel.injectable.ts +++ b/src/renderer/utils/channel/message-to-channel.injectable.ts @@ -3,9 +3,9 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { messageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; +import type { SendMessageToChannel } from "../../../common/utils/channel/message-to-channel-injection-token"; +import { sendMessageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; import sendToMainInjectable from "./send-to-main.injectable"; -import type { MessageChannel } from "../../../common/utils/channel/message-channel-injection-token"; const messageToChannelInjectable = getInjectable({ id: "message-to-channel", @@ -13,14 +13,12 @@ const messageToChannelInjectable = getInjectable({ instantiate: (di) => { const sendToMain = di.inject(sendToMainInjectable); - // TODO: Figure out way to improve typing in internals - // Notice that this should be injected using "messageToChannelInjectionToken" which is typed correctly. - return (channel: MessageChannel, message?: unknown) => { + return ((channel, message) => { sendToMain(channel.id, message); - }; + }) as SendMessageToChannel; }, - injectionToken: messageToChannelInjectionToken, + injectionToken: sendMessageToChannelInjectionToken, }); export default messageToChannelInjectable; diff --git a/src/renderer/utils/channel/message-to-channel.test.ts b/src/renderer/utils/channel/message-to-channel.test.ts deleted file mode 100644 index 443abfb0dc..0000000000 --- a/src/renderer/utils/channel/message-to-channel.test.ts +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import type { MessageToChannel } from "../../../common/utils/channel/message-to-channel-injection-token"; -import type { MessageChannel } from "../../../common/utils/channel/message-channel-injection-token"; -import { getDiForUnitTesting } from "../../getDiForUnitTesting"; -import { messageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; -import ipcRendererInjectable from "./ipc-renderer.injectable"; -import type { IpcRenderer } from "electron"; - -describe("message to channel from renderer", () => { - let messageToChannel: MessageToChannel; - let sendMock: jest.Mock; - - beforeEach(() => { - const di = getDiForUnitTesting({ doGeneralOverrides: true }); - - sendMock = jest.fn(); - - di.override(ipcRendererInjectable, () => ({ - send: sendMock, - }) as unknown as IpcRenderer); - - messageToChannel = di.inject(messageToChannelInjectionToken); - }); - - it("given string as message, when messaging to channel, sends stringified message", () => { - messageToChannel(someChannel, "some-message"); - - expect(sendMock).toHaveBeenCalledWith("some-channel-id", '"some-message"'); - }); - - it("given boolean as message, when messaging to channel, sends stringified message", () => { - messageToChannel(someChannel, true); - - expect(sendMock).toHaveBeenCalledWith("some-channel-id", "true"); - }); - - it("given number as message, when messaging to channel, sends stringified message", () => { - messageToChannel(someChannel, 42); - - expect(sendMock).toHaveBeenCalledWith("some-channel-id", "42"); - }); - - it("given object as message, when messaging to channel, sends stringified message", () => { - messageToChannel(someChannel, { some: "object" }); - - expect(sendMock).toHaveBeenCalledWith( - "some-channel-id", - JSON.stringify({ some: "object" }), - ); - }); -}); - -const someChannel: MessageChannel = { id: "some-channel-id" }; diff --git a/src/renderer/utils/channel/request-from-channel.injectable.ts b/src/renderer/utils/channel/request-from-channel.injectable.ts index f77287a2ed..fd0815b1a3 100644 --- a/src/renderer/utils/channel/request-from-channel.injectable.ts +++ b/src/renderer/utils/channel/request-from-channel.injectable.ts @@ -4,10 +4,8 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import ipcRendererInjectable from "./ipc-renderer.injectable"; +import type { RequestFromChannel } from "../../../common/utils/channel/request-from-channel-injection-token"; import { requestFromChannelInjectionToken } from "../../../common/utils/channel/request-from-channel-injection-token"; -import { pipeline } from "@ogre-tools/fp"; -import { tentativeStringifyJson } from "../../../common/utils/tentative-stringify-json"; -import { tentativeParseJson } from "../../../common/utils/tentative-parse-json"; const requestFromChannelInjectable = getInjectable({ id: "request-from-channel", @@ -15,13 +13,7 @@ const requestFromChannelInjectable = getInjectable({ instantiate: (di) => { const ipcRenderer = di.inject(ipcRendererInjectable); - return async (channel, ...[request]) => - await pipeline( - request, - tentativeStringifyJson, - (req) => ipcRenderer.invoke(channel.id, req), - tentativeParseJson, - ); + return ((channel, request) => ipcRenderer.invoke(channel.id, request)) as RequestFromChannel; }, injectionToken: requestFromChannelInjectionToken, diff --git a/src/renderer/utils/channel/request-from-channel.test.ts b/src/renderer/utils/channel/request-from-channel.test.ts deleted file mode 100644 index d7b343bf02..0000000000 --- a/src/renderer/utils/channel/request-from-channel.test.ts +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import type { MessageChannel } from "../../../common/utils/channel/message-channel-injection-token"; -import { getDiForUnitTesting } from "../../getDiForUnitTesting"; -import ipcRendererInjectable from "./ipc-renderer.injectable"; -import type { IpcRenderer } from "electron"; -import type { AsyncFnMock } from "@async-fn/jest"; -import asyncFn from "@async-fn/jest"; -import type { RequestFromChannel } from "../../../common/utils/channel/request-from-channel-injection-token"; -import { requestFromChannelInjectionToken } from "../../../common/utils/channel/request-from-channel-injection-token"; -import requestFromChannelInjectable from "./request-from-channel.injectable"; -import { getPromiseStatus } from "../../../common/test-utils/get-promise-status"; - -describe("request from channel in renderer", () => { - let requestFromChannel: RequestFromChannel; - let invokeMock: AsyncFnMock<(channelId: string, request: any) => any>; - - beforeEach(() => { - const di = getDiForUnitTesting({ doGeneralOverrides: true }); - - di.unoverride(requestFromChannelInjectable); - - invokeMock = asyncFn(); - - di.override(ipcRendererInjectable, () => ({ - invoke: invokeMock, - }) as unknown as IpcRenderer); - - requestFromChannel = di.inject(requestFromChannelInjectionToken); - }); - - describe("when messaging to channel", () => { - let actualPromise: Promise; - - beforeEach(() => { - actualPromise = requestFromChannel(someChannel, "some-message"); - }); - - it("sends stringified message", () => { - expect(invokeMock).toHaveBeenCalledWith("some-channel-id", '"some-message"'); - }); - - it("does not resolve yet", async () => { - const promiseStatus = await getPromiseStatus(actualPromise); - - expect(promiseStatus.fulfilled).toBe(false); - }); - - it("when invoking resolves, resolves", async () => { - await invokeMock.resolve("some-response"); - - const actual = await actualPromise; - - expect(actual).toBe("some-response"); - }); - - it("when invoking resolves with stringified string, resolves with string", async () => { - await invokeMock.resolve('"some-response"'); - - const actual = await actualPromise; - - expect(actual).toBe("some-response"); - }); - - it("when invoking resolves with stringified boolean, resolves with boolean", async () => { - await invokeMock.resolve("true"); - - const actual = await actualPromise; - - expect(actual).toBe(true); - }); - - it("when invoking resolves with stringified number, resolves with number", async () => { - await invokeMock.resolve("42"); - - const actual = await actualPromise; - - expect(actual).toBe(42); - }); - - it("when invoking resolves with stringified object, resolves with object", async () => { - await invokeMock.resolve(JSON.stringify({ some: "object" })); - - const actual = await actualPromise; - - expect(actual).toEqual({ some: "object" }); - }); - }); - - it("given string as message, when messaging to channel, sends stringified message", () => { - requestFromChannel(someChannel, "some-message"); - - expect(invokeMock).toHaveBeenCalledWith("some-channel-id", '"some-message"'); - }); - - it("given boolean as message, when messaging to channel, sends stringified message", () => { - requestFromChannel(someChannel, true); - - expect(invokeMock).toHaveBeenCalledWith("some-channel-id", "true"); - }); - - it("given number as message, when messaging to channel, sends stringified message", () => { - requestFromChannel(someChannel, 42); - - expect(invokeMock).toHaveBeenCalledWith("some-channel-id", "42"); - }); - - it("given object as message, when messaging to channel, sends stringified message", () => { - requestFromChannel(someChannel, { some: "object" }); - - expect(invokeMock).toHaveBeenCalledWith( - "some-channel-id", - JSON.stringify({ some: "object" }), - ); - }); -}); - -const someChannel: MessageChannel = { id: "some-channel-id" }; diff --git a/src/renderer/utils/channel/send-to-main.injectable.ts b/src/renderer/utils/channel/send-to-main.injectable.ts index 0811a78798..6eb4540062 100644 --- a/src/renderer/utils/channel/send-to-main.injectable.ts +++ b/src/renderer/utils/channel/send-to-main.injectable.ts @@ -3,9 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import type { JsonValue } from "type-fest"; import ipcRendererInjectable from "./ipc-renderer.injectable"; -import { tentativeStringifyJson } from "../../../common/utils/tentative-stringify-json"; const sendToMainInjectable = getInjectable({ id: "send-to-main", @@ -13,11 +11,8 @@ const sendToMainInjectable = getInjectable({ instantiate: (di) => { const ipcRenderer = di.inject(ipcRendererInjectable); - // TODO: Figure out way to improve typing in internals - return (channelId: string, message: JsonValue extends T ? T : never ) => { - const stringifiedMessage = tentativeStringifyJson(message); - - ipcRenderer.send(channelId, ...(stringifiedMessage ? [stringifiedMessage] : [])); + return (channelId: string, message: any) => { + ipcRenderer.send(channelId, message); }; }, }); diff --git a/src/renderer/utils/resolve-proxy/resolve-system-proxy.injectable.ts b/src/renderer/utils/resolve-proxy/resolve-system-proxy.injectable.ts index 8fcb9063d0..5468a8c7b7 100644 --- a/src/renderer/utils/resolve-proxy/resolve-system-proxy.injectable.ts +++ b/src/renderer/utils/resolve-proxy/resolve-system-proxy.injectable.ts @@ -5,14 +5,13 @@ import { getInjectable } from "@ogre-tools/injectable"; import { resolveSystemProxyInjectionToken } from "../../../common/utils/resolve-system-proxy/resolve-system-proxy-injection-token"; import requestFromChannelInjectable from "../channel/request-from-channel.injectable"; -import resolveSystemProxyChannelInjectable from "../../../common/utils/resolve-system-proxy/resolve-system-proxy-channel.injectable"; +import { resolveSystemProxyChannel } from "../../../common/utils/resolve-system-proxy/resolve-system-proxy-channel"; const resolveSystemProxyInjectable = getInjectable({ id: "resolve-system-proxy-for-renderer", instantiate: (di) => { const requestFromChannel = di.inject(requestFromChannelInjectable); - const resolveSystemProxyChannel = di.inject(resolveSystemProxyChannelInjectable); return async (url) => requestFromChannel(resolveSystemProxyChannel, url); }, diff --git a/src/renderer/utils/sync-box/provide-initial-values-for-sync-boxes.injectable.ts b/src/renderer/utils/sync-box/provide-initial-values-for-sync-boxes.injectable.ts index f7d692cdef..b356aa0b32 100644 --- a/src/renderer/utils/sync-box/provide-initial-values-for-sync-boxes.injectable.ts +++ b/src/renderer/utils/sync-box/provide-initial-values-for-sync-boxes.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { beforeFrameStartsInjectionToken } from "../../before-frame-starts/before-frame-starts-injection-token"; -import syncBoxInitialValueChannelInjectable from "../../../common/utils/sync-box/sync-box-initial-value-channel.injectable"; +import { syncBoxInitialValueChannel } from "../../../common/utils/sync-box/channels"; import createSyncBoxStateInjectable from "../../../common/utils/sync-box/sync-box-state.injectable"; import { requestFromChannelInjectionToken } from "../../../common/utils/channel/request-from-channel-injection-token"; import { runInAction } from "mobx"; @@ -17,7 +17,6 @@ const provideInitialValuesForSyncBoxesInjectable = getInjectable({ instantiate: (di) => { const requestFromChannel = di.inject(requestFromChannelInjectionToken); - const syncBoxInitialValueChannel = di.inject(syncBoxInitialValueChannelInjectable); const syncBoxes = di.injectMany(syncBoxInjectionToken); diff --git a/src/test-utils/channel-fakes/override-channels.ts b/src/test-utils/channel-fakes/override-channels.ts index 7d3a20cd75..798fcd84af 100644 --- a/src/test-utils/channel-fakes/override-channels.ts +++ b/src/test-utils/channel-fakes/override-channels.ts @@ -3,18 +3,27 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import type { DiContainer } from "@ogre-tools/injectable"; +import type { SendToViewArgs } from "../../main/start-main-application/lens-window/application-window/create-lens-window.injectable"; import { overrideMessagingFromMainToWindow } from "./override-messaging-from-main-to-window"; import { overrideMessagingFromWindowToMain } from "./override-messaging-from-window-to-main"; import { overrideRequestingFromWindowToMain } from "./override-requesting-from-window-to-main"; -export const overrideChannels = (mainDi: DiContainer) => { - const overrideMessagingFromMainToWindowForWindow = overrideMessagingFromMainToWindow(mainDi); +export interface OverrideChannels { + overrideForWindow: (windowDi: DiContainer, windowId: string) => void; + sendToWindow: (windowId: string, args: SendToViewArgs) => void; +} + +export const overrideChannels = (mainDi: DiContainer): OverrideChannels => { + const { overrideEnlistForWindow, sendToWindow } = overrideMessagingFromMainToWindow(); const overrideMessagingFromWindowToForWindow = overrideMessagingFromWindowToMain(mainDi); const overrideRequestingFromWindowToMainForWindow = overrideRequestingFromWindowToMain(mainDi); - return (windowDi: DiContainer, windowId: string) => { - overrideMessagingFromMainToWindowForWindow(windowDi, windowId); - overrideMessagingFromWindowToForWindow(windowDi); - overrideRequestingFromWindowToMainForWindow(windowDi); + return { + overrideForWindow: (windowDi, windowId) => { + overrideEnlistForWindow(windowDi, windowId); + overrideMessagingFromWindowToForWindow(windowDi); + overrideRequestingFromWindowToMainForWindow(windowDi); + }, + sendToWindow, }; }; diff --git a/src/test-utils/channel-fakes/override-messaging-from-main-to-window.ts b/src/test-utils/channel-fakes/override-messaging-from-main-to-window.ts index 852b2cfb0b..f9275c18b2 100644 --- a/src/test-utils/channel-fakes/override-messaging-from-main-to-window.ts +++ b/src/test-utils/channel-fakes/override-messaging-from-main-to-window.ts @@ -3,18 +3,22 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import type { MessageChannelListener } from "../../common/utils/channel/message-channel-listener-injection-token"; -import sendToChannelInElectronBrowserWindowInjectable from "../../main/start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable"; -import type { SendToViewArgs } from "../../main/start-main-application/lens-window/application-window/create-lens-window.injectable"; import enlistMessageChannelListenerInjectableInRenderer from "../../renderer/utils/channel/channel-listeners/enlist-message-channel-listener.injectable"; import type { DiContainer } from "@ogre-tools/injectable"; -import { tentativeParseJson } from "../../common/utils/tentative-parse-json"; -import { getOrInsert } from "../../common/utils"; +import { getOrInsert, getOrInsertSet } from "../../common/utils"; +import type { SendToViewArgs } from "../../main/start-main-application/lens-window/application-window/create-lens-window.injectable"; +import { deserialize, serialize } from "v8"; type ListenerSet = Set>; type WindowListenerMap = Map; type ListenerFakeMap = Map; -export const overrideMessagingFromMainToWindow = (mainDi: DiContainer) => { +export interface OverriddenWindowMessaging { + sendToWindow(windowId: string, args: SendToViewArgs): void; + overrideEnlistForWindow(windowDi: DiContainer, windowId: string): void; +} + +export const overrideMessagingFromMainToWindow = (): OverriddenWindowMessaging => { const messageChannelListenerFakesForRenderer: ListenerFakeMap = new Map(); const getWindowListeners = (channelId: string, windowId: string) => { @@ -24,68 +28,52 @@ export const overrideMessagingFromMainToWindow = (mainDi: DiContainer) => { new Map(), ); - return getOrInsert( - channelListeners, - windowId, - new Set(), - ); + return getOrInsertSet(channelListeners, windowId); }; - mainDi.override( - sendToChannelInElectronBrowserWindowInjectable, + return { + overrideEnlistForWindow: (windowDi, windowId) => { + windowDi.override( + enlistMessageChannelListenerInjectableInRenderer, - () => - ( - windowId: string, - browserWindow, - { channel: channelId, frameInfo, data = [] }: SendToViewArgs, - ) => { - const windowListeners = getWindowListeners(channelId, windowId); - - if (frameInfo) { - throw new Error( - `Tried to send message to frame "${frameInfo.frameId}" in process "${frameInfo.processId}" using channel "${channelId}" which isn't supported yet.`, + () => (listener) => { + const windowListeners = getWindowListeners( + listener.channel.id, + windowId, ); - } - if (data.length > 1) { - throw new Error( - `Tried to send message to channel "${channelId}" with more than one argument which is not supported in MessageChannelListener yet.`, - ); - } + windowListeners.add(listener); - if (windowListeners.size === 0) { - throw new Error( - `Tried to send message to channel "${channelId}" but there where no listeners. Current channels with listeners: "${[ - ...messageChannelListenerFakesForRenderer.keys(), - ].join('", "')}"`, - ); - } + return () => { + windowListeners.delete(listener); + }; + }, + ); + }, + sendToWindow: (windowId, { channel, data, frameInfo }) => { + try { + data = deserialize(serialize(data)); + } catch (error) { + throw new Error(`Tried to send a message to channel "${channel}" that is not compatible with StructuredClone: ${error}`); + } - const message = tentativeParseJson(data[0]); + const windowListeners = getWindowListeners(channel, windowId); - windowListeners.forEach((listener) => - listener.handler(message), + if (frameInfo) { + throw new Error( + `Tried to send message to frame "${frameInfo.frameId}" in process "${frameInfo.processId}" using channel "${channel}" which isn't supported yet.`, ); - }, - ); + } - return (windowDi: DiContainer, windowId: string) => { - windowDi.override( - enlistMessageChannelListenerInjectableInRenderer, - - () => (listener) => { - const windowListeners = getWindowListeners( - listener.channel.id, - windowId, + if (windowListeners.size === 0) { + throw new Error( + `Tried to send message to channel "${channel}" but there where no listeners. Current channels with listeners: "${[ + ...messageChannelListenerFakesForRenderer.keys(), + ].join('", "')}"`, ); + } - windowListeners.add(listener); - - return () => { - windowListeners.delete(listener); - }; - }, - ); + windowListeners.forEach((listener) => listener.handler(data)); + }, }; }; diff --git a/src/test-utils/channel-fakes/override-messaging-from-window-to-main.ts b/src/test-utils/channel-fakes/override-messaging-from-window-to-main.ts index ba6813235b..f00f4e626c 100644 --- a/src/test-utils/channel-fakes/override-messaging-from-window-to-main.ts +++ b/src/test-utils/channel-fakes/override-messaging-from-window-to-main.ts @@ -3,54 +3,36 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import type { DiContainer } from "@ogre-tools/injectable"; -import assert from "assert"; -import type { MessageChannel } from "../../common/utils/channel/message-channel-injection-token"; -import type { MessageChannelListener } from "../../common/utils/channel/message-channel-listener-injection-token"; +import type { MessageChannel, MessageChannelListener } from "../../common/utils/channel/message-channel-listener-injection-token"; import enlistMessageChannelListenerInjectableInMain from "../../main/utils/channel/channel-listeners/enlist-message-channel-listener.injectable"; +import { getOrInsertSet } from "../../renderer/utils"; import sendToMainInjectable from "../../renderer/utils/channel/send-to-main.injectable"; export const overrideMessagingFromWindowToMain = (mainDi: DiContainer) => { const messageChannelListenerFakesForMain = new Map< string, - Set>> + Set>> >(); mainDi.override( enlistMessageChannelListenerInjectableInMain, () => (listener) => { - const channelId = listener.channel.id; + const listeners = getOrInsertSet(messageChannelListenerFakesForMain, listener.channel.id); - if (!messageChannelListenerFakesForMain.has(channelId)) { - messageChannelListenerFakesForMain.set(channelId, new Set()); - } - - const listeners = messageChannelListenerFakesForMain.get( - channelId, - ); - - assert(listeners); - - // TODO: Figure out typing - listeners.add( - listener as unknown as MessageChannelListener>, - ); + listeners.add(listener); return () => { - // TODO: Figure out typing - listeners.delete( - listener as unknown as MessageChannelListener>, - ); + listeners.delete(listener); }; }, ); return (windowDi: DiContainer) => { windowDi.override(sendToMainInjectable, () => (channelId, message) => { - const listeners = - messageChannelListenerFakesForMain.get(channelId) || new Set(); + const listeners = messageChannelListenerFakesForMain.get(channelId); - if (listeners.size === 0) { + if (!listeners || listeners.size === 0) { throw new Error( `Tried to send message to channel "${channelId}" but there where no listeners. Current channels with listeners: "${[ ...messageChannelListenerFakesForMain.keys(), diff --git a/src/test-utils/channel-fakes/override-requesting-from-window-to-main.ts b/src/test-utils/channel-fakes/override-requesting-from-window-to-main.ts index 8ee4227289..ddf758f5b6 100644 --- a/src/test-utils/channel-fakes/override-requesting-from-window-to-main.ts +++ b/src/test-utils/channel-fakes/override-requesting-from-window-to-main.ts @@ -3,35 +3,29 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import type { DiContainer } from "@ogre-tools/injectable"; -import type { RequestChannel } from "../../common/utils/channel/request-channel-injection-token"; -import type { RequestChannelListener } from "../../common/utils/channel/request-channel-listener-injection-token"; +import type { RequestChannel } from "../../common/utils/channel/request-channel-listener-injection-token"; +import type { RequestFromChannel } from "../../common/utils/channel/request-from-channel-injection-token"; import enlistRequestChannelListenerInjectableInMain from "../../main/utils/channel/channel-listeners/enlist-request-channel-listener.injectable"; +import type { RequestChannelListener } from "../../main/utils/channel/channel-listeners/listener-tokens"; import requestFromChannelInjectable from "../../renderer/utils/channel/request-from-channel.injectable"; export const overrideRequestingFromWindowToMain = (mainDi: DiContainer) => { const requestChannelListenerFakesForMain = new Map< - string, - RequestChannelListener> - >(); + string, + RequestChannelListener> + >(); mainDi.override( enlistRequestChannelListenerInjectableInMain, () => (listener) => { - if (requestChannelListenerFakesForMain.get(listener.channel.id)) { + if (requestChannelListenerFakesForMain.has(listener.channel.id)) { throw new Error( `Tried to enlist listener for channel "${listener.channel.id}", but it was already enlisted`, ); } - requestChannelListenerFakesForMain.set( - listener.channel.id, - - // TODO: Figure out typing - listener as unknown as RequestChannelListener< - RequestChannel - >, - ); + requestChannelListenerFakesForMain.set(listener.channel.id, listener); return () => { requestChannelListenerFakesForMain.delete(listener.channel.id); @@ -43,7 +37,7 @@ export const overrideRequestingFromWindowToMain = (mainDi: DiContainer) => { windowDi.override( requestFromChannelInjectable, - () => async (channel, ...[request]) => { + () => (async (channel, request) => { const requestListener = requestChannelListenerFakesForMain.get(channel.id); if (!requestListener) { @@ -53,7 +47,7 @@ export const overrideRequestingFromWindowToMain = (mainDi: DiContainer) => { } return requestListener.handler(request); - }, + }) as RequestFromChannel, ); }; }; From a0a630a75999bcadfdd3c0acbf796979fae2a70a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Oct 2022 08:36:38 -0400 Subject: [PATCH 3/7] Bump @swc/core from 1.3.6 to 1.3.7 (#6406) Bumps [@swc/core](https://github.com/swc-project/swc) from 1.3.6 to 1.3.7. - [Release notes](https://github.com/swc-project/swc/releases) - [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md) - [Commits](https://github.com/swc-project/swc/compare/v1.3.6...v1.3.7) --- updated-dependencies: - dependency-name: "@swc/core" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 138 +++++++++++++++++++++++++-------------------------- 2 files changed, 70 insertions(+), 70 deletions(-) diff --git a/package.json b/package.json index 8e9b9637a1..a958b19b5a 100644 --- a/package.json +++ b/package.json @@ -301,7 +301,7 @@ "@pmmmwh/react-refresh-webpack-plugin": "^0.5.8", "@sentry/types": "^6.19.7", "@swc/cli": "^0.1.57", - "@swc/core": "^1.3.6", + "@swc/core": "^1.3.7", "@swc/jest": "^0.2.23", "@testing-library/dom": "^7.31.2", "@testing-library/jest-dom": "^5.16.5", diff --git a/yarn.lock b/yarn.lock index f08316ed57..f88d1c497e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1616,101 +1616,101 @@ slash "3.0.0" source-map "^0.7.3" -"@swc/core-android-arm-eabi@1.3.6": - version "1.3.6" - resolved "https://registry.yarnpkg.com/@swc/core-android-arm-eabi/-/core-android-arm-eabi-1.3.6.tgz#0b127ccc7e6ea3e652e250afc3322d17aacec664" - integrity sha512-FQk/4cRRDoMPLgSm/1WvEqRqlSgBb6Twd5W13NYUbXJpzPGoPHhzwaCEbpGjPKG/OvAqA2NVrWquuJjhDvQyVQ== +"@swc/core-android-arm-eabi@1.3.7": + version "1.3.7" + resolved "https://registry.yarnpkg.com/@swc/core-android-arm-eabi/-/core-android-arm-eabi-1.3.7.tgz#31dc887e5dc2db25ac1a9503478ea6cabc1da9ac" + integrity sha512-zvUpTBOUnXDkfp2JXv1T3NfyimxsAnqEfT65gWC/3ZpB/gmc59vqYVko4Pifyvuxo5aVvEdT2gfHlWM/aXwtpg== dependencies: "@swc/wasm" "1.2.122" -"@swc/core-android-arm64@1.3.6": - version "1.3.6" - resolved "https://registry.yarnpkg.com/@swc/core-android-arm64/-/core-android-arm64-1.3.6.tgz#9f0e76328ef35793157dfe84a40499a2f437981b" - integrity sha512-6qjZYatlFAN0IKhhYFsN+BaywooHFpK9/A/jMkjgIfbUoDz3wPJWZc2MDvcttgqZ+cfsSCcGeNw++H894z1zfw== +"@swc/core-android-arm64@1.3.7": + version "1.3.7" + resolved "https://registry.yarnpkg.com/@swc/core-android-arm64/-/core-android-arm64-1.3.7.tgz#2b6d35343d68946b5bc2b654fa2fa4c0e8afe4d6" + integrity sha512-qnh1aYTrIjuFOkgxUYG8SGzpPD92o/w5hrHUy71LfUbHf5HRs7FpMgQXtTGnk33S/uMCvSv7V/ewv+t+N6tlVA== dependencies: "@swc/wasm" "1.2.130" -"@swc/core-darwin-arm64@1.3.6": - version "1.3.6" - resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.6.tgz#9a87819bf4879a165a7b4b868577f76dc94562e3" - integrity sha512-2qjaABxA7cloVTkS+uDEcVQ5buSi8de7qEv6P6InDE/iCjnI5ALyDxn7eauJJsVKimh9DyqN9sSZJ/z9U4FDUQ== +"@swc/core-darwin-arm64@1.3.7": + version "1.3.7" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.7.tgz#addfcf1dd1562b04ead371a3a228f1e33eb8c2d3" + integrity sha512-q8NgUK/CleCmGYIuskL1sCad8opkfJD/8GWd+MkGSi+MGkExrLMmJftgG5FCj0l/xCHxGGNYj1TCrM/qV6CheA== -"@swc/core-darwin-x64@1.3.6": - version "1.3.6" - resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.3.6.tgz#804109765a69d8d7dab09d55f4bf0918254b3cf3" - integrity sha512-+OtW18d2o3RUuXodB41ZDj0iRCeXNL0OxVU0jTl7iyCWDypmCzhalbaQXD/ZJxgnpGRB7/s2ZwNR/gzjXgz9VA== +"@swc/core-darwin-x64@1.3.7": + version "1.3.7" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.3.7.tgz#d0886d5c0573c871a42cac77cfaf091c6cc2768d" + integrity sha512-dKrJkZYbF7Qi1wQgyVnR1a5Vk8UN7fJ/WlK6pZVJwMvWLoZgYE+U0Nn7RsVB4LmOxHtaJF7eesbGUm2y2NVEwA== -"@swc/core-freebsd-x64@1.3.6": - version "1.3.6" - resolved "https://registry.yarnpkg.com/@swc/core-freebsd-x64/-/core-freebsd-x64-1.3.6.tgz#f5450dede877f61cee427c1ea16165eb74fcfe36" - integrity sha512-f+ePNodn7ET9qEa93VMfnsPNnubWKIkn0EfxmfzJCt/abNVZ7+DyCSABfWKkexOZ8OuNyxnBCdKLL6nlizxkhQ== +"@swc/core-freebsd-x64@1.3.7": + version "1.3.7" + resolved "https://registry.yarnpkg.com/@swc/core-freebsd-x64/-/core-freebsd-x64-1.3.7.tgz#2fa4f8554fcf3101a411570032b3ccfcd4833d3e" + integrity sha512-ENHthc4iFPlBj0xaf2DbJLDzYSBA4QMQEA2HhZoSWWMsqhg8mGZxwgRd6+loROGZ2a5HKMZXIxCev8BbYnE0OA== dependencies: "@swc/wasm" "1.2.130" -"@swc/core-linux-arm-gnueabihf@1.3.6": - version "1.3.6" - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.6.tgz#851871559363783818ee38725a6391b83ed3aff0" - integrity sha512-JwdJmqKzsdq7Itg5ssKDEY9mP3AkQ+XENF6WXXlaNu1U/InqQhD0DqsFzw4TQ4LzB7lB7Wj+dv3JjKIhnHNNag== +"@swc/core-linux-arm-gnueabihf@1.3.7": + version "1.3.7" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.7.tgz#76e5f6d114c3051c12bfb603bb51bfee67d512e0" + integrity sha512-anE65tcRLr/fYayXkpwZ7p7Ft5HCH4rvi3wSFdK8ycRWn9fVZhyWUJkJ3p1S0R19xr7hcb14hyxqPbd4m0I4yA== dependencies: "@swc/wasm" "1.2.130" -"@swc/core-linux-arm64-gnu@1.3.6": - version "1.3.6" - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.6.tgz#2afd9f3d4f2b051b79ed9f3549ccc8fa81ca6809" - integrity sha512-sRoPnwYFX+t95S7khi4KL2lZMZwbuzvPUf8NYmtTzfqVIseo8HD6IMgyeaQHYDfwDGF5elQGi4ALjRx2huSi0Q== +"@swc/core-linux-arm64-gnu@1.3.7": + version "1.3.7" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.7.tgz#924076423e4ac7eb3d95f5dc5de03d3301aac81a" + integrity sha512-Qv6f76Tt8t51qb29R2isWvuQM26Xi7ZJavAv0hMdCxfkF+h1Yd14j82H7afGzdONH1LyLaPrhWSQirU/ZtBtdA== -"@swc/core-linux-arm64-musl@1.3.6": - version "1.3.6" - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.6.tgz#607cc220c8640f2d36e4e2426784a6a0fc55fa1e" - integrity sha512-XT8vRcxGaKujiplFfuMtGRgZ3Nx611TMVLUg91alzEIe2Adtrpaumzrwv2vqVdMr4X4GBK9z0rHsqkDLPhmuaw== +"@swc/core-linux-arm64-musl@1.3.7": + version "1.3.7" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.7.tgz#967ce8320b9c39d3ff7efe495b3af03ddfc8cf2b" + integrity sha512-paYbmvm7+7QxjyMzRd4X4tyhHw5VgkGCMBYC3PbfpuI7SsCdmEFG9v1t5uMbTf60VU1wB4/n+AxY9KCZLfK7DQ== -"@swc/core-linux-x64-gnu@1.3.6": - version "1.3.6" - resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.6.tgz#725386afc5092cf945245ba0d500f6fc1411efd9" - integrity sha512-nip81Ngcx8cory+FtapKhXb/rgh/pTAlvTiwJjMhsE3xcKRsbnJEPMVIoArCBV0BmYJBLWvOtpHf8B62JS7L5w== +"@swc/core-linux-x64-gnu@1.3.7": + version "1.3.7" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.7.tgz#2f55017c05f0a7a9099d1b85ee6ae22bee93a118" + integrity sha512-tkIHt64mmqEVM0CTGvUsB37Pv7AD/BinOEe6oPfMcS/2a00kYvXn9kEVKPqNTpiFpjYGoFQJaVV8UsD+iv8IvQ== -"@swc/core-linux-x64-musl@1.3.6": - version "1.3.6" - resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.6.tgz#b59ac6a51192713a500b81b558979e56761b5e0a" - integrity sha512-IzrQB67BY/rSZPJXWU3XzpkJqh4vYkYuOUmz1yrV/vxgPjJp/kUllfBYsHCiIedb7sjvfTt409SIN0FlPJY2+Q== +"@swc/core-linux-x64-musl@1.3.7": + version "1.3.7" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.7.tgz#ce3a83a99389436e8ef1d86a59b6bdba16b2a0e3" + integrity sha512-V0xeTS8kvnTlghO1YyO1QgfPqsY896MknYCzBeK9CGKkGbc3JaxSoyb11nbGEDEaUwzDd9gj9L4D2uP+IWpoyw== -"@swc/core-win32-arm64-msvc@1.3.6": - version "1.3.6" - resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.6.tgz#50b7c16904f159dca5d4b29225dd55c11626ac95" - integrity sha512-gLsE/4qgqTxy0OOFJKi9QRs9mVYv4yOXSwPB2Rb+grOmNnG+Ds2LWqGEaABKDErnUtTQiOzLpdwesNZxeJgMhA== +"@swc/core-win32-arm64-msvc@1.3.7": + version "1.3.7" + resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.7.tgz#11e53a2b79f7de2b78e4f10cc45c45e87753b0ce" + integrity sha512-LeauQIok8tw4Mjmj7wlc7C62HCUx3xa5k6tNQnKWbDs7odZVWisgDxn7RSl9/xxlC8wPLTVUyBh3O1rHigVfWg== dependencies: "@swc/wasm" "1.2.130" -"@swc/core-win32-ia32-msvc@1.3.6": - version "1.3.6" - resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.6.tgz#8e9d55586184b2a11978fe9dbc9a8a3a16d2e54a" - integrity sha512-0Jr7KMGEPapYGni+97oNOeVP7edBwjMGQ9HsJUUN1uIE7fALQ+zVGuwbc+22myql2Uhh5V5hZx5xtVraqLVMHw== +"@swc/core-win32-ia32-msvc@1.3.7": + version "1.3.7" + resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.7.tgz#126b930a77af3d0dcbacf07782d6f20a16511b32" + integrity sha512-E1C8bpUrml0vIv4FTSP7f4CwkZVGsCY9fBsBHCC4j9N1mtQk8/nzpGOUsPo4QP+FTYJiNKedZ4Cy7baihnV4Lw== dependencies: "@swc/wasm" "1.2.130" -"@swc/core-win32-x64-msvc@1.3.6": - version "1.3.6" - resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.6.tgz#a3c2bcf71b26cc4984adce4bfefb214664ce3b01" - integrity sha512-O3F/jxqaFwGq9XxYeCIVRCDIR4+GdSBu/5io6TkN8O5QLqB3/KOJVDn6TALtbL6ClwjUwZt66HKnYeSx19j2Ow== +"@swc/core-win32-x64-msvc@1.3.7": + version "1.3.7" + resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.7.tgz#a1298b635d2cbbcf3cba3dbd37cdd6b577296efa" + integrity sha512-Ti9H/1hqBrxhYtNLVaLsahO/iiJn1Zd4qSc0LZpl6wBJxP4LltLV4MLeib6i8lg11pj4ijIhzZfC6bT614ee3w== -"@swc/core@^1.3.6": - version "1.3.6" - resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.3.6.tgz#909af865ee5044fe138ff85b40afb5d171d621a1" - integrity sha512-L3EemOWywrxXsRQFeU50PYFwrDKOxi2RGTT+TT3CcbIszwc7qnE6vsVzEll/eK32H1veicc0EegkZgtD4PFNRA== +"@swc/core@^1.3.7": + version "1.3.7" + resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.3.7.tgz#46eaa4af5f61ced1694fca64fb6d93ba5485747a" + integrity sha512-g4ptYRZRE+g/6wLB3WBuWhAWJsZDUeiSOvKVM1Wdn29Vi/EgLuVaY5ssz0HLQJxuDSJGwtAOZA8exh4+AKNHLw== optionalDependencies: - "@swc/core-android-arm-eabi" "1.3.6" - "@swc/core-android-arm64" "1.3.6" - "@swc/core-darwin-arm64" "1.3.6" - "@swc/core-darwin-x64" "1.3.6" - "@swc/core-freebsd-x64" "1.3.6" - "@swc/core-linux-arm-gnueabihf" "1.3.6" - "@swc/core-linux-arm64-gnu" "1.3.6" - "@swc/core-linux-arm64-musl" "1.3.6" - "@swc/core-linux-x64-gnu" "1.3.6" - "@swc/core-linux-x64-musl" "1.3.6" - "@swc/core-win32-arm64-msvc" "1.3.6" - "@swc/core-win32-ia32-msvc" "1.3.6" - "@swc/core-win32-x64-msvc" "1.3.6" + "@swc/core-android-arm-eabi" "1.3.7" + "@swc/core-android-arm64" "1.3.7" + "@swc/core-darwin-arm64" "1.3.7" + "@swc/core-darwin-x64" "1.3.7" + "@swc/core-freebsd-x64" "1.3.7" + "@swc/core-linux-arm-gnueabihf" "1.3.7" + "@swc/core-linux-arm64-gnu" "1.3.7" + "@swc/core-linux-arm64-musl" "1.3.7" + "@swc/core-linux-x64-gnu" "1.3.7" + "@swc/core-linux-x64-musl" "1.3.7" + "@swc/core-win32-arm64-msvc" "1.3.7" + "@swc/core-win32-ia32-msvc" "1.3.7" + "@swc/core-win32-x64-msvc" "1.3.7" "@swc/jest@^0.2.23": version "0.2.23" From b4ba9c2c796ddcdb2209d0329fb8d079aaa77698 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Oct 2022 08:37:03 -0400 Subject: [PATCH 4/7] Bump postcss from 8.4.17 to 8.4.18 (#6405) Bumps [postcss](https://github.com/postcss/postcss) from 8.4.17 to 8.4.18. - [Release notes](https://github.com/postcss/postcss/releases) - [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md) - [Commits](https://github.com/postcss/postcss/compare/8.4.17...8.4.18) --- updated-dependencies: - dependency-name: postcss dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index a958b19b5a..eac06bfb68 100644 --- a/package.json +++ b/package.json @@ -403,7 +403,7 @@ "node-loader": "^2.0.0", "nodemon": "^2.0.20", "playwright": "^1.27.0", - "postcss": "^8.4.17", + "postcss": "^8.4.18", "postcss-loader": "^6.2.1", "query-string": "^7.1.1", "randomcolor": "^0.6.2", diff --git a/yarn.lock b/yarn.lock index f88d1c497e..9f517e5b04 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10109,10 +10109,10 @@ postcss@^6.0.14, postcss@^6.0.2: source-map "^0.6.1" supports-color "^5.4.0" -postcss@^8.3.0, postcss@^8.4.14, postcss@^8.4.17, postcss@^8.4.7: - version "8.4.17" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.17.tgz#f87863ec7cd353f81f7ab2dec5d67d861bbb1be5" - integrity sha512-UNxNOLQydcOFi41yHNMcKRZ39NeXlr8AxGuZJsdub8vIb12fHzcq37DTU/QtbI6WLxNg2gF9Z+8qtRwTj1UI1Q== +postcss@^8.3.0, postcss@^8.4.14, postcss@^8.4.18, postcss@^8.4.7: + version "8.4.18" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.18.tgz#6d50046ea7d3d66a85e0e782074e7203bc7fbca2" + integrity sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA== dependencies: nanoid "^3.3.4" picocolors "^1.0.0" From 4d4b8b026fa8e872cc08e689b6f99186813a5f0e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Oct 2022 09:15:07 -0400 Subject: [PATCH 5/7] Bump react-select from 5.4.0 to 5.5.0 (#6404) * Bump react-select from 5.4.0 to 5.5.0 Bumps [react-select](https://github.com/JedWatson/react-select) from 5.4.0 to 5.5.0. - [Release notes](https://github.com/JedWatson/react-select/releases) - [Changelog](https://github.com/JedWatson/react-select/blob/master/docs/CHANGELOG.md) - [Commits](https://github.com/JedWatson/react-select/compare/react-select@5.4.0...react-select@5.5.0) --- updated-dependencies: - dependency-name: react-select dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Update snapshots Signed-off-by: Sebastian Malton Signed-off-by: dependabot[bot] Signed-off-by: Sebastian Malton Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Sebastian Malton --- package.json | 2 +- ...tory-from-list-in-preferences.test.ts.snap | 4 +-- ...lling-helm-chart-from-new-tab.test.ts.snap | 4 +-- .../namespace-select-filter.test.tsx.snap | 6 ++--- yarn.lock | 27 ++++++++++++++++--- 5 files changed, 31 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index eac06bfb68..9f11a786f4 100644 --- a/package.json +++ b/package.json @@ -411,7 +411,7 @@ "react-refresh": "^0.14.0", "react-refresh-typescript": "^2.0.7", "react-router-dom": "^5.3.4", - "react-select": "^5.4.0", + "react-select": "^5.5.0", "react-select-event": "^5.5.1", "react-table": "^7.8.0", "react-window": "^1.8.7", diff --git a/src/features/helm-charts/__snapshots__/add-helm-repository-from-list-in-preferences.test.ts.snap b/src/features/helm-charts/__snapshots__/add-helm-repository-from-list-in-preferences.test.ts.snap index 2e520db845..12975a3f66 100644 --- a/src/features/helm-charts/__snapshots__/add-helm-repository-from-list-in-preferences.test.ts.snap +++ b/src/features/helm-charts/__snapshots__/add-helm-repository-from-list-in-preferences.test.ts.snap @@ -1756,7 +1756,7 @@ exports[`add helm repository from list in preferences when navigating to prefere />
when clicked renders 1`] = `
when clicked when 'test-2' is clicked when cl
when clicked when 'test-2' is clicked when cl
=7" -react-select@^5.4.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/react-select/-/react-select-5.4.0.tgz#81f6ac73906126706f104751ee14437bd16798f4" - integrity sha512-CjE9RFLUvChd5SdlfG4vqxZd55AZJRrLrHzkQyTYeHlpOztqcgnyftYAolJ0SGsBev6zAs6qFrjm6KU3eo2hzg== +react-select@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/react-select/-/react-select-5.5.0.tgz#c82286e20b26194738186ada54cc8a0c677dfc6e" + integrity sha512-yzA+eavdxpF5Onf0u9KZ84qxr8r/CwPPn777bRkslbDtEUYx2+m13OrhP3WVa30+aWYxwkO/pkLcZ7q7r/6OhQ== dependencies: "@babel/runtime" "^7.12.0" "@emotion/cache" "^11.4.0" "@emotion/react" "^11.8.1" + "@floating-ui/dom" "^1.0.1" "@types/react-transition-group" "^4.4.0" memoize-one "^5.0.0" prop-types "^15.6.0" react-transition-group "^4.3.0" + use-isomorphic-layout-effect "^1.1.2" react-swipeable@^6.1.0: version "6.2.2" @@ -12446,6 +12460,11 @@ url-parse@^1.5.10: querystringify "^2.1.1" requires-port "^1.0.0" +use-isomorphic-layout-effect@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz#497cefb13d863d687b08477d9e5a164ad8c1a6fb" + integrity sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA== + use-memo-one@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/use-memo-one/-/use-memo-one-1.1.2.tgz#0c8203a329f76e040047a35a1197defe342fab20" From 3649db7bc0f37433f45df3259e0ab6d4ead129cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Oct 2022 09:15:21 -0400 Subject: [PATCH 6/7] Bump electron from 19.1.2 to 19.1.3 (#6409) Bumps [electron](https://github.com/electron/electron) from 19.1.2 to 19.1.3. - [Release notes](https://github.com/electron/electron/releases) - [Changelog](https://github.com/electron/electron/blob/main/docs/breaking-changes.md) - [Commits](https://github.com/electron/electron/compare/v19.1.2...v19.1.3) --- updated-dependencies: - dependency-name: electron dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 9f11a786f4..802be21633 100644 --- a/package.json +++ b/package.json @@ -374,7 +374,7 @@ "css-loader": "^6.7.1", "deepdash": "^5.3.9", "dompurify": "^2.4.0", - "electron": "^19.1.2", + "electron": "^19.1.3", "electron-builder": "^23.6.0", "electron-notarize": "^0.3.0", "esbuild": "^0.15.10", diff --git a/yarn.lock b/yarn.lock index 31569dbf05..f3f32900ed 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5162,10 +5162,10 @@ electron-window-state@^5.0.3: jsonfile "^4.0.0" mkdirp "^0.5.1" -electron@^19.1.2: - version "19.1.2" - resolved "https://registry.yarnpkg.com/electron/-/electron-19.1.2.tgz#4b0858b74a76be6998af103a6d81f3784d93e7dc" - integrity sha512-KbKz9eFfm10aBYWJ5dwR/73Y9L8gjflXUSSYzBZSW2FJEEaNk3ZtxGMw77iAocQU/G8tCZ7fNxQq/vNI2Foz+g== +electron@^19.1.3: + version "19.1.3" + resolved "https://registry.yarnpkg.com/electron/-/electron-19.1.3.tgz#90a2b6c3d738789d657477d87d1539f008be6536" + integrity sha512-P2kfFc8UqVvPHE1w9qTZSPNpfOqd+CK34K3wBqJwokzYdVBLsVkbIoLxyByjJ/cU35WaeCL5bsI8kXALfPvebw== dependencies: "@electron/get" "^1.14.1" "@types/node" "^16.11.26" From 57f06b850e044cc7f8e0f40c591e0238e228603f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Oct 2022 09:15:36 -0400 Subject: [PATCH 7/7] Bump playwright from 1.27.0 to 1.27.1 (#6403) Bumps [playwright](https://github.com/Microsoft/playwright) from 1.27.0 to 1.27.1. - [Release notes](https://github.com/Microsoft/playwright/releases) - [Commits](https://github.com/Microsoft/playwright/compare/v1.27.0...v1.27.1) --- updated-dependencies: - dependency-name: playwright dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 802be21633..15e0310fea 100644 --- a/package.json +++ b/package.json @@ -402,7 +402,7 @@ "node-gyp": "^8.3.0", "node-loader": "^2.0.0", "nodemon": "^2.0.20", - "playwright": "^1.27.0", + "playwright": "^1.27.1", "postcss": "^8.4.18", "postcss-loader": "^6.2.1", "query-string": "^7.1.1", diff --git a/yarn.lock b/yarn.lock index f3f32900ed..f321690ab1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9974,17 +9974,17 @@ pkg-up@^3.1.0: dependencies: find-up "^3.0.0" -playwright-core@1.27.0: - version "1.27.0" - resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.27.0.tgz#e5f9d2bc19ebdd9581a01e74f019bb91aa7cf55d" - integrity sha512-VBKaaFUVKDo3akW+o4DwbK1ZyXh46tcSwQKPK3lruh8IJd5feu55XVZx4vOkbb2uqrNdIF51sgsadYT533SdpA== +playwright-core@1.27.1: + version "1.27.1" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.27.1.tgz#840ef662e55a3ed759d8b5d3d00a5f885a7184f4" + integrity sha512-9EmeXDncC2Pmp/z+teoVYlvmPWUC6ejSSYZUln7YaP89Z6lpAaiaAnqroUt/BoLo8tn7WYShcfaCh+xofZa44Q== -playwright@^1.27.0: - version "1.27.0" - resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.27.0.tgz#68a0e29f1756da105b22291a7c3f402ae749213a" - integrity sha512-F+0+0RD03LS+KdNAMMp63OBzu+NwYYLd52pKLczuSlTsV5b/SLkUoNhSfzDFngEFOuRL2gk0LlfGW3mKiUBk6w== +playwright@^1.27.1: + version "1.27.1" + resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.27.1.tgz#4eecac5899566c589d4220ca8acc16abe8a67450" + integrity sha512-xXYZ7m36yTtC+oFgqH0eTgullGztKSRMb4yuwLPl8IYSmgBM88QiB+3IWb1mRIC9/NNwcgbG0RwtFlg+EAFQHQ== dependencies: - playwright-core "1.27.0" + playwright-core "1.27.1" plist@^3.0.1, plist@^3.0.4: version "3.0.5"