UNPKG

socket.io-rfjs

Version:

Integration of RF.js RPC engine and socket.io

271 lines (254 loc) 8.58 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.RFConnect = factory()); }(this, (function () { 'use strict'; function getAugmentedNamespace(n) { if (n.__esModule) return n; var a = Object.defineProperty({}, '__esModule', {value: true}); Object.keys(n).forEach(function (k) { var d = Object.getOwnPropertyDescriptor(n, k); Object.defineProperty(a, k, d.get ? d : { enumerable: true, get: function () { return n[k]; } }); }); return a; } class RFManager { __callbacks = new Map(); __sendQueue = []; __awaiting = {}; constructor(functions = []) { this.__sendRaw = (data) => this.__sendQueue.push(data); this.__readyState = 0; this.__functions = new Map( functions.map((f) => [ f.name, async (...args) => await this.__callFunc(f, args), ]) ); } RFPrepare(sendMessage) { this.__sendRaw = sendMessage; this.__sendQueue.forEach((message) => this.__sendRaw(message)); this.__sendQueue = null; return new Promise((resolve, reject) => { if (this.__readyState == 2) { resolve(); } else { this.__send( "availableFuncs", Array.from(this.__functions.keys()) ); this.__readyIndicator = { resolve, reject }; } }); } RFMessageReceived(message) { message = JSON.parse(message); this.__dispatch(message.type, message.data); } __dispatch(type, data) { ({ availableFuncs: () => { data.forEach((name) => { this[name] = (...args) => this.__callServerFunc(name, args); }); this.__send("funcsReceived", true); this.__readyState++; if (this.__readyState == 2) { this.__readyIndicator.resolve(); delete this.__readyIndicator; } }, functionResult: () => { if (!this.__awaiting[data.reqId]) { return; } this.__awaiting[data.reqId][data.resultType](data.result); delete this.__awaiting[data.reqId]; }, error: () => { console.error(data); }, callClientCallback: () => { let { id, args } = data; let func = this.__callbacks.get(id); if (func) { func(...this.__deserializeArgs(args)); } }, callClientFunc: () => { let fun = this.__functions.get(data.fname); if (!fun) { return; } fun(...this.__deserializeArgs(data.args)) .then((res) => { this.__send("functionResult", { reqId: data.reqId, resultType: "resolve", result: res, }); }) .catch((error) => { this.__send( JSON.stringify({ type: "functionResult", data: { reqId: data.reqId, resultType: "reject", result: error.toString(), }, }) ); }); }, funcsReceived: () => { this.__readyState++; if (this.__readyState == 2) { this.__readyIndicator.resolve(); delete this.__readyIndicator; } }, }[type]()); } __send(type, data) { this.__sendRaw( JSON.stringify({ type, data, }) ); } __deserializeArgs(args) { return args.map((a) => this.__deserializeArg(a)); } __deserializeArg(arg) { if (typeof arg == "object") { return ( { object: () => this.__deserializeObject(arg.data), function: () => async (...args) => { this.__callServerCallback(arg.data, args); }, }[arg.type]() || arg ); } else { return arg; } } __deserializeObject(object) { return Object.entries(object) .map((_key, value) => this.__deserializeArg(value)) .reduce((pv, cv) => ({ ...pv, [cv[0]]: cv[1] }), {}); } __callServerCallback(id, args) { this.__send( JSON.stringify({ type: "callServerCallback", data: { id, args: this.__serializeArgs(args), }, }) ); } __callServerFunc(fname, args) { return new Promise((resolve, reject) => { let reqId = Math.random().toString(16).substr(2); this.__send("callFunc", { fname, args: this.__serializeArgs(args), reqId, }); this.__awaiting[reqId] = { resolve, reject, }; }); } __serializeArgs(args) { return args.map(this.__serializeArg); } __serializeArg = (arg) => { let _this = this; let scenario = { object: () => ({ type: "object", data: _this.__serializeObject(arg), }), function: function () { return { type: "function", data: _this.__registerCallback(arg), }; }, }[typeof arg]; return scenario ? scenario() : arg; }; __serializeObject(object) { return Object.entries(object) .map((_key, value) => this.__serializeArg(value)) .reduce((pv, cv) => ({ ...pv, [cv[0]]: cv[1] }), {}); } __registerCallback(func) { let foundFunction = Array.from(this.__callbacks.entries()).find( (funcInfo) => { let [, fun] = funcInfo; return func == fun; } ); let id; if (foundFunction) { [id] = foundFunction; } else { id = Math.random().toString(16).substr(2); this.__callbacks.set(id, func); } return id; } RFAddFunc(func) { this.__functions.set( func.name, async (...args) => await this.__callFunc(func, args) ); this.__send( JSON.stringify({ type: "availableFuncs", data: Array.from(this.functions.keys()), }) ); } async __callFunc(func, args) { return new Promise(async (resolve, reject) => { try { resolve(await func(...args)); } catch (e) { reject(e); } }); } } var client$1 = /*#__PURE__*/Object.freeze({ __proto__: null, 'default': RFManager }); var require$$0 = /*@__PURE__*/getAugmentedNamespace(client$1); var client = async (socket, functions = []) => { let RFM = require$$0.default; socket.rf = new RFM(functions); socket.on("_rfjs_server_signal", (d) => { socket.rf.RFMessageReceived(d); }); await socket.rf.RFPrepare((d) => { socket.emit("_rfjs_client_signal", d); }); }; return client; })));