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