export function exposeApiContext() {
try {
if (!contextBridge || !ipcRenderer) {
throw new Error(
"Failed to load electron modules: contextBridge or ipcRenderer is undefined",
);
}
contextBridge.exposeInMainWorld("electronAPI", {
anilist: {
request: (payload: AniListRequest): Promise<AniListResponseEnvelope> =>
ipcRenderer.invoke("anilist:request", payload),
clearCache: (searchQuery?: string) =>
ipcRenderer.invoke("anilist:clearCache", searchQuery),
getRateLimitStatus: () =>
ipcRenderer.invoke("anilist:getRateLimitStatus"),
onSearchCacheCleared: (
handler: (payload: { searchQuery?: string }) => void,
) => {
const listener = (
_event: Electron.IpcRendererEvent,
payload: { searchQuery?: string },
) => handler(payload);
ipcRenderer.on("anilist:search-cache-cleared", listener);
return () =>
ipcRenderer.removeListener(
"anilist:search-cache-cleared",
listener,
);
},
},
mangaSource: {
search: (source: MangaSource, query: string, limit?: number) =>
ipcRenderer.invoke("mangaSource:search", source, query, limit),
getMangaDetail: (source: MangaSource, slug: string) =>
ipcRenderer.invoke("mangaSource:getMangaDetail", source, slug),
},
shell: {
openExternal: (url: string): Promise<ShellOperationResult> =>
ipcRenderer.invoke("shell:openExternal", url),
},
});
console.log("[APIContext] ✅ API context exposed in main world");
} catch (error) {
console.error("[APIContext] ❌ Error exposing API context:", error);
}
}
Exposes the Electron API context bridge to the renderer process. Provides secure IPC interfaces for AniList GraphQL requests, manga source searches, and shell operations.