@vuu-ui/vuu-data-remote 0.8.92 → 0.8.94

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 (47) hide show
  1. package/cjs/ConnectionManager.js +175 -0
  2. package/cjs/ConnectionManager.js.map +1 -0
  3. package/cjs/DedicatedWorker.js +61 -0
  4. package/cjs/DedicatedWorker.js.map +1 -0
  5. package/cjs/WebSocketConnection.js +23 -0
  6. package/cjs/WebSocketConnection.js.map +1 -0
  7. package/cjs/data-source.js +1 -0
  8. package/cjs/data-source.js.map +1 -1
  9. package/cjs/index.js +2 -5
  10. package/cjs/index.js.map +1 -1
  11. package/cjs/inlined-worker.js +598 -327
  12. package/cjs/inlined-worker.js.map +1 -1
  13. package/cjs/vuu-data-source.js +40 -18
  14. package/cjs/vuu-data-source.js.map +1 -1
  15. package/esm/ConnectionManager.js +173 -0
  16. package/esm/ConnectionManager.js.map +1 -0
  17. package/esm/DedicatedWorker.js +59 -0
  18. package/esm/DedicatedWorker.js.map +1 -0
  19. package/esm/WebSocketConnection.js +21 -0
  20. package/esm/WebSocketConnection.js.map +1 -0
  21. package/esm/data-source.js +1 -0
  22. package/esm/data-source.js.map +1 -1
  23. package/esm/index.js +1 -1
  24. package/esm/inlined-worker.js +598 -327
  25. package/esm/inlined-worker.js.map +1 -1
  26. package/esm/vuu-data-source.js +41 -19
  27. package/esm/vuu-data-source.js.map +1 -1
  28. package/package.json +7 -7
  29. package/types/ConnectionManager.d.ts +35 -0
  30. package/types/DedicatedWorker.d.ts +9 -0
  31. package/types/WebSocketConnection.d.ts +68 -0
  32. package/types/index.d.ts +3 -2
  33. package/types/inlined-worker.d.ts +1 -1
  34. package/types/server-proxy/server-proxy.d.ts +8 -3
  35. package/types/server-proxy/viewport.d.ts +6 -3
  36. package/types/vuu-data-source.d.ts +2 -2
  37. package/cjs/connection-manager.js +0 -224
  38. package/cjs/connection-manager.js.map +0 -1
  39. package/cjs/server-proxy/messages.js +0 -6
  40. package/cjs/server-proxy/messages.js.map +0 -1
  41. package/esm/connection-manager.js +0 -219
  42. package/esm/connection-manager.js.map +0 -1
  43. package/esm/server-proxy/messages.js +0 -4
  44. package/esm/server-proxy/messages.js.map +0 -1
  45. package/types/connection-manager.d.ts +0 -52
  46. package/types/connectionTypes.d.ts +0 -5
  47. package/types/websocket-connection.d.ts +0 -24
@@ -1,7 +1,10 @@
1
1
  const workerSourceCode = `
2
+ var __defProp = Object.defineProperty;
2
3
  var __typeError = (msg) => {
3
4
  throw TypeError(msg);
4
5
  };
6
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
7
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
8
  var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
6
9
  var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
7
10
  var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
@@ -75,6 +78,8 @@ function getFullRange({ from, to }, bufferSize = 0, totalRowCount = Number.MAX_S
75
78
  var withinRange = (value, { from, to }) => value >= from && value < to;
76
79
  var WindowRange = class _WindowRange {
77
80
  constructor(from, to) {
81
+ __publicField(this, "from");
82
+ __publicField(this, "to");
78
83
  this.from = from;
79
84
  this.to = to;
80
85
  }
@@ -91,7 +96,6 @@ var WindowRange = class _WindowRange {
91
96
  };
92
97
 
93
98
  // ../vuu-utils/src/datasource-utils.ts
94
- var isConnectionStatusMessage = (msg) => msg.type === "connection-status";
95
99
  var isConnectionQualityMetrics = (msg) => msg.type === "connection-metrics";
96
100
  var isVisualLinkMessage = (msg) => msg.type.endsWith("_VISUAL_LINK");
97
101
  var isViewportMessage = (msg) => "viewport" in msg;
@@ -104,29 +108,29 @@ var NO_OP = () => void 0;
104
108
  var DEFAULT_DEBUG_LEVEL = false ? "error" : "info";
105
109
  var { loggingLevel = DEFAULT_DEBUG_LEVEL } = getLoggingSettings();
106
110
  var logger = (category) => {
107
- const debugEnabled5 = loggingLevel === "debug";
108
- const infoEnabled5 = debugEnabled5 || loggingLevel === "info";
109
- const warnEnabled = infoEnabled5 || loggingLevel === "warn";
111
+ const debugEnabled4 = loggingLevel === "debug";
112
+ const infoEnabled4 = debugEnabled4 || loggingLevel === "info";
113
+ const warnEnabled = infoEnabled4 || loggingLevel === "warn";
110
114
  const errorEnabled = warnEnabled || loggingLevel === "error";
111
- const info5 = infoEnabled5 ? (message) => console.info(\`[\${category}] \${message}\`) : NO_OP;
112
- const warn4 = warnEnabled ? (message) => console.warn(\`[\${category}] \${message}\`) : NO_OP;
113
- const debug5 = debugEnabled5 ? (message) => console.debug(\`[\${category}] \${message}\`) : NO_OP;
114
- const error4 = errorEnabled ? (message) => console.error(\`[\${category}] \${message}\`) : NO_OP;
115
+ const info4 = infoEnabled4 ? (message) => console.info(\`[\${category}] \${message}\`) : NO_OP;
116
+ const warn3 = warnEnabled ? (message) => console.warn(\`[\${category}] \${message}\`) : NO_OP;
117
+ const debug4 = debugEnabled4 ? (message) => console.debug(\`[\${category}] \${message}\`) : NO_OP;
118
+ const error3 = errorEnabled ? (message) => console.error(\`[\${category}] \${message}\`) : NO_OP;
115
119
  if (false) {
116
120
  return {
117
121
  errorEnabled,
118
- error: error4
122
+ error: error3
119
123
  };
120
124
  } else {
121
125
  return {
122
- debugEnabled: debugEnabled5,
123
- infoEnabled: infoEnabled5,
126
+ debugEnabled: debugEnabled4,
127
+ infoEnabled: infoEnabled4,
124
128
  warnEnabled,
125
129
  errorEnabled,
126
- info: info5,
127
- warn: warn4,
128
- debug: debug5,
129
- error: error4
130
+ info: info4,
131
+ warn: warn3,
132
+ debug: debug4,
133
+ error: error3
130
134
  };
131
135
  }
132
136
  };
@@ -153,8 +157,8 @@ var { debug, debugEnabled } = logger("range-monitor");
153
157
  var RangeMonitor = class {
154
158
  constructor(source) {
155
159
  this.source = source;
156
- this.range = { from: 0, to: 0 };
157
- this.timestamp = 0;
160
+ __publicField(this, "range", { from: 0, to: 0 });
161
+ __publicField(this, "timestamp", 0);
158
162
  }
159
163
  isSet() {
160
164
  return this.timestamp !== 0;
@@ -174,12 +178,116 @@ var RangeMonitor = class {
174
178
  }
175
179
  };
176
180
 
181
+ // ../vuu-utils/src/event-emitter.ts
182
+ function isArrayOfListeners(listeners) {
183
+ return Array.isArray(listeners);
184
+ }
185
+ function isOnlyListener(listeners) {
186
+ return !Array.isArray(listeners);
187
+ }
188
+ var _events;
189
+ var EventEmitter = class {
190
+ constructor() {
191
+ __privateAdd(this, _events, /* @__PURE__ */ new Map());
192
+ }
193
+ addListener(event, listener) {
194
+ const listeners = __privateGet(this, _events).get(event);
195
+ if (!listeners) {
196
+ __privateGet(this, _events).set(event, listener);
197
+ } else if (isArrayOfListeners(listeners)) {
198
+ listeners.push(listener);
199
+ } else if (isOnlyListener(listeners)) {
200
+ __privateGet(this, _events).set(event, [listeners, listener]);
201
+ }
202
+ }
203
+ removeListener(event, listener) {
204
+ if (!__privateGet(this, _events).has(event)) {
205
+ return;
206
+ }
207
+ const listenerOrListeners = __privateGet(this, _events).get(event);
208
+ let position = -1;
209
+ if (listenerOrListeners === listener) {
210
+ __privateGet(this, _events).delete(event);
211
+ } else if (Array.isArray(listenerOrListeners)) {
212
+ for (let i = listenerOrListeners.length; i-- > 0; ) {
213
+ if (listenerOrListeners[i] === listener) {
214
+ position = i;
215
+ break;
216
+ }
217
+ }
218
+ if (position < 0) {
219
+ return;
220
+ }
221
+ if (listenerOrListeners.length === 1) {
222
+ listenerOrListeners.length = 0;
223
+ __privateGet(this, _events).delete(event);
224
+ } else {
225
+ listenerOrListeners.splice(position, 1);
226
+ }
227
+ }
228
+ }
229
+ removeAllListeners(event) {
230
+ if (event && __privateGet(this, _events).has(event)) {
231
+ __privateGet(this, _events).delete(event);
232
+ } else if (event === void 0) {
233
+ __privateGet(this, _events).clear();
234
+ }
235
+ }
236
+ emit(event, ...args) {
237
+ if (__privateGet(this, _events)) {
238
+ const handler = __privateGet(this, _events).get(event);
239
+ if (handler) {
240
+ this.invokeHandler(handler, args);
241
+ }
242
+ }
243
+ }
244
+ once(event, listener) {
245
+ const handler = (...args) => {
246
+ this.removeListener(event, handler);
247
+ listener(...args);
248
+ };
249
+ this.on(event, handler);
250
+ }
251
+ on(event, listener) {
252
+ this.addListener(event, listener);
253
+ }
254
+ hasListener(event, listener) {
255
+ const listeners = __privateGet(this, _events).get(event);
256
+ if (Array.isArray(listeners)) {
257
+ return listeners.includes(listener);
258
+ } else {
259
+ return listeners === listener;
260
+ }
261
+ }
262
+ invokeHandler(handler, args) {
263
+ if (isArrayOfListeners(handler)) {
264
+ handler.slice().forEach((listener) => this.invokeHandler(listener, args));
265
+ } else {
266
+ switch (args.length) {
267
+ case 0:
268
+ handler();
269
+ break;
270
+ case 1:
271
+ handler(args[0]);
272
+ break;
273
+ case 2:
274
+ handler(args[0], args[1]);
275
+ break;
276
+ default:
277
+ handler.call(null, ...args);
278
+ }
279
+ }
280
+ }
281
+ };
282
+ _events = new WeakMap();
283
+
177
284
  // ../vuu-utils/src/keyset.ts
178
285
  var EMPTY = [];
179
286
  var KeySet = class {
180
287
  constructor(range) {
181
- this.keys = /* @__PURE__ */ new Map();
182
- this.nextKeyValue = 0;
288
+ __publicField(this, "keys", /* @__PURE__ */ new Map());
289
+ __publicField(this, "nextKeyValue", 0);
290
+ __publicField(this, "range");
183
291
  this.range = range;
184
292
  this.init(range);
185
293
  }
@@ -239,6 +347,38 @@ var KeySet = class {
239
347
  }
240
348
  };
241
349
 
350
+ // ../vuu-utils/src/promise-utils.ts
351
+ var _promise, _resolve, _reject, _resolved;
352
+ var DeferredPromise = class {
353
+ constructor() {
354
+ __privateAdd(this, _promise);
355
+ __privateAdd(this, _resolve, () => console.log("resolve was not set"));
356
+ __privateAdd(this, _reject, () => console.log("reject was not set"));
357
+ __privateAdd(this, _resolved, false);
358
+ __privateSet(this, _promise, new Promise((resolve, reject) => {
359
+ __privateSet(this, _resolve, resolve);
360
+ __privateSet(this, _reject, reject);
361
+ }));
362
+ }
363
+ get promise() {
364
+ return __privateGet(this, _promise);
365
+ }
366
+ get isResolved() {
367
+ return __privateGet(this, _resolved);
368
+ }
369
+ resolve(value) {
370
+ __privateSet(this, _resolved, true);
371
+ return __privateGet(this, _resolve).call(this, value);
372
+ }
373
+ get reject() {
374
+ return __privateGet(this, _reject);
375
+ }
376
+ };
377
+ _promise = new WeakMap();
378
+ _resolve = new WeakMap();
379
+ _reject = new WeakMap();
380
+ _resolved = new WeakMap();
381
+
242
382
  // ../vuu-utils/src/protocol-message-utils.ts
243
383
  var MENU_RPC_TYPES = [
244
384
  "VIEW_PORT_MENUS_SELECT_RPC",
@@ -411,7 +551,12 @@ var ArrayBackedMovingWindow = class {
411
551
  // Note, the buffer is already accounted for in the range passed in here
412
552
  constructor({ from: clientFrom, to: clientTo }, { from, to }, bufferSize) {
413
553
  __privateAdd(this, _range);
414
- this.setRowCount = (rowCount) => {
554
+ __publicField(this, "bufferSize");
555
+ __publicField(this, "internalData");
556
+ __publicField(this, "rowsWithinRange");
557
+ __publicField(this, "clientRange");
558
+ __publicField(this, "rowCount");
559
+ __publicField(this, "setRowCount", (rowCount) => {
415
560
  var _a;
416
561
  (_a = log.info) == null ? void 0 : _a.call(log, \`setRowCount \${rowCount}\`);
417
562
  if (rowCount < this.internalData.length) {
@@ -428,8 +573,8 @@ var ArrayBackedMovingWindow = class {
428
573
  }
429
574
  }
430
575
  this.rowCount = rowCount;
431
- };
432
- this.bufferBreakout = (from, to) => {
576
+ });
577
+ __publicField(this, "bufferBreakout", (from, to) => {
433
578
  const bufferPerimeter = this.bufferSize * 0.25;
434
579
  if (__privateGet(this, _range).to - to < bufferPerimeter) {
435
580
  return true;
@@ -438,7 +583,7 @@ var ArrayBackedMovingWindow = class {
438
583
  } else {
439
584
  return false;
440
585
  }
441
- };
586
+ });
442
587
  this.bufferSize = bufferSize;
443
588
  this.clientRange = new WindowRange(clientFrom, clientTo);
444
589
  __privateSet(this, _range, new WindowRange(from, to));
@@ -618,6 +763,7 @@ var NO_UPDATE_STATUS = {
618
763
  size: 0,
619
764
  ts: 0
620
765
  };
766
+ var _status;
621
767
  var Viewport = class {
622
768
  constructor({
623
769
  aggregations,
@@ -632,29 +778,50 @@ var Viewport = class {
632
778
  viewport,
633
779
  visualLink
634
780
  }, postMessageToClient) {
781
+ __privateAdd(this, _status, "");
782
+ __publicField(this, "aggregations");
635
783
  /** batchMode is irrelevant for Vuu Table, it was introduced to try and improve rendering performance of AgGrid */
636
- this.batchMode = true;
637
- this.hasUpdates = false;
638
- this.pendingUpdates = [];
639
- this.pendingOperations = /* @__PURE__ */ new Map();
640
- this.pendingRangeRequests = [];
641
- this.rowCountChanged = false;
642
- this.selectedRows = [];
643
- this.useBatchMode = true;
644
- this.lastUpdateStatus = NO_UPDATE_STATUS;
645
- this.updateThrottleTimer = void 0;
646
- this.rangeMonitor = new RangeMonitor("ViewPort");
647
- this.disabled = false;
648
- this.isTree = false;
784
+ __publicField(this, "batchMode", true);
785
+ __publicField(this, "bufferSize");
786
+ /**
787
+ * clientRange is always the range requested by the client. We should assume
788
+ * these are the rows visible to the user
789
+ */
790
+ __publicField(this, "clientRange");
791
+ __publicField(this, "columns");
792
+ __publicField(this, "dataWindow");
793
+ __publicField(this, "filter");
794
+ __publicField(this, "groupBy");
795
+ __publicField(this, "sort");
796
+ __publicField(this, "hasUpdates", false);
797
+ __publicField(this, "pendingUpdates", []);
798
+ __publicField(this, "keys");
799
+ __publicField(this, "pendingLinkedParent");
800
+ __publicField(this, "pendingOperations", /* @__PURE__ */ new Map());
801
+ __publicField(this, "pendingRangeRequests", []);
802
+ __publicField(this, "postMessageToClient");
803
+ __publicField(this, "rowCountChanged", false);
804
+ __publicField(this, "selectedRows", []);
805
+ __publicField(this, "useBatchMode", true);
806
+ __publicField(this, "lastUpdateStatus", NO_UPDATE_STATUS);
807
+ __publicField(this, "updateThrottleTimer");
808
+ __publicField(this, "rangeMonitor", new RangeMonitor("ViewPort"));
809
+ __publicField(this, "clientViewportId");
810
+ __publicField(this, "disabled", false);
811
+ __publicField(this, "isTree", false);
812
+ __publicField(this, "links");
813
+ __publicField(this, "linkedParent");
814
+ __publicField(this, "serverViewportId");
649
815
  // TODO roll disabled/suspended into status
650
- this.status = "";
651
- this.suspended = false;
652
- this.suspendTimer = null;
816
+ __publicField(this, "suspended", false);
817
+ __publicField(this, "suspendTimer", null);
818
+ __publicField(this, "table");
819
+ __publicField(this, "title");
653
820
  // Records SIZE only updates
654
- this.setLastSizeOnlyUpdateSize = (size) => {
821
+ __publicField(this, "setLastSizeOnlyUpdateSize", (size) => {
655
822
  this.lastUpdateStatus.size = size;
656
- };
657
- this.setLastUpdate = (mode) => {
823
+ });
824
+ __publicField(this, "setLastUpdate", (mode) => {
658
825
  const { ts: lastTS, mode: lastMode } = this.lastUpdateStatus;
659
826
  let elapsedTime = 0;
660
827
  if (lastMode === mode) {
@@ -669,8 +836,8 @@ var Viewport = class {
669
836
  }
670
837
  this.lastUpdateStatus.mode = mode;
671
838
  return elapsedTime;
672
- };
673
- this.rangeRequestAlreadyPending = (range) => {
839
+ });
840
+ __publicField(this, "rangeRequestAlreadyPending", (range) => {
674
841
  const { bufferSize } = this;
675
842
  const bufferThreshold = bufferSize * 0.25;
676
843
  let { from: stillPendingFrom } = range;
@@ -684,8 +851,8 @@ var Viewport = class {
684
851
  }
685
852
  }
686
853
  return false;
687
- };
688
- this.sendThrottledSizeMessage = () => {
854
+ });
855
+ __publicField(this, "sendThrottledSizeMessage", () => {
689
856
  this.updateThrottleTimer = void 0;
690
857
  this.lastUpdateStatus.count = 3;
691
858
  this.postMessageToClient({
@@ -694,15 +861,15 @@ var Viewport = class {
694
861
  size: this.lastUpdateStatus.size,
695
862
  type: "viewport-update"
696
863
  });
697
- };
864
+ });
698
865
  // If we are receiving multiple SIZE updates but no data, table is loading rows
699
866
  // outside of our viewport. We can safely throttle these requests. Doing so will
700
867
  // alleviate pressure on UI DataTable.
701
- this.shouldThrottleMessage = (mode) => {
868
+ __publicField(this, "shouldThrottleMessage", (mode) => {
702
869
  const elapsedTime = this.setLastUpdate(mode);
703
870
  return mode === "size-only" && elapsedTime > 0 && elapsedTime < 500 && this.lastUpdateStatus.count > 3;
704
- };
705
- this.throttleMessage = (mode) => {
871
+ });
872
+ __publicField(this, "throttleMessage", (mode) => {
706
873
  if (this.shouldThrottleMessage(mode)) {
707
874
  info == null ? void 0 : info("throttling updates setTimeout to 2000");
708
875
  if (this.updateThrottleTimer === void 0) {
@@ -717,13 +884,13 @@ var Viewport = class {
717
884
  this.updateThrottleTimer = void 0;
718
885
  }
719
886
  return false;
720
- };
721
- this.getNewRowCount = () => {
887
+ });
888
+ __publicField(this, "getNewRowCount", () => {
722
889
  if (this.rowCountChanged && this.dataWindow) {
723
890
  this.rowCountChanged = false;
724
891
  return this.dataWindow.rowCount;
725
892
  }
726
- };
893
+ });
727
894
  this.aggregations = aggregations;
728
895
  this.bufferSize = bufferSize;
729
896
  this.clientRange = range;
@@ -756,9 +923,15 @@ var Viewport = class {
756
923
  var _a;
757
924
  return (_a = this.dataWindow.rowCount) != null ? _a : 0;
758
925
  }
926
+ get status() {
927
+ return __privateGet(this, _status);
928
+ }
929
+ set status(status) {
930
+ __privateSet(this, _status, status);
931
+ }
759
932
  subscribe() {
760
933
  const { filter } = this.filter;
761
- this.status = this.status === "subscribed" ? "resubscribing" : "subscribing";
934
+ this.status = __privateGet(this, _status) === "subscribed" ? "resubscribing" : "subscribing";
762
935
  return {
763
936
  type: CREATE_VP,
764
937
  table: this.table,
@@ -1269,6 +1442,7 @@ var Viewport = class {
1269
1442
  }
1270
1443
  }
1271
1444
  };
1445
+ _status = new WeakMap();
1272
1446
  var toClientRow = ({ rowIndex, rowKey, sel: isSelected, data }, keys, selectedRows) => {
1273
1447
  return [
1274
1448
  rowIndex,
@@ -1321,36 +1495,56 @@ function addLabelsToLinks(links, viewports) {
1321
1495
  }
1322
1496
  var ServerProxy = class {
1323
1497
  constructor(connection, callback) {
1324
- this.authToken = "";
1325
- this.user = "user";
1326
- this.pendingRequests = /* @__PURE__ */ new Map();
1327
- this.queuedRequests = [];
1328
- this.cachedTableMetaRequests = /* @__PURE__ */ new Map();
1329
- this.cachedTableSchemas = /* @__PURE__ */ new Map();
1498
+ __publicField(this, "connection");
1499
+ __publicField(this, "postMessageToClient");
1500
+ __publicField(this, "viewports");
1501
+ __publicField(this, "mapClientToServerViewport");
1502
+ __publicField(this, "authToken", "");
1503
+ __publicField(this, "user", "user");
1504
+ __publicField(this, "pendingLogin");
1505
+ __publicField(this, "pendingRequests", /* @__PURE__ */ new Map());
1506
+ __publicField(this, "sessionId");
1507
+ __publicField(this, "queuedRequests", []);
1508
+ __publicField(this, "cachedTableMetaRequests", /* @__PURE__ */ new Map());
1509
+ __publicField(this, "cachedTableSchemas", /* @__PURE__ */ new Map());
1510
+ __publicField(this, "tableList");
1511
+ __publicField(this, "reconnect", async () => {
1512
+ await this.login(this.authToken);
1513
+ const [activeViewports, inactiveViewports] = partition(
1514
+ Array.from(this.viewports.values()),
1515
+ isActiveViewport
1516
+ );
1517
+ this.viewports.clear();
1518
+ this.mapClientToServerViewport.clear();
1519
+ const reconnectViewports = (viewports) => {
1520
+ viewports.forEach((viewport) => {
1521
+ const { clientViewportId } = viewport;
1522
+ this.awaitResponseToMessage(
1523
+ viewport.subscribe(),
1524
+ clientViewportId
1525
+ ).then((msg) => {
1526
+ if (msg.type === "CREATE_VP_SUCCESS") {
1527
+ this.mapClientToServerViewport.set(
1528
+ clientViewportId,
1529
+ msg.viewPortId
1530
+ );
1531
+ this.viewports.set(msg.viewPortId, viewport);
1532
+ viewport.status = "subscribed";
1533
+ viewport.serverViewportId = msg.viewPortId;
1534
+ }
1535
+ });
1536
+ });
1537
+ };
1538
+ reconnectViewports(activeViewports);
1539
+ setTimeout(() => {
1540
+ reconnectViewports(inactiveViewports);
1541
+ }, 2e3);
1542
+ });
1330
1543
  this.connection = connection;
1331
1544
  this.postMessageToClient = callback;
1332
1545
  this.viewports = /* @__PURE__ */ new Map();
1333
1546
  this.mapClientToServerViewport = /* @__PURE__ */ new Map();
1334
- }
1335
- async reconnect() {
1336
- await this.login(this.authToken);
1337
- const [activeViewports, inactiveViewports] = partition(
1338
- Array.from(this.viewports.values()),
1339
- isActiveViewport
1340
- );
1341
- this.viewports.clear();
1342
- this.mapClientToServerViewport.clear();
1343
- const reconnectViewports = (viewports) => {
1344
- viewports.forEach((viewport) => {
1345
- const { clientViewportId } = viewport;
1346
- this.viewports.set(clientViewportId, viewport);
1347
- this.sendMessageToServer(viewport.subscribe(), clientViewportId);
1348
- });
1349
- };
1350
- reconnectViewports(activeViewports);
1351
- setTimeout(() => {
1352
- reconnectViewports(inactiveViewports);
1353
- }, 2e3);
1547
+ connection.on("reconnected", this.reconnect);
1354
1548
  }
1355
1549
  async login(authToken, user = "user") {
1356
1550
  if (authToken) {
@@ -1367,6 +1561,16 @@ var ServerProxy = class {
1367
1561
  error2("login, cannot login until auth token has been obtained");
1368
1562
  }
1369
1563
  }
1564
+ disconnect() {
1565
+ this.viewports.forEach((viewport) => {
1566
+ const { clientViewportId } = viewport;
1567
+ this.unsubscribe(clientViewportId);
1568
+ this.postMessageToClient({
1569
+ clientViewportId,
1570
+ type: "viewport-clear"
1571
+ });
1572
+ });
1573
+ }
1370
1574
  subscribe(message) {
1371
1575
  if (!this.mapClientToServerViewport.has(message.viewport)) {
1372
1576
  const pendingTableSchema = this.getTableMeta(message.table);
@@ -1432,30 +1636,38 @@ var ServerProxy = class {
1432
1636
  error2(\`spurious subscribe call \${message.viewport}\`);
1433
1637
  }
1434
1638
  }
1639
+ /**
1640
+ * Currently we only queue range requests, this may change
1641
+ */
1642
+ addRequestToQueue(queuedRequest) {
1643
+ const isDifferentTypeViewport = (qr) => qr.clientViewportId !== queuedRequest.clientViewportId || queuedRequest.message.type !== qr.message.type;
1644
+ if (!this.queuedRequests.every(isDifferentTypeViewport)) {
1645
+ this.queuedRequests = this.queuedRequests.filter(isDifferentTypeViewport);
1646
+ }
1647
+ this.queuedRequests.push(queuedRequest);
1648
+ }
1435
1649
  processQueuedRequests() {
1436
- const messageTypesProcessed = {};
1437
- while (this.queuedRequests.length) {
1438
- const queuedRequest = this.queuedRequests.pop();
1439
- if (queuedRequest) {
1440
- const { clientViewportId, message, requestId } = queuedRequest;
1441
- if (message.type === "CHANGE_VP_RANGE") {
1442
- if (messageTypesProcessed.CHANGE_VP_RANGE) {
1443
- continue;
1444
- }
1445
- messageTypesProcessed.CHANGE_VP_RANGE = true;
1446
- const serverViewportId = this.mapClientToServerViewport.get(clientViewportId);
1447
- if (serverViewportId) {
1448
- this.sendMessageToServer(
1449
- {
1450
- ...message,
1451
- viewPortId: serverViewportId
1452
- },
1453
- requestId
1454
- );
1455
- }
1456
- }
1650
+ const newQueue = [];
1651
+ for (const queuedRequest of this.queuedRequests) {
1652
+ const { clientViewportId, message, requestId } = queuedRequest;
1653
+ const serverViewportId = this.mapClientToServerViewport.get(clientViewportId);
1654
+ if (serverViewportId) {
1655
+ this.sendMessageToServer(
1656
+ {
1657
+ ...message,
1658
+ viewPortId: serverViewportId
1659
+ },
1660
+ requestId
1661
+ );
1662
+ } else if (this.viewports.has(clientViewportId)) {
1663
+ newQueue.push(queuedRequest);
1664
+ } else {
1665
+ console.warn(
1666
+ \`ServerProxy processQueuedRequests, \${message.type} request not found \${clientViewportId}\`
1667
+ );
1457
1668
  }
1458
1669
  }
1670
+ this.queuedRequests = newQueue;
1459
1671
  }
1460
1672
  unsubscribe(clientViewportId) {
1461
1673
  const serverViewportId = this.mapClientToServerViewport.get(clientViewportId);
@@ -1506,36 +1718,33 @@ var ServerProxy = class {
1506
1718
  requestId,
1507
1719
  message.range
1508
1720
  );
1509
- info2 == null ? void 0 : info2(\`setViewRange \${message.range.from} - \${message.range.to}\`);
1510
- if (serverRequest) {
1511
- if (true) {
1512
- info2 == null ? void 0 : info2(
1513
- \`CHANGE_VP_RANGE [\${message.range.from}-\${message.range.to}] => [\${serverRequest.from}-\${serverRequest.to}]\`
1514
- );
1721
+ if (viewport.status === "subscribed") {
1722
+ info2 == null ? void 0 : info2(\`setViewRange \${message.range.from} - \${message.range.to}\`);
1723
+ if (serverRequest) {
1724
+ if (true) {
1725
+ info2 == null ? void 0 : info2(
1726
+ \`CHANGE_VP_RANGE [\${message.range.from}-\${message.range.to}] => [\${serverRequest.from}-\${serverRequest.to}]\`
1727
+ );
1728
+ }
1729
+ this.sendMessageToServer(serverRequest, requestId);
1515
1730
  }
1516
- const sentToServer = this.sendIfReady(
1517
- serverRequest,
1518
- requestId,
1519
- viewport.status === "subscribed"
1520
- );
1521
- if (!sentToServer) {
1522
- this.queuedRequests.push({
1523
- clientViewportId: message.viewport,
1524
- message: serverRequest,
1525
- requestId
1731
+ if (rows) {
1732
+ info2 == null ? void 0 : info2(\`setViewRange \${rows.length} rows returned from cache\`);
1733
+ this.postMessageToClient({
1734
+ mode: "batch",
1735
+ type: "viewport-update",
1736
+ clientViewportId: viewport.clientViewportId,
1737
+ rows
1526
1738
  });
1739
+ } else if (debounceRequest) {
1740
+ this.postMessageToClient(debounceRequest);
1527
1741
  }
1528
- }
1529
- if (rows) {
1530
- info2 == null ? void 0 : info2(\`setViewRange \${rows.length} rows returned from cache\`);
1531
- this.postMessageToClient({
1532
- mode: "batch",
1533
- type: "viewport-update",
1534
- clientViewportId: viewport.clientViewportId,
1535
- rows
1742
+ } else if (serverRequest) {
1743
+ this.addRequestToQueue({
1744
+ clientViewportId: message.viewport,
1745
+ message: serverRequest,
1746
+ requestId
1536
1747
  });
1537
- } else if (debounceRequest) {
1538
- this.postMessageToClient(debounceRequest);
1539
1748
  }
1540
1749
  }
1541
1750
  setConfig(viewport, message) {
@@ -1751,6 +1960,8 @@ var ServerProxy = class {
1751
1960
  );
1752
1961
  } else if (isVuuMenuRpcRequest(message)) {
1753
1962
  return this.menuRpcCall(message);
1963
+ } else if (message.type === "disconnect") {
1964
+ return this.disconnect();
1754
1965
  } else {
1755
1966
  const { type, requestId } = message;
1756
1967
  switch (type) {
@@ -2064,13 +2275,12 @@ var ServerProxy = class {
2064
2275
  }
2065
2276
  break;
2066
2277
  case "VIEW_PORT_MENU_REJ": {
2067
- console.log(\`send menu error back to client\`);
2068
- const { error: error4, rpcName, vpId } = body;
2278
+ const { error: error3, rpcName, vpId } = body;
2069
2279
  const viewport = this.viewports.get(vpId);
2070
2280
  if (viewport) {
2071
2281
  this.postMessageToClient({
2072
2282
  clientViewportId: viewport.clientViewportId,
2073
- error: error4,
2283
+ error: error3,
2074
2284
  rpcName,
2075
2285
  type: "VIEW_PORT_MENU_REJ",
2076
2286
  requestId
@@ -2198,233 +2408,291 @@ var ServerProxy = class {
2198
2408
  }
2199
2409
  };
2200
2410
 
2201
- // src/websocket-connection.ts
2202
- var { debug: debug4, debugEnabled: debugEnabled4, error: error3, info: info3, infoEnabled: infoEnabled3, warn: warn3 } = logger(
2203
- "websocket-connection"
2204
- );
2205
- var connectionAttemptStatus = {};
2206
- var setWebsocket = Symbol("setWebsocket");
2207
- var connectionCallback = Symbol("connectionCallback");
2208
- async function connect(connectionString, protocol, callback, retryLimitDisconnect = 10, retryLimitStartup = 5) {
2209
- connectionAttemptStatus[connectionString] = {
2210
- status: "connecting",
2211
- connect: {
2212
- allowed: retryLimitStartup,
2213
- remaining: retryLimitStartup
2214
- },
2215
- reconnect: {
2216
- allowed: retryLimitDisconnect,
2217
- remaining: retryLimitDisconnect
2218
- }
2219
- };
2220
- return makeConnection(connectionString, protocol, callback);
2221
- }
2222
- async function reconnect(_) {
2223
- throw Error("connection broken");
2224
- }
2225
- async function makeConnection(url, protocol, callback, connection) {
2226
- const {
2227
- status: currentStatus,
2228
- connect: connectStatus,
2229
- reconnect: reconnectStatus
2230
- } = connectionAttemptStatus[url];
2231
- const trackedStatus = currentStatus === "connecting" ? connectStatus : reconnectStatus;
2232
- try {
2233
- callback({ type: "connection-status", status: "connecting" });
2234
- const reconnecting = typeof connection !== "undefined";
2235
- const ws = await createWebsocket(url, protocol);
2236
- console.info(
2237
- "%c\u26A1 %cconnected",
2238
- "font-size: 24px;color: green;font-weight: bold;",
2239
- "color:green; font-size: 14px;"
2240
- );
2241
- if (connection !== void 0) {
2242
- connection[setWebsocket](ws);
2243
- }
2244
- const websocketConnection = connection != null ? connection : new WebsocketConnection(ws, url, protocol, callback);
2245
- const status = reconnecting ? "reconnected" : "connection-open-awaiting-session";
2246
- callback({ type: "connection-status", status });
2247
- websocketConnection.status = status;
2248
- trackedStatus.remaining = trackedStatus.allowed;
2249
- return websocketConnection;
2250
- } catch (err) {
2251
- const retry = --trackedStatus.remaining > 0;
2252
- callback({
2253
- type: "connection-status",
2254
- status: "disconnected",
2255
- reason: "failed to connect",
2256
- retry
2257
- });
2258
- if (retry) {
2259
- return makeConnectionIn(url, protocol, callback, connection, 2e3);
2260
- } else {
2261
- callback({
2262
- type: "connection-status",
2263
- status: "failed",
2264
- reason: "unable to connect",
2265
- retry
2266
- });
2267
- throw Error("Failed to establish connection");
2268
- }
2411
+ // src/WebSocketConnection.ts
2412
+ var isWebSocketConnectionMessage = (msg) => {
2413
+ if ("connectionStatus" in msg) {
2414
+ return [
2415
+ "connecting",
2416
+ "connected",
2417
+ "connection-open-awaiting-session",
2418
+ "reconnecting",
2419
+ "reconnected",
2420
+ "disconnected",
2421
+ "closed",
2422
+ "failed"
2423
+ ].includes(msg.connectionStatus);
2424
+ } else {
2425
+ return false;
2269
2426
  }
2270
- }
2271
- var makeConnectionIn = (url, protocol, callback, connection, delay) => new Promise((resolve) => {
2272
- setTimeout(() => {
2273
- resolve(makeConnection(url, protocol, callback, connection));
2274
- }, delay);
2275
- });
2276
- var createWebsocket = (websocketUrl, protocol) => new Promise((resolve, reject) => {
2277
- if (infoEnabled3 && protocol !== void 0) {
2278
- info3(\`WebSocket Protocol \${protocol == null ? void 0 : protocol.toString()}\`);
2279
- }
2280
- const ws = new WebSocket(websocketUrl, protocol);
2281
- ws.onopen = () => resolve(ws);
2282
- ws.onerror = (evt) => reject(evt);
2283
- });
2284
- var closeWarn = () => {
2285
- warn3 == null ? void 0 : warn3(\`Connection cannot be closed, socket not yet opened\`);
2286
2427
  };
2287
- var sendWarn = (msg) => {
2288
- warn3 == null ? void 0 : warn3(\`Message cannot be sent, socket closed \${msg.body.type}\`);
2428
+ var DEFAULT_RETRY_LIMITS = {
2429
+ connect: 5,
2430
+ reconnect: 8
2289
2431
  };
2290
- var parseMessage = (message) => {
2432
+ var DEFAULT_CONNECTION_TIMEOUT = 1e4;
2433
+ var ConnectingEndState = {
2434
+ connecting: "connected",
2435
+ reconnecting: "reconnected"
2436
+ };
2437
+ var parseWebSocketMessage = (message) => {
2291
2438
  try {
2292
2439
  return JSON.parse(message);
2293
2440
  } catch (e) {
2294
2441
  throw Error(\`Error parsing JSON response from server \${message}\`);
2295
2442
  }
2296
2443
  };
2297
- var WebsocketConnection = class {
2298
- constructor(ws, url, protocol, callback) {
2299
- this.close = closeWarn;
2300
- this.requiresLogin = true;
2301
- this.send = sendWarn;
2302
- this.status = "ready";
2303
- this.messagesCount = 0;
2304
- this.connectionMetricsInterval = null;
2305
- this.handleWebsocketMessage = (evt) => {
2306
- const vuuMessageFromServer = parseMessage(evt.data);
2307
- this.messagesCount += 1;
2308
- if (true) {
2309
- if (debugEnabled4 && vuuMessageFromServer.body.type !== "HB") {
2310
- debug4 == null ? void 0 : debug4(\`<<< \${vuuMessageFromServer.body.type}\`);
2311
- }
2312
- }
2313
- this[connectionCallback](vuuMessageFromServer);
2314
- };
2315
- this.url = url;
2316
- this.protocol = protocol;
2317
- this[connectionCallback] = callback;
2318
- this[setWebsocket](ws);
2444
+ var _callback, _confirmedOpen, _connectionState, _connectionTimeout, _deferredConnection, _protocols, _reconnectAttempts, _requiresLogin, _url, _ws;
2445
+ var WebSocketConnection = class extends EventEmitter {
2446
+ constructor({
2447
+ callback,
2448
+ connectionTimeout = DEFAULT_CONNECTION_TIMEOUT,
2449
+ protocols,
2450
+ retryLimits = DEFAULT_RETRY_LIMITS,
2451
+ url
2452
+ }) {
2453
+ super();
2454
+ __privateAdd(this, _callback);
2455
+ /**
2456
+ We are not confirmedOpen until we receive the first message from the
2457
+ server. If we get an unexpected close event before that, we consider
2458
+ the reconnect attempts as still within the connection phase, not true
2459
+ reconnection. This can happen e.g. when connecting to remote host via
2460
+ a proxy.
2461
+ */
2462
+ __privateAdd(this, _confirmedOpen, false);
2463
+ __privateAdd(this, _connectionState);
2464
+ __privateAdd(this, _connectionTimeout);
2465
+ __privateAdd(this, _deferredConnection);
2466
+ __privateAdd(this, _protocols);
2467
+ __privateAdd(this, _reconnectAttempts);
2468
+ __privateAdd(this, _requiresLogin, true);
2469
+ __privateAdd(this, _url);
2470
+ __privateAdd(this, _ws);
2471
+ __publicField(this, "receive", (evt) => {
2472
+ const vuuMessageFromServer = parseWebSocketMessage(evt.data);
2473
+ __privateGet(this, _callback).call(this, vuuMessageFromServer);
2474
+ });
2475
+ __publicField(this, "send", (msg) => {
2476
+ var _a;
2477
+ (_a = __privateGet(this, _ws)) == null ? void 0 : _a.send(JSON.stringify(msg));
2478
+ });
2479
+ __privateSet(this, _callback, callback);
2480
+ __privateSet(this, _connectionTimeout, connectionTimeout);
2481
+ __privateSet(this, _url, url);
2482
+ __privateSet(this, _protocols, protocols);
2483
+ __privateSet(this, _reconnectAttempts, {
2484
+ retryAttemptsTotal: retryLimits.reconnect,
2485
+ retryAttemptsRemaining: retryLimits.reconnect,
2486
+ secondsToNextRetry: 1
2487
+ });
2488
+ __privateSet(this, _connectionState, {
2489
+ connectionPhase: "connecting",
2490
+ connectionStatus: "closed",
2491
+ retryAttemptsTotal: retryLimits.connect,
2492
+ retryAttemptsRemaining: retryLimits.connect,
2493
+ secondsToNextRetry: 1
2494
+ });
2319
2495
  }
2320
- reconnect() {
2321
- reconnect(this);
2322
- }
2323
- [(connectionCallback, setWebsocket)](ws) {
2324
- const callback = this[connectionCallback];
2325
- ws.onmessage = (evt) => {
2326
- this.status = "connected";
2327
- ws.onmessage = this.handleWebsocketMessage;
2328
- this.handleWebsocketMessage(evt);
2329
- };
2330
- this.connectionMetricsInterval = setInterval(() => {
2331
- callback({
2332
- type: "connection-metrics",
2333
- messagesLength: this.messagesCount
2496
+ get connectionTimeout() {
2497
+ return __privateGet(this, _connectionTimeout);
2498
+ }
2499
+ get protocols() {
2500
+ return __privateGet(this, _protocols);
2501
+ }
2502
+ get requiresLogin() {
2503
+ return __privateGet(this, _requiresLogin);
2504
+ }
2505
+ get isClosed() {
2506
+ return this.status === "closed";
2507
+ }
2508
+ get isDisconnected() {
2509
+ return this.status === "disconnected";
2510
+ }
2511
+ get isConnecting() {
2512
+ return __privateGet(this, _connectionState).connectionPhase === "connecting";
2513
+ }
2514
+ get status() {
2515
+ return __privateGet(this, _connectionState).connectionStatus;
2516
+ }
2517
+ set status(connectionStatus) {
2518
+ __privateSet(this, _connectionState, {
2519
+ ...__privateGet(this, _connectionState),
2520
+ connectionStatus
2521
+ });
2522
+ this.emit("connection-status", __privateGet(this, _connectionState));
2523
+ }
2524
+ get connectionState() {
2525
+ return __privateGet(this, _connectionState);
2526
+ }
2527
+ get hasConnectionAttemptsRemaining() {
2528
+ return __privateGet(this, _connectionState).retryAttemptsRemaining > 0;
2529
+ }
2530
+ get confirmedOpen() {
2531
+ return __privateGet(this, _confirmedOpen);
2532
+ }
2533
+ /**
2534
+ * We are 'confirmedOpen' when we see the first message transmitted
2535
+ * from the server. This ensures that even if we have one or more
2536
+ * proxies in our route to the endPoint, all connections have been
2537
+ * opened successfully.
2538
+ * First time in here (on our initial successful connection) we switch
2539
+ * from 'connect' phase to 'reconnect' phase. We may have different
2540
+ * retry configurations for these two phases.
2541
+ */
2542
+ set confirmedOpen(confirmedOpen) {
2543
+ __privateSet(this, _confirmedOpen, confirmedOpen);
2544
+ if (confirmedOpen && this.isConnecting) {
2545
+ __privateSet(this, _connectionState, {
2546
+ ...__privateGet(this, _connectionState),
2547
+ connectionPhase: "reconnecting",
2548
+ ...__privateGet(this, _reconnectAttempts)
2334
2549
  });
2335
- this.messagesCount = 0;
2336
- }, 2e3);
2337
- ws.onerror = () => {
2338
- error3(\`\u26A1 connection error\`);
2339
- callback({
2340
- type: "connection-status",
2341
- status: "disconnected",
2342
- reason: "error"
2550
+ } else if (confirmedOpen) {
2551
+ __privateSet(this, _connectionState, {
2552
+ ...__privateGet(this, _connectionState),
2553
+ ...__privateGet(this, _reconnectAttempts)
2343
2554
  });
2344
- if (this.connectionMetricsInterval) {
2345
- clearInterval(this.connectionMetricsInterval);
2346
- this.connectionMetricsInterval = null;
2555
+ }
2556
+ }
2557
+ get url() {
2558
+ return __privateGet(this, _url);
2559
+ }
2560
+ async connect(clientCall = true) {
2561
+ var _a;
2562
+ const state = __privateGet(this, _connectionState);
2563
+ if (this.isConnecting && __privateGet(this, _deferredConnection) === void 0) {
2564
+ __privateSet(this, _deferredConnection, new DeferredPromise());
2565
+ }
2566
+ const { connectionTimeout, protocols, url } = this;
2567
+ this.status = state.connectionPhase;
2568
+ const timer = setTimeout(() => {
2569
+ throw Error(
2570
+ \`Failed to open WebSocket connection to \${url}, timed out after \${connectionTimeout}ms\`
2571
+ );
2572
+ }, connectionTimeout);
2573
+ const ws2 = __privateSet(this, _ws, new WebSocket(url, protocols));
2574
+ ws2.onopen = () => {
2575
+ const connectedStatus = ConnectingEndState[state.connectionPhase];
2576
+ this.status = connectedStatus;
2577
+ clearTimeout(timer);
2578
+ if (__privateGet(this, _deferredConnection)) {
2579
+ __privateGet(this, _deferredConnection).resolve(void 0);
2580
+ __privateSet(this, _deferredConnection, void 0);
2347
2581
  }
2348
- if (this.status === "connection-open-awaiting-session") {
2349
- error3(
2350
- \`Websocket connection lost before Vuu session established, check websocket configuration\`
2351
- );
2352
- } else if (this.status !== "closed") {
2353
- reconnect(this);
2354
- this.send = queue;
2582
+ if (this.isConnecting) {
2583
+ this.emit("connected");
2584
+ } else {
2585
+ this.emit("reconnected");
2355
2586
  }
2356
2587
  };
2357
- ws.onclose = () => {
2358
- info3 == null ? void 0 : info3(\`\u26A1 connection close\`);
2359
- callback({
2360
- type: "connection-status",
2361
- status: "disconnected",
2362
- reason: "close"
2363
- });
2364
- if (this.connectionMetricsInterval) {
2365
- clearInterval(this.connectionMetricsInterval);
2366
- this.connectionMetricsInterval = null;
2367
- }
2368
- if (this.status !== "closed") {
2369
- reconnect(this);
2370
- this.send = queue;
2371
- }
2588
+ ws2.onerror = () => {
2589
+ clearTimeout(timer);
2372
2590
  };
2373
- const send = (msg) => {
2374
- if (true) {
2375
- if (debugEnabled4 && msg.body.type !== "HB_RESP") {
2376
- debug4 == null ? void 0 : debug4(\`>>> \${msg.body.type}\`);
2591
+ ws2.onclose = () => {
2592
+ if (!this.isClosed) {
2593
+ this.confirmedOpen = false;
2594
+ this.status = "disconnected";
2595
+ if (this.hasConnectionAttemptsRemaining) {
2596
+ this.reconnect();
2597
+ } else {
2598
+ this.close("failure");
2377
2599
  }
2378
2600
  }
2379
- ws.send(JSON.stringify(msg));
2380
2601
  };
2381
- const queue = (msg) => {
2382
- info3 == null ? void 0 : info3(\`TODO queue message until websocket reconnected \${msg.body.type}\`);
2383
- };
2384
- this.send = send;
2385
- this.close = () => {
2386
- this.status = "closed";
2387
- ws.close();
2388
- this.close = closeWarn;
2389
- this.send = sendWarn;
2390
- info3 == null ? void 0 : info3("close websocket");
2602
+ ws2.onmessage = (evt) => {
2603
+ if (!this.confirmedOpen) {
2604
+ this.confirmedOpen = true;
2605
+ }
2606
+ this.receive(evt);
2391
2607
  };
2608
+ if (clientCall) {
2609
+ return (_a = __privateGet(this, _deferredConnection)) == null ? void 0 : _a.promise;
2610
+ }
2611
+ }
2612
+ reconnect() {
2613
+ const { retryAttemptsRemaining, secondsToNextRetry } = __privateGet(this, _connectionState);
2614
+ setTimeout(() => {
2615
+ __privateSet(this, _connectionState, {
2616
+ ...__privateGet(this, _connectionState),
2617
+ retryAttemptsRemaining: retryAttemptsRemaining - 1,
2618
+ secondsToNextRetry: secondsToNextRetry * 2
2619
+ });
2620
+ this.connect(false);
2621
+ }, secondsToNextRetry * 1e3);
2622
+ }
2623
+ close(reason = "shutdown") {
2624
+ var _a;
2625
+ this.status = "closed";
2626
+ if (reason === "failure") {
2627
+ if (__privateGet(this, _deferredConnection)) {
2628
+ __privateGet(this, _deferredConnection).reject(Error("connection failed"));
2629
+ __privateSet(this, _deferredConnection, void 0);
2630
+ }
2631
+ } else {
2632
+ (_a = __privateGet(this, _ws)) == null ? void 0 : _a.close();
2633
+ }
2634
+ this.emit("closed", reason);
2635
+ __privateSet(this, _ws, void 0);
2392
2636
  }
2393
2637
  };
2638
+ _callback = new WeakMap();
2639
+ _confirmedOpen = new WeakMap();
2640
+ _connectionState = new WeakMap();
2641
+ _connectionTimeout = new WeakMap();
2642
+ _deferredConnection = new WeakMap();
2643
+ _protocols = new WeakMap();
2644
+ _reconnectAttempts = new WeakMap();
2645
+ _requiresLogin = new WeakMap();
2646
+ _url = new WeakMap();
2647
+ _ws = new WeakMap();
2394
2648
 
2395
2649
  // src/worker.ts
2396
2650
  var server;
2397
- var { info: info4, infoEnabled: infoEnabled4 } = logger("worker");
2398
- async function connectToServer(url, protocol, token, username, onConnectionStatusChange, retryLimitDisconnect, retryLimitStartup) {
2399
- const connection = await connect(
2400
- url,
2401
- protocol,
2402
- // if this was called during connect, we would get a ReferenceError, but it will
2403
- // never be called until subscriptions have been made, so this is safe.
2404
- //TODO do we need to listen in to the connection messages here so we can lock back in, in the event of a reconnenct ?
2405
- (msg) => {
2651
+ var { info: info3, infoEnabled: infoEnabled3 } = logger("worker");
2652
+ var getRetryLimits = (retryLimitDisconnect, retryLimitStartup) => {
2653
+ if (retryLimitDisconnect !== void 0 && retryLimitStartup !== void 0) {
2654
+ return {
2655
+ connect: retryLimitStartup,
2656
+ reconnect: retryLimitDisconnect
2657
+ };
2658
+ } else if (retryLimitDisconnect !== void 0) {
2659
+ return {
2660
+ connect: retryLimitDisconnect,
2661
+ reconnect: retryLimitDisconnect
2662
+ };
2663
+ } else if (retryLimitStartup !== void 0) {
2664
+ return {
2665
+ connect: retryLimitStartup,
2666
+ reconnect: retryLimitStartup
2667
+ };
2668
+ }
2669
+ };
2670
+ var ws;
2671
+ var sendMessageToClient = (message) => {
2672
+ postMessage(message);
2673
+ };
2674
+ async function connectToServer(url, protocols, token, username, retryLimitDisconnect, retryLimitStartup) {
2675
+ const websocketConnection = ws = new WebSocketConnection({
2676
+ callback: (msg) => {
2406
2677
  if (isConnectionQualityMetrics(msg)) {
2407
2678
  postMessage({ type: "connection-metrics", messages: msg });
2408
- } else if (isConnectionStatusMessage(msg)) {
2409
- onConnectionStatusChange(msg);
2410
- if (msg.status === "reconnected") {
2411
- server.reconnect();
2412
- }
2679
+ } else if (isWebSocketConnectionMessage(msg)) {
2680
+ postMessage(msg);
2413
2681
  } else {
2414
2682
  server.handleMessageFromServer(msg);
2415
2683
  }
2416
2684
  },
2417
- retryLimitDisconnect,
2418
- retryLimitStartup
2419
- );
2420
- server = new ServerProxy(connection, (msg) => sendMessageToClient(msg));
2421
- if (connection.requiresLogin) {
2685
+ protocols,
2686
+ retryLimits: getRetryLimits(retryLimitStartup, retryLimitDisconnect),
2687
+ url
2688
+ });
2689
+ websocketConnection.on("connection-status", postMessage);
2690
+ await websocketConnection.connect();
2691
+ server = new ServerProxy(websocketConnection, sendMessageToClient);
2692
+ if (websocketConnection.requiresLogin) {
2422
2693
  await server.login(token, username);
2423
2694
  }
2424
2695
  }
2425
- function sendMessageToClient(message) {
2426
- postMessage(message);
2427
- }
2428
2696
  var handleMessageFromClient = async ({
2429
2697
  data: message
2430
2698
  }) => {
@@ -2436,7 +2704,6 @@ var handleMessageFromClient = async ({
2436
2704
  message.protocol,
2437
2705
  message.token,
2438
2706
  message.username,
2439
- postMessage,
2440
2707
  message.retryLimitDisconnect,
2441
2708
  message.retryLimitStartup
2442
2709
  );
@@ -2445,16 +2712,20 @@ var handleMessageFromClient = async ({
2445
2712
  postMessage({ type: "connection-failed", reason: String(err) });
2446
2713
  }
2447
2714
  break;
2715
+ case "disconnect":
2716
+ server.disconnect();
2717
+ ws == null ? void 0 : ws.close();
2718
+ break;
2448
2719
  case "subscribe":
2449
- infoEnabled4 && info4(\`client subscribe: \${JSON.stringify(message)}\`);
2720
+ infoEnabled3 && info3(\`client subscribe: \${JSON.stringify(message)}\`);
2450
2721
  server.subscribe(message);
2451
2722
  break;
2452
2723
  case "unsubscribe":
2453
- infoEnabled4 && info4(\`client unsubscribe: \${JSON.stringify(message)}\`);
2724
+ infoEnabled3 && info3(\`client unsubscribe: \${JSON.stringify(message)}\`);
2454
2725
  server.unsubscribe(message.viewport);
2455
2726
  break;
2456
2727
  default:
2457
- infoEnabled4 && info4(\`client message: \${JSON.stringify(message)}\`);
2728
+ infoEnabled3 && info3(\`client message: \${JSON.stringify(message)}\`);
2458
2729
  server.handleMessageFromClient(message);
2459
2730
  }
2460
2731
  };