fleetcode/ipc-adapter.ts

99 lines
2.8 KiB
TypeScript

// Communication adapter that works in both Electron and Web modes
import { io, Socket } from "socket.io-client";
type EventCallback = (event: any, ...args: any[]) => void;
export interface IPCAdapter {
send(channel: string, ...args: any[]): void;
invoke(channel: string, ...args: any[]): Promise<any>;
on(channel: string, callback: EventCallback): void;
}
class ElectronAdapter implements IPCAdapter {
private ipcRenderer: any;
constructor() {
this.ipcRenderer = require("electron").ipcRenderer;
}
send(channel: string, ...args: any[]): void {
this.ipcRenderer.send(channel, ...args);
}
invoke(channel: string, ...args: any[]): Promise<any> {
return this.ipcRenderer.invoke(channel, ...args);
}
on(channel: string, callback: EventCallback): void {
this.ipcRenderer.on(channel, callback);
}
}
class WebAdapter implements IPCAdapter {
private socket: Socket;
private responseHandlers = new Map<number, { resolve: (value: any) => void; reject: (reason?: any) => void }>();
private requestCounter = 0;
constructor() {
this.socket = io();
// Handle invoke responses from server
this.socket.on("invoke-response", (requestId: number, error: any, result: any) => {
const handler = this.responseHandlers.get(requestId);
if (handler) {
this.responseHandlers.delete(requestId);
if (error) {
handler.reject(error);
} else {
handler.resolve(result);
}
}
});
}
send(channel: string, ...args: any[]): void {
this.socket.emit(channel, ...args);
}
invoke(channel: string, ...args: any[]): Promise<any> {
return new Promise((resolve, reject) => {
const requestId = this.requestCounter++;
this.responseHandlers.set(requestId, { resolve, reject });
// Set timeout for invoke
setTimeout(() => {
if (this.responseHandlers.has(requestId)) {
this.responseHandlers.delete(requestId);
reject(new Error(`Invoke timeout: ${channel}`));
}
}, 10000);
this.socket.emit("invoke", requestId, channel, ...args);
});
}
on(channel: string, callback: EventCallback): void {
this.socket.on(channel, (...args: any[]) => {
// Mimic Electron's event object structure
const event = {};
callback(event, ...args);
});
}
}
// Detect environment and create appropriate adapter
function createAdapter(): IPCAdapter {
// Check if running in Electron
const isElectron = typeof window !== "undefined" &&
typeof (window as any).process !== "undefined" &&
(window as any).process.type === "renderer";
if (isElectron) {
return new ElectronAdapter();
} else {
return new WebAdapter();
}
}
export const ipcAdapter = createAdapter();