UNPKG

diffusion

Version:

Diffusion JavaScript client

255 lines (254 loc) 9.74 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __values = (this && this.__values) || function(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); }; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; var __spreadArray = (this && this.__spreadArray) || function (to, from) { for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) to[j] = from[i]; return to; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getSharedConversationSetFactory = exports.SharedSessionConnector = exports.getSharedWorker = exports.SharedWorkerMessageRouter = void 0; var errors_1 = require("./../../../errors/errors"); var conversation_id_1 = require("./../../conversation/conversation-id"); var conversation_set_1 = require("./../../conversation/conversation-set"); var emitter_1 = require("./../../events/emitter"); var stream_1 = require("./../../events/stream"); var uint8array_1 = require("./../../util/uint8array"); var worker_command_1 = require("./../../webworker/worker-command"); var Long = require("long"); /** * A message router is responsible for receiving messages from a shared worker * and passing them on to the correct connectors. Each named client session will * register one connector. */ var SharedWorkerMessageRouter = /** @class */ (function () { function SharedWorkerMessageRouter(workerJs) { var _this = this; /** * The listeners indexed by the session name. */ this.listeners = {}; this.worker = new SharedWorker(workerJs); this.worker.port.onmessage = function (message) { var e_1, _a; var sessionName = message.data[0]; // tslint:disable-next-line:strict-type-predicates if (_this.listeners[sessionName] !== undefined) { try { for (var _b = __values(_this.listeners[sessionName]), _c = _b.next(); !_c.done; _c = _b.next()) { var listener = _c.value; listener.apply(void 0, __spreadArray([message.data[1]], __read(message.data.slice(2)))); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_1) throw e_1.error; } } } }; } /** * Get the underlying shared worker * * @return the shared worker */ SharedWorkerMessageRouter.prototype.getWorker = function () { return this.worker; }; /** * Add a listener callback to messages coming from a named shared session. * * @param sessionName the name of the shared session * @param listener the callback function */ SharedWorkerMessageRouter.prototype.addListener = function (sessionName, listener) { // tslint:disable-next-line:strict-type-predicates if (this.listeners[sessionName] === undefined) { this.listeners[sessionName] = [listener]; } else { this.listeners[sessionName].push(listener); } }; /** * Remove a listener * * @param sessionName the name of the shared session * @param listenerId the id assigned to the listener */ SharedWorkerMessageRouter.prototype.removeListener = function (sessionName, listener) { // tslint:disable-next-line:strict-type-predicates if (this.listeners[sessionName] !== undefined) { this.listeners[sessionName] = this.listeners[sessionName].filter(function (l) { return l !== listener; }); } }; return SharedWorkerMessageRouter; }()); exports.SharedWorkerMessageRouter = SharedWorkerMessageRouter; /** * The SharedWorker message routers indexed by the URL of the worker JS file */ var sharedWorkers = {}; /** * Get a shared worker message router * * @param workerJs the JS file name that contains the worker code, should * contain the path to the `diffusion-worker.js` file. * @return An interface to the shared worker that allows communicating * with named shared sessions */ function getSharedWorker(workerJs) { if (!window || !window.SharedWorker) { throw new errors_1.RuntimeError('SharedWorker could not be found!'); } // tslint:disable-next-line:strict-type-predicates if (sharedWorkers[workerJs] === undefined) { sharedWorkers[workerJs] = new SharedWorkerMessageRouter(workerJs); } return sharedWorkers[workerJs]; } exports.getSharedWorker = getSharedWorker; /** * A connector to a shared session running inside a web worker * * The messages coming from the shared worker be emitted as events on the * stream. * * ## Events emitted * * `connect_event` the internal session's `connect` event * * `reconnect_event` the internal session's `reconnect` event * * `disconnect_event` the internal session's `disconnect` event * * `close_event` the internal session's `close` event * * `error_event` the internal session's `error` event * * `command_response` a response from a command request has been received * */ var SharedSessionConnector = /** @class */ (function (_super) { __extends(SharedSessionConnector, _super); function SharedSessionConnector(sessionName, workerJs) { var _this = this; var factory = emitter_1.Emitter.create(); _this = _super.call(this, factory) || this; _this.emitter = factory.emitter(_this); _this.sessionName = sessionName; _this.router = getSharedWorker(workerJs); _this.worker = _this.router.getWorker(); _this.listener = function (command) { var messages = []; for (var _i = 1; _i < arguments.length; _i++) { messages[_i - 1] = arguments[_i]; } if (messages.length < 2) { _this.emitter.emit(command, messages[0]); } else { _this.emitter.emit(command, messages); } }; _this.router.addListener(sessionName, _this.listener); return _this; } /** * Send a message to the shared session inside the web worker */ SharedSessionConnector.prototype.send = function (command, message) { this.worker.port.postMessage([this.sessionName, command, message]); }; /** * Send a message to the shared session */ SharedSessionConnector.prototype.sendMessage = function (msg) { var msgData = { type: msg.type, encoding: msg.encoding, data: uint8array_1.uint8ToBase64(msg.data), stream: uint8array_1.uint8ToBase64(msg.getBuffer()), headers: msg.headers, id: msg.id, topic: msg.topic }; this.send(worker_command_1.WorkerCommand.MESSAGE, JSON.stringify(msgData)); }; /** * Disconnect any listeners from the shared session */ SharedSessionConnector.prototype.disconnect = function () { this.router.removeListener(this.sessionName, this.listener); }; return SharedSessionConnector; }(stream_1.StreamImpl)); exports.SharedSessionConnector = SharedSessionConnector; /** * A factory for conversation sets with conversation IDs obtained from the * shared session. * * @param connector the shared session connector */ function getSharedConversationSetFactory(connector) { var pendingCidRequests = []; function nextCid() { return new Promise(function (resolve) { pendingCidRequests.push(resolve); connector.send(worker_command_1.WorkerCommand.CID); }); } connector.on('cid_event', function (cidStr) { if (pendingCidRequests.length > 0) { var resolve = pendingCidRequests.shift(); resolve(new conversation_id_1.ConversationId(Long.fromString(cidStr))); } }); return function () { return new conversation_set_1.ConversationSet(nextCid); }; } exports.getSharedConversationSetFactory = getSharedConversationSetFactory;