mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Make IPC usage injectable
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
ac42d7e365
commit
78ead4f2b9
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* 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 "../cluster-types";
|
||||
import type { RequestChannel } from "../utils/channel/request-channel-injection-token";
|
||||
import { requestChannelInjectionToken } from "../utils/channel/request-channel-injection-token";
|
||||
|
||||
export type GetShellAuthTokenChannel = RequestChannel<
|
||||
{
|
||||
clusterId: ClusterId;
|
||||
tabId: string;
|
||||
},
|
||||
Uint8Array
|
||||
>;
|
||||
|
||||
const getShellAuthTokenChannelInjectable = getInjectable({
|
||||
id: "get-shell-auth-token-channel",
|
||||
instantiate: (): GetShellAuthTokenChannel => ({
|
||||
id: "get-shell-auth-token-channel",
|
||||
}),
|
||||
injectionToken: requestChannelInjectionToken,
|
||||
});
|
||||
|
||||
export default getShellAuthTokenChannelInjectable;
|
||||
23
src/common/shell-authentication/get-auth-token.injectable.ts
Normal file
23
src/common/shell-authentication/get-auth-token.injectable.ts
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* 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 { ChannelRequest } from "../utils/channel/request-channel-injection-token";
|
||||
import { requestFromChannelInjectionToken } from "../utils/channel/request-from-channel-injection-token";
|
||||
import type { GetShellAuthTokenChannel } from "./get-auth-token-channel.injectable";
|
||||
import getShellAuthTokenChannelInjectable from "./get-auth-token-channel.injectable";
|
||||
|
||||
export type GetShellAuthToken = ChannelRequest<GetShellAuthTokenChannel>;
|
||||
|
||||
const getShellAuthTokenInjectable = getInjectable({
|
||||
id: "get-shell-auth-token",
|
||||
instantiate: (di): GetShellAuthToken => {
|
||||
const requestFromChannel = di.inject(requestFromChannelInjectionToken);
|
||||
const getShellAuthTokenChannel = di.inject(getShellAuthTokenChannelInjectable);
|
||||
|
||||
return (arg) => requestFromChannel(getShellAuthTokenChannel, arg);
|
||||
},
|
||||
});
|
||||
|
||||
export default getShellAuthTokenInjectable;
|
||||
12
src/common/utils/channel/allowed-types.ts
Normal file
12
src/common/utils/channel/allowed-types.ts
Normal file
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { TypedArray } from "type-fest";
|
||||
|
||||
export type IpcPrimative = string | boolean | number | bigint | null | undefined;
|
||||
export type IpcClasses = Date | RegExp | TypedArray;
|
||||
export type IpcValue = IpcPrimative | IpcObject | IpcArray | IpcClasses;
|
||||
export type IpcObject = { [Key in string]?: IpcValue };
|
||||
export type IpcArray = IpcValue[];
|
||||
@ -1,12 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
|
||||
export interface Channel<MessageTemplate = void, ReturnTemplate = void> {
|
||||
id: string;
|
||||
_messageTemplate?: MessageTemplate;
|
||||
_returnTemplate?: ReturnTemplate;
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@ 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 { requestChannelHandlerInjectionToken } 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";
|
||||
@ -183,7 +183,7 @@ describe("channel", () => {
|
||||
handler: requestListenerInMainMock,
|
||||
}),
|
||||
|
||||
injectionToken: requestChannelListenerInjectionToken,
|
||||
injectionToken: requestChannelHandlerInjectionToken,
|
||||
});
|
||||
|
||||
mainDi.register(testChannelListenerInMainInjectable);
|
||||
|
||||
@ -4,11 +4,11 @@
|
||||
*/
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { RequestChannel } from "./request-channel-injection-token";
|
||||
import type { RequestChannelListener } from "./request-channel-listener-injection-token";
|
||||
import type { RequestChannelHandlerDescriptor } from "./request-channel-listener-injection-token";
|
||||
|
||||
export type EnlistRequestChannelListener = <
|
||||
TChannel extends RequestChannel<any, any>,
|
||||
>(listener: RequestChannelListener<TChannel>) => () => void;
|
||||
>(listener: RequestChannelHandlerDescriptor<TChannel>) => () => void;
|
||||
|
||||
export const enlistRequestChannelListenerInjectionToken =
|
||||
getInjectionToken<EnlistRequestChannelListener>({
|
||||
|
||||
@ -6,7 +6,7 @@ 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 { requestChannelHandlerInjectionToken } from "./request-channel-listener-injection-token";
|
||||
import { enlistMessageChannelListenerInjectionToken } from "./enlist-message-channel-listener-injection-token";
|
||||
import { enlistRequestChannelListenerInjectionToken } from "./enlist-request-channel-listener-injection-token";
|
||||
|
||||
@ -17,7 +17,7 @@ const listeningOfChannelsInjectable = getInjectable({
|
||||
const enlistMessageChannelListener = di.inject(enlistMessageChannelListenerInjectionToken);
|
||||
const enlistRequestChannelListener = di.inject(enlistRequestChannelListenerInjectionToken);
|
||||
const messageChannelListeners = di.injectMany(messageChannelListenerInjectionToken);
|
||||
const requestChannelListeners = di.injectMany(requestChannelListenerInjectionToken);
|
||||
const requestChannelListeners = di.injectMany(requestChannelHandlerInjectionToken);
|
||||
|
||||
return getStartableStoppable("listening-of-channels", () => {
|
||||
const messageChannelDisposers = messageChannelListeners.map(enlistMessageChannelListener);
|
||||
|
||||
@ -4,17 +4,19 @@
|
||||
*/
|
||||
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { JsonValue } from "type-fest";
|
||||
import type { IpcValue } from "./allowed-types";
|
||||
|
||||
export interface RequestChannel<
|
||||
Request extends JsonValue | void = void,
|
||||
Response extends JsonValue | void = void,
|
||||
Request extends IpcValue | void = void,
|
||||
Response extends IpcValue | void = void,
|
||||
> {
|
||||
id: string;
|
||||
_requestSignature?: Request;
|
||||
_responseSignature?: Response;
|
||||
id: Request | Response extends boolean ? string : string;
|
||||
}
|
||||
|
||||
export type ChannelRequest<Channel> = Channel extends RequestChannel<infer Request, infer Response>
|
||||
? (arg: Request) => Promise<Response>
|
||||
: never;
|
||||
|
||||
export const requestChannelInjectionToken = getInjectionToken<RequestChannel<any, any>>({
|
||||
id: "request-channel",
|
||||
});
|
||||
|
||||
@ -2,24 +2,42 @@
|
||||
* 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 { DiContainerForInjection, Injectable } from "@ogre-tools/injectable";
|
||||
import { getInjectable, getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { RequestChannel } from "./request-channel-injection-token";
|
||||
|
||||
export interface RequestChannelListener<TChannel extends RequestChannel<any, any>> {
|
||||
channel: TChannel;
|
||||
export type RequestChannelHandler<Channel> = Channel extends RequestChannel<infer Request, infer Response>
|
||||
? (request: Request) => Response | Promise<Response>
|
||||
: never;
|
||||
|
||||
handler: (
|
||||
request: SetRequired<TChannel, "_requestSignature">["_requestSignature"]
|
||||
) =>
|
||||
| SetRequired<TChannel, "_responseSignature">["_responseSignature"]
|
||||
| Promise<
|
||||
SetRequired<TChannel, "_responseSignature">["_responseSignature"]
|
||||
>;
|
||||
export interface RequestChannelHandlerDescriptor<Channel> {
|
||||
channel: Channel;
|
||||
handler: RequestChannelHandler<Channel>;
|
||||
}
|
||||
|
||||
export const requestChannelListenerInjectionToken = getInjectionToken<RequestChannelListener<RequestChannel<any, any>>>(
|
||||
export const requestChannelHandlerInjectionToken = getInjectionToken<RequestChannelHandlerDescriptor<RequestChannel<any, any>>>(
|
||||
{
|
||||
id: "request-channel-listener",
|
||||
id: "request-channel-handler",
|
||||
},
|
||||
);
|
||||
|
||||
export function getRequestChannelHandlerInjectable<
|
||||
ChannelInjectionToken,
|
||||
Channel = ChannelInjectionToken extends Injectable<infer Channel, RequestChannel<any, any>, void>
|
||||
? Channel
|
||||
: never,
|
||||
>(
|
||||
channelInjectionToken: ChannelInjectionToken,
|
||||
instantiate: (di: DiContainerForInjection) => RequestChannelHandler<Channel>,
|
||||
) {
|
||||
const token = channelInjectionToken as unknown as Injectable<RequestChannel<any, any>, RequestChannel<any, any>, void>;
|
||||
|
||||
return getInjectable({
|
||||
id: `${token.id}-handler`,
|
||||
instantiate: (di) => ({
|
||||
channel: di.inject(token),
|
||||
handler: instantiate(di),
|
||||
}),
|
||||
injectionToken: requestChannelHandlerInjectionToken,
|
||||
});
|
||||
}
|
||||
|
||||
@ -3,19 +3,19 @@
|
||||
* 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 type RequestFromChannel = <
|
||||
TChannel extends RequestChannel<any, any>,
|
||||
Channel,
|
||||
Request = Channel extends RequestChannel<infer Request, any> ? Request : never,
|
||||
Response = Channel extends RequestChannel<any, infer Response> ? Response : never,
|
||||
>(
|
||||
channel: TChannel,
|
||||
...request: TChannel["_requestSignature"] extends void
|
||||
channel: Channel,
|
||||
...request: Request extends void
|
||||
? []
|
||||
: [TChannel["_requestSignature"]]
|
||||
) => Promise<SetRequired<TChannel, "_responseSignature">["_responseSignature"]>;
|
||||
: [Request]
|
||||
) => Promise<Response>;
|
||||
|
||||
export const requestFromChannelInjectionToken =
|
||||
getInjectionToken<RequestFromChannel>({
|
||||
id: "request-from-request-channel",
|
||||
});
|
||||
export const requestFromChannelInjectionToken = getInjectionToken<RequestFromChannel>({
|
||||
id: "request-from-request-channel",
|
||||
});
|
||||
|
||||
@ -3,8 +3,8 @@
|
||||
* 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 { RequestChannelHandlerDescriptor } from "../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import { requestChannelHandlerInjectionToken } from "../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import type { AppPathsChannel } from "../../common/app-paths/app-paths-channel.injectable";
|
||||
import appPathsChannelInjectable from "../../common/app-paths/app-paths-channel.injectable";
|
||||
import appPathsInjectable from "../../common/app-paths/app-paths.injectable";
|
||||
@ -12,7 +12,7 @@ import appPathsInjectable from "../../common/app-paths/app-paths.injectable";
|
||||
const appPathsRequestChannelListenerInjectable = getInjectable({
|
||||
id: "app-paths-request-channel-listener",
|
||||
|
||||
instantiate: (di): RequestChannelListener<AppPathsChannel> => {
|
||||
instantiate: (di): RequestChannelHandlerDescriptor<AppPathsChannel> => {
|
||||
const channel = di.inject(appPathsChannelInjectable);
|
||||
const appPaths = di.inject(appPathsInjectable);
|
||||
|
||||
@ -21,7 +21,7 @@ const appPathsRequestChannelListenerInjectable = getInjectable({
|
||||
handler: () => appPaths,
|
||||
};
|
||||
},
|
||||
injectionToken: requestChannelListenerInjectionToken,
|
||||
injectionToken: requestChannelHandlerInjectionToken,
|
||||
});
|
||||
|
||||
export default appPathsRequestChannelListenerInjectable;
|
||||
|
||||
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import getShellAuthTokenChannelInjectable from "../../../../common/shell-authentication/get-auth-token-channel.injectable";
|
||||
import { getRequestChannelHandlerInjectable } from "../../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import shellRequestAuthenticatorInjectable from "./request-authenticator.injectable";
|
||||
|
||||
const getShellAuthTokenChannelHandlerInjectable = getRequestChannelHandlerInjectable(
|
||||
getShellAuthTokenChannelInjectable,
|
||||
(di) => {
|
||||
const authenticator = di.inject(shellRequestAuthenticatorInjectable);
|
||||
|
||||
return ({ clusterId, tabId }) => authenticator.getTokenFor(clusterId, tabId);
|
||||
},
|
||||
);
|
||||
|
||||
export default getShellAuthTokenChannelHandlerInjectable;
|
||||
@ -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 { syncBoxInjectionToken } from "../../../common/utils/sync-box/sync-box-injection-token";
|
||||
import { requestChannelListenerInjectionToken } from "../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import { getRequestChannelHandlerInjectable } from "../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
|
||||
const syncBoxInitialValueChannelListenerInjectable = getInjectable({
|
||||
id: "sync-box-initial-value-channel-listener",
|
||||
|
||||
instantiate: (di) => {
|
||||
const channel = di.inject(syncBoxInitialValueChannelInjectable);
|
||||
const syncBoxInitialValueChannelListenerInjectable = getRequestChannelHandlerInjectable(
|
||||
syncBoxInitialValueChannelInjectable,
|
||||
(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;
|
||||
|
||||
@ -8,10 +8,10 @@ import { WebSocketApi } from "./websocket-api";
|
||||
import isEqual from "lodash/isEqual";
|
||||
import url from "url";
|
||||
import { makeObservable, observable } from "mobx";
|
||||
import { ipcRenderer } from "electron";
|
||||
import logger from "../../common/logger";
|
||||
import { once } from "lodash";
|
||||
import { type TerminalMessage, TerminalChannels } from "../../common/terminal/channels";
|
||||
import type { GetShellAuthToken } from "../../common/shell-authentication/get-auth-token.injectable";
|
||||
|
||||
enum TerminalColor {
|
||||
RED = "\u001b[31m",
|
||||
@ -38,6 +38,7 @@ export interface TerminalEvents extends WebSocketEvents {
|
||||
|
||||
export interface TerminalApiDependencies {
|
||||
readonly hostedClusterId: string;
|
||||
getShellAuthToken: GetShellAuthToken;
|
||||
}
|
||||
|
||||
export class TerminalApi extends WebSocketApi<TerminalEvents> {
|
||||
@ -66,12 +67,10 @@ export class TerminalApi extends WebSocketApi<TerminalEvents> {
|
||||
this.emitStatus("Connecting ...");
|
||||
}
|
||||
|
||||
const authTokenArray = await ipcRenderer.invoke("cluster:shell-api", this.dependencies.hostedClusterId, this.query.id);
|
||||
|
||||
if (!(authTokenArray instanceof Uint8Array)) {
|
||||
throw new TypeError("ShellApi token is not a Uint8Array");
|
||||
}
|
||||
|
||||
const authTokenArray = await this.dependencies.getShellAuthToken({
|
||||
clusterId: this.dependencies.hostedClusterId,
|
||||
tabId: this.query.id,
|
||||
});
|
||||
const { hostname, protocol, port } = location;
|
||||
const socketUrl = url.format({
|
||||
protocol: protocol.includes("https") ? "wss" : "ws",
|
||||
|
||||
@ -4,14 +4,14 @@
|
||||
*/
|
||||
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 { RequestChannelHandlerDescriptor } from "../../common/utils/channel/request-channel-listener-injection-token";
|
||||
import enlistRequestChannelListenerInjectableInMain from "../../main/utils/channel/channel-listeners/enlist-request-channel-listener.injectable";
|
||||
import requestFromChannelInjectable from "../../renderer/utils/channel/request-from-channel.injectable";
|
||||
|
||||
export const overrideRequestingFromWindowToMain = (mainDi: DiContainer) => {
|
||||
const requestChannelListenerFakesForMain = new Map<
|
||||
string,
|
||||
RequestChannelListener<RequestChannel<any, any>>
|
||||
RequestChannelHandlerDescriptor<RequestChannel<any, any>>
|
||||
>();
|
||||
|
||||
mainDi.override(
|
||||
@ -28,7 +28,7 @@ export const overrideRequestingFromWindowToMain = (mainDi: DiContainer) => {
|
||||
listener.channel.id,
|
||||
|
||||
// TODO: Figure out typing
|
||||
listener as unknown as RequestChannelListener<
|
||||
listener as unknown as RequestChannelHandlerDescriptor<
|
||||
RequestChannel<any, any>
|
||||
>,
|
||||
);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user