Initial Commit

This commit is contained in:
Draculabo committed 2025-12-23 01:38:53 +08:00
commit d0417339c1
158 files changed
+31368

No files matched your search

+136
View File
@@ -0,0 +1,136 @@
import { IPC_CHANNELS } from '@/constants';
// Custom IPC Client that correctly builds method paths
function createIPCClient(port: MessagePort) {
let requestId = 0;
const pendingRequests = new Map<
string,
{ resolve: (v: any) => void; reject: (e: any) => void }
>();
port.onmessage = (event) => {
try {
const data = typeof event.data === 'string' ? JSON.parse(event.data) : event.data;
const id = data.i || data.id;
const pending = pendingRequests.get(id);
if (pending) {
pendingRequests.delete(id);
if (data.e || data.error) {
const errorMsg = data.e?.m || data.error?.message || JSON.stringify(data.e || data.error);
console.error('[IPCClient] Error response:', errorMsg);
pending.reject(new Error(errorMsg));
} else {
// ORPC response format: { i, p: { b: { json: value }, s?: statusCode } }
// Or error: { i, p: { s: 500, b: { json: { code, message } } } }
let result;
const payload = data.p;
// Check for error status
if (payload?.s && payload.s >= 400) {
const errorData = payload.b?.json;
const errorMsg = errorData?.message || errorData?.code || 'Server error';
console.error('[IPCClient] Server error:', errorData);
pending.reject(new Error(errorMsg));
return;
}
// Extract successful result
if (payload?.b?.json !== undefined) {
result = payload.b.json;
} else if (data.r !== undefined) {
// Fallback to 'r' field if present
result = data.r?.b?.json ?? data.r;
} else if ('result' in data) {
result = data.result;
}
pending.resolve(result);
}
} else {
console.warn('[IPCClient] No pending request for id:', id);
}
} catch (e) {
console.error('[IPCClient] Error parsing response:', e, event.data);
}
};
async function callMethod(path: string[], input?: unknown): Promise<any> {
const id = String(++requestId);
const methodPath = path.join('/');
return new Promise((resolve, reject) => {
pendingRequests.set(id, { resolve, reject });
// ORPC MessagePort protocol format
const payload = {
i: id,
p: {
u: `orpc://localhost/${methodPath}`,
b: { json: input ?? null },
},
};
port.postMessage(JSON.stringify(payload));
setTimeout(() => {
if (pendingRequests.has(id)) {
pendingRequests.delete(id);
reject(new Error(`Request /${methodPath} timed out`));
}
}, 10000);
});
}
// Create a Proxy that builds the path chain
function createProxyChain(pathSoFar: string[] = []): any {
return new Proxy(() => {}, {
get(_target, prop: string) {
if (prop === 'then' || prop === 'catch' || prop === 'finally') {
// Don't intercept promise methods
return undefined;
}
// Build deeper path
return createProxyChain([...pathSoFar, prop]);
},
apply(_target, _thisArg, args) {
// Called as function - execute RPC
const input = args[0];
return callMethod(pathSoFar, input);
},
});
}
return createProxyChain();
}
class IPCManager {
private readonly clientPort: MessagePort;
private readonly serverPort: MessagePort;
public readonly client: any; // Will be typed via usage
private initialized: boolean = false;
constructor() {
const { port1, port2 } = new MessageChannel();
this.clientPort = port1;
this.serverPort = port2;
this.client = createIPCClient(this.clientPort);
}
public initialize() {
if (this.initialized) {
return;
}
this.clientPort.start();
window.postMessage(IPC_CHANNELS.START_ORPC_SERVER, '*', [this.serverPort]);
this.initialized = true;
}
}
export const ipc = new IPCManager();
ipc.initialize();