Files
geo/apps/desktop-client/src/main/renderer-devtools-proxy.ts
T

75 lines
2.1 KiB
TypeScript
Raw Normal View History

import type { WebContents } from "electron/main";
interface RendererProxyRequest {
url: string;
method: string;
headers?: Record<string, string>;
body?: string;
}
interface RendererProxyResponse {
ok: boolean;
status: number;
statusText: string;
headers: Record<string, string>;
bodyText: string;
error?: string;
}
let rendererWebContents: WebContents | null = null;
export function registerRendererDevtoolsProxyTarget(webContents: WebContents): void {
rendererWebContents = webContents;
webContents.once("destroyed", () => {
if (rendererWebContents === webContents) {
rendererWebContents = null;
}
});
}
export function canUseRendererDevtoolsProxy(): boolean {
return Boolean(process.env.ELECTRON_RENDERER_URL && rendererWebContents && !rendererWebContents.isDestroyed());
}
export async function rendererDevtoolsFetch(
request: RendererProxyRequest,
): Promise<RendererProxyResponse> {
if (!rendererWebContents || rendererWebContents.isDestroyed()) {
throw new Error("renderer_devtools_proxy_unavailable");
}
const script = `(async () => {
try {
const response = await fetch(${JSON.stringify(request.url)}, {
method: ${JSON.stringify(request.method)},
headers: ${JSON.stringify(request.headers ?? {})},
body: ${JSON.stringify(request.body ?? null)},
});
const bodyText = await response.text();
return JSON.stringify({
ok: response.ok,
status: response.status,
statusText: response.statusText,
headers: Object.fromEntries(response.headers.entries()),
bodyText,
});
} catch (error) {
return JSON.stringify({
ok: false,
status: 0,
statusText: "",
headers: {},
bodyText: "",
error: String(error && (error.message || error)),
});
}
})()`;
const serialized = await rendererWebContents.executeJavaScript(script, true);
if (typeof serialized !== "string" || !serialized) {
throw new Error("renderer_devtools_proxy_empty_response");
}
return JSON.parse(serialized) as RendererProxyResponse;
}