fix(desktop): patch React DevTools manifest for Electron compatibility
This commit is contained in:
@@ -1,10 +1,68 @@
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { existsSync } from "node:fs";
|
import { existsSync } from "node:fs";
|
||||||
import { mkdir, writeFile, unlink } from "node:fs/promises";
|
import { mkdir, readFile, writeFile, unlink } from "node:fs/promises";
|
||||||
import { app, session, net } from "electron";
|
import { app, session, net } from "electron";
|
||||||
|
|
||||||
const REACT_DEVTOOLS_EXTENSION_ID = "fmkadmapgofadopljbjfkapdkoienihi";
|
const REACT_DEVTOOLS_EXTENSION_ID = "fmkadmapgofadopljbjfkapdkoienihi";
|
||||||
|
|
||||||
|
type ReactDevToolsContentScript = {
|
||||||
|
matches: string[];
|
||||||
|
js: string[];
|
||||||
|
run_at: "document_start" | "document_end";
|
||||||
|
world?: "MAIN";
|
||||||
|
};
|
||||||
|
|
||||||
|
type ReactDevToolsManifest = {
|
||||||
|
version?: string;
|
||||||
|
manifest_version?: number;
|
||||||
|
content_scripts?: ReactDevToolsContentScript[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const ELECTRON_COMPATIBLE_CONTENT_SCRIPTS: ReactDevToolsContentScript[] = [
|
||||||
|
{
|
||||||
|
matches: ["<all_urls>"],
|
||||||
|
js: ["build/proxy.js"],
|
||||||
|
run_at: "document_start",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
matches: ["<all_urls>"],
|
||||||
|
js: ["build/installHook.js"],
|
||||||
|
run_at: "document_start",
|
||||||
|
world: "MAIN",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
matches: ["<all_urls>"],
|
||||||
|
js: ["build/hookSettingsInjector.js"],
|
||||||
|
run_at: "document_start",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
matches: ["<all_urls>"],
|
||||||
|
js: ["build/fileFetcher.js"],
|
||||||
|
run_at: "document_end",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
function hasStaticReactHookScript(manifest: ReactDevToolsManifest): boolean {
|
||||||
|
return (
|
||||||
|
manifest.content_scripts?.some((script) => script.js.includes("build/installHook.js")) ?? false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function patchReactDevToolsForElectron(extensionPath: string): Promise<void> {
|
||||||
|
const manifestPath = path.join(extensionPath, "manifest.json");
|
||||||
|
const manifest = JSON.parse(await readFile(manifestPath, "utf-8")) as ReactDevToolsManifest;
|
||||||
|
|
||||||
|
if (manifest.manifest_version !== 3 || hasStaticReactHookScript(manifest)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// React DevTools v7 relies on chrome.scripting.registerContentScripts,
|
||||||
|
// which Electron does not reliably inject into app pages. Static scripts do.
|
||||||
|
manifest.content_scripts = ELECTRON_COMPATIBLE_CONTENT_SCRIPTS;
|
||||||
|
await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
|
||||||
|
console.log(`[DevTools] Patched React DevTools ${manifest.version} content scripts for Electron`);
|
||||||
|
}
|
||||||
|
|
||||||
export async function loadReactDevTools(): Promise<void> {
|
export async function loadReactDevTools(): Promise<void> {
|
||||||
const extensionsDir = path.join(app.getPath("userData"), "extensions");
|
const extensionsDir = path.join(app.getPath("userData"), "extensions");
|
||||||
const extensionPath = path.join(extensionsDir, REACT_DEVTOOLS_EXTENSION_ID);
|
const extensionPath = path.join(extensionsDir, REACT_DEVTOOLS_EXTENSION_ID);
|
||||||
@@ -33,6 +91,7 @@ export async function loadReactDevTools(): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
await patchReactDevToolsForElectron(extensionPath);
|
||||||
const ext = await session.defaultSession.extensions.loadExtension(extensionPath, {
|
const ext = await session.defaultSession.extensions.loadExtension(extensionPath, {
|
||||||
allowFileAccess: true,
|
allowFileAccess: true,
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user