@fluxstack/live-client 0.1.0 → 0.3.0

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.
package/dist/index.js CHANGED
@@ -6,6 +6,8 @@ var LiveConnection = class {
6
6
  reconnectTimeout = null;
7
7
  heartbeatInterval = null;
8
8
  componentCallbacks = /* @__PURE__ */ new Map();
9
+ binaryCallbacks = /* @__PURE__ */ new Map();
10
+ roomBinaryHandlers = /* @__PURE__ */ new Set();
9
11
  pendingRequests = /* @__PURE__ */ new Map();
10
12
  stateListeners = /* @__PURE__ */ new Set();
11
13
  _state = {
@@ -86,6 +88,7 @@ var LiveConnection = class {
86
88
  this.log("Connecting...", { url });
87
89
  try {
88
90
  const ws = new WebSocket(url);
91
+ ws.binaryType = "arraybuffer";
89
92
  this.ws = ws;
90
93
  ws.onopen = () => {
91
94
  this.log("Connected");
@@ -94,19 +97,34 @@ var LiveConnection = class {
94
97
  this.startHeartbeat();
95
98
  };
96
99
  ws.onmessage = (event) => {
100
+ if (event.data instanceof ArrayBuffer) {
101
+ this.handleBinaryMessage(new Uint8Array(event.data));
102
+ return;
103
+ }
97
104
  try {
98
- const response = JSON.parse(event.data);
99
- this.log("Received", { type: response.type, componentId: response.componentId });
100
- this.handleMessage(response);
105
+ const parsed = JSON.parse(event.data);
106
+ if (Array.isArray(parsed)) {
107
+ for (const msg of parsed) {
108
+ this.log("Received", { type: msg.type, componentId: msg.componentId });
109
+ this.handleMessage(msg);
110
+ }
111
+ } else {
112
+ this.log("Received", { type: parsed.type, componentId: parsed.componentId });
113
+ this.handleMessage(parsed);
114
+ }
101
115
  } catch {
102
116
  this.log("Failed to parse message");
103
117
  this.setState({ error: "Failed to parse message" });
104
118
  }
105
119
  };
106
- ws.onclose = () => {
107
- this.log("Disconnected");
120
+ ws.onclose = (event) => {
121
+ this.log("Disconnected", { code: event.code, reason: event.reason });
108
122
  this.setState({ connected: false, connecting: false, connectionId: null });
109
123
  this.stopHeartbeat();
124
+ if (event.code === 4003) {
125
+ this.setState({ error: "Connection rejected: origin not allowed" });
126
+ return;
127
+ }
110
128
  this.attemptReconnect();
111
129
  };
112
130
  ws.onerror = () => {
@@ -281,6 +299,37 @@ var LiveConnection = class {
281
299
  }
282
300
  });
283
301
  }
302
+ /** Parse and route binary frames (state delta, room events, room state) */
303
+ handleBinaryMessage(buffer) {
304
+ if (buffer.length < 3) return;
305
+ const frameType = buffer[0];
306
+ if (frameType === 1) {
307
+ const idLen = buffer[1];
308
+ if (buffer.length < 2 + idLen) return;
309
+ const componentId = new TextDecoder().decode(buffer.subarray(2, 2 + idLen));
310
+ const payload = buffer.subarray(2 + idLen);
311
+ const callback = this.binaryCallbacks.get(componentId);
312
+ if (callback) callback(payload);
313
+ } else if (frameType === 2 || frameType === 3) {
314
+ for (const callback of this.roomBinaryHandlers) {
315
+ callback(buffer);
316
+ }
317
+ }
318
+ }
319
+ /** Register a handler for binary room frames (0x02 / 0x03). Returns unsubscribe. */
320
+ registerRoomBinaryHandler(callback) {
321
+ this.roomBinaryHandlers.add(callback);
322
+ return () => {
323
+ this.roomBinaryHandlers.delete(callback);
324
+ };
325
+ }
326
+ /** Register a binary message handler for a component */
327
+ registerBinaryHandler(componentId, callback) {
328
+ this.binaryCallbacks.set(componentId, callback);
329
+ return () => {
330
+ this.binaryCallbacks.delete(componentId);
331
+ };
332
+ }
284
333
  /** Register a component message callback */
285
334
  registerComponent(componentId, callback) {
286
335
  this.log("Registering component", componentId);
@@ -316,6 +365,8 @@ var LiveConnection = class {
316
365
  destroy() {
317
366
  this.disconnect();
318
367
  this.componentCallbacks.clear();
368
+ this.binaryCallbacks.clear();
369
+ this.roomBinaryHandlers.clear();
319
370
  for (const [, req] of this.pendingRequests) {
320
371
  clearTimeout(req.timeout);
321
372
  req.reject(new Error("Connection destroyed"));
@@ -326,6 +377,25 @@ var LiveConnection = class {
326
377
  };
327
378
 
328
379
  // src/component.ts
380
+ function isPlainObject(v) {
381
+ return v !== null && typeof v === "object" && !Array.isArray(v) && Object.getPrototypeOf(v) === Object.prototype;
382
+ }
383
+ function deepMerge(target, source, seen) {
384
+ if (!seen) seen = /* @__PURE__ */ new Set();
385
+ if (seen.has(source)) return target;
386
+ seen.add(source);
387
+ const result = { ...target };
388
+ for (const key of Object.keys(source)) {
389
+ const newVal = source[key];
390
+ const oldVal = result[key];
391
+ if (isPlainObject(oldVal) && isPlainObject(newVal)) {
392
+ result[key] = deepMerge(oldVal, newVal, seen);
393
+ } else {
394
+ result[key] = newVal;
395
+ }
396
+ }
397
+ return result;
398
+ }
329
399
  var LiveComponentHandle = class {
330
400
  connection;
331
401
  componentName;
@@ -474,6 +544,21 @@ var LiveComponentHandle = class {
474
544
  }
475
545
  return response.result;
476
546
  }
547
+ /**
548
+ * Fire an action without waiting for a response (fire-and-forget).
549
+ * Useful for high-frequency operations like game input where the
550
+ * server doesn't need to send back a result.
551
+ */
552
+ fire(action, payload = {}) {
553
+ if (!this._mounted || !this._componentId) return;
554
+ this.connection.sendMessage({
555
+ type: "CALL_ACTION",
556
+ componentId: this._componentId,
557
+ action,
558
+ payload,
559
+ expectResponse: false
560
+ });
561
+ }
477
562
  // ── State ──
478
563
  /**
479
564
  * Subscribe to state changes.
@@ -486,6 +571,26 @@ var LiveComponentHandle = class {
486
571
  this.stateListeners.delete(callback);
487
572
  };
488
573
  }
574
+ /**
575
+ * Register a binary decoder for this component.
576
+ * When the server sends a BINARY_STATE_DELTA frame targeting this component,
577
+ * the decoder converts the raw payload into a delta object which is merged into state.
578
+ * Returns an unsubscribe function.
579
+ */
580
+ setBinaryDecoder(decoder) {
581
+ if (!this._componentId) {
582
+ throw new Error("Component must be mounted before setting binary decoder");
583
+ }
584
+ return this.connection.registerBinaryHandler(this._componentId, (payload) => {
585
+ try {
586
+ const delta = decoder(payload);
587
+ this._state = deepMerge(this._state, delta);
588
+ this.notifyStateChange(this._state, delta);
589
+ } catch (e) {
590
+ console.error("Binary decode error:", e);
591
+ }
592
+ });
593
+ }
489
594
  /**
490
595
  * Subscribe to errors.
491
596
  * Returns an unsubscribe function.
@@ -502,7 +607,7 @@ var LiveComponentHandle = class {
502
607
  case "STATE_UPDATE": {
503
608
  const newState = msg.payload?.state;
504
609
  if (newState) {
505
- this._state = { ...this._state, ...newState };
610
+ this._state = deepMerge(this._state, newState);
506
611
  this.notifyStateChange(this._state, null);
507
612
  }
508
613
  break;
@@ -510,7 +615,7 @@ var LiveComponentHandle = class {
510
615
  case "STATE_DELTA": {
511
616
  const delta = msg.payload?.delta;
512
617
  if (delta) {
513
- this._state = { ...this._state, ...delta };
618
+ this._state = deepMerge(this._state, delta);
514
619
  this.notifyStateChange(this._state, delta);
515
620
  }
516
621
  break;
@@ -552,6 +657,180 @@ var LiveComponentHandle = class {
552
657
  };
553
658
 
554
659
  // src/rooms.ts
660
+ function isPlainObject2(v) {
661
+ return v !== null && typeof v === "object" && !Array.isArray(v) && Object.getPrototypeOf(v) === Object.prototype;
662
+ }
663
+ function deepMerge2(target, source, seen) {
664
+ if (!seen) seen = /* @__PURE__ */ new Set();
665
+ if (seen.has(source)) return target;
666
+ seen.add(source);
667
+ const result = { ...target };
668
+ for (const key of Object.keys(source)) {
669
+ const newVal = source[key];
670
+ const oldVal = result[key];
671
+ if (isPlainObject2(oldVal) && isPlainObject2(newVal)) {
672
+ result[key] = deepMerge2(oldVal, newVal, seen);
673
+ } else {
674
+ result[key] = newVal;
675
+ }
676
+ }
677
+ return result;
678
+ }
679
+ var BINARY_ROOM_EVENT = 2;
680
+ var BINARY_ROOM_STATE = 3;
681
+ var _decoder = new TextDecoder();
682
+ function msgpackDecode(buf) {
683
+ return _decodeAt(buf, 0).value;
684
+ }
685
+ function _decodeAt(buf, offset) {
686
+ if (offset >= buf.length) return { value: null, offset };
687
+ const byte = buf[offset];
688
+ const view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
689
+ if (byte < 128) return { value: byte, offset: offset + 1 };
690
+ if (byte >= 128 && byte <= 143) return _decodeMap(buf, offset + 1, byte & 15);
691
+ if (byte >= 144 && byte <= 159) return _decodeArr(buf, offset + 1, byte & 15);
692
+ if (byte >= 160 && byte <= 191) {
693
+ const len = byte & 31;
694
+ return { value: _decoder.decode(buf.subarray(offset + 1, offset + 1 + len)), offset: offset + 1 + len };
695
+ }
696
+ if (byte >= 224) return { value: byte - 256, offset: offset + 1 };
697
+ switch (byte) {
698
+ case 192:
699
+ return { value: null, offset: offset + 1 };
700
+ case 194:
701
+ return { value: false, offset: offset + 1 };
702
+ case 195:
703
+ return { value: true, offset: offset + 1 };
704
+ case 196: {
705
+ const l = buf[offset + 1];
706
+ return { value: buf.slice(offset + 2, offset + 2 + l), offset: offset + 2 + l };
707
+ }
708
+ case 197: {
709
+ const l = view.getUint16(offset + 1, false);
710
+ return { value: buf.slice(offset + 3, offset + 3 + l), offset: offset + 3 + l };
711
+ }
712
+ case 198: {
713
+ const l = view.getUint32(offset + 1, false);
714
+ return { value: buf.slice(offset + 5, offset + 5 + l), offset: offset + 5 + l };
715
+ }
716
+ case 203:
717
+ return { value: view.getFloat64(offset + 1, false), offset: offset + 9 };
718
+ case 204:
719
+ return { value: buf[offset + 1], offset: offset + 2 };
720
+ case 205:
721
+ return { value: view.getUint16(offset + 1, false), offset: offset + 3 };
722
+ case 206:
723
+ return { value: view.getUint32(offset + 1, false), offset: offset + 5 };
724
+ case 208:
725
+ return { value: view.getInt8(offset + 1), offset: offset + 2 };
726
+ case 209:
727
+ return { value: view.getInt16(offset + 1, false), offset: offset + 3 };
728
+ case 210:
729
+ return { value: view.getInt32(offset + 1, false), offset: offset + 5 };
730
+ case 217: {
731
+ const l = buf[offset + 1];
732
+ return { value: _decoder.decode(buf.subarray(offset + 2, offset + 2 + l)), offset: offset + 2 + l };
733
+ }
734
+ case 218: {
735
+ const l = view.getUint16(offset + 1, false);
736
+ return { value: _decoder.decode(buf.subarray(offset + 3, offset + 3 + l)), offset: offset + 3 + l };
737
+ }
738
+ case 219: {
739
+ const l = view.getUint32(offset + 1, false);
740
+ return { value: _decoder.decode(buf.subarray(offset + 5, offset + 5 + l)), offset: offset + 5 + l };
741
+ }
742
+ case 220:
743
+ return _decodeArr(buf, offset + 3, view.getUint16(offset + 1, false));
744
+ case 221:
745
+ return _decodeArr(buf, offset + 5, view.getUint32(offset + 1, false));
746
+ case 222:
747
+ return _decodeMap(buf, offset + 3, view.getUint16(offset + 1, false));
748
+ case 223:
749
+ return _decodeMap(buf, offset + 5, view.getUint32(offset + 1, false));
750
+ }
751
+ return { value: null, offset: offset + 1 };
752
+ }
753
+ function _decodeArr(buf, offset, count) {
754
+ const arr = new Array(count);
755
+ for (let i = 0; i < count; i++) {
756
+ const r = _decodeAt(buf, offset);
757
+ arr[i] = r.value;
758
+ offset = r.offset;
759
+ }
760
+ return { value: arr, offset };
761
+ }
762
+ function _decodeMap(buf, offset, count) {
763
+ const obj = {};
764
+ for (let i = 0; i < count; i++) {
765
+ const k = _decodeAt(buf, offset);
766
+ offset = k.offset;
767
+ const v = _decodeAt(buf, offset);
768
+ offset = v.offset;
769
+ obj[String(k.value)] = v.value;
770
+ }
771
+ return { value: obj, offset };
772
+ }
773
+ function parseRoomFrame(buf) {
774
+ if (buf.length < 6) return null;
775
+ let offset = 0;
776
+ const frameType = buf[offset++];
777
+ const compIdLen = buf[offset++];
778
+ if (offset + compIdLen > buf.length) return null;
779
+ const componentId = _decoder.decode(buf.subarray(offset, offset + compIdLen));
780
+ offset += compIdLen;
781
+ const roomIdLen = buf[offset++];
782
+ if (offset + roomIdLen > buf.length) return null;
783
+ const roomId = _decoder.decode(buf.subarray(offset, offset + roomIdLen));
784
+ offset += roomIdLen;
785
+ if (offset + 2 > buf.length) return null;
786
+ const eventLen = buf[offset] << 8 | buf[offset + 1];
787
+ offset += 2;
788
+ if (offset + eventLen > buf.length) return null;
789
+ const event = _decoder.decode(buf.subarray(offset, offset + eventLen));
790
+ offset += eventLen;
791
+ return { frameType, componentId, roomId, event, payload: buf.subarray(offset) };
792
+ }
793
+ var ROOM_RESERVED_KEYS = /* @__PURE__ */ new Set([
794
+ "id",
795
+ "joined",
796
+ "state",
797
+ "join",
798
+ "leave",
799
+ "emit",
800
+ "on",
801
+ "onSystem",
802
+ "setState",
803
+ "call",
804
+ "apply",
805
+ "bind",
806
+ "prototype",
807
+ "length",
808
+ "name",
809
+ "arguments",
810
+ "caller",
811
+ Symbol.toPrimitive,
812
+ Symbol.toStringTag,
813
+ Symbol.hasInstance
814
+ ]);
815
+ function wrapWithStateProxy(target, getState, setStateFn) {
816
+ return new Proxy(target, {
817
+ get(obj, prop, receiver) {
818
+ if (ROOM_RESERVED_KEYS.has(prop) || typeof prop === "symbol") {
819
+ return Reflect.get(obj, prop, receiver);
820
+ }
821
+ const desc = Object.getOwnPropertyDescriptor(obj, prop);
822
+ if (desc) return Reflect.get(obj, prop, receiver);
823
+ if (prop in obj) return Reflect.get(obj, prop, receiver);
824
+ const st = getState();
825
+ return st?.[prop];
826
+ },
827
+ set(_obj, prop, value) {
828
+ if (typeof prop === "symbol") return false;
829
+ setStateFn({ [prop]: value });
830
+ return true;
831
+ }
832
+ });
833
+ }
555
834
  var RoomManager = class {
556
835
  componentId;
557
836
  defaultRoom;
@@ -560,12 +839,29 @@ var RoomManager = class {
560
839
  sendMessage;
561
840
  sendMessageAndWait;
562
841
  globalUnsubscribe = null;
842
+ binaryUnsubscribe = null;
843
+ onBinaryMessage = null;
844
+ onMessageFactory = null;
563
845
  constructor(options) {
564
846
  this.componentId = options.componentId;
565
847
  this.defaultRoom = options.defaultRoom || null;
566
848
  this.sendMessage = options.sendMessage;
567
849
  this.sendMessageAndWait = options.sendMessageAndWait;
850
+ this.onBinaryMessage = options.onBinaryMessage ?? null;
851
+ this.onMessageFactory = options.onMessage;
568
852
  this.globalUnsubscribe = options.onMessage((msg) => this.handleServerMessage(msg));
853
+ if (options.onBinaryMessage) {
854
+ this.binaryUnsubscribe = options.onBinaryMessage((frame) => this.handleBinaryFrame(frame));
855
+ }
856
+ }
857
+ /** Re-subscribe message and binary handlers (needed after destroy/remount in React Strict Mode) */
858
+ resubscribe() {
859
+ if (!this.globalUnsubscribe && this.onMessageFactory) {
860
+ this.globalUnsubscribe = this.onMessageFactory((msg) => this.handleServerMessage(msg));
861
+ }
862
+ if (!this.binaryUnsubscribe && this.onBinaryMessage) {
863
+ this.binaryUnsubscribe = this.onBinaryMessage((frame) => this.handleBinaryFrame(frame));
864
+ }
569
865
  }
570
866
  handleServerMessage(msg) {
571
867
  if (msg.componentId !== this.componentId) return;
@@ -587,10 +883,11 @@ var RoomManager = class {
587
883
  break;
588
884
  }
589
885
  case "ROOM_STATE": {
590
- room.state = { ...room.state, ...msg.data };
886
+ const stateChanges = msg.data?.state ?? msg.data;
887
+ room.state = deepMerge2(room.state, stateChanges);
591
888
  const stateHandlers = room.handlers.get("$state:change");
592
889
  if (stateHandlers) {
593
- for (const handler of stateHandlers) handler(msg.data);
890
+ for (const handler of stateHandlers) handler(stateChanges);
594
891
  }
595
892
  break;
596
893
  }
@@ -603,6 +900,34 @@ var RoomManager = class {
603
900
  break;
604
901
  }
605
902
  }
903
+ /** Handle binary room frames (0x02 ROOM_EVENT, 0x03 ROOM_STATE) */
904
+ handleBinaryFrame(frame) {
905
+ const parsed = parseRoomFrame(frame);
906
+ if (!parsed) return;
907
+ if (parsed.componentId !== this.componentId) return;
908
+ const room = this.rooms.get(parsed.roomId);
909
+ if (!room) return;
910
+ const data = msgpackDecode(parsed.payload);
911
+ if (parsed.frameType === BINARY_ROOM_EVENT) {
912
+ const handlers = room.handlers.get(parsed.event);
913
+ if (handlers) {
914
+ for (const handler of handlers) {
915
+ try {
916
+ handler(data);
917
+ } catch (error) {
918
+ console.error(`[Room:${parsed.roomId}] Handler error for '${parsed.event}':`, error);
919
+ }
920
+ }
921
+ }
922
+ } else if (parsed.frameType === BINARY_ROOM_STATE) {
923
+ const stateChanges = data?.state ?? data;
924
+ room.state = deepMerge2(room.state, stateChanges);
925
+ const stateHandlers = room.handlers.get("$state:change");
926
+ if (stateHandlers) {
927
+ for (const handler of stateHandlers) handler(stateChanges);
928
+ }
929
+ }
930
+ }
606
931
  getOrCreateRoom(roomId) {
607
932
  if (!this.rooms.has(roomId)) {
608
933
  this.rooms.set(roomId, {
@@ -683,7 +1008,7 @@ var RoomManager = class {
683
1008
  },
684
1009
  setState: (updates) => {
685
1010
  if (!this.componentId) return;
686
- room.state = { ...room.state, ...updates };
1011
+ room.state = deepMerge2(room.state, updates);
687
1012
  this.sendMessage({
688
1013
  type: "ROOM_STATE_SET",
689
1014
  componentId: this.componentId,
@@ -693,8 +1018,13 @@ var RoomManager = class {
693
1018
  });
694
1019
  }
695
1020
  };
696
- this.handles.set(roomId, handle);
697
- return handle;
1021
+ const proxied = wrapWithStateProxy(
1022
+ handle,
1023
+ () => room.state,
1024
+ (updates) => handle.setState(updates)
1025
+ );
1026
+ this.handles.set(roomId, proxied);
1027
+ return proxied;
698
1028
  }
699
1029
  /** Create the $room proxy */
700
1030
  createProxy() {
@@ -744,6 +1074,14 @@ var RoomManager = class {
744
1074
  }
745
1075
  }
746
1076
  });
1077
+ if (this.defaultRoom && defaultHandle) {
1078
+ const room = this.getOrCreateRoom(this.defaultRoom);
1079
+ return wrapWithStateProxy(
1080
+ proxyFn,
1081
+ () => room.state,
1082
+ (updates) => defaultHandle.setState(updates)
1083
+ );
1084
+ }
747
1085
  return proxyFn;
748
1086
  }
749
1087
  /** List of rooms currently joined */
@@ -758,9 +1096,12 @@ var RoomManager = class {
758
1096
  setComponentId(id) {
759
1097
  this.componentId = id;
760
1098
  }
761
- /** Cleanup */
1099
+ /** Cleanup — unsubscribes handlers but keeps factory refs for resubscribe() */
762
1100
  destroy() {
763
1101
  this.globalUnsubscribe?.();
1102
+ this.globalUnsubscribe = null;
1103
+ this.binaryUnsubscribe?.();
1104
+ this.binaryUnsubscribe = null;
764
1105
  for (const [, room] of this.rooms) {
765
1106
  room.handlers.clear();
766
1107
  }
@@ -1133,6 +1474,70 @@ var StateValidator = class {
1133
1474
  };
1134
1475
  }
1135
1476
  };
1477
+
1478
+ // src/index.ts
1479
+ var _sharedConnection = null;
1480
+ var _sharedConnectionUrl = null;
1481
+ var _statusListeners = /* @__PURE__ */ new Set();
1482
+ function getOrCreateConnection(url) {
1483
+ const resolvedUrl = url ?? `ws://${typeof location !== "undefined" ? location.host : "localhost:3000"}/api/live/ws`;
1484
+ if (_sharedConnection && _sharedConnectionUrl === resolvedUrl) {
1485
+ return _sharedConnection;
1486
+ }
1487
+ if (_sharedConnection) {
1488
+ _sharedConnection.destroy();
1489
+ }
1490
+ _sharedConnection = new LiveConnection({ url: resolvedUrl });
1491
+ _sharedConnectionUrl = resolvedUrl;
1492
+ _sharedConnection.onStateChange((state) => {
1493
+ for (const cb of _statusListeners) {
1494
+ cb(state.connected);
1495
+ }
1496
+ });
1497
+ return _sharedConnection;
1498
+ }
1499
+ function useLive(componentName, initialState, options = {}) {
1500
+ const { url, room, userId, autoMount = true, debug = false } = options;
1501
+ const connection = getOrCreateConnection(url);
1502
+ const handle = new LiveComponentHandle(connection, componentName, {
1503
+ initialState,
1504
+ room,
1505
+ userId,
1506
+ autoMount,
1507
+ debug
1508
+ });
1509
+ return {
1510
+ call: (action, payload) => handle.call(action, payload ?? {}),
1511
+ on: (callback) => handle.onStateChange(callback),
1512
+ onError: (callback) => handle.onError(callback),
1513
+ get state() {
1514
+ return handle.state;
1515
+ },
1516
+ get mounted() {
1517
+ return handle.mounted;
1518
+ },
1519
+ get componentId() {
1520
+ return handle.componentId;
1521
+ },
1522
+ get error() {
1523
+ return handle.error;
1524
+ },
1525
+ destroy: () => handle.destroy(),
1526
+ handle
1527
+ };
1528
+ }
1529
+ function onConnectionChange(callback) {
1530
+ _statusListeners.add(callback);
1531
+ if (_sharedConnection) {
1532
+ callback(_sharedConnection.state.connected);
1533
+ }
1534
+ return () => {
1535
+ _statusListeners.delete(callback);
1536
+ };
1537
+ }
1538
+ function getConnection(url) {
1539
+ return getOrCreateConnection(url);
1540
+ }
1136
1541
  export {
1137
1542
  AdaptiveChunkSizer,
1138
1543
  ChunkedUploader,
@@ -1142,7 +1547,10 @@ export {
1142
1547
  StateValidator,
1143
1548
  clearPersistedState,
1144
1549
  createBinaryChunkMessage,
1550
+ getConnection,
1145
1551
  getPersistedState,
1146
- persistState
1552
+ onConnectionChange,
1553
+ persistState,
1554
+ useLive
1147
1555
  };
1148
1556
  //# sourceMappingURL=index.js.map