2023-07-04 09:14:36 +00:00
|
|
|
import { addHandler, handleMessage } from "@lumeweb/libkernel/module";
|
|
|
|
import type { ActiveQuery } from "@lumeweb/libkernel/module";
|
2023-04-06 20:52:37 +00:00
|
|
|
import { createClient, SwarmClient } from "@lumeweb/kernel-swarm-client";
|
2023-04-09 00:17:44 +00:00
|
|
|
import { RpcNetwork, RpcQueryOptions, setupStream } from "@lumeweb/rpc-client";
|
2023-03-18 16:33:08 +00:00
|
|
|
import type { RPCRequest, RPCResponse } from "@lumeweb/interface-relay";
|
2022-07-21 17:04:17 +00:00
|
|
|
|
|
|
|
onmessage = handleMessage;
|
|
|
|
|
2022-08-31 18:30:16 +00:00
|
|
|
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
|
|
|
|
2022-08-31 18:30:16 +00:00
|
|
|
let defaultNetwork: RpcNetwork;
|
2022-08-31 20:40:54 +00:00
|
|
|
let moduleReadyResolve: Function;
|
|
|
|
let moduleReady: Promise<void> = new Promise((resolve) => {
|
|
|
|
moduleReadyResolve = resolve;
|
|
|
|
});
|
2022-08-31 18:30:16 +00:00
|
|
|
|
|
|
|
const networkInstances = new Map<number, RpcNetwork>();
|
|
|
|
|
2023-07-04 09:45:40 +00:00
|
|
|
addHandler("presentKey", handlePresentKey);
|
2022-08-31 18:30:16 +00:00
|
|
|
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);
|
|
|
|
|
2023-07-04 09:45:40 +00:00
|
|
|
async function handlePresentKey() {
|
2022-08-31 18:30:16 +00:00
|
|
|
if (!defaultNetwork) {
|
|
|
|
defaultNetwork = networkInstances.get(await createNetwork()) as RpcNetwork;
|
|
|
|
}
|
2022-08-31 20:40:54 +00:00
|
|
|
moduleReadyResolve();
|
2022-08-31 18:30:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
2023-03-18 16:33:08 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2022-08-31 20:40:54 +00:00
|
|
|
const network = await getNetwork(aq);
|
2022-08-31 18:30:16 +00:00
|
|
|
|
2022-08-31 04:28:34 +00:00
|
|
|
let resp: RPCResponse | null = null;
|
2022-07-21 17:04:17 +00:00
|
|
|
|
|
|
|
try {
|
2023-03-18 16:33:08 +00:00
|
|
|
const rpcQuery = network.factory.simple({
|
|
|
|
relay,
|
|
|
|
query,
|
|
|
|
options,
|
2022-09-01 00:03:11 +00:00
|
|
|
});
|
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) {
|
2023-03-19 19:22:41 +00:00
|
|
|
const network = await getNetwork(aq);
|
|
|
|
const swarm: SwarmClient = network.swarm;
|
|
|
|
|
2023-03-29 20:54:58 +00:00
|
|
|
await swarm.start();
|
2023-03-29 20:53:47 +00:00
|
|
|
await swarm.ready();
|
2023-03-19 19:22:41 +00:00
|
|
|
|
2022-08-31 20:40:54 +00:00
|
|
|
await (
|
|
|
|
await getNetwork(aq)
|
2023-03-18 16:33:08 +00:00
|
|
|
).readyWithRelays;
|
2022-07-21 17:04:17 +00:00
|
|
|
aq.respond();
|
|
|
|
}
|
2023-07-04 09:14:36 +00:00
|
|
|
|
2022-08-31 18:30:16 +00:00
|
|
|
async function createNetwork(def = true): Promise<number> {
|
2023-03-19 19:20:53 +00:00
|
|
|
const dhtInstance = new RpcNetwork(createClient(def));
|
2022-08-31 18:30:16 +00:00
|
|
|
const id = nextId();
|
|
|
|
networkInstances.set(id, dhtInstance);
|
|
|
|
|
2023-04-09 00:17:44 +00:00
|
|
|
dhtInstance.swarm.on("setup", async (peer: any) => setupStream(peer));
|
|
|
|
|
2022-08-31 18:30:16 +00:00
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
2022-08-31 20:40:54 +00:00
|
|
|
async function getNetwork(aq: ActiveQuery): Promise<RpcNetwork> {
|
2023-03-19 19:21:27 +00:00
|
|
|
const { network = null } = aq?.callerInput ?? {};
|
2022-08-31 18:30:16 +00:00
|
|
|
|
2022-08-31 20:40:54 +00:00
|
|
|
await moduleReady;
|
|
|
|
|
2022-08-31 18:30:16 +00:00
|
|
|
if (!network) {
|
|
|
|
return defaultNetwork;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!networkInstances.has(network)) {
|
|
|
|
const err = "Invalid network id";
|
|
|
|
aq.reject(err);
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return networkInstances.get(network) as RpcNetwork;
|
|
|
|
}
|