*Initial version
This commit is contained in:
parent
bb0c5fe92e
commit
05f3916b4a
|
@ -0,0 +1,13 @@
|
|||
import esbuild from "esbuild";
|
||||
|
||||
esbuild.buildSync({
|
||||
entryPoints: ["src/index.ts"],
|
||||
outfile: "dist/index.js",
|
||||
format: "esm",
|
||||
bundle: true,
|
||||
legalComments: "external",
|
||||
// minify: true
|
||||
define: {
|
||||
global: "self",
|
||||
},
|
||||
});
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"name": "@lumeweb/kernel-dht",
|
||||
"author": {
|
||||
"name": "Hammer Technologies LLC",
|
||||
"email": "contact@lumeweb.com"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
"build-script": "tsc --project tsconfig.build.json && mv dist-build/build.js dist-build/build.mjs",
|
||||
"compile": "npm run build-script && node build.js",
|
||||
"build": "npm run compile && node ./dist-build/build.mjs dev"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@lumeweb/dht-web": "https://github.com/LumeWeb/dht-web.git",
|
||||
"hyperswarm": "^4.0.2",
|
||||
"libkmodule": "^0.2.12",
|
||||
"libskynet": "^0.0.62"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-commonjs": "^22.0.1",
|
||||
"@rollup/plugin-node-resolve": "^13.3.0",
|
||||
"@rollup/plugin-typescript": "^8.3.3",
|
||||
"@types/jest": "^28.1.3",
|
||||
"@types/read": "^0.0.29",
|
||||
"buffer": "^6.0.3",
|
||||
"esbuild": "^0.14.48",
|
||||
"inspectpack": "^4.7.1",
|
||||
"jest": "^28.1.1",
|
||||
"jest-puppeteer": "^6.1.0",
|
||||
"libskynetnode": "^0.1.3",
|
||||
"prettier": "^2.7.1",
|
||||
"puppeteer": "^15.2.0",
|
||||
"read": "^1.0.7",
|
||||
"rollup": "^2.75.7",
|
||||
"rollup-plugin-polyfill-node": "^0.9.0",
|
||||
"ts-loader": "^9.3.1",
|
||||
"typescript": "^4.7.4",
|
||||
"webpack": "^5.73.0",
|
||||
"webpack-cli": "^4.10.0"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
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;
|
||||
};
|
||||
}
|
||||
|
||||
export const nextId = idFactory(1);
|
|
@ -0,0 +1,169 @@
|
|||
// @ts-ignore
|
||||
import DHT from "@lumeweb/dht-web";
|
||||
import { addHandler, handleMessage } from "libkmodule";
|
||||
import type { ActiveQuery } from "libkmodule";
|
||||
import { nextId } from "./id";
|
||||
import { Buffer } from "buffer";
|
||||
|
||||
let dht: DHT;
|
||||
|
||||
const connections = new Map();
|
||||
|
||||
onmessage = handleMessage;
|
||||
|
||||
addHandler("presentSeed", handlePresentSeed);
|
||||
addHandler("connect", handleConnect);
|
||||
addHandler("listenSocketEvent", handleListenSocketEvent, {
|
||||
receiveUpdates: true,
|
||||
});
|
||||
addHandler("close", handleCloseSocketEvent);
|
||||
addHandler("write", handleWriteSocketEvent);
|
||||
addHandler("addRelay", handleAddRelay);
|
||||
addHandler("removeRelay", handleRemoveRelay);
|
||||
addHandler("clearRelays", handleClearRelays);
|
||||
addHandler("ready", handleReady);
|
||||
|
||||
function handlePresentSeed(aq: ActiveQuery) {
|
||||
const keyPair = aq.callerInput.myskyRootKeypair;
|
||||
if (!dht) {
|
||||
dht = new DHT({ keyPair });
|
||||
}
|
||||
}
|
||||
|
||||
async function handleConnect(aq: ActiveQuery) {
|
||||
const { pubkey, options = {} } = aq.callerInput;
|
||||
|
||||
let socket: any;
|
||||
|
||||
try {
|
||||
// @ts-ignore
|
||||
socket = await dht.connect(
|
||||
typeof pubkey === "string" ? Buffer.from(pubkey, "hex") : pubkey,
|
||||
options
|
||||
);
|
||||
} catch (e: any) {
|
||||
aq.reject(e);
|
||||
return;
|
||||
}
|
||||
|
||||
const id = nextId();
|
||||
|
||||
socket.on("open", () => {
|
||||
connections.set(id, socket);
|
||||
aq.respond({ id });
|
||||
});
|
||||
|
||||
socket.on("error", (e: any) => {
|
||||
connections.set(id, socket);
|
||||
aq.reject(e);
|
||||
});
|
||||
}
|
||||
|
||||
function handleListenSocketEvent(aq: ActiveQuery) {
|
||||
const { event = null } = aq.callerInput;
|
||||
const id = validateConnection(aq);
|
||||
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!event) {
|
||||
aq.reject("Invalid event");
|
||||
return;
|
||||
}
|
||||
|
||||
const socket = connections.get(id);
|
||||
const cb = (data: Buffer) => {
|
||||
aq.sendUpdate(data);
|
||||
};
|
||||
|
||||
socket.on(event, cb);
|
||||
socket.on("close", () => {
|
||||
socket.off(socket, cb);
|
||||
aq.respond();
|
||||
});
|
||||
|
||||
aq.setReceiveUpdate?.((data: any) => {
|
||||
switch (data?.action) {
|
||||
case "off":
|
||||
socket.off(socket, cb);
|
||||
aq.respond();
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function handleCloseSocketEvent(aq: ActiveQuery) {
|
||||
const id = validateConnection(aq);
|
||||
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
|
||||
connections.get(id).end();
|
||||
|
||||
aq.respond();
|
||||
}
|
||||
|
||||
function handleWriteSocketEvent(aq: ActiveQuery) {
|
||||
const id = validateConnection(aq);
|
||||
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
const { message = null } = aq.callerInput;
|
||||
|
||||
if (!message) {
|
||||
aq.reject("empty message");
|
||||
return false;
|
||||
}
|
||||
|
||||
connections.get(id).write(message);
|
||||
|
||||
aq.respond();
|
||||
}
|
||||
|
||||
function validateConnection(aq: ActiveQuery): number | boolean {
|
||||
const { id = null } = aq.callerInput;
|
||||
|
||||
if (!id || !connections.has(id)) {
|
||||
aq.reject("Invalid connection id");
|
||||
return false;
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
async function handleAddRelay(aq: ActiveQuery) {
|
||||
const { pubkey = null } = aq.callerInput;
|
||||
|
||||
if (!pubkey) {
|
||||
aq.reject("invalid pubkey");
|
||||
return;
|
||||
}
|
||||
|
||||
aq.respond(await dht.addRelay(pubkey));
|
||||
}
|
||||
|
||||
function handleRemoveRelay(aq: ActiveQuery) {
|
||||
const { pubkey = null } = aq.callerInput;
|
||||
|
||||
if (!pubkey) {
|
||||
aq.reject("invalid pubkey");
|
||||
return;
|
||||
}
|
||||
|
||||
aq.respond(dht.removeRelay(pubkey));
|
||||
}
|
||||
|
||||
function handleClearRelays(aq: ActiveQuery) {
|
||||
dht.clearRelays();
|
||||
|
||||
aq.respond();
|
||||
}
|
||||
|
||||
async function handleReady(aq: ActiveQuery) {
|
||||
// @ts-ignore
|
||||
await dht.ready();
|
||||
aq.respond();
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"declaration": true,
|
||||
"outDir": "./dist-build",
|
||||
"strict": true,
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"include": ["src-build"],
|
||||
"exclude": ["node_modules", "**/__tests__/*"]
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"declaration": true,
|
||||
"moduleResolution": "node",
|
||||
"outDir": "./build",
|
||||
"strict": true,
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "**/__tests__/*"]
|
||||
}
|
Loading…
Reference in New Issue