"use strict"; let websocket = require("websocket"); let {http} = require("./HTTPServer"); let {randomUUID} = require("crypto"); const { Client } = require("./Client.js"); let wsServer = new websocket.server({ httpServer: http, autoAcceptConnections: true }); let global = new Map(); let clients = new Map(); wsServer.addListener("connect",(socket) => { let local = new Client(); let id = randomUUID(); socket.id = id; local.id = id; local.socket = socket; local.created_at = new Date(); clients.set(id, local); emit("connect", global, local); socket.addListener("close",()=>{ emit("disconnect", global, local); clients.delete(id); }); socket.addListener("message",({type,utf8Data}) => { if(type == "utf8") { let json; try{ json = JSON.parse(utf8Data); emit('services', global, local, json); let [payload, id, action] = json; if(typeof id === "string") { action = id; } emitService(global, local, id, payload, action); }catch{ emit("messageError", global, local, utf8Data); } } }); }); /** * @type {Map} */ let events = new Map(); /** * @type {Map} */ let services = [] /** * * @param {string} event * @param {(global:Map, client:Client, data:any) => any} func */ exports.addListener = (event, func) => { if(!events.has(event)) { events.set(event,[]); }; events.get(event).push(func); }; /** * * @param {string} event * @param {(data:{global:Map, client:Client, message:any,response:Function,end:Function,next:Function}) => any} func */ exports.addService = (func) => { services.push(func); }; function emit(event,...args) { if(events.has(event)) { for (const callback of events.get(event)) { callback(...args); } }; }; /** * * @param {Map} global * @param {Client} local * @param {number} id * @param {{[key:string]:any}} payload * @param {"R"|"S"} action */ async function emitService(global, client, id, payload, action) { let willContinue = false; for (const callback of services) { await callback({ message: payload, action, client, global, response:(obj)=>{ client.send([obj, id, 'C']) // continue }, end:(obj)=>{ client.send([obj, id, 'E']) // stopped data stream (this channel) }, next:function(){ willContinue = true; } }); if(willContinue === false) break; } }; exports.websocket = wsServer;