znapi
Version:
Better TS/JS API for zeronet-conservancy (WIP)
91 lines (90 loc) • 2.73 kB
JavaScript
import { ZNAPIGeneric } from './common.js';
export class WSAPI extends ZNAPIGeneric {
waitingCb = {};
messageQueue = [];
nextMsgId = 0;
isConnected = false;
isReconnecting = false;
ws;
wsUrl;
constructor(config) {
super();
this.wsUrl = config.wsUrl || 'ws://127.0.0.1:43110/ZeroNet-Internal/Websocket';
}
connect() {
this.ws = new WebSocket(this.wsUrl);
this.ws.addEventListener('message', (...args) => this.onMessage(...args));
this.ws.addEventListener('open', (...args) => this.onOpenWebsocket(...args));
this.ws.addEventListener('error', (...args) => this.onError(...args));
this.ws.addEventListener('close', (...args) => this.onCloseWebsocket(...args));
}
reconnect() {
if (this.isReconnecting)
return;
setTimeout(() => { this.isReconnecting = false; this.connect(); }, 10000);
}
onMessage(e) {
const message = JSON.parse(e.data);
const cmd = message.cmd;
if (cmd === "response") {
if (this.waitingCb[message.to] != null) {
this.waitingCb[message.to](message.result);
}
else {
console.log("Websocket callback not found:", message);
}
}
else if (cmd === "ping") {
/* return response(message.id, "pong"); */
}
else {
// err
this.processCallback(cmd, message);
}
}
onError(e) {
console.log(e);
// TODO
this.isConnected = false;
this.reconnect();
}
onOpenWebsocket(e) {
this.isConnected = true;
console.log('WS open!');
const msgs = [...this.messageQueue];
for (let msg of msgs) {
this.ws.send(JSON.stringify(msg));
}
this.messageQueue = [];
this.send({
cmd: 'serverInfo',
}, (info) => {
console.log('####\n', info);
});
}
onCloseWebsocket(e) {
console.log('Connection closed');
console.log(e);
this.isConnected = false;
this.reconnect();
}
send(message, cb) {
message.id = this.nextMsgId;
++this.nextMsgId;
if (this.isConnected) {
this.ws.send(JSON.stringify(message));
}
else {
console.log("Not connected, adding message to queue", message);
this.messageQueue.push(message);
}
if (cb) {
this.waitingCb[message.id] = cb;
}
}
requestPermission(permission) {
return new Promise((resolve, reject) => {
reject("Cannot request permissions in dev mode");
});
}
}