partyfn
Version:
RPC on Durable Objects
76 lines • 2 kB
JavaScript
// src/index.ts
import { nanoid } from "nanoid";
var rpcCaches = /* @__PURE__ */ new Map();
var RPCClient = class {
constructor(channel, socket) {
this.channel = channel;
this.socket = socket;
const cache = rpcCaches.get(channel);
if (!cache) {
rpcCaches.set(channel, /* @__PURE__ */ new Map());
}
this.rpcCache = rpcCaches.get(channel);
this.socket.addEventListener(
"message",
(event) => {
const message = JSON.parse(
event.data
);
if ((message.type === "success" || message.type === "error") && message.channel === this.channel && message.rpc === true) {
this.resolve(message);
}
},
{ signal: this.controller.signal }
);
}
rpcCache;
controller = new AbortController();
rpc(id, timeout = 1e4) {
const resolver = Promise.withResolvers();
this.rpcCache.set(id, resolver);
setTimeout(() => {
this.rpcCache.delete(id);
resolver.reject(new Error(`RPC call ${id} timed out`));
}, timeout);
return resolver.promise;
}
async call(action, timeout = 1e4) {
const id = nanoid(8);
this.socket.send(
JSON.stringify({
id,
channel: this.channel,
rpc: true,
action
})
);
return this.rpc(id, timeout);
}
async resolve(response) {
if (response.type === "exception") {
this.onException(response.exception);
return;
}
const resolver = this.rpcCache.get(response.id);
if (!resolver) {
console.warn(`No resolver found for id: ${response.id}`);
return;
}
if (response.type === "success") {
resolver.resolve(response.result);
} else {
resolver.reject(new Error(response.error.join("\n")));
}
}
onException(exception) {
console.warn("Override this method to handle exceptions");
console.error(exception);
}
destroy() {
this.controller.abort();
}
};
export {
RPCClient
};
//# sourceMappingURL=index.js.map