UNPKG

z-ipc

Version:

Z-IPC is an easy-to-use, extensible and fully type-safe IPC solution for JavaScript environments.

158 lines (152 loc) 3.57 kB
// src/core/adapter.ts function defineAdapter(adapter) { return adapter; } // src/core/rpc-error.ts var RpcError = class extends Error { constructor(message, remoteStack) { super(message); this.remoteStack = remoteStack; } }; // src/core/client.ts function createClient(adapter) { const eventListeners = /* @__PURE__ */ new Map(); adapter.subscribe((message) => { if (message.kind !== "event") return; const listeners = eventListeners.get(message.name); if (!listeners) return; for (const listener of listeners) { listener(message.payload); } }); return { protocol: void 0, call: (method, ...args) => { const id = Math.random(); return new Promise((resolve, reject) => { const responseListener = (response) => { if (response.kind !== "rpc-response") return; if (response.id !== id) return; adapter.unsubscribe(responseListener); if (response.result.error) { reject( new RpcError( response.result.message, response.result.stack ) ); } else { resolve(response.result.value); } }; adapter.subscribe(responseListener); adapter.publish({ kind: "rpc-request", id, method, args }); }); }, subscribe: (event, listener) => { if (!eventListeners.has(event)) { eventListeners.set(event, /* @__PURE__ */ new Set()); } const listeners = eventListeners.get(event); listeners.add(listener); }, unsubscribe: (event, listener) => { if (!eventListeners.has(event)) { return; } const listeners = eventListeners.get(event); listeners.delete(listener); if (listeners.size === 0) { eventListeners.delete(event); } } }; } // src/core/message.ts function createOkResponse(id, value) { return { kind: "rpc-response", id, result: { error: false, value } }; } function createErrorResponse(id, error) { return { kind: "rpc-response", id, result: { error: true, message: error.message, stack: error.stack ?? "???" } }; } // src/core/protocol.ts function defineMethod(handler) { return { kind: "method", handler }; } function defineEvent() { return { kind: "event" }; } // src/core/server.ts function createServer(adapter, protocol) { adapter.subscribe(async (message) => { if (message.kind !== "rpc-request") { return; } const method = protocol[message.method]; if (!method || method.kind !== "method") { adapter.publish( createErrorResponse(message.id, new TypeError("Unknown method")) ); return; } try { const result = await method.handler(...message.args); adapter.publish(createOkResponse(message.id, result)); } catch (error) { console.error(error); if (error instanceof Error) { adapter.publish(createErrorResponse(message.id, error)); } else { adapter.publish( createErrorResponse(message.id, new Error("Unknown error")) ); } } }); return { protocol, emit: (event, payload) => { adapter.publish({ kind: "event", name: event, payload }); } }; } export { RpcError, createClient, createErrorResponse, createOkResponse, createServer, defineAdapter, defineEvent, defineMethod };