UNPKG

socio

Version:

A WebSocket Real-Time Communication (RTC) API framework.

60 lines (59 loc) 2.37 kB
import { LogHandler, E } from "./logging.js"; import { WebSocket as nodeWebSocket } from "ws"; import { socio_decode, socio_encode, ClientMessageKind } from './utils.js'; export class AdminClient extends LogHandler { #ws; #client_id = ''; #client_secret = ''; static #key = 1; #is_ready = false; #queries = {}; constructor({ url = '', client_secret = '', logging = { verbose: false, hard_crash: false } }) { super({ prefix: 'SocioAdmin', ...logging }); if (client_secret.length < 16) throw new E('client_secret length must be at least 16 char for safety. Got ', client_secret.length); this.#client_secret = client_secret; this.#ws = new nodeWebSocket(url); this.#ws.on('error', this.HandleError); this.#ws.on('message', this.#Message.bind(this)); } #Message(d, isBinary) { const { kind, data } = socio_decode(d); switch (kind) { case ClientMessageKind.CON: { this.#client_id = data; if (this.#is_ready !== false && typeof this.#is_ready === "function") this.#is_ready(true); if (this.verbose) this.done(`Connected.`, this.#client_id); this.#is_ready = true; break; } case ClientMessageKind.RES: { this.HandleInfo('recv:', kind, data); this.#HandleBasicPromiseMessage(data); break; } default: throw new E(`Unrecognized message kind!`, kind, data); } } get #GenKey() { AdminClient.#key += 1; return AdminClient.#key; } #HandleBasicPromiseMessage(data) { if (data.id in this.#queries) this.#queries[data.id](data?.result || null); delete this.#queries[data.id]; } Run(function_name, ...args) { const id = this.#GenKey; const prom = new Promise((res) => { this.#queries[id] = res; }); this.#ws.send(socio_encode({ kind: 'ADMIN', data: { id: id, client_secret: this.#client_secret, function: function_name, args: args } })); return prom; } ready() { return this.#is_ready === true ? (new Promise(res => res(true))) : (new Promise(res => this.#is_ready = res)); } Close() { this.#ws.close(); } }