import { contextBridge, ipcRenderer, webUtils } from "electron"; // This preload runs in Electron's sandbox and is tsc-compiled (not bundled), so it MUST // NOT emit any runtime module load other than "electron" — a require() of a local or // third-party module throws and aborts the preload before exposeInMainWorld runs, leaving // window.paseoDesktop undefined (the 0.1.108 regression, #2103). Keep this literal in sync // with PASEO_BROWSER_PROFILE_PARTITION in features/browser-profile.ts; preload-sandbox.test.ts // guards both the no-local-import rule and this drift. Type-only imports are fine (erased at emit). const PASEO_BROWSER_PROFILE_PARTITION = "persist:paseo-browser"; type EventHandler = (payload: unknown) => void; interface AttachedBrowserRegistration { browserId: string; workspaceId: string; webContentsId: number; } contextBridge.exposeInMainWorld("paseoDesktop", { platform: process.platform, invoke: (command: string, args?: Record) => ipcRenderer.invoke("paseo:invoke", command, args), getPendingOpenProject: () => ipcRenderer.invoke("paseo:get-pending-open-project") as Promise, events: { on: (event: string, handler: EventHandler): Promise<() => void> => { const listener = (_ipcEvent: Electron.IpcRendererEvent, payload: unknown) => { handler(payload); }; ipcRenderer.on(`paseo:event:${event}`, listener); return Promise.resolve(() => { ipcRenderer.removeListener(`paseo:event:${event}`, listener); }); }, }, window: { openNew: (options?: { pendingOpenProjectPath?: string | null }) => ipcRenderer.invoke("paseo:window:openNew", options), getCurrentWindow: () => ({ toggleMaximize: () => ipcRenderer.invoke("paseo:window:toggleMaximize"), setFullscreen: (fullscreen: boolean) => ipcRenderer.invoke("paseo:window:setFullscreen", fullscreen), isFullscreen: () => ipcRenderer.invoke("paseo:window:isFullscreen"), updateWindowControls: (update: { height?: number; backgroundColor?: string; foregroundColor?: string; }) => ipcRenderer.invoke("paseo:window:updateWindowControls", update), onResized: (handler: EventHandler): (() => void) => { const listener = (_ipcEvent: Electron.IpcRendererEvent, payload: unknown) => { handler(payload); }; ipcRenderer.on("paseo:window:resized", listener); return () => { ipcRenderer.removeListener("paseo:window:resized", listener); }; }, setBadgeCount: (count?: number) => ipcRenderer.invoke("paseo:window:setBadgeCount", count), }), }, dialog: { ask: (message: string, options?: Record) => ipcRenderer.invoke("paseo:dialog:ask", message, options), askWithCheckbox: (message: string, options: Record) => ipcRenderer.invoke("paseo:dialog:askWithCheckbox", message, options), open: (options?: Record) => ipcRenderer.invoke("paseo:dialog:open", options), }, notification: { isSupported: () => ipcRenderer.invoke("paseo:notification:isSupported"), sendNotification: (payload: { title: string; body?: string; data?: Record }) => ipcRenderer.invoke("paseo:notification:send", payload), }, opener: { openUrl: (url: string) => ipcRenderer.invoke("paseo:opener:openUrl", url), }, editor: { listTargets: () => ipcRenderer.invoke("paseo:editor:listTargets"), openTarget: (input: { editorId: string; path: string; cwd?: string; mode?: "open" | "reveal"; }) => ipcRenderer.invoke("paseo:editor:openTarget", input), }, webUtils: { getPathForFile: (file: File) => webUtils.getPathForFile(file), }, menu: { showContextMenu: (input?: Record) => ipcRenderer.invoke("paseo:menu:showContextMenu", input), setCapturingShortcut: (capturing: boolean) => ipcRenderer.invoke("paseo:menu:set-capturing-shortcut", capturing), }, browser: { profilePartition: PASEO_BROWSER_PROFILE_PARTITION, registerAttachedBrowser: (input: AttachedBrowserRegistration) => ipcRenderer.invoke("paseo:browser:register-attached", input), unregisterWorkspaceBrowser: (browserId: string) => ipcRenderer.invoke("paseo:browser:unregister-workspace-browser", browserId), setWorkspaceActiveBrowser: (input: { workspaceId: string; browserId: string | null }) => ipcRenderer.invoke("paseo:browser:set-workspace-active-browser", input), openDevTools: (browserId: string) => ipcRenderer.invoke("paseo:browser:open-devtools", browserId), clearProfile: (legacyBrowserIds: string[]) => ipcRenderer.invoke("paseo:browser:clear-profile", legacyBrowserIds), executeAutomationCommand: (request: Record) => ipcRenderer.invoke("paseo:browser:execute-automation-command", request), captureElement: ( browserId: string, rect: { x: number; y: number; width: number; height: number }, ) => ipcRenderer.invoke("paseo:browser:capture-element", browserId, rect), copyElement: (payload: { text?: string; imageDataUrl?: string }) => ipcRenderer.invoke("paseo:browser:copy-element", payload), }, });