UNPKG

@ably/laravel-echo

Version:

Laravel Echo library for beautiful Ably integration

1,480 lines (1,459 loc) 82 kB
function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; } function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } function _get() { return _get = "undefined" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); } function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); } function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function () { return !!t; })(); } function _possibleConstructorReturn(t, e) { if (e && ("object" == typeof e || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); } function _regeneratorRuntime() { _regeneratorRuntime = function () { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function (t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == typeof h && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function (t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(typeof e + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function (e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function () { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function (e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function (t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function (t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function (t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function (t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error("illegal catch attempt"); }, delegateYield: function (e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; } function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); } function _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; } function _superPropGet(t, e, o, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), e, o); return 2 & r && "function" == typeof p ? function (t) { return p.apply(o, t); } : p; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } /** * This class represents a basic channel. */ var Channel = /*#__PURE__*/function () { function Channel() { _classCallCheck(this, Channel); } return _createClass(Channel, [{ key: "listenForWhisper", value: /** * Listen for a whisper event on the channel instance. */ function listenForWhisper(event, callback) { return this.listen('.client-' + event, callback); } /** * Listen for an event on the channel instance. */ }, { key: "notification", value: function notification(callback) { return this.listen('.Illuminate\\Notifications\\Events\\BroadcastNotificationCreated', callback); } /** * Stop listening for a whisper event on the channel instance. */ }, { key: "stopListeningForWhisper", value: function stopListeningForWhisper(event, callback) { return this.stopListening('.client-' + event, callback); } }]); }(); /****************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ function __rest(s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; } function __awaiter(thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); } typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; /** * Event name formatter */ var EventFormatter = /*#__PURE__*/function () { /** * Create a new class instance. */ function EventFormatter(namespace) { _classCallCheck(this, EventFormatter); this.namespace = namespace; // } /** * Format the given event name. */ return _createClass(EventFormatter, [{ key: "format", value: function format(event) { if (['.', '\\'].includes(event.charAt(0))) { return event.substring(1); } else if (this.namespace) { event = this.namespace + '.' + event; } return event.replace(/\./g, '\\'); } /** * Set the event namespace. */ }, { key: "setNamespace", value: function setNamespace(value) { this.namespace = value; } }]); }(); /** * This class represents an Ably channel. */ var AblyChannel = /*#__PURE__*/function (_Channel) { /** * Create a new class instance. */ function AblyChannel(ably, name, options) { var _this; var autoSubscribe = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; _classCallCheck(this, AblyChannel); _this = _callSuper(this, AblyChannel); _this._alertErrorListeners = function (err) { if (err) { _this.errorListeners.forEach(function (listener) { return listener(err); }); } }; _this.name = name; _this.ably = ably; _this.options = options; _this.eventFormatter = new EventFormatter(_this.options.namespace); _this.subscribedListeners = []; _this.errorListeners = []; _this.channel = ably.channels.get(name); _this.callbacks = new Map(); if (autoSubscribe) { _this.subscribe(); } return _this; } /** * Subscribe to an Ably channel. */ _inherits(AblyChannel, _Channel); return _createClass(AblyChannel, [{ key: "subscribe", value: function subscribe() { var _this2 = this; this.channel.on(function (stateChange) { var previous = stateChange.previous, current = stateChange.current, reason = stateChange.reason; if (previous !== 'attached' && current == 'attached') { _this2.subscribedListeners.forEach(function (listener) { return listener(); }); } else if (reason) { _this2._alertErrorListeners(stateChange); } }); this.channel.attach(this._alertErrorListeners); } /** * Unsubscribe from an Ably channel, unregister all callbacks and finally detach the channel */ }, { key: "unsubscribe", value: function unsubscribe() { this.channel.unsubscribe(); this.callbacks.clear(); this.unregisterError(); this.unregisterSubscribed(); this.channel.off(); this.channel.detach(); } /** * Listen for an event on the channel instance. */ }, { key: "listen", value: function listen(event, callback) { this.callbacks.set(callback, function (_a) { var data = _a.data, metaData = __rest(_a, ["data"]); return callback(data, metaData); }); this.channel.subscribe(this.eventFormatter.format(event), this.callbacks.get(callback)); return this; } /** * Listen for all events on the channel instance. */ }, { key: "listenToAll", value: function listenToAll(callback) { var _this3 = this; this.callbacks.set(callback, function (_a) { var name = _a.name, data = _a.data, metaData = __rest(_a, ["name", "data"]); var namespace = _this3.options.namespace.replace(/\./g, '\\'); var formattedEvent = name.startsWith(namespace) ? name.substring(namespace.length + 1) : '.' + name; callback(formattedEvent, data, metaData); }); this.channel.subscribe(this.callbacks.get(callback)); return this; } /** * Stop listening for an event on the channel instance. */ }, { key: "stopListening", value: function stopListening(event, callback) { if (callback) { this.channel.unsubscribe(this.eventFormatter.format(event), this.callbacks.get(callback)); this.callbacks["delete"](callback); } else { this.channel.unsubscribe(this.eventFormatter.format(event)); } return this; } /** * Stop listening for all events on the channel instance. */ }, { key: "stopListeningToAll", value: function stopListeningToAll(callback) { if (callback) { this.channel.unsubscribe(this.callbacks.get(callback)); this.callbacks["delete"](callback); } else { this.channel.unsubscribe(); } return this; } /** * Register a callback to be called anytime a subscription succeeds. */ }, { key: "subscribed", value: function subscribed(callback) { this.subscribedListeners.push(callback); return this; } /** * Register a callback to be called anytime a subscription error occurs. */ }, { key: "error", value: function error(callback) { this.errorListeners.push(callback); return this; } /** * Unregisters given error callback from the listeners. * @param callback * @returns AblyChannel */ }, { key: "unregisterSubscribed", value: function unregisterSubscribed(callback) { if (callback) { this.subscribedListeners = this.subscribedListeners.filter(function (s) { return s != callback; }); } else { this.subscribedListeners = []; } return this; } /** * Unregisters given error callback from the listeners. * @param callback * @returns AblyChannel */ }, { key: "unregisterError", value: function unregisterError(callback) { if (callback) { this.errorListeners = this.errorListeners.filter(function (e) { return e != callback; }); } else { this.errorListeners = []; } return this; } }]); }(Channel); var AblyPrivateChannel = /*#__PURE__*/function (_AblyChannel) { function AblyPrivateChannel(ably, name, options, auth) { var _this; _classCallCheck(this, AblyPrivateChannel); _this = _callSuper(this, AblyPrivateChannel, [ably, name, options, false]); _this.channel.on('failed', auth.onChannelFailed(_this)); _this.subscribe(); return _this; } /** * Send a whisper event to other clients in the channel. */ _inherits(AblyPrivateChannel, _AblyChannel); return _createClass(AblyPrivateChannel, [{ key: "whisper", value: function whisper(eventName, data, callback) { if (callback) { this.channel.publish("client-".concat(eventName), data, callback); } else { this.channel.publish("client-".concat(eventName), data); } return this; } }]); }(AblyChannel); /** * This class represents an Ably presence channel. */ var AblyPresenceChannel = /*#__PURE__*/function (_AblyChannel) { function AblyPresenceChannel(ably, name, options, auth) { var _this; _classCallCheck(this, AblyPresenceChannel); _this = _callSuper(this, AblyPresenceChannel, [ably, name, options, false]); _this.channel.on('failed', auth.onChannelFailed(_this)); _this.channel.on('attached', function () { return _this.enter(_this.presenceData, _this._alertErrorListeners); }); _this.subscribe(); return _this; } _inherits(AblyPresenceChannel, _AblyChannel); return _createClass(AblyPresenceChannel, [{ key: "unsubscribe", value: function unsubscribe() { this.leave(this.presenceData, this._alertErrorListeners); this.channel.presence.unsubscribe(); _superPropGet(AblyPresenceChannel, "unsubscribe", this, 3)([]); } /** * Register a callback to be called anytime the member list changes. */ }, { key: "here", value: function here(callback) { var _this2 = this; this.channel.presence.subscribe(['enter', 'update', 'leave'], function () { return _this2.channel.presence.get(function (err, members) { return callback(members.map(function (_ref) { var data = _ref.data; return data; }), err); }); }); return this; } /** * Listen for someone joining the channel. */ }, { key: "joining", value: function joining(callback) { this.channel.presence.subscribe(['enter', 'update'], function (_a) { var data = _a.data, metaData = __rest(_a, ["data"]); callback(data, metaData); }); return this; } /** * Listen for someone leaving the channel. */ }, { key: "leaving", value: function leaving(callback) { this.channel.presence.subscribe('leave', function (_a) { var data = _a.data, metaData = __rest(_a, ["data"]); callback(data, metaData); }); return this; } /** * Enter presence * @param data - Data to be published while entering the channel * @param callback - success/error callback (err) => {} * @returns AblyPresenceChannel */ }, { key: "enter", value: function enter(data, callback) { this.channel.presence.enter(data, callback); return this; } /** * Leave presence * @param data - Data to be published while leaving the channel * @param callback - success/error callback (err) => {} * @returns AblyPresenceChannel */ }, { key: "leave", value: function leave(data, callback) { this.channel.presence.leave(data, callback); return this; } /** * Update presence * @param data - Update presence with data * @param callback - success/error callback (err) => {} * @returns AblyPresenceChannel */ }, { key: "update", value: function update(data, callback) { this.channel.presence.update(data, callback); return this; } /** * Send a whisper event to other clients in the channel. */ }, { key: "whisper", value: function whisper(eventName, data, callback) { if (callback) { this.channel.publish("client-".concat(eventName), data, callback); } else { this.channel.publish("client-".concat(eventName), data); } return this; } }]); }(AblyChannel); var isNullOrUndefined = function isNullOrUndefined(obj) { return obj == null || obj === undefined; }; /** * @throws Exception if parsing error */ var parseJwt = function parseJwt(jwtToken) { // Get Token Header var base64HeaderUrl = jwtToken.split('.')[0]; var base64Header = base64HeaderUrl.replace('-', '+').replace('_', '/'); var header = JSON.parse(fromBase64UrlEncoded(base64Header)); // Get Token payload var base64Url = jwtToken.split('.')[1]; var base64 = base64Url.replace('-', '+').replace('_', '/'); var payload = JSON.parse(fromBase64UrlEncoded(base64)); return { header: header, payload: payload }; }; // RSA4f - omitted `capability` property var toTokenDetails = function toTokenDetails(jwtToken) { var _parseJwt = parseJwt(jwtToken), payload = _parseJwt.payload; return { clientId: payload['x-ably-clientId'], expires: payload.exp * 1000, issued: payload.iat * 1000, token: jwtToken }; }; var isBrowser = (typeof window === "undefined" ? "undefined" : _typeof(window)) === 'object'; /** * Helper method to decode base64 url encoded string * https://stackoverflow.com/a/78178053 * @param base64 base64 url encoded string * @returns decoded text string */ var fromBase64UrlEncoded = function fromBase64UrlEncoded(base64) { var base64Encoded = base64.replace(/-/g, '+').replace(/_/g, '/'); var padding = base64.length % 4 === 0 ? '' : '='.repeat(4 - base64.length % 4); var base64WithPadding = base64Encoded + padding; if (isBrowser) { return atob(base64WithPadding); } return Buffer.from(base64WithPadding, 'base64').toString(); }; /** * Helper method to encode text into base64 url encoded string * https://stackoverflow.com/a/78178053 * @param base64 text * @returns base64 url encoded string */ var toBase64UrlEncoded = function toBase64UrlEncoded(text) { var encoded = ''; if (isBrowser) { encoded = btoa(text); } else { encoded = Buffer.from(text).toString('base64'); } return encoded.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); }; var isAbsoluteUrl = function isAbsoluteUrl(url) { return url && url.indexOf('http://') === 0 || url.indexOf('https://') === 0; }; var fullUrl = function fullUrl(url) { var _a, _b, _c; if (!isAbsoluteUrl(url) && typeof window != 'undefined') { var host = (_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.hostname; var port = (_b = window === null || window === void 0 ? void 0 : window.location) === null || _b === void 0 ? void 0 : _b.port; var protocol = (_c = window === null || window === void 0 ? void 0 : window.location) === null || _c === void 0 ? void 0 : _c.protocol.replace(':', ''); if (host && port && protocol) { return protocol + '://' + host + ':' + port + url; } } return url; }; var httpClient; function httpRequest(options, callback) { if (!httpClient) { httpClient = new Ably.Rest.Platform.Http(); } // Automatically set by browser if (isBrowser) { delete options.headers['Content-Length']; // XHR warning - Refused to set unsafe header "Content-Length" } else { options.method = options.method.toLowerCase(); } httpClient.doUri(options.method, null, options.uri, options.headers, options.body, options.paramsIfNoHeaders || {}, callback); } var httpRequestAsync = function httpRequestAsync(options) { return new Promise(function (resolve, reject) { httpRequest(options, function (err, res) { if (err) { reject(err); } else { if (typeof res === 'string') { resolve(JSON.parse(res)); } else if (!isBrowser && Buffer.isBuffer(res)) { try { resolve(JSON.parse(res.toString())); } catch (e) { resolve(res); } } else { resolve(res); } } }); }); }; var channelAttachAuthorized = false; /** * Modifies existing channel attach with custom authz implementation */ var beforeChannelAttach = function beforeChannelAttach(ablyClient, authorize) { var dummyRealtimeChannel = ablyClient.channels.get('dummy'); dummyRealtimeChannel.__proto__.authorizeChannel = authorize; if (channelAttachAuthorized) { return; } var internalAttach = dummyRealtimeChannel.__proto__._attach; if (isNullOrUndefined(internalAttach)) { console.warn('Failed to enable authorize for pre-attach, please check for right library version'); return; } function customInternalAttach(forceReattach, attachReason, errCallback) { var _this = this; if (this.authorizing) { return; } this.authorizing = true; var bindedInternalAttach = internalAttach.bind(this); this.authorizeChannel(this, function (error) { _this.authorizing = false; if (error) { if (errCallback) { errCallback(error); } else { console.error("channel ".concat(_this.name, " auth error => ").concat(error)); } return; } else { bindedInternalAttach(forceReattach, attachReason, errCallback); } }); } dummyRealtimeChannel.__proto__._attach = customInternalAttach; channelAttachAuthorized = true; }; var SequentialAuthTokenRequestExecuter = /*#__PURE__*/_createClass(function SequentialAuthTokenRequestExecuter() { var _this = this; var token = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; var requestTokenFn = arguments.length > 1 ? arguments[1] : undefined; _classCallCheck(this, SequentialAuthTokenRequestExecuter); this.execute = function (tokenRequestFn) { return new Promise(function (resolve, reject) { _this.queue.run(function () { return __awaiter(_this, void 0, void 0, /*#__PURE__*/_regeneratorRuntime().mark(function _callee() { var _yield$tokenRequestFn, _token, info; return _regeneratorRuntime().wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: _context.prev = 0; _context.next = 3; return tokenRequestFn(this.cachedToken); case 3: _yield$tokenRequestFn = _context.sent; _token = _yield$tokenRequestFn.token; info = _yield$tokenRequestFn.info; this.cachedToken = _token; resolve({ token: _token, info: info }); _context.next = 13; break; case 10: _context.prev = 10; _context.t0 = _context["catch"](0); reject(_context.t0); case 13: case "end": return _context.stop(); } }, _callee, this, [[0, 10]]); })); }); }); }; this.request = function (channelName) { return _this.execute(function (token) { return _this.requestTokenFn(channelName, token); }); }; this.cachedToken = token; this.requestTokenFn = requestTokenFn; this.queue = new TaskQueue(); }); var TaskQueue = /*#__PURE__*/_createClass(function TaskQueue() { var _this2 = this; var tasks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; var concurrentCount = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; _classCallCheck(this, TaskQueue); this.canRunNext = function () { return _this2.running.length < _this2.count && _this2.todo.length; }; this.run = function (task) { return __awaiter(_this2, void 0, void 0, /*#__PURE__*/_regeneratorRuntime().mark(function _callee2() { var currentTask; return _regeneratorRuntime().wrap(function _callee2$(_context2) { while (1) switch (_context2.prev = _context2.next) { case 0: if (task) { this.todo.push(task); } case 1: if (!this.canRunNext()) { _context2.next = 9; break; } currentTask = this.todo.shift(); this.running.push(currentTask); _context2.next = 6; return currentTask(); case 6: this.running.shift(); _context2.next = 1; break; case 9: case "end": return _context2.stop(); } }, _callee2, this); })); }; this.total = tasks.length; this.todo = tasks; this.running = []; this.count = concurrentCount; }); var AblyAuth = /*#__PURE__*/_createClass(function AblyAuth(ablyConnector, options) { var _this = this; _classCallCheck(this, AblyAuth); this.expiredAuthChannels = new Set(); this.setExpired = function (channelName) { return _this.expiredAuthChannels.add(channelName); }; this.isExpired = function (channelName) { return _this.expiredAuthChannels.has(channelName); }; this.removeExpired = function (channelName) { return _this.expiredAuthChannels["delete"](channelName); }; this.options = { queryTime: true, useTokenAuth: true, authCallback: function authCallback(_, callback) { return __awaiter(_this, void 0, void 0, /*#__PURE__*/_regeneratorRuntime().mark(function _callee() { var _yield$this$authReque, _token, tokenDetails; return _regeneratorRuntime().wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: _context.prev = 0; _context.next = 3; return this.authRequestExecuter.request(null); case 3: _yield$this$authReque = _context.sent; _token = _yield$this$authReque.token; tokenDetails = toTokenDetails(_token); callback(null, tokenDetails); _context.next = 12; break; case 9: _context.prev = 9; _context.t0 = _context["catch"](0); callback(_context.t0, null); case 12: case "end": return _context.stop(); } }, _callee, this, [[0, 9]]); })); }, echoMessages: false // https://docs.ably.io/client-lib-development-guide/features/#TO3h }; this.requestToken = function (channelName, existingToken) { return __awaiter(_this, void 0, void 0, /*#__PURE__*/_regeneratorRuntime().mark(function _callee2() { var postData, postOptions; return _regeneratorRuntime().wrap(function _callee2$(_context2) { while (1) switch (_context2.prev = _context2.next) { case 0: postData = JSON.stringify({ channel_name: channelName, token: existingToken }); postOptions = { uri: this.authEndpoint, method: 'POST', headers: _extends({ Accept: 'application/json', 'Content-Type': 'application/json', 'Content-Length': postData.length }, this.authHeaders), body: postData }; _context2.next = 4; return httpRequestAsync(postOptions); case 4: return _context2.abrupt("return", _context2.sent); case 5: case "end": return _context2.stop(); } }, _callee2, this); })); }; this.ablyClient = function () { return _this.ablyConnector.ably; }; this.existingToken = function () { return _this.ablyClient().auth.tokenDetails; }; this.getChannel = function (name) { return _this.ablyConnector.channels[name]; }; this.enableAuthorizeBeforeChannelAttach = function () { var ablyClient = _this.ablyClient(); ablyClient.auth.getTimestamp(_this.options.queryTime, function () { return void 0; }); // generates serverTimeOffset in the background beforeChannelAttach(ablyClient, function (realtimeChannel, errorCallback) { var channelName = realtimeChannel.name; if (channelName.startsWith('public:')) { errorCallback(null); return; } // Use cached token if has channel capability and is not expired var tokenDetails = _this.existingToken(); if (tokenDetails && !_this.isExpired(channelName)) { var capability = parseJwt(tokenDetails.token).payload['x-ably-capability']; var tokenHasChannelCapability = capability.includes("".concat(channelName, "\"")); // checks with server time using offset, otherwise local time if (tokenHasChannelCapability && tokenDetails.expires > ablyClient.auth.getTimestampUsingOffset()) { errorCallback(null); return; } } // explicitly request token for given channel name _this.authRequestExecuter.request(channelName).then(function (_ref) { var jwtToken = _ref.token, info = _ref.info; // get upgraded token with channel access var echoChannel = _this.getChannel(channelName); _this.setPresenceInfo(echoChannel, info); _this.tryAuthorizeOnSameConnection(_extends(_extends({}, _this.options), { token: toTokenDetails(jwtToken) }), function (err, _tokenDetails) { if (err) { errorCallback(err); } else { _this.removeExpired(channelName); errorCallback(null); } }); })["catch"](function (err) { return errorCallback(err); }); }); }; this.allowReconnectOnUserLogin = function () { var ablyConnection = _this.ablyClient().connection; var _connectionFailedCallback = function connectionFailedCallback(stateChange) { if (stateChange.reason.code == 40102) { // 40102 denotes mismatched clientId ablyConnection.off(_connectionFailedCallback); console.warn("User login detected, re-connecting again!"); _this.onClientIdChanged(); } }; ablyConnection.on('failed', _connectionFailedCallback); }; /** * This will be called when (guest)user logs in and new clientId is returned in the jwt token. * If client tries to authenticate with new clientId on same connection, ably server returns * error and connection goes into failed state. * See https://github.com/ably/laravel-broadcaster/issues/45 for more details. * There's a separate test case added for user login flow => ably-user-login.test.ts. */ this.onClientIdChanged = function () { _this.ablyClient().connect(); for (var _i = 0, _Object$values = Object.values(_this.ablyConnector.channels); _i < _Object$values.length; _i++) { var ablyChannel = _Object$values[_i]; ablyChannel.channel.attach(ablyChannel._alertErrorListeners); } }; this.tryAuthorizeOnSameConnection = function (authOptions, callback) { _this.ablyClient().auth.authorize(null, authOptions, callback); }; this.onChannelFailed = function (echoAblyChannel) { return function (stateChange) { var _a; // channel capability rejected https://help.ably.io/error/40160 if (((_a = stateChange.reason) === null || _a === void 0 ? void 0 : _a.code) == 40160) { _this.handleChannelAuthError(echoAblyChannel); } }; }; this.handleChannelAuthError = function (echoAblyChannel) { if (echoAblyChannel.skipAuth) { return; } var channelName = echoAblyChannel.name; // get upgraded token with channel access _this.authRequestExecuter.request(channelName).then(function (_ref2) { var jwtToken = _ref2.token, info = _ref2.info; _this.setPresenceInfo(echoAblyChannel, info); _this.tryAuthorizeOnSameConnection(_extends(_extends({}, _this.options), { token: toTokenDetails(jwtToken) }), function (err, _tokenDetails) { if (err) { echoAblyChannel._alertErrorListeners(err); } else { echoAblyChannel.skipAuth = true; echoAblyChannel.channel.once('attached', function () { echoAblyChannel.skipAuth = false; }); echoAblyChannel.channel.attach(echoAblyChannel._alertErrorListeners); } }); })["catch"](function (err) { return echoAblyChannel._alertErrorListeners(err); }); }; this.setPresenceInfo = function (echoAblyChannel, info) { if (echoAblyChannel instanceof AblyPresenceChannel) { echoAblyChannel.presenceData = info; } }; this.ablyConnector = ablyConnector; var authEndpoint = options.authEndpoint, headers = options.auth.headers, token = options.token, requestTokenFn = options.requestTokenFn; this.authEndpoint = fullUrl(authEndpoint); this.authHeaders = headers; this.authRequestExecuter = new SequentialAuthTokenRequestExecuter(token, requestTokenFn !== null && requestTokenFn !== void 0 ? requestTokenFn : this.requestToken); }); /** * This class represents a Pusher channel. */ var PusherChannel = /*#__PURE__*/function (_Channel) { /** * Create a new class instance. */ function PusherChannel(pusher, name, options) { var _this; _classCallCheck(this, PusherChannel); _this = _callSuper(this, PusherChannel); _this.name = name; _this.pusher = pusher; _this.options = options; _this.eventFormatter = new EventFormatter(_this.options.namespace); _this.subscribe(); return _this; } /** * Subscribe to a Pusher channel. */ _inherits(PusherChannel, _Channel); return _createClass(PusherChannel, [{ key: "subscribe", value: function subscribe() { this.subscription = this.pusher.subscribe(this.name); } /** * Unsubscribe from a Pusher channel. */ }, { key: "unsubscribe", value: function unsubscribe() { this.pusher.unsubscribe(this.name); } /** * Listen for an event on the channel instance. */ }, { key: "listen", value: function listen(event, callback) { this.on(this.eventFormatter.format(event), callback); return this; } /** * Listen for all events on the channel instance. */ }, { key: "listenToAll", value: function listenToAll(callback) { var _this2 = this; this.subscription.bind_global(function (event, data) { if (event.startsWith('pusher:')) { return; } var namespace = _this2.options.namespace.replace(/\./g, '\\'); var formattedEvent = event.startsWith(namespace) ? event.substring(namespace.length + 1) : '.' + event; callback(formattedEvent, data); }); return this; } /** * Stop listening for an event on the channel instance. */ }, { key: "stopListening", value: function stopListening(event, callback) { if (callback) { this.subscription.unbind(this.eventFormatter.format(event), callback); } else { this.subscription.unbind(this.eventFormatter.format(event)); } return this; } /** * Stop listening for all events on the channel instance. */ }, { key: "stopListeningToAll", value: function stopListeningToAll(callback) { if (callback) { this.subscription.unbind_global(callback); } else { this.subscription.unbind_global(); } return this; } /** * Register a callback to be called anytime a subscription succeeds. */ }, { key: "subscribed", value: function subscribed(callback) { this.on('pusher:subscription_succeeded', function () { callback(); }); return this; } /** * Register a callback to be called anytime a subscription error occurs. */ }, { key: "error", value: function error(callback) { this.on('pusher:subscription_error', function (status) { callback(status); }); return this; } /** * Bind a channel to an event. */ }, { key: "on", value: function on(event, callback) { this.subscription.bind(event, callback); return this; } }]); }(Channel); /** * This class represents a Pusher private channel. */ var PusherPrivateChannel = /*#__PURE__*/function (_PusherChannel) { function PusherPrivateChannel() { _classCallCheck(this, PusherPrivateChannel); return _callSuper(this, PusherPrivateChannel, arguments); } _inherits(PusherPrivateChannel, _PusherChannel); return _createClass(PusherPrivateChannel, [{ key: "whisper", value: /** * Send a whisper event to other clients in the channel. */ function whisper(eventName, data) { this.pusher.channels.channels[this.name].trigger("client-".concat(eventName), data); return this; } }]); }(PusherChannel); /** * This class represents a Pusher private channel. */ var PusherEncryptedPrivateChannel = /*#__PURE__*/function (_PusherChannel) { function PusherEncryptedPrivateChannel() { _classCallCheck(this, PusherEncryptedPrivateChannel); return _callSuper(this, PusherEncryptedPrivateChannel, arguments); } _inherits(PusherEncryptedPrivateChannel, _PusherChannel); return _createClass(PusherEncryptedPrivateChannel, [{ key: "whisper", value: /** * Send a whisper event to other clients in the channel. */ function whisper(eventName, data) { this.pusher.channels.channels[this.name].trigger("client-".concat(eventName), data); return this; } }]); }(PusherChannel); /** * This class represents a Pusher presence channel. */ var PusherPresenceChannel = /*#__PURE__*/function (_PusherChannel) { function PusherPresenceChannel() { _classCallCheck(this, PusherPresenceChannel); return _callSuper(this, PusherPresenceChannel, arguments); } _inherits(PusherPresenceChannel, _PusherChannel); return _createClass(PusherPresenceChannel, [{ key: "here", value: /**