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
JavaScript
// 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
};