kernel-rpc/src/index.ts

125 lines
2.8 KiB
TypeScript
Raw Normal View History

2023-07-04 09:14:36 +00:00
import { addHandler, handleMessage } from "@lumeweb/libkernel/module";
import type { ActiveQuery } from "@lumeweb/libkernel/module";
import { createClient, SwarmClient } from "@lumeweb/kernel-swarm-client";
import { RpcNetwork, RpcQueryOptions, setupStream } from "@lumeweb/rpc-client";
import type { RPCRequest, RPCResponse } from "@lumeweb/interface-relay";
2022-07-21 17:04:17 +00:00
onmessage = handleMessage;
function idFactory(start = 1, step = 1, limit = 2 ** 32) {
let id = start;
return function nextId() {
const nextId = id;
id += step;
if (id >= limit) id = start;
return nextId;
};
}
const nextId = idFactory(1);
2022-07-21 17:04:17 +00:00
let defaultNetwork: RpcNetwork;
let moduleReadyResolve: Function;
let moduleReady: Promise<void> = new Promise((resolve) => {
moduleReadyResolve = resolve;
});
const networkInstances = new Map<number, RpcNetwork>();
addHandler("presentKey", handlePresentKey);
addHandler("createNetwork", handleCreateNetwork);
2022-08-31 04:28:34 +00:00
addHandler("simpleQuery", handleSimpleQuery);
2022-07-21 17:04:17 +00:00
addHandler("ready", handleReady);
async function handlePresentKey() {
if (!defaultNetwork) {
defaultNetwork = networkInstances.get(await createNetwork()) as RpcNetwork;
}
moduleReadyResolve();
}
async function handleCreateNetwork(aq: ActiveQuery) {
aq.respond(await createNetwork(false));
}
2023-07-04 09:14:36 +00:00
2022-08-31 04:28:34 +00:00
async function handleSimpleQuery(aq: ActiveQuery) {
const {
query = undefined,
relay = undefined,
2022-08-31 04:28:34 +00:00
options = undefined,
} = aq.callerInput as {
query: RPCRequest;
options: RpcQueryOptions;
relay: Buffer | string;
};
if (!query) {
aq.reject("RPCRequest query required");
return;
}
const network = await getNetwork(aq);
2022-08-31 04:28:34 +00:00
let resp: RPCResponse | null = null;
2022-07-21 17:04:17 +00:00
try {
const rpcQuery = network.factory.simple({
relay,
query,
options,
});
2022-08-31 04:28:34 +00:00
resp = await rpcQuery.result;
} catch (e: any) {
aq.reject(e);
}
if (resp?.error) {
aq.reject(resp?.error);
return;
}
2022-07-21 17:04:17 +00:00
aq.respond(resp);
}
async function handleReady(aq: ActiveQuery) {
const network = await getNetwork(aq);
const swarm: SwarmClient = network.swarm;
2023-03-29 20:54:58 +00:00
await swarm.start();
await swarm.ready();
await (
await getNetwork(aq)
).readyWithRelays;
2022-07-21 17:04:17 +00:00
aq.respond();
}
2023-07-04 09:14:36 +00:00
async function createNetwork(def = true): Promise<number> {
2023-03-19 19:20:53 +00:00
const dhtInstance = new RpcNetwork(createClient(def));
const id = nextId();
networkInstances.set(id, dhtInstance);
dhtInstance.swarm.on("setup", async (peer: any) => setupStream(peer));
return id;
}
async function getNetwork(aq: ActiveQuery): Promise<RpcNetwork> {
const { network = null } = aq?.callerInput ?? {};
await moduleReady;
if (!network) {
return defaultNetwork;
}
if (!networkInstances.has(network)) {
const err = "Invalid network id";
aq.reject(err);
throw err;
}
return networkInstances.get(network) as RpcNetwork;
}