@webex/calling 3.12.0-mobius-socket.17 → 3.12.0-mobius-socket.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/CallingClient/utils/request.js +6 -3
  2. package/dist/CallingClient/utils/request.js.map +1 -1
  3. package/dist/CallingClient/utils/request.test.js +2 -2
  4. package/dist/CallingClient/utils/request.test.js.map +1 -1
  5. package/dist/CallingClient/utils/types.js.map +1 -1
  6. package/dist/SDKConnector/types.js.map +1 -1
  7. package/dist/mobius-socket/config.js +7 -44
  8. package/dist/mobius-socket/config.js.map +1 -1
  9. package/dist/mobius-socket/errors.js +25 -21
  10. package/dist/mobius-socket/errors.js.map +1 -1
  11. package/dist/mobius-socket/index.js +0 -44
  12. package/dist/mobius-socket/index.js.map +1 -1
  13. package/dist/mobius-socket/mobius-socket-events.test.js +20 -48
  14. package/dist/mobius-socket/mobius-socket-events.test.js.map +1 -1
  15. package/dist/mobius-socket/mobius-socket.js +302 -701
  16. package/dist/mobius-socket/mobius-socket.js.map +1 -1
  17. package/dist/mobius-socket/mobius-socket.test.js +435 -718
  18. package/dist/mobius-socket/mobius-socket.test.js.map +1 -1
  19. package/dist/mobius-socket/socket/socket-base.js +70 -78
  20. package/dist/mobius-socket/socket/socket-base.js.map +1 -1
  21. package/dist/mobius-socket/socket.test.js +36 -61
  22. package/dist/mobius-socket/socket.test.js.map +1 -1
  23. package/dist/mobius-socket/types.js +7 -0
  24. package/dist/mobius-socket/types.js.map +1 -0
  25. package/dist/module/CallingClient/utils/request.js +3 -2
  26. package/dist/module/mobius-socket/config.js +7 -10
  27. package/dist/module/mobius-socket/errors.js +17 -0
  28. package/dist/module/mobius-socket/index.js +0 -3
  29. package/dist/module/mobius-socket/mobius-socket.js +211 -401
  30. package/dist/module/mobius-socket/socket/socket-base.js +64 -69
  31. package/dist/module/mobius-socket/types.js +1 -0
  32. package/dist/types/CallingClient/utils/request.d.ts.map +1 -1
  33. package/dist/types/CallingClient/utils/types.d.ts +1 -1
  34. package/dist/types/CallingClient/utils/types.d.ts.map +1 -1
  35. package/dist/types/SDKConnector/types.d.ts +15 -0
  36. package/dist/types/SDKConnector/types.d.ts.map +1 -1
  37. package/dist/types/mobius-socket/config.d.ts +7 -8
  38. package/dist/types/mobius-socket/config.d.ts.map +1 -1
  39. package/dist/types/mobius-socket/errors.d.ts +7 -0
  40. package/dist/types/mobius-socket/errors.d.ts.map +1 -1
  41. package/dist/types/mobius-socket/index.d.ts +3 -5
  42. package/dist/types/mobius-socket/index.d.ts.map +1 -1
  43. package/dist/types/mobius-socket/mobius-socket.d.ts +26 -37
  44. package/dist/types/mobius-socket/mobius-socket.d.ts.map +1 -1
  45. package/dist/types/mobius-socket/socket/socket-base.d.ts +10 -10
  46. package/dist/types/mobius-socket/socket/socket-base.d.ts.map +1 -1
  47. package/dist/types/mobius-socket/types.d.ts +21 -0
  48. package/dist/types/mobius-socket/types.d.ts.map +1 -0
  49. package/package.json +1 -1
@@ -1,11 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  var _Reflect$construct = require("@babel/runtime-corejs2/core-js/reflect/construct");
4
- var _Array$from = require("@babel/runtime-corejs2/core-js/array/from");
5
- var _Symbol = require("@babel/runtime-corejs2/core-js/symbol");
6
- var _Symbol$iterator = require("@babel/runtime-corejs2/core-js/symbol/iterator");
7
- var _Array$isArray2 = require("@babel/runtime-corejs2/core-js/array/is-array");
8
- var _Object$keys2 = require("@babel/runtime-corejs2/core-js/object/keys");
4
+ var _Object$keys = require("@babel/runtime-corejs2/core-js/object/keys");
9
5
  var _Object$getOwnPropertySymbols = require("@babel/runtime-corejs2/core-js/object/get-own-property-symbols");
10
6
  var _Object$getOwnPropertyDescriptor = require("@babel/runtime-corejs2/core-js/object/get-own-property-descriptor");
11
7
  var _Object$getOwnPropertyDescriptors = require("@babel/runtime-corejs2/core-js/object/get-own-property-descriptors");
@@ -17,11 +13,10 @@ _Object$defineProperty(exports, "__esModule", {
17
13
  });
18
14
  exports.default = void 0;
19
15
  var _map = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/map"));
20
- var _now = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/date/now"));
21
- var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
22
16
  var _isArray = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/array/is-array"));
17
+ var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
23
18
  var _stringify = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/json/stringify"));
24
- var _keys = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/keys"));
19
+ var _now = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/date/now"));
25
20
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/defineProperty"));
26
21
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/slicedToArray"));
27
22
  var _typeof2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/typeof"));
@@ -31,17 +26,12 @@ var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime
31
26
  var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/getPrototypeOf"));
32
27
  var _get2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/get"));
33
28
  var _inherits2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/inherits"));
34
- var _set2 = _interopRequireDefault(require("lodash/set"));
35
- var _camelCase2 = _interopRequireDefault(require("lodash/camelCase"));
36
29
  var _events = require("events");
37
30
  var _backoff = _interopRequireDefault(require("backoff"));
38
31
  var _socket = _interopRequireDefault(require("./socket"));
39
32
  var _errors = require("./errors");
40
- function ownKeys(e, r) { var t = _Object$keys2(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return _Object$getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
33
+ function ownKeys(e, r) { var t = _Object$keys(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return _Object$getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
41
34
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor(t, r)); }); } return e; }
42
- function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof _Symbol && r[_Symbol$iterator] || r["@@iterator"]; if (!t) { if (_Array$isArray2(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
43
- function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? _Array$from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
44
- function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
45
35
  function _callSuper(t, o, e) { return o = (0, _getPrototypeOf2.default)(o), (0, _possibleConstructorReturn2.default)(t, _isNativeReflectConstruct() ? _Reflect$construct(o, e || [], (0, _getPrototypeOf2.default)(t).constructor) : o.apply(t, e)); }
46
36
  function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(_Reflect$construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
47
37
  function _superPropGet(t, o, e, r) { var p = (0, _get2.default)((0, _getPrototypeOf2.default)(1 & r ? t.prototype : t), o, e); return 2 & r && "function" == typeof p ? function (t) { return p.apply(e, t); } : p; } // @ts-nocheck
@@ -49,14 +39,10 @@ function _superPropGet(t, o, e, r) { var p = (0, _get2.default)((0, _getPrototyp
49
39
  * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file
50
40
  */
51
41
  var normalReconnectReasons = ['idle', 'done (forced)'];
52
- var DEFAULT_MOBIUS_WEBSOCKET_SESSION = 'mobius-websocket-session';
53
42
  var MOBIUS_SOCKET_NAMESPACE = 'MobiusSocket';
54
43
  var TOKEN_REFRESH_INTERVAL_MS = 1 * 60 * 60 * 1000; // 1 hour
55
44
 
56
45
  function normalizeMobiusAuthToken(token) {
57
- if (typeof token !== 'string') {
58
- return token;
59
- }
60
46
  return token.replace(/^Bearer\s+/i, '');
61
47
  }
62
48
  var MobiusSocket = /*#__PURE__*/function (_EventEmitter) {
@@ -71,20 +57,16 @@ var MobiusSocket = /*#__PURE__*/function (_EventEmitter) {
71
57
  _this.webex = webex;
72
58
  _this.config = config;
73
59
  _this.logger = webex.logger || console;
74
- _this.defaultSessionId = DEFAULT_MOBIUS_WEBSOCKET_SESSION;
75
60
  _this.connected = false;
76
61
  _this.connecting = false;
77
62
  _this.hasEverConnected = false;
78
63
  _this.socket = undefined;
79
- _this.sockets = new _map.default();
80
- _this.backoffCalls = new _map.default();
81
- _this._shutdownSwitchoverBackoffCalls = new _map.default();
82
- _this._seenAsyncEventIdsBySession = new _map.default();
83
- _this._connectPromises = new _map.default();
84
- _this.mercuryTimeOffset = undefined;
85
- _this._tokenRefreshTimer = undefined;
86
- _this._tokenRefreshInFlight = undefined;
87
- _this._bindInternalEvents();
64
+ _this.backoffCall = undefined;
65
+ _this.shutdownSwitchoverBackoffCall = undefined;
66
+ _this.seenAsyncEventIds = new _map.default();
67
+ _this.connectPromise = undefined;
68
+ _this.tokenRefreshTimer = undefined;
69
+ _this.tokenRefreshInFlight = undefined;
88
70
  return _this;
89
71
  }
90
72
  (0, _inherits2.default)(MobiusSocket, _EventEmitter);
@@ -97,143 +79,50 @@ var MobiusSocket = /*#__PURE__*/function (_EventEmitter) {
97
79
  this.removeAllListeners(eventName);
98
80
  return this;
99
81
  }
100
- }, {
101
- key: "_bindInternalEvents",
102
- value: function _bindInternalEvents() {
103
- var _this2 = this;
104
- /*
105
- When one of these legacy feature gets updated, this event would be triggered
106
- * group-message-notifications
107
- * mention-notifications
108
- * thread-notifications
109
- */
110
- this.on('event:featureToggle_update', function (envelope) {
111
- if (envelope && envelope.data) {
112
- _this2.webex.internal.feature.updateFeature(envelope.data.featureToggle);
113
- }
114
- });
115
- /*
116
- * When Cluster Migrations, notify clients using ActiveClusterStatusEvent via mercury
117
- * https://wwwin-github.cisco.com/pages/Webex/crr-docs/techdocs/rr-002.html#wip-notifying-clients-of-cluster-migrations
118
- * */
119
- this.on('event:ActiveClusterStatusEvent', function (envelope) {
120
- var _this2$webex$internal;
121
- if (typeof ((_this2$webex$internal = _this2.webex.internal.services) === null || _this2$webex$internal === void 0 ? void 0 : _this2$webex$internal.switchActiveClusterIds) === 'function' && envelope && envelope.data) {
122
- var _envelope$data;
123
- _this2.webex.internal.services.switchActiveClusterIds((_envelope$data = envelope.data) === null || _envelope$data === void 0 ? void 0 : _envelope$data.activeClusters);
124
- }
125
- });
126
- /*
127
- * Using cache-invalidation via mercury to instead the method of polling via the new /timestamp endpoint from u2c
128
- * https://wwwin-github.cisco.com/pages/Webex/crr-docs/techdocs/rr-005.html#websocket-notifications
129
- * */
130
- this.on('event:u2c.cache-invalidation', function (envelope) {
131
- var _this2$webex$internal2;
132
- if (typeof ((_this2$webex$internal2 = _this2.webex.internal.services) === null || _this2$webex$internal2 === void 0 ? void 0 : _this2$webex$internal2.invalidateCache) === 'function' && envelope && envelope.data) {
133
- var _envelope$data2;
134
- _this2.webex.internal.services.invalidateCache((_envelope$data2 = envelope.data) === null || _envelope$data2 === void 0 ? void 0 : _envelope$data2.timestamp);
135
- }
136
- });
137
- }
138
82
 
139
83
  /**
140
84
  * Attach event listeners to a socket.
141
85
  * @param {Socket} socket - The socket to attach listeners to
142
- * @param {sessionId} sessionId - The socket related session ID
143
86
  * @returns {void}
144
87
  */
145
88
  }, {
146
- key: "_attachSocketEventListeners",
147
- value: function _attachSocketEventListeners(socket, sessionId) {
148
- var _this3 = this;
89
+ key: "attachSocketEventListeners",
90
+ value: function attachSocketEventListeners(socket) {
91
+ var _this2 = this;
149
92
  socket.on('close', function (event) {
150
- return _this3._onclose(sessionId, event, socket);
93
+ return _this2.onclose(event, socket);
151
94
  });
152
95
  socket.on('message', function () {
153
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
154
- args[_key] = arguments[_key];
155
- }
156
- return _this3._onmessage.apply(_this3, [sessionId].concat(args));
157
- });
158
- socket.on('pong', function () {
159
- for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
160
- args[_key2] = arguments[_key2];
161
- }
162
- return _this3._setTimeOffset.apply(_this3, [sessionId].concat(args));
96
+ return _this2.onmessage.apply(_this2, arguments);
163
97
  });
164
- socket.on('sequence-mismatch', function () {
165
- for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
166
- args[_key3] = arguments[_key3];
167
- }
168
- return _this3._emit.apply(_this3, [sessionId, 'sequence-mismatch'].concat(args));
169
- });
170
- socket.on('ping-pong-latency', function () {
171
- for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
172
- args[_key4] = arguments[_key4];
173
- }
174
- return _this3._emit.apply(_this3, [sessionId, 'ping-pong-latency'].concat(args));
175
- });
176
- }
177
-
178
- /**
179
- * Returns the per-session cache of seen async_event IDs, creating it on first access.
180
- * @param {string} sessionId - The session identifier.
181
- * @returns {Map<string, boolean>} Ordered cache of seen event IDs for the session.
182
- */
183
- }, {
184
- key: "_getSeenAsyncEventIds",
185
- value: function _getSeenAsyncEventIds(sessionId) {
186
- var seenAsyncEventIds = this._seenAsyncEventIdsBySession.get(sessionId);
187
- if (!seenAsyncEventIds) {
188
- seenAsyncEventIds = new _map.default();
189
- this._seenAsyncEventIdsBySession.set(sessionId, seenAsyncEventIds);
190
- }
191
- return seenAsyncEventIds;
192
- }
193
-
194
- /**
195
- * Clears the dedup cache for one session or for all sessions when omitted.
196
- * @param {string} [sessionId] - Optional session identifier.
197
- * @returns {void}
198
- */
199
- }, {
200
- key: "_clearSeenAsyncEventIds",
201
- value: function _clearSeenAsyncEventIds(sessionId) {
202
- if (sessionId) {
203
- this._seenAsyncEventIdsBySession.delete(sessionId);
204
- return;
205
- }
206
- this._seenAsyncEventIdsBySession.clear();
207
98
  }
208
99
 
209
100
  /**
210
101
  * Tracks a newly seen async_event ID and reports whether a duplicate should be suppressed.
211
- * @param {string} sessionId - The session identifier.
212
102
  * @param {object} envelope - Parsed websocket message envelope.
213
- * @returns {boolean} True when the event has already been seen for this session.
103
+ * @returns {boolean} True when the event has already been seen.
214
104
  */
215
105
  }, {
216
- key: "_trackAsyncEventAndShouldSuppressDuplicate",
217
- value: function _trackAsyncEventAndShouldSuppressDuplicate(sessionId, envelope) {
106
+ key: "trackAsyncEventAndShouldSuppressDuplicate",
107
+ value: function trackAsyncEventAndShouldSuppressDuplicate(envelope) {
218
108
  if ((envelope === null || envelope === void 0 ? void 0 : envelope.type) !== 'async_event' || !envelope.eventId) {
219
109
  return false;
220
110
  }
221
- var seenAsyncEventIds = this._getSeenAsyncEventIds(sessionId);
222
- if (seenAsyncEventIds.has(envelope.eventId)) {
223
- var previousValue = seenAsyncEventIds.get(envelope.eventId);
224
-
111
+ if (this.seenAsyncEventIds.has(envelope.eventId)) {
225
112
  // Refresh recency so frequently retransmitted eventIds stay protected longer.
226
- seenAsyncEventIds.delete(envelope.eventId);
227
- seenAsyncEventIds.set(envelope.eventId, previousValue);
228
- this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": duplicate async_event suppressed for ").concat(sessionId, ", eventId=").concat(envelope.eventId));
113
+ // This deletion and setting again makes the data recent since javascript map maintains order as well
114
+ var previousValue = this.seenAsyncEventIds.get(envelope.eventId);
115
+ this.seenAsyncEventIds.delete(envelope.eventId);
116
+ this.seenAsyncEventIds.set(envelope.eventId, previousValue);
117
+ this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": duplicate async_event suppressed, eventId=").concat(envelope.eventId));
229
118
  return true;
230
119
  }
231
- this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": tracking async_event for ").concat(sessionId, ", eventId=").concat(envelope.eventId));
232
- seenAsyncEventIds.set(envelope.eventId, true);
233
- if (seenAsyncEventIds.size > this.config.dedupCacheMaxSize) {
234
- var oldestEventId = seenAsyncEventIds.keys().next().value;
235
- seenAsyncEventIds.delete(oldestEventId);
236
- this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": evicted oldest async_event from dedup cache for ").concat(sessionId, ", eventId=").concat(oldestEventId));
120
+ this.logger.log("".concat(MOBIUS_SOCKET_NAMESPACE, ": tracking async_event, eventId=").concat(envelope.eventId));
121
+ this.seenAsyncEventIds.set(envelope.eventId, true);
122
+ if (this.seenAsyncEventIds.size > this.config.dedupCacheMaxSize) {
123
+ var oldestEventId = this.seenAsyncEventIds.keys().next().value;
124
+ this.seenAsyncEventIds.delete(oldestEventId);
125
+ this.logger.log("".concat(MOBIUS_SOCKET_NAMESPACE, ": evicted oldest async_event from dedup cache, eventId=").concat(oldestEventId));
237
126
  }
238
127
  return false;
239
128
  }
@@ -242,154 +131,88 @@ var MobiusSocket = /*#__PURE__*/function (_EventEmitter) {
242
131
  * Handle imminent shutdown by establishing a new connection while keeping
243
132
  * the current one alive (make-before-break).
244
133
  * Idempotent: will no-op if already in progress.
245
- * @param {string} sessionId - The session ID for which the shutdown is imminent
246
- * @returns {void}
247
134
  */
248
135
  }, {
249
- key: "_handleImminentShutdown",
250
- value: function _handleImminentShutdown(sessionId) {
251
- var _this4 = this;
252
- var oldSocket = this.sockets.get(sessionId);
136
+ key: "handleImminentShutdown",
137
+ value: function handleImminentShutdown() {
138
+ var _this3 = this;
139
+ var oldSocket = this.socket;
253
140
  try {
254
- // Idempotent: if we already have a switchover backoff call for this session,
255
- // a switchover is in progress – do nothing.
256
- if (this._shutdownSwitchoverBackoffCalls.get(sessionId)) {
257
- this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": [shutdown] switchover already in progress for ").concat(sessionId));
141
+ if (this.shutdownSwitchoverBackoffCall) {
142
+ this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": [shutdown] switchover already in progress"));
258
143
  return;
259
144
  }
260
- var switchoverId = "".concat((0, _now.default)());
261
- this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": [shutdown] switchover start, id=").concat(switchoverId, " for ").concat(sessionId));
262
- this._connectWithBackoff(undefined, sessionId, {
145
+ this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": [shutdown] switchover start"));
146
+ this.connectWithBackoff(undefined, {
263
147
  isShutdownSwitchover: true,
264
148
  attemptOptions: {
265
149
  isShutdownSwitchover: true,
266
150
  onSuccess: function onSuccess(newSocket, webSocketUrl) {
267
- _this4.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": [shutdown] switchover connected, url: ").concat(webSocketUrl, " for ").concat(sessionId));
268
-
269
- // Atomically switch active socket reference
270
- _this4.socket = _this4.sockets.get(_this4.defaultSessionId);
271
- _this4.connected = _this4.hasConnectedSockets(); // remain connected throughout
272
-
273
- _this4._emit(sessionId, 'event:mercury_shutdown_switchover_complete', {
151
+ _this3.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": [shutdown] switchover connected, url: ").concat(webSocketUrl));
152
+
153
+ // Promote the new socket now that the switchover succeeded
154
+ newSocket.connecting = false;
155
+ newSocket.connected = true;
156
+ _this3.socket = newSocket;
157
+ _this3.connected = true;
158
+ _this3.emitEvent('event:mobius_shutdown_switchover_complete', {
274
159
  url: webSocketUrl
275
160
  });
276
161
  if (oldSocket) {
277
- _this4.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": [shutdown] old socket retained; server will close with 4001"));
162
+ _this3.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": [shutdown] old socket retained; server will close with 4001"));
278
163
  }
279
164
  }
280
165
  }
281
166
  }).then(function () {
282
- _this4.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": [shutdown] switchover completed successfully for ").concat(sessionId));
167
+ _this3.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": [shutdown] switchover completed successfully"));
283
168
  }).catch(function (err) {
284
- _this4.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": [shutdown] switchover exhausted retries; will fall back to normal reconnection for ").concat(sessionId, ": "), err);
285
- _this4._emit(sessionId, 'event:mercury_shutdown_switchover_failed', {
169
+ _this3.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": [shutdown] switchover exhausted retries; will fall back to normal reconnection: "), err);
170
+ _this3.emitEvent('event:mobius_shutdown_switchover_failed', {
286
171
  reason: err
287
172
  });
288
- // Old socket will eventually close with 4001, triggering normal reconnection
289
173
  });
290
174
  } catch (e) {
291
- this.logger.error("".concat(MOBIUS_SOCKET_NAMESPACE, ": [shutdown] error during switchover for ").concat(sessionId), e);
292
- this._shutdownSwitchoverBackoffCalls.delete(sessionId);
293
- this._emit(sessionId, 'event:mercury_shutdown_switchover_failed', {
175
+ this.logger.error("".concat(MOBIUS_SOCKET_NAMESPACE, ": [shutdown] error during switchover"), e);
176
+ this.shutdownSwitchoverBackoffCall = undefined;
177
+ this.emitEvent('event:mobius_shutdown_switchover_failed', {
294
178
  reason: e
295
179
  });
296
180
  }
297
181
  }
298
182
 
299
183
  /**
300
- * Get the last error.
301
- * @returns {any} The last error.
302
- */
303
- }, {
304
- key: "getLastError",
305
- value: function getLastError() {
306
- return this.lastError;
307
- }
308
-
309
- /**
310
- * Get all active socket connections
311
- * @returns {Map} Map of sessionId to socket instances
312
- */
313
- }, {
314
- key: "getSockets",
315
- value: function getSockets() {
316
- return this.sockets;
317
- }
318
-
319
- /**
320
- * Get a specific socket by connection ID
321
- * @param {string} sessionId - The connection identifier
322
- * @returns {Socket|undefined} The socket instance or undefined if not found
323
- */
324
- }, {
325
- key: "getSocket",
326
- value: function getSocket() {
327
- var sessionId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.defaultSessionId;
328
- return this.sockets.get(sessionId);
329
- }
330
-
331
- /**
332
- * Get the websocket URL for a currently connected session.
333
- * @param {string} [sessionId=this.defaultSessionId] - The session identifier.
184
+ * Get the websocket URL for the currently connected socket.
334
185
  * @returns {string|undefined} The connected websocket URL, or undefined when not connected.
335
186
  */
336
187
  }, {
337
188
  key: "getConnectedWebSocketUrl",
338
189
  value: function getConnectedWebSocketUrl() {
339
- var sessionId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.defaultSessionId;
340
- var socket = this.getSocket(sessionId);
341
- if (!(socket !== null && socket !== void 0 && socket.connected)) {
190
+ var _this$socket;
191
+ if (!((_this$socket = this.socket) !== null && _this$socket !== void 0 && _this$socket.connected)) {
342
192
  return undefined;
343
193
  }
344
- return socket.url;
345
- }
346
-
347
- /**
348
- * Sends a payload on the active connected socket
349
- * @param {Object} payload - The data to send
350
- * @param {string} [sessionId=this.defaultSessionId] - The session identifier
351
- * @returns {Promise}
352
- */
353
- }, {
354
- key: "send",
355
- value: function send(payload) {
356
- var sessionId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.defaultSessionId;
357
- var socket = this.getSocket(sessionId);
358
- if (!socket || !socket.connected) {
359
- return _promise.default.reject(new Error("Mobius socket is not connected for session ".concat(sessionId)));
360
- }
361
- return socket.send(payload);
194
+ return this.socket.url;
362
195
  }
363
196
 
364
197
  /**
365
198
  * Sends a websocket request and resolves when the matching response arrives.
366
- * @param {Object} payload - The websocket request payload.
367
- * @param {string|Object} [sessionIdOrOptions=this.defaultSessionId] - Session ID or request options.
368
- * @param {Object} [options={}] - Additional request options.
369
- * @returns {Promise<Object>}
199
+ * @param {MobiusSocketRequestPayload} payload - The websocket request payload.
200
+ * @param {MobiusSocketRequestOptions} [options={}] - Additional request options.
201
+ * @returns {Promise<SocketResponse>}
370
202
  */
371
203
  }, {
372
204
  key: "sendWssRequest",
373
205
  value: function sendWssRequest(payload) {
374
- var _this5 = this;
375
- var sessionIdOrOptions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.defaultSessionId;
376
- var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
206
+ var _this4 = this;
207
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
377
208
  if (!payload || (0, _typeof2.default)(payload) !== 'object' || (0, _isArray.default)(payload)) {
378
209
  return _promise.default.reject(new Error('`payload` is required'));
379
210
  }
380
- var sessionId = this.defaultSessionId;
381
- var requestOptions = options;
382
- if (typeof sessionIdOrOptions === 'string') {
383
- sessionId = sessionIdOrOptions;
384
- } else if (sessionIdOrOptions && (0, _typeof2.default)(sessionIdOrOptions) === 'object') {
385
- requestOptions = sessionIdOrOptions;
211
+ if (!this.socket || !this.socket.connected) {
212
+ return _promise.default.reject(new Error('Mobius socket is not connected'));
386
213
  }
387
- var socket = this.getSocket(sessionId);
388
- if (!socket || !socket.connected) {
389
- return _promise.default.reject(new Error("Mobius socket is not connected for session ".concat(sessionId)));
390
- }
391
- return socket.sendRequest(payload, {
392
- timeout: requestOptions.timeout,
214
+ var requestConfigOptions = {
215
+ timeout: options.timeout,
393
216
  matchesResponse: function matchesResponse(response, request) {
394
217
  return (response === null || response === void 0 ? void 0 : response.type) === 'response_event' && (response === null || response === void 0 ? void 0 : response.subtype) === request.type && (response === null || response === void 0 ? void 0 : response.trackingId) === request.trackingId;
395
218
  },
@@ -400,21 +223,22 @@ var MobiusSocket = /*#__PURE__*/function (_EventEmitter) {
400
223
  return response === null || response === void 0 ? void 0 : response.statusMessage;
401
224
  },
402
225
  createError: function createError(response, statusCode, statusMessage) {
403
- return _this5._createWssResponseError(response, statusCode, statusMessage);
226
+ return _this4.createWssResponseError(response, statusCode, statusMessage);
404
227
  },
405
228
  createTimeoutError: function createTimeoutError(request) {
406
- return _this5._createWssResponseError({
229
+ return _this4.createWssResponseError({
407
230
  type: 'response_event',
408
231
  subtype: request.type,
409
232
  trackingId: request.trackingId
410
233
  }, 408, 'Mobius websocket response timed out');
411
234
  }
412
- });
235
+ };
236
+ return this.socket.sendRequest(payload, requestConfigOptions);
413
237
  }
414
238
 
415
239
  /**
416
- * Check if the plugin is connected
417
- * @returns {boolean} True if connected
240
+ * Check if the socket is connected.
241
+ * @returns {boolean} True if connected.
418
242
  */
419
243
  }, {
420
244
  key: "isConnected",
@@ -423,66 +247,22 @@ var MobiusSocket = /*#__PURE__*/function (_EventEmitter) {
423
247
  }
424
248
 
425
249
  /**
426
- * Check if a socket is connected
427
- * @param {string} [sessionId] - Optional session identifier
428
- * @returns {boolean|undefined} True if the socket is connected
429
- */
430
- }, {
431
- key: "hasConnectedSockets",
432
- value: function hasConnectedSockets(sessionId) {
433
- if (sessionId) {
434
- var _this$sockets$get;
435
- return Boolean((_this$sockets$get = this.sockets.get(sessionId)) === null || _this$sockets$get === void 0 ? void 0 : _this$sockets$get.connected);
436
- }
437
- var _iterator = _createForOfIteratorHelper(this.sockets.values()),
438
- _step;
439
- try {
440
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
441
- var socket = _step.value;
442
- if (socket !== null && socket !== void 0 && socket.connected) {
443
- return true;
444
- }
445
- }
446
- } catch (err) {
447
- _iterator.e(err);
448
- } finally {
449
- _iterator.f();
450
- }
451
- return false;
452
- }
453
-
454
- /**
455
- * Check if any sockets are connecting
456
- * @param {string} [sessionId=this.defaultSessionId] - The session identifier
457
- * @returns {boolean|undefined} True if the socket is connecting
458
- */
459
- }, {
460
- key: "hasConnectingSockets",
461
- value: function hasConnectingSockets() {
462
- var sessionId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.defaultSessionId;
463
- var socket = this.sockets.get(sessionId || this.defaultSessionId);
464
- return Boolean(socket === null || socket === void 0 ? void 0 : socket.connecting);
465
- }
466
-
467
- /**
468
- * Connect to Mobius for a specific session.
250
+ * Connect to Mobius.
469
251
  * @param {string} [webSocketUrl] - Optional websocket URL override. Falls back to the device websocket URL.
470
- * @param {string} [sessionId=this.defaultSessionId] - The session identifier for this connection.
471
- * @returns {Promise<void>} Resolves when connection flow completes for the session.
252
+ * @returns {Promise<void>} Resolves when connection flow completes.
472
253
  */
473
254
  }, {
474
255
  key: "connect",
475
256
  value: function connect(webSocketUrl) {
476
- var _this6 = this;
477
- var sessionId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.defaultSessionId;
478
- // First check if there's already a connection promise for this session
479
- if (this._connectPromises.has(sessionId)) {
480
- this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": connection ").concat(sessionId, " already in progress, returning existing promise"));
481
- return this._connectPromises.get(sessionId);
482
- }
483
- var sessionSocket = this.sockets.get(sessionId);
484
- if (sessionSocket !== null && sessionSocket !== void 0 && sessionSocket.connected || sessionSocket !== null && sessionSocket !== void 0 && sessionSocket.connecting) {
485
- this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": connection ").concat(sessionId, " already connected, will not connect again"));
257
+ var _this$socket2,
258
+ _this$socket3,
259
+ _this5 = this;
260
+ if (this.connectPromise) {
261
+ this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": connection already in progress, returning existing promise"));
262
+ return this.connectPromise;
263
+ }
264
+ if ((_this$socket2 = this.socket) !== null && _this$socket2 !== void 0 && _this$socket2.connected || (_this$socket3 = this.socket) !== null && _this$socket3 !== void 0 && _this$socket3.connecting) {
265
+ this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": already connected, will not connect again"));
486
266
  return _promise.default.resolve();
487
267
  }
488
268
 
@@ -493,118 +273,61 @@ var MobiusSocket = /*#__PURE__*/function (_EventEmitter) {
493
273
  }
494
274
 
495
275
  // Cache the caller-provided URL for reconnect
496
- var resolvedUrl = webSocketUrl || this.socketUrl;
497
276
  if (webSocketUrl) {
498
277
  this.socketUrl = webSocketUrl;
499
278
  }
500
279
  this.connecting = true;
501
- this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": starting connection attempt for ").concat(sessionId).concat(Number(this.config.initialConnectionMaxRetries) === 0 && !this.hasEverConnected ? ' (initial retries disabled)' : ''));
280
+ this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": starting connection attempt").concat(Number(this.config.initialConnectionMaxRetries) === 0 && !this.hasEverConnected ? ' (initial retries disabled)' : ''));
502
281
  var connectPromise = _promise.default.resolve(this.webex.internal.device.registered || this.webex.internal.device.register()).then(function () {
503
- _this6.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": connecting ").concat(sessionId));
504
- return _this6._connectWithBackoff(resolvedUrl, sessionId);
282
+ _this5.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": connecting"));
283
+ return _this5.connectWithBackoff(_this5.socketUrl);
505
284
  }).finally(function () {
506
- _this6._connectPromises.delete(sessionId);
285
+ _this5.connectPromise = undefined;
507
286
  });
508
- this._connectPromises.set(sessionId, connectPromise);
287
+ this.connectPromise = connectPromise;
509
288
  return connectPromise;
510
289
  }
511
- }, {
512
- key: "logout",
513
- value: function logout() {
514
- this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": logout() called"));
515
- return this.disconnectAll(this.config.beforeLogoutOptionsCloseReason && !normalReconnectReasons.includes(this.config.beforeLogoutOptionsCloseReason) ? {
516
- code: 3050,
517
- reason: this.config.beforeLogoutOptionsCloseReason
518
- } : undefined);
519
- }
520
290
 
521
291
  /**
522
- * Disconnect a Mobius socket for a specific session.
523
- * @param {object} [options] - Optional websocket close options (for example: `{code, reason}`).
524
- * @param {string} [sessionId=this.defaultSessionId] - The session identifier to disconnect.
525
- * @returns {Promise<void>} Resolves after disconnect cleanup and close handling are initiated/completed.
292
+ * Disconnect the Mobius socket.
293
+ * @param {MobiusSocketCloseOptions} [options] - Optional websocket close options (code, reason).
294
+ * @returns {Promise<void>} Resolves after disconnect cleanup and close handling complete.
526
295
  */
527
296
  }, {
528
297
  key: "disconnect",
529
298
  value: function disconnect(options) {
530
- var _this7 = this;
531
- var sessionId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.defaultSessionId;
532
- this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, "#disconnect: connecting state: ").concat(this.connecting, ", connected state: ").concat(this.connected, ", socket exists: ").concat(!!this.socket, ", options: ").concat((0, _stringify.default)(options)));
533
- var backoffCall = this.backoffCalls.get(sessionId);
534
- if (backoffCall) {
535
- this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": aborting connection ").concat(sessionId));
536
- backoffCall.abort();
537
- this.backoffCalls.delete(sessionId);
538
- }
539
- var shutdownSwitchoverBackoffCall = this._shutdownSwitchoverBackoffCalls.get(sessionId);
540
- if (shutdownSwitchoverBackoffCall) {
541
- this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": aborting shutdown switchover connection ").concat(sessionId));
542
- shutdownSwitchoverBackoffCall.abort();
543
- this._shutdownSwitchoverBackoffCalls.delete(sessionId);
544
- }
545
- // Clean up any pending connection promises
546
- this._connectPromises.delete(sessionId);
547
- var sessionSocket = this.sockets.get(sessionId);
548
- this._clearSeenAsyncEventIds(sessionId);
549
- if (!sessionSocket) {
550
- this.connected = this.hasConnectedSockets();
551
- if (!this.hasConnectedSockets()) {
552
- this._stopTokenRefreshTimer();
553
- }
299
+ var _this6 = this;
300
+ this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, "#disconnect: connecting state: ").concat(this.connecting, ",\n connected state: ").concat(this.connected, ", socket exists: ").concat(!!this.socket, ",\n options: ").concat((0, _stringify.default)(options)));
301
+ if (this.backoffCall) {
302
+ this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": aborting connection"));
303
+ this.backoffCall.abort();
304
+ this.backoffCall = undefined;
305
+ }
306
+ if (this.shutdownSwitchoverBackoffCall) {
307
+ this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": aborting shutdown switchover connection"));
308
+ this.shutdownSwitchoverBackoffCall.abort();
309
+ this.shutdownSwitchoverBackoffCall = undefined;
310
+ }
311
+ this.connectPromise = undefined;
312
+ this.seenAsyncEventIds.clear();
313
+ if (!this.socket) {
314
+ this.connected = false;
315
+ this.stopTokenRefreshTimer();
554
316
  return _promise.default.resolve();
555
317
  }
556
- sessionSocket.removeAllListeners('message');
557
- sessionSocket.connecting = false;
558
- sessionSocket.connected = false;
559
- return _promise.default.resolve(sessionSocket.close(options || undefined)).finally(function () {
560
- _this7.connected = _this7.hasConnectedSockets();
561
- if (!_this7.hasConnectedSockets()) {
562
- _this7._stopTokenRefreshTimer();
563
- }
318
+ this.socket.removeAllListeners('message');
319
+ this.socket.connecting = false;
320
+ this.socket.connected = false;
321
+ return _promise.default.resolve(this.socket.close(options || undefined)).finally(function () {
322
+ _this6.connected = false;
323
+ _this6.stopTokenRefreshTimer();
564
324
  });
565
325
  }
566
326
 
567
- /**
568
- * Disconnect all socket connections
569
- * @param {object} options - Close options
570
- * @returns {Promise} Promise that resolves when all connections are closed
571
- */
572
- }, {
573
- key: "disconnectAll",
574
- value: function disconnectAll(options) {
575
- var _this8 = this;
576
- var disconnectPromises = [];
577
- var _iterator2 = _createForOfIteratorHelper(this.sockets.keys()),
578
- _step2;
579
- try {
580
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
581
- var sessionId = _step2.value;
582
- disconnectPromises.push(this.disconnect(options, sessionId));
583
- }
584
- } catch (err) {
585
- _iterator2.e(err);
586
- } finally {
587
- _iterator2.f();
588
- }
589
- return _promise.default.all(disconnectPromises).then(function () {
590
- _this8.connected = false;
591
- _this8.socket = undefined;
592
- _this8.sockets.clear();
593
- _this8.backoffCalls.clear();
594
- _this8._shutdownSwitchoverBackoffCalls.clear();
595
- _this8._clearSeenAsyncEventIds();
596
- _this8._stopTokenRefreshTimer();
597
- _this8._connectPromises.clear();
598
- });
599
- }
327
+ // eslint-disable-next-line class-methods-use-this
600
328
  }, {
601
- key: "processRegistrationStatusEvent",
602
- value: function processRegistrationStatusEvent(message) {
603
- this.localClusterServiceUrls = message.localClusterServiceUrls;
604
- }
605
- }, {
606
- key: "_createWssResponseError",
607
- value: function _createWssResponseError(response, statusCode, statusMessage) {
329
+ key: "createWssResponseError",
330
+ value: function createWssResponseError(response, statusCode, statusMessage) {
608
331
  var error = new Error(statusMessage || "Mobius websocket request failed with status ".concat(statusCode || 'unknown'));
609
332
  error.name = 'MobiusSocketResponseError';
610
333
  error.statusCode = statusCode;
@@ -614,40 +337,19 @@ var MobiusSocket = /*#__PURE__*/function (_EventEmitter) {
614
337
  return error;
615
338
  }
616
339
  }, {
617
- key: "_applyOverrides",
618
- value: function _applyOverrides(event) {
619
- if (!event || !event.headers) {
620
- return;
621
- }
622
- var headerKeys = (0, _keys.default)(event.headers);
623
- headerKeys.forEach(function (keyPath) {
624
- (0, _set2.default)(event, keyPath, event.headers[keyPath]);
625
- });
626
- }
627
- }, {
628
- key: "_prepareUrl",
629
- value: function _prepareUrl(webSocketUrl) {
340
+ key: "prepareUrl",
341
+ value: function prepareUrl(webSocketUrl) {
630
342
  if (!webSocketUrl) {
343
+ // TODO: Circle back to this logic when mobius implements the shutdown switchover
631
344
  webSocketUrl = this.webex.internal.device.webSocketUrl;
632
345
  }
633
-
634
- // TODO: Validate the host against the service catalog
635
- // const hostFromUrl = url.parse(webSocketUrl, true)?.host;
636
- // const isValidHost = this.webex.internal.services.isValidHost(hostFromUrl);
637
- // if (!isValidHost) {
638
- // this.logger.error(
639
- // `${MOBIUS_SOCKET_NAMESPACE}: host ${hostFromUrl} is not a valid host from host catalog`
640
- // );
641
- // return Promise.resolve('');
642
- // }
643
-
644
346
  return _promise.default.resolve(webSocketUrl);
645
347
  }
646
348
  }, {
647
- key: "_attemptConnection",
648
- value: function _attemptConnection(socketUrl, sessionId, callback) {
649
- var _this9 = this;
650
- var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
349
+ key: "attemptConnection",
350
+ value: function attemptConnection(socketUrl, callback) {
351
+ var _this7 = this;
352
+ var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
651
353
  var _options$isShutdownSw = options.isShutdownSwitchover,
652
354
  isShutdownSwitchover = _options$isShutdownSw === void 0 ? false : _options$isShutdownSw,
653
355
  _options$onSuccess = options.onSuccess,
@@ -655,16 +357,15 @@ var MobiusSocket = /*#__PURE__*/function (_EventEmitter) {
655
357
  var socket = new _socket.default();
656
358
  socket.connecting = true;
657
359
  var newWSUrl;
658
- this._attachSocketEventListeners(socket, sessionId);
659
- var backoffCall = isShutdownSwitchover ? this._shutdownSwitchoverBackoffCalls.get(sessionId) : this.backoffCalls.get(sessionId);
360
+ this.attachSocketEventListeners(socket);
361
+ var backoffCall = isShutdownSwitchover ? this.shutdownSwitchoverBackoffCall : this.backoffCall;
660
362
 
661
363
  // Check appropriate backoff call based on connection type
662
364
  if (!backoffCall) {
663
365
  var mode = isShutdownSwitchover ? 'switchover backoff call' : 'backoffCall';
664
- var msg = "".concat(MOBIUS_SOCKET_NAMESPACE, ": prevent socket open when ").concat(mode, " no longer defined for ").concat(sessionId);
366
+ var msg = "".concat(MOBIUS_SOCKET_NAMESPACE, ": prevent socket open when ").concat(mode, " no longer defined");
665
367
  var err = new Error(msg);
666
368
  this.logger.info(msg);
667
-
668
369
  // Call the callback with the error before rejecting
669
370
  callback(err);
670
371
  return _promise.default.reject(err);
@@ -673,11 +374,11 @@ var MobiusSocket = /*#__PURE__*/function (_EventEmitter) {
673
374
  // For shutdown switchover, don't set socket yet (make-before-break)
674
375
  // For normal connection, set socket before opening to allow disconnect() to close it
675
376
  if (!isShutdownSwitchover) {
676
- this.sockets.set(sessionId, socket);
377
+ this.socket = socket;
677
378
  }
678
- return this._prepareAndOpenSocket(socket, socketUrl, sessionId, isShutdownSwitchover).then(function (webSocketUrl) {
379
+ return this.prepareAndOpenSocket(socket, socketUrl, isShutdownSwitchover).then(function (webSocketUrl) {
679
380
  newWSUrl = webSocketUrl;
680
- _this9.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": ").concat(isShutdownSwitchover ? '[shutdown] switchover' : '', " connected to mobius socket, success, action: connected for ").concat(sessionId, ", url: ").concat(newWSUrl));
381
+ _this7.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": ").concat(isShutdownSwitchover ? '[shutdown] switchover' : '', " connected to mobius socket, success, url: ").concat(newWSUrl));
681
382
 
682
383
  // Custom success handler for shutdown switchover
683
384
  if (onSuccess) {
@@ -692,145 +393,130 @@ var MobiusSocket = /*#__PURE__*/function (_EventEmitter) {
692
393
  }).catch(function (reason) {
693
394
  // For shutdown, simpler error handling - just callback for retry
694
395
  if (isShutdownSwitchover) {
695
- _this9.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": [shutdown] switchover attempt failed for ").concat(sessionId), reason);
396
+ _this7.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": [shutdown] switchover attempt failed"), reason);
696
397
  return callback(reason);
697
398
  }
698
399
 
699
- // Normal connection error handling (existing complex logic)
700
- _this9.lastError = reason; // remember the last error
701
-
702
- var backoffCallNormal = _this9.backoffCalls.get(sessionId);
703
- // Suppress connection errors that appear to be network related. This
704
- // may end up suppressing metrics during outages, but we might not care
705
- // (especially since many of our outages happen in a way that client
706
- // metrics can't be trusted).
400
+ // Normal connection error handling
401
+ var backoffCallNormal = _this7.backoffCall;
402
+ // Suppress connection errors that appear to be network related (code 1006).
707
403
  if (reason.code !== 1006 && backoffCallNormal && (backoffCallNormal === null || backoffCallNormal === void 0 ? void 0 : backoffCallNormal.getNumRetries()) > 0) {
708
- _this9._emit(sessionId, 'connection_failed', reason, {
709
- sessionId: sessionId,
404
+ _this7.emitEvent('connection_failed', reason, {
710
405
  retries: backoffCallNormal === null || backoffCallNormal === void 0 ? void 0 : backoffCallNormal.getNumRetries()
711
406
  });
712
407
  }
713
- _this9.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": connection attempt failed for ").concat(sessionId), reason, (backoffCallNormal === null || backoffCallNormal === void 0 ? void 0 : backoffCallNormal.getNumRetries()) === 0 ? reason.stack : '');
714
- // UnknownResponse is produced by IE for any 4XXX; treated it like a bad
408
+ _this7.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": connection attempt failed"), reason, (backoffCallNormal === null || backoffCallNormal === void 0 ? void 0 : backoffCallNormal.getNumRetries()) === 0 ? reason.stack : '');
409
+
410
+ // UnknownResponse is produced by IE for any 4XXX; treat it like a bad
715
411
  // web socket url and let WDM handle the token checking
716
412
  if (reason instanceof _errors.UnknownResponse) {
717
- _this9.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": received unknown response code for ").concat(sessionId, ", refreshing device registration"));
718
- return _this9.webex.internal.device.refresh().then(function () {
413
+ _this7.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": received unknown response code, refreshing device registration"));
414
+ return _this7.webex.internal.device.refresh().then(function () {
719
415
  return callback(reason);
720
416
  });
721
417
  }
722
418
  // NotAuthorized implies expired token
723
419
  if (reason instanceof _errors.NotAuthorized) {
724
- _this9.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": received authorization error for ").concat(sessionId, ", reauthorizing"));
725
- return _this9.webex.credentials.refresh({
420
+ _this7.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": received authorization error, reauthorizing"));
421
+ return _this7.webex.credentials.refresh({
726
422
  force: true
727
423
  }).then(function () {
728
424
  return callback(reason);
729
425
  });
730
426
  }
731
- // // NotFound implies expired web socket url
732
- // else if (reason instanceof NotFound) {
733
- // this.logger.info(`mercury: received not found error, refreshing device registration`);
734
- // return this.webex.internal.device.refresh()
735
- // .then(() => callback(reason));
736
- // }
737
- // BadRequest implies current credentials are for a Service Account
738
- // Forbidden implies current user is not entitled for Webex
739
427
  if (reason instanceof _errors.BadRequest || reason instanceof _errors.Forbidden) {
740
- _this9.logger.warn("".concat(MOBIUS_SOCKET_NAMESPACE, ": received unrecoverable response from ").concat(MOBIUS_SOCKET_NAMESPACE, " for ").concat(sessionId));
428
+ _this7.logger.warn("".concat(MOBIUS_SOCKET_NAMESPACE, ": received unrecoverable response from ").concat(MOBIUS_SOCKET_NAMESPACE));
741
429
  backoffCallNormal === null || backoffCallNormal === void 0 ? void 0 : backoffCallNormal.abort();
742
430
  return callback(reason);
743
431
  }
744
432
  return callback(reason);
745
433
  }).catch(function (reason) {
746
- _this9.logger.error("".concat(MOBIUS_SOCKET_NAMESPACE, ": failed to handle connection failure for ").concat(sessionId), reason);
434
+ _this7.logger.error("".concat(MOBIUS_SOCKET_NAMESPACE, ": failed to handle connection failure"), reason);
747
435
  callback(reason);
748
436
  });
749
437
  }
750
438
  }, {
751
- key: "_prepareAndOpenSocket",
752
- value: function _prepareAndOpenSocket(socket, socketUrl, sessionId) {
753
- var _this0 = this;
754
- var isShutdownSwitchover = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
439
+ key: "prepareAndOpenSocket",
440
+ value: function prepareAndOpenSocket(socket, socketUrl) {
441
+ var _this8 = this;
442
+ var isShutdownSwitchover = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
755
443
  var logPrefix = isShutdownSwitchover ? '[shutdown] switchover' : 'connection';
756
- return _promise.default.all([this._prepareUrl(socketUrl), this.webex.credentials.getUserToken()]).then(function (_ref) {
444
+ return _promise.default.all([this.prepareUrl(socketUrl), this.webex.credentials.getUserToken()]).then(function (_ref) {
757
445
  var _ref2 = (0, _slicedToArray2.default)(_ref, 2),
758
446
  webSocketUrl = _ref2[0],
759
447
  token = _ref2[1];
760
448
  var options = {
761
- forceCloseDelay: _this0.config.forceCloseDelay,
762
- wssResponseTimeout: _this0.config.wssResponseTimeout,
763
- skipAckEventId: _this0.config.skipAckEventId,
764
- skipAckEventType: _this0.config.skipAckEventType,
449
+ forceCloseDelay: _this8.config.forceCloseDelay,
450
+ wssResponseTimeout: _this8.config.wssResponseTimeout,
765
451
  token: normalizeMobiusAuthToken(token.toString()),
766
452
  refreshToken: function refreshToken() {
767
- return _this0._refreshToken();
453
+ return _this8.refreshToken();
768
454
  },
769
- trackingId: "".concat(_this0.webex.sessionId, "_").concat((0, _now.default)()),
770
- logger: _this0.logger
455
+ trackingId: "".concat(_this8.webex.sessionId, "_").concat((0, _now.default)()),
456
+ logger: _this8.logger
771
457
  };
772
- if (_this0.webex.config.defaultMobiusSocketOptions) {
458
+ if (_this8.webex.config.defaultMobiusSocketOptions) {
773
459
  var customOptionsMsg = isShutdownSwitchover ? 'setting custom options for switchover' : 'setting custom options';
774
- _this0.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": ").concat(customOptionsMsg));
775
- options = _objectSpread(_objectSpread({}, options), _this0.webex.config.defaultMobiusSocketOptions);
460
+ _this8.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": ").concat(customOptionsMsg));
461
+ options = _objectSpread(_objectSpread({}, options), _this8.webex.config.defaultMobiusSocketOptions);
776
462
  }
777
463
 
778
- // Set the socket before opening it. This allows a disconnect() to close
779
- // the socket if it is in the process of being opened.
780
- _this0.sockets.set(sessionId, socket);
781
- _this0.socket = _this0.sockets.get(_this0.defaultSessionId);
782
- _this0.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, " ").concat(logPrefix, " url for ").concat(sessionId, ": ").concat(webSocketUrl));
464
+ // Only promote the socket reference for normal connections.
465
+ // Shutdown switchover keeps the old socket active until the new one succeeds.
466
+ if (!isShutdownSwitchover) {
467
+ _this8.socket = socket;
468
+ }
469
+ _this8.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, " ").concat(logPrefix, " url: ").concat(webSocketUrl));
783
470
  return socket.open(webSocketUrl, options).then(function () {
784
471
  return webSocketUrl;
785
472
  });
786
473
  });
787
474
  }
788
475
  }, {
789
- key: "_connectWithBackoff",
790
- value: function _connectWithBackoff(webSocketUrl, sessionId) {
791
- var _this1 = this;
792
- var context = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
476
+ key: "connectWithBackoff",
477
+ value: function connectWithBackoff(webSocketUrl) {
478
+ var _this9 = this;
479
+ var context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
793
480
  var _context$isShutdownSw = context.isShutdownSwitchover,
794
481
  isShutdownSwitchover = _context$isShutdownSw === void 0 ? false : _context$isShutdownSw,
795
482
  _context$attemptOptio = context.attemptOptions,
796
483
  attemptOptions = _context$attemptOptio === void 0 ? {} : _context$attemptOptio;
797
484
  return new _promise.default(function (resolve, reject) {
798
- // eslint gets confused about whether call is actually used
799
485
  // eslint-disable-next-line prefer-const
800
486
  var call;
801
- var isInitialConnect = !isShutdownSwitchover && !_this1.hasEverConnected;
802
- var initialRetryLimit = _this1.config.initialConnectionMaxRetries == null ? null : Number(_this1.config.initialConnectionMaxRetries);
487
+ var isInitialConnect = !isShutdownSwitchover && !_this9.hasEverConnected;
488
+ var initialRetryLimit = _this9.config.initialConnectionMaxRetries == null ? null : Number(_this9.config.initialConnectionMaxRetries);
803
489
  var isInitialConnectWithoutRetries = isInitialConnect && initialRetryLimit === 0;
804
490
  var onComplete = function onComplete(err) {
805
- var sid = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : sessionId;
806
491
  if (isShutdownSwitchover) {
807
- _this1._shutdownSwitchoverBackoffCalls.delete(sid);
492
+ _this9.shutdownSwitchoverBackoffCall = undefined;
808
493
  } else {
809
- _this1.backoffCalls.delete(sid);
494
+ _this9.backoffCall = undefined;
810
495
  }
811
- var sessionSocket = _this1.sockets.get(sid);
812
496
  if (err) {
813
497
  var msg = isShutdownSwitchover ? "[shutdown] switchover failed after ".concat(call.getNumRetries(), " retries") : "failed to connect after ".concat(call.getNumRetries(), " retries");
814
- _this1.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": ").concat(msg, "; log statement about next retry was inaccurate; ").concat(err));
815
- if (sessionSocket) {
816
- sessionSocket.connecting = false;
817
- sessionSocket.connected = false;
498
+ _this9.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": ").concat(msg, "; ").concat(err));
499
+ // Only mutate socket flags for normal connections.
500
+ // During shutdown switchover, this.socket is the old live socket — don't touch it.
501
+ if (!isShutdownSwitchover && _this9.socket) {
502
+ _this9.socket.connecting = false;
503
+ _this9.socket.connected = false;
818
504
  }
819
505
  return reject(err);
820
506
  }
821
507
 
822
- // Update overall connected status
823
- if (sessionSocket) {
824
- sessionSocket.connecting = false;
825
- sessionSocket.connected = true;
508
+ // For normal connections, mark the socket as connected.
509
+ // Shutdown switchover promotion is handled by the onSuccess callback.
510
+ if (!isShutdownSwitchover && _this9.socket) {
511
+ _this9.socket.connecting = false;
512
+ _this9.socket.connected = true;
826
513
  }
827
- // Default success handling for normal connections
828
514
  if (!isShutdownSwitchover) {
829
- _this1.connecting = _this1.hasConnectingSockets();
830
- _this1.connected = _this1.hasConnectedSockets();
831
- _this1.hasEverConnected = true;
832
- _this1._startTokenRefreshTimer();
833
- _this1._emit(sid, 'online');
515
+ _this9.connecting = false;
516
+ _this9.connected = true;
517
+ _this9.hasEverConnected = true;
518
+ _this9.startTokenRefreshTimer();
519
+ _this9.emitEvent('online');
834
520
  }
835
521
  return resolve();
836
522
  };
@@ -838,14 +524,14 @@ var MobiusSocket = /*#__PURE__*/function (_EventEmitter) {
838
524
  call = _backoff.default.call(function (callback) {
839
525
  var attemptNum = call.getNumRetries();
840
526
  var attemptLogPrefix = isShutdownSwitchover ? '[shutdown] switchover' : 'connection';
841
- _this1.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": executing ").concat(attemptLogPrefix, " attempt ").concat(attemptNum, " for ").concat(sessionId));
842
- _this1._attemptConnection(webSocketUrl, sessionId, callback, attemptOptions);
527
+ _this9.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": executing ").concat(attemptLogPrefix, " attempt ").concat(attemptNum));
528
+ _this9.attemptConnection(webSocketUrl, callback, attemptOptions);
843
529
  }, function (err) {
844
- return onComplete(err, sessionId);
530
+ return onComplete(err);
845
531
  });
846
532
  call.setStrategy(new _backoff.default.ExponentialStrategy({
847
- initialDelay: _this1.config.backoffTimeReset,
848
- maxDelay: _this1.config.backoffTimeMax
533
+ initialDelay: _this9.config.backoffTimeReset,
534
+ maxDelay: _this9.config.backoffTimeMax
849
535
  }));
850
536
  if (isInitialConnectWithoutRetries) {
851
537
  call.retryIf(function () {
@@ -853,192 +539,141 @@ var MobiusSocket = /*#__PURE__*/function (_EventEmitter) {
853
539
  });
854
540
  } else if (isInitialConnect && initialRetryLimit > 0) {
855
541
  call.failAfter(initialRetryLimit);
856
- } else if (_this1.config.maxRetries) {
857
- call.failAfter(_this1.config.maxRetries);
542
+ } else if (_this9.config.maxRetries) {
543
+ call.failAfter(_this9.config.maxRetries);
858
544
  }
859
545
 
860
- // Store the call BEFORE setting up event handlers to prevent race conditions
861
- // Store backoff call reference BEFORE starting (so it's available in _attemptConnection)
546
+ // Store backoff call reference BEFORE starting (so it's available in attemptConnection)
862
547
  if (isShutdownSwitchover) {
863
- _this1._shutdownSwitchoverBackoffCalls.set(sessionId, call);
548
+ _this9.shutdownSwitchoverBackoffCall = call;
864
549
  } else {
865
- _this1.backoffCalls.set(sessionId, call);
550
+ _this9.backoffCall = call;
866
551
  }
867
552
  call.on('abort', function () {
868
553
  var msg = isShutdownSwitchover ? 'Shutdown Switchover' : 'Connection';
869
- _this1.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": ").concat(msg, " aborted for ").concat(sessionId));
870
- reject(new Error("MobiusSocket ".concat(msg, " Aborted for ").concat(sessionId)));
554
+ _this9.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": ").concat(msg, " aborted"));
555
+ reject(new Error("MobiusSocket ".concat(msg, " Aborted")));
871
556
  });
872
557
  call.on('callback', function (err) {
873
558
  if (err) {
874
559
  if (isInitialConnectWithoutRetries) {
875
- // retryIf(() => false) already disabled retries for this initial connect;
876
- // this branch only avoids logging the generic "attempting retry" message.
877
- _this1.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": initial connect failed for ").concat(sessionId, "; retries already disabled"));
560
+ _this9.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": initial connect failed; retries already disabled"));
878
561
  return;
879
562
  }
880
563
  var number = call.getNumRetries();
881
- var delay = Math.min(call.strategy_.nextBackoffDelay_, _this1.config.backoffTimeMax);
564
+ var delay = Math.min(call.strategy_.nextBackoffDelay_, _this9.config.backoffTimeMax);
882
565
  var callbackLogPrefix = isShutdownSwitchover ? '[shutdown] switchover' : '';
883
- _this1.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": ").concat(callbackLogPrefix, " failed to connect; attempting retry ").concat(number + 1, " in ").concat(delay, " ms for ").concat(sessionId));
566
+ _this9.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": ").concat(callbackLogPrefix, " failed to connect; attempting retry ").concat(number + 1, " in ").concat(delay, " ms"));
884
567
  /* istanbul ignore if */
885
568
  if (process.env.NODE_ENV === 'development') {
886
- _this1.logger.debug("".concat(MOBIUS_SOCKET_NAMESPACE, ": "), err, err.stack);
569
+ _this9.logger.debug("".concat(MOBIUS_SOCKET_NAMESPACE, ": "), err, err.stack);
887
570
  }
888
571
  return;
889
572
  }
890
- _this1.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": connected ").concat(sessionId));
573
+ _this9.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": connected"));
891
574
  });
892
575
  call.start();
893
576
  });
894
577
  }
895
578
  }, {
896
- key: "_emit",
897
- value: function _emit(sessionId, eventName) {
898
- for (var _len5 = arguments.length, args = new Array(_len5 > 2 ? _len5 - 2 : 0), _key5 = 2; _key5 < _len5; _key5++) {
899
- args[_key5 - 2] = arguments[_key5];
579
+ key: "emitEvent",
580
+ value: function emitEvent(eventName) {
581
+ for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
582
+ args[_key - 1] = arguments[_key];
900
583
  }
901
584
  try {
902
- if (!sessionId || !eventName) {
585
+ if (!eventName) {
903
586
  return;
904
587
  }
905
- var suffix = sessionId === this.defaultSessionId ? '' : ":".concat(sessionId);
906
- this.emit.apply(this, ["".concat(eventName).concat(suffix)].concat(args));
588
+ this.emit.apply(this, [eventName].concat(args));
907
589
  } catch (error) {
908
590
  // Safely handle errors without causing additional issues during cleanup
909
- try {
910
- this.logger.error("".concat(MOBIUS_SOCKET_NAMESPACE, ": error occurred in event handler:"), error, ' with args: ', [sessionId, eventName].concat(args));
911
- } catch (logError) {
912
- // If even logging fails, just ignore to prevent cascading errors during cleanup
913
- // eslint-disable-next-line no-console
914
- console.error('MobiusSocket _emit error handling failed:', logError);
915
- }
916
- }
917
- }
918
- }, {
919
- key: "_getEventHandlers",
920
- value: function _getEventHandlers(eventType) {
921
- if (!eventType) {
922
- return [];
923
- }
924
- var _eventType$split = eventType.split('.'),
925
- _eventType$split2 = (0, _slicedToArray2.default)(_eventType$split, 2),
926
- namespace = _eventType$split2[0],
927
- name = _eventType$split2[1];
928
- var handlers = [];
929
- if (!this.webex[namespace] && !this.webex.internal[namespace]) {
930
- return handlers;
931
- }
932
- var handlerName = (0, _camelCase2.default)("process_".concat(name, "_event"));
933
- if ((this.webex[namespace] || this.webex.internal[namespace])[handlerName]) {
934
- handlers.push({
935
- name: handlerName,
936
- namespace: namespace
937
- });
591
+ this.logger.error("".concat(MOBIUS_SOCKET_NAMESPACE, ": error occurred in event handler:"), error, ' with args: ', [eventName].concat(args));
938
592
  }
939
- return handlers;
940
593
  }
941
594
  }, {
942
- key: "_startTokenRefreshTimer",
943
- value: function _startTokenRefreshTimer() {
944
- var _this10 = this;
945
- if (this._tokenRefreshTimer || !this.hasConnectedSockets()) {
595
+ key: "startTokenRefreshTimer",
596
+ value: function startTokenRefreshTimer() {
597
+ var _this0 = this;
598
+ if (this.tokenRefreshTimer || !this.connected) {
946
599
  return;
947
600
  }
948
- this._tokenRefreshTimer = setInterval(function () {
949
- _this10._refreshToken().catch(function (error) {
950
- _this10.logger.error("".concat(MOBIUS_SOCKET_NAMESPACE, ": periodic token refresh failed"), error);
601
+ this.tokenRefreshTimer = setInterval(function () {
602
+ _this0.refreshToken().catch(function (error) {
603
+ _this0.logger.error("".concat(MOBIUS_SOCKET_NAMESPACE, ": periodic token refresh failed"), error);
951
604
  });
952
605
  }, TOKEN_REFRESH_INTERVAL_MS);
953
606
  }
954
607
  }, {
955
- key: "_stopTokenRefreshTimer",
956
- value: function _stopTokenRefreshTimer() {
957
- if (!this._tokenRefreshTimer) {
608
+ key: "stopTokenRefreshTimer",
609
+ value: function stopTokenRefreshTimer() {
610
+ if (!this.tokenRefreshTimer) {
958
611
  return;
959
612
  }
960
- clearInterval(this._tokenRefreshTimer);
961
- this._tokenRefreshTimer = undefined;
613
+ clearInterval(this.tokenRefreshTimer);
614
+ this.tokenRefreshTimer = undefined;
962
615
  }
963
616
  }, {
964
- key: "_refreshToken",
965
- value: function _refreshToken() {
966
- var _this11 = this;
967
- if (this._tokenRefreshInFlight) {
968
- return this._tokenRefreshInFlight;
617
+ key: "refreshToken",
618
+ value: function refreshToken() {
619
+ var _this1 = this;
620
+ if (this.tokenRefreshInFlight) {
621
+ return this.tokenRefreshInFlight;
969
622
  }
970
- if (!this.hasConnectedSockets()) {
971
- this._stopTokenRefreshTimer();
623
+ if (!this.connected) {
624
+ this.stopTokenRefreshTimer();
972
625
  return _promise.default.resolve();
973
626
  }
974
627
  var tokenPromise = this.webex.credentials.canRefresh ? this.webex.credentials.refresh({
975
628
  force: true
976
629
  }).then(function () {
977
- return _this11.webex.credentials.getUserToken();
630
+ return _this1.webex.credentials.getUserToken();
978
631
  }) : this.webex.credentials.getUserToken();
979
- this._tokenRefreshInFlight = tokenPromise.then(function (token) {
632
+ this.tokenRefreshInFlight = tokenPromise.then(function (token) {
633
+ var _this1$socket;
980
634
  if (!token) {
981
635
  throw new Error('Mobius token refresh did not return a token');
982
636
  }
983
637
  var refreshedToken = normalizeMobiusAuthToken(token.toString());
984
- var authPayloadPromises = [];
985
- var _iterator3 = _createForOfIteratorHelper(_this11.sockets.values()),
986
- _step3;
987
- try {
988
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
989
- var socket = _step3.value;
990
- if (socket !== null && socket !== void 0 && socket.connected) {
991
- authPayloadPromises.push(socket.refresh(refreshedToken));
992
- }
993
- }
994
- } catch (err) {
995
- _iterator3.e(err);
996
- } finally {
997
- _iterator3.f();
638
+ if ((_this1$socket = _this1.socket) !== null && _this1$socket !== void 0 && _this1$socket.connected) {
639
+ return _this1.socket.refresh(refreshedToken);
998
640
  }
999
- return _promise.default.all(authPayloadPromises);
641
+ return undefined;
1000
642
  }).catch(function (error) {
1001
- _this11.logger.error("".concat(MOBIUS_SOCKET_NAMESPACE, ": failed to refresh/re-auth Mobius sockets"), error);
643
+ _this1.logger.error("".concat(MOBIUS_SOCKET_NAMESPACE, ": failed to refresh/re-auth Mobius socket"), error);
1002
644
  throw error;
1003
645
  }).finally(function () {
1004
- _this11._tokenRefreshInFlight = undefined;
646
+ _this1.tokenRefreshInFlight = undefined;
1005
647
  });
1006
- return this._tokenRefreshInFlight;
648
+ return this.tokenRefreshInFlight;
1007
649
  }
1008
650
  }, {
1009
- key: "_onclose",
1010
- value: function _onclose(sessionId, event, sourceSocket) {
651
+ key: "onclose",
652
+ value: function onclose(event, sourceSocket) {
1011
653
  // I don't see any way to avoid the complexity or statement count in here.
1012
654
  /* eslint complexity: [0] */
1013
655
 
1014
656
  try {
1015
657
  var reason = event.reason && event.reason.toLowerCase();
1016
- var sessionSocket = this.sockets.get(sessionId);
1017
658
  var socketUrl;
1018
- event.sessionId = sessionId;
1019
- var isActiveSocket = sourceSocket === sessionSocket;
659
+ var isActiveSocket = sourceSocket === this.socket;
1020
660
  if (sourceSocket) {
1021
661
  socketUrl = sourceSocket.url;
1022
662
  }
1023
- this.sockets.delete(sessionId);
663
+
664
+ // Only tear down state if the currently active socket closed
1024
665
  if (isActiveSocket) {
1025
- // Only tear down state if the currently active socket closed
1026
- if (sessionSocket) {
1027
- sessionSocket.removeAllListeners();
1028
- if (sessionId === this.defaultSessionId) {
1029
- this.socket = undefined;
1030
- }
1031
- this._emit(sessionId, 'offline', event);
1032
- }
1033
- // Update overall connected status
1034
- this.connecting = this.hasConnectingSockets();
1035
- this.connected = this.hasConnectedSockets();
1036
- if (!this.hasConnectedSockets()) {
1037
- this._stopTokenRefreshTimer();
666
+ if (this.socket) {
667
+ this.socket.removeAllListeners();
668
+ this.socket = undefined;
669
+ this.emitEvent('offline', event);
1038
670
  }
671
+ this.connecting = false;
672
+ this.connected = false;
673
+ this.stopTokenRefreshTimer();
1039
674
  } else {
1040
675
  // Old socket closed; do not flip connection state
1041
- this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": [shutdown] non-active socket closed, code=").concat(event.code, " for ").concat(sessionId));
676
+ this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": [shutdown] non-active socket closed, code=").concat(event.code));
1042
677
  // Clean up listeners from old socket now that it's closed
1043
678
  if (sourceSocket) {
1044
679
  sourceSocket.removeAllListeners();
@@ -1046,145 +681,111 @@ var MobiusSocket = /*#__PURE__*/function (_EventEmitter) {
1046
681
  }
1047
682
  switch (event.code) {
1048
683
  case 1003:
1049
- // metric: disconnect
1050
- this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": service rejected last message for ").concat(sessionId, "; will not reconnect: ").concat(event.reason));
1051
- if (isActiveSocket) this._emit(sessionId, 'offline.permanent', event);
684
+ this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": service rejected last message; will not reconnect: ").concat(event.reason));
685
+ if (isActiveSocket) this.emitEvent('offline.permanent', event);
1052
686
  break;
1053
687
  case 4000:
1054
- // metric: disconnect
1055
- this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": socket ").concat(sessionId, " replaced; will not reconnect"));
1056
- if (isActiveSocket) this._emit(sessionId, 'offline.replaced', event);
1057
- // If not active, nothing to do
688
+ this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": socket replaced; will not reconnect"));
689
+ if (isActiveSocket) this.emitEvent('offline.replaced', event);
1058
690
  break;
1059
691
  case 4001:
1060
692
  // replaced during shutdown
1061
693
  if (isActiveSocket) {
1062
694
  // Server closed active socket with 4001, meaning it expected this connection
1063
- // to be replaced, but the switchover in _handleImminentShutdown failed.
1064
- // This is a permanent failure - do not reconnect.
1065
- this.logger.warn("".concat(MOBIUS_SOCKET_NAMESPACE, ": active socket closed with 4001; shutdown switchover failed for ").concat(sessionId));
1066
- this._emit(sessionId, 'offline.permanent', event);
695
+ // to be replaced, but the switchover in handleImminentShutdown failed.
696
+ this.logger.warn("".concat(MOBIUS_SOCKET_NAMESPACE, ": active socket closed with 4001; shutdown switchover failed"));
697
+ this.emitEvent('offline.permanent', event);
1067
698
  } else {
1068
699
  // Expected: old socket closed after successful switchover
1069
- this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": old socket closed with 4001 (replaced during shutdown); no reconnect needed for ").concat(sessionId));
1070
- this._emit(sessionId, 'offline.replaced', event);
700
+ this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": old socket closed with 4001 (replaced during shutdown); no reconnect needed"));
701
+ this.emitEvent('offline.replaced', event);
1071
702
  }
1072
703
  break;
1073
704
  case 1001:
1074
705
  case 1005:
1075
706
  case 1006:
1076
707
  case 1011:
1077
- this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": socket ").concat(sessionId, " disconnected; reconnecting"));
708
+ this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": socket disconnected; reconnecting"));
1078
709
  if (isActiveSocket) {
1079
- this._emit(sessionId, 'offline.transient', event);
1080
- this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": [shutdown] reconnecting active socket to recover for ").concat(sessionId));
1081
- this._reconnect(socketUrl, sessionId);
710
+ this.emitEvent('offline.transient', event);
711
+ this.reconnect(socketUrl);
1082
712
  }
1083
- // metric: disconnect
1084
- // if (code == 1011 && reason !== ping error) metric: unexpected disconnect
1085
713
  break;
1086
714
  case 1000:
1087
715
  case 3050:
1088
- // 3050 indicates logout form of closure, default to old behavior, use config reason defined by consumer to proceed with the permanent block
1089
716
  if (normalReconnectReasons.includes(reason)) {
1090
- this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": socket ").concat(sessionId, " disconnected; reconnecting"));
717
+ this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": socket disconnected; reconnecting"));
1091
718
  if (isActiveSocket) {
1092
- this._emit(sessionId, 'offline.transient', event);
1093
- this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": [shutdown] reconnecting due to normal close for ").concat(sessionId));
1094
- this._reconnect(socketUrl, sessionId);
719
+ this.emitEvent('offline.transient', event);
720
+ this.reconnect(socketUrl);
1095
721
  }
1096
- // metric: disconnect
1097
- // if (reason === done forced) metric: force closure
1098
722
  } else {
1099
- this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": socket ").concat(sessionId, " disconnected; will not reconnect: ").concat(event.reason));
1100
- if (isActiveSocket) this._emit(sessionId, 'offline.permanent', event);
723
+ this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": socket disconnected; will not reconnect: ").concat(event.reason));
724
+ if (isActiveSocket) this.emitEvent('offline.permanent', event);
1101
725
  }
1102
726
  break;
1103
727
  default:
1104
- this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": socket ").concat(sessionId, " disconnected unexpectedly; will not reconnect"));
1105
- // unexpected disconnect
1106
- if (isActiveSocket) this._emit(sessionId, 'offline.permanent', event);
728
+ this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": socket disconnected unexpectedly; will not reconnect"));
729
+ if (isActiveSocket) this.emitEvent('offline.permanent', event);
1107
730
  }
1108
731
  } catch (error) {
1109
- this.logger.error("".concat(MOBIUS_SOCKET_NAMESPACE, ": error occurred in close handler for ").concat(sessionId), error);
732
+ this.logger.error("".concat(MOBIUS_SOCKET_NAMESPACE, ": error occurred in close handler"), error);
1110
733
  }
1111
734
  }
1112
735
  }, {
1113
- key: "_onmessage",
1114
- value: function _onmessage(sessionId, event) {
1115
- var _this12 = this;
1116
- this._setTimeOffset(sessionId, event);
736
+ key: "onmessage",
737
+ value: function onmessage(event) {
1117
738
  var envelope = event.data;
1118
- if (process.env.ENABLE_MERCURY_LOGGING) {
1119
- this.logger.debug("".concat(MOBIUS_SOCKET_NAMESPACE, ": message envelope from ").concat(sessionId, ": "), envelope);
739
+ if (process.env.ENABLE_MOBIUS_LOGGING) {
740
+ this.logger.debug("".concat(MOBIUS_SOCKET_NAMESPACE, ": message envelope: "), envelope);
1120
741
  }
1121
- envelope.sessionId = sessionId;
1122
742
 
1123
743
  // Handle shutdown message shape: { type: 'shutdown' }
1124
744
  if (envelope && envelope.type === 'shutdown') {
1125
- this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": [shutdown] imminent shutdown message received for ").concat(sessionId));
1126
- this._emit(sessionId, 'event:mercury_shutdown_imminent', envelope);
1127
- this._handleImminentShutdown(sessionId);
745
+ this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": [shutdown] imminent shutdown message received"));
746
+ this.emitEvent('event:mobius_shutdown_imminent', envelope); // This is not yet not implemented, keeping for future support
747
+
748
+ this.handleImminentShutdown();
1128
749
  return _promise.default.resolve();
1129
750
  }
1130
- if (this._trackAsyncEventAndShouldSuppressDuplicate(sessionId, envelope)) {
751
+ if (this.trackAsyncEventAndShouldSuppressDuplicate(envelope)) {
1131
752
  return _promise.default.resolve();
1132
753
  }
1133
754
 
1134
- // Mobius: emit event:<type> for typed messages (e.g., register.response)
755
+ // Emit event:<type> for typed messages (e.g., register.response)
1135
756
  if (envelope.type) {
1136
- this._emit(sessionId, "event:".concat(envelope.type), envelope);
757
+ this.emitEvent("event:".concat(envelope.type), envelope);
1137
758
  }
1138
- envelope.sessionId = sessionId;
759
+
1139
760
  // Use data/payload if present, otherwise treat the envelope itself as the data (flat format)
1140
761
  var data = envelope.data || envelope;
1141
- this._applyOverrides(data);
1142
762
 
1143
- // Support both Mercury-enveloped (data.eventType) and flat (eventType) formats
763
+ // Support both Mobius-enveloped (data.eventType) and flat (eventType) formats
1144
764
  var eventType = (data === null || data === void 0 ? void 0 : data.eventType) || envelope.eventType;
1145
765
  if (!eventType) {
1146
- this._emit(sessionId, 'event', envelope);
766
+ this.emitEvent('event', envelope);
1147
767
  return _promise.default.resolve();
1148
768
  }
1149
- return this._getEventHandlers(eventType).reduce(function (promise, handler) {
1150
- return promise.then(function () {
1151
- var namespace = handler.namespace,
1152
- name = handler.name;
1153
- return new _promise.default(function (resolve) {
1154
- resolve((_this12.webex[namespace] || _this12.webex.internal[namespace])[name](data));
1155
- }).catch(function (reason) {
1156
- return _this12.logger.error("".concat(MOBIUS_SOCKET_NAMESPACE, ": error occurred in autowired event handler for ").concat(eventType, " from ").concat(sessionId), reason);
1157
- });
1158
- });
1159
- }, _promise.default.resolve()).then(function () {
1160
- _this12._emit(sessionId, 'event', envelope);
1161
- var _eventType$split3 = eventType.split('.'),
1162
- _eventType$split4 = (0, _slicedToArray2.default)(_eventType$split3, 1),
1163
- namespace = _eventType$split4[0];
1164
- if (namespace === eventType) {
1165
- _this12._emit(sessionId, "event:".concat(namespace), envelope);
1166
- } else {
1167
- _this12._emit(sessionId, "event:".concat(namespace), envelope);
1168
- _this12._emit(sessionId, "event:".concat(eventType), envelope);
769
+ try {
770
+ // TODO: Remove if event:namespace is not required
771
+ this.emitEvent('event', envelope);
772
+ var _eventType$split = eventType.split('.'),
773
+ _eventType$split2 = (0, _slicedToArray2.default)(_eventType$split, 1),
774
+ namespace = _eventType$split2[0];
775
+ this.emitEvent("event:".concat(namespace), envelope);
776
+ if (namespace !== eventType) {
777
+ this.emitEvent("event:".concat(eventType), envelope);
1169
778
  }
1170
- }).catch(function (reason) {
1171
- _this12.logger.error("".concat(MOBIUS_SOCKET_NAMESPACE, ": error occurred processing socket message from ").concat(sessionId), reason);
1172
- });
1173
- }
1174
- }, {
1175
- key: "_setTimeOffset",
1176
- value: function _setTimeOffset(sessionId, event) {
1177
- var wsWriteTimestamp = event.data.wsWriteTimestamp;
1178
- if (typeof wsWriteTimestamp === 'number' && wsWriteTimestamp > 0) {
1179
- this.mercuryTimeOffset = (0, _now.default)() - wsWriteTimestamp;
779
+ } catch (reason) {
780
+ this.logger.error("".concat(MOBIUS_SOCKET_NAMESPACE, ": error occurred processing socket message"), reason);
1180
781
  }
782
+ return _promise.default.resolve();
1181
783
  }
1182
784
  }, {
1183
- key: "_reconnect",
1184
- value: function _reconnect(webSocketUrl) {
1185
- var sessionId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.defaultSessionId;
1186
- this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": reconnecting ").concat(sessionId));
1187
- return this.connect(webSocketUrl || this.socketUrl, sessionId);
785
+ key: "reconnect",
786
+ value: function reconnect(webSocketUrl) {
787
+ this.logger.info("".concat(MOBIUS_SOCKET_NAMESPACE, ": reconnecting"));
788
+ return this.connect(webSocketUrl || this.socketUrl);
1188
789
  }
1189
790
  }]);
1190
791
  }(_events.EventEmitter);