diffusion
Version:
Diffusion JavaScript client
255 lines (254 loc) • 9.74 kB
JavaScript
;
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;