@liveblocks/core 1.0.7 → 1.0.8

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 (3) hide show
  1. package/dist/index.d.ts +292 -252
  2. package/dist/index.js +97 -130
  3. package/package.json +2 -1
package/dist/index.d.ts CHANGED
@@ -508,78 +508,54 @@ declare type Observable<T> = {
508
508
  subscribeOnce(callback: Callback<T>): UnsubscribeCallback;
509
509
  };
510
510
 
511
- declare type AppOnlyAuthToken = {
512
- appId: string;
513
- roomId?: never;
514
- scopes: string[];
515
- };
516
- declare type RoomAuthToken = {
517
- appId: string;
518
- roomId: string;
519
- scopes: string[];
520
- actor: number;
521
- maxConnectionsPerRoom?: number;
522
- info?: Json;
523
- groupIds?: string[];
524
- } & ({
525
- id: string;
526
- anonymousId?: never;
527
- } | {
528
- id?: never;
529
- anonymousId: string;
530
- });
531
- declare type AuthToken = AppOnlyAuthToken | RoomAuthToken;
532
- declare function isAppOnlyAuthToken(data: JsonObject): data is AppOnlyAuthToken;
533
- declare function isRoomAuthToken(data: JsonObject): data is RoomAuthToken;
534
- declare function isAuthToken(data: JsonObject): data is AuthToken;
535
-
536
- declare enum ClientMsgCode {
537
- UPDATE_PRESENCE = 100,
538
- BROADCAST_EVENT = 103,
539
- FETCH_STORAGE = 200,
540
- UPDATE_STORAGE = 201
511
+ interface IWebSocketEvent {
512
+ type: string;
513
+ }
514
+ interface IWebSocketCloseEvent extends IWebSocketEvent {
515
+ readonly code: number;
516
+ readonly wasClean: boolean;
517
+ readonly reason: string;
518
+ }
519
+ interface IWebSocketMessageEvent extends IWebSocketEvent {
520
+ readonly data: string | Buffer | ArrayBuffer | readonly Buffer[];
521
+ }
522
+ interface IWebSocketInstance {
523
+ readonly CONNECTING: number;
524
+ readonly OPEN: number;
525
+ readonly CLOSING: number;
526
+ readonly CLOSED: number;
527
+ readonly readyState: number;
528
+ addEventListener(type: "close", listener: (this: IWebSocketInstance, ev: IWebSocketCloseEvent) => unknown): void;
529
+ addEventListener(type: "message", listener: (this: IWebSocketInstance, ev: IWebSocketMessageEvent) => unknown): void;
530
+ addEventListener(type: "open" | "error", listener: (this: IWebSocketInstance, ev: IWebSocketEvent) => unknown): void;
531
+ removeEventListener(type: "close", listener: (this: IWebSocketInstance, ev: IWebSocketCloseEvent) => unknown): void;
532
+ removeEventListener(type: "message", listener: (this: IWebSocketInstance, ev: IWebSocketMessageEvent) => unknown): void;
533
+ removeEventListener(type: "open" | "error", listener: (this: IWebSocketInstance, ev: IWebSocketEvent) => unknown): void;
534
+ close(): void;
535
+ send(data: string): void;
541
536
  }
542
537
  /**
543
- * Messages that can be sent from the client to the server.
538
+ * Either the browser-based WebSocket API or Node.js' WebSocket API (from the
539
+ * 'ws' package).
540
+ *
541
+ * This type defines the minimal WebSocket API that Liveblocks needs from
542
+ * a WebSocket implementation, and is a minimal subset of the browser-based
543
+ * WebSocket APIs and Node.js' WebSocket API so that both implementations are
544
+ * assignable to this type.
544
545
  */
545
- declare type ClientMsg<TPresence extends JsonObject, TRoomEvent extends Json> = BroadcastEventClientMsg<TRoomEvent> | UpdatePresenceClientMsg<TPresence> | UpdateStorageClientMsg | FetchStorageClientMsg;
546
- declare type BroadcastEventClientMsg<TRoomEvent extends Json> = {
547
- type: ClientMsgCode.BROADCAST_EVENT;
548
- event: TRoomEvent;
549
- };
550
- declare type UpdatePresenceClientMsg<TPresence extends JsonObject> = {
551
- readonly type: ClientMsgCode.UPDATE_PRESENCE;
552
- /**
553
- * Set this to any number to signify that this is a Full Presence™
554
- * update, not a patch.
555
- *
556
- * The numeric value itself no longer has specific meaning. Historically,
557
- * this field was intended so that clients could ignore these broadcasted
558
- * full presence messages, but it turned out that getting a full presence
559
- * "keyframe" from time to time was useful.
560
- *
561
- * So nowadays, the presence (pun intended) of this `targetActor` field
562
- * is a backward-compatible way of expressing that the `data` contains
563
- * all presence fields, and isn't a partial "patch".
564
- */
565
- readonly targetActor: number;
566
- readonly data: TPresence;
567
- } | {
568
- readonly type: ClientMsgCode.UPDATE_PRESENCE;
569
- /**
570
- * Absence of the `targetActor` field signifies that this is a Partial
571
- * Presence™ "patch".
572
- */
573
- readonly targetActor?: undefined;
574
- readonly data: Partial<TPresence>;
575
- };
576
- declare type UpdateStorageClientMsg = {
577
- readonly type: ClientMsgCode.UPDATE_STORAGE;
578
- readonly ops: Op[];
579
- };
580
- declare type FetchStorageClientMsg = {
581
- readonly type: ClientMsgCode.FETCH_STORAGE;
582
- };
546
+ interface IWebSocket {
547
+ new (address: string): IWebSocketInstance;
548
+ }
549
+ declare enum WebsocketCloseCodes {
550
+ CLOSE_ABNORMAL = 1006,
551
+ INVALID_MESSAGE_FORMAT = 4000,
552
+ NOT_ALLOWED = 4001,
553
+ MAX_NUMBER_OF_MESSAGES_PER_SECONDS = 4002,
554
+ MAX_NUMBER_OF_CONCURRENT_CONNECTIONS = 4003,
555
+ MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP = 4004,
556
+ MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM = 4005,
557
+ CLOSE_WITHOUT_RETRY = 4999
558
+ }
583
559
 
584
560
  declare type ReadonlyArrayWithLegacyMethods<T> = readonly T[] & {
585
561
  /**
@@ -638,48 +614,6 @@ declare type OthersEvent<TPresence extends JsonObject, TUserMeta extends BaseUse
638
614
  type: "reset";
639
615
  };
640
616
 
641
- declare type JsonTreeNode = {
642
- readonly type: "Json";
643
- readonly id: string;
644
- readonly key: string;
645
- readonly payload: Json;
646
- };
647
- declare type LiveTreeNode<TName extends `Live${string}` = `Live${string}`> = {
648
- readonly type: TName;
649
- readonly id: string;
650
- readonly key: string;
651
- readonly payload: LsonTreeNode[];
652
- };
653
- declare type LsonTreeNode = LiveTreeNode | JsonTreeNode;
654
- declare type UserTreeNode = {
655
- readonly type: "User";
656
- readonly id: string;
657
- readonly key: string;
658
- readonly payload: {
659
- readonly connectionId: number;
660
- readonly id?: string;
661
- readonly info?: Json;
662
- readonly presence: JsonObject;
663
- readonly isReadOnly: boolean;
664
- };
665
- };
666
- declare type TreeNode = LsonTreeNode | UserTreeNode;
667
-
668
- type DevToolsTreeNode_JsonTreeNode = JsonTreeNode;
669
- type DevToolsTreeNode_LiveTreeNode<TName extends `Live${string}` = `Live${string}`> = LiveTreeNode<TName>;
670
- type DevToolsTreeNode_LsonTreeNode = LsonTreeNode;
671
- type DevToolsTreeNode_UserTreeNode = UserTreeNode;
672
- type DevToolsTreeNode_TreeNode = TreeNode;
673
- declare namespace DevToolsTreeNode {
674
- export {
675
- DevToolsTreeNode_JsonTreeNode as JsonTreeNode,
676
- DevToolsTreeNode_LiveTreeNode as LiveTreeNode,
677
- DevToolsTreeNode_LsonTreeNode as LsonTreeNode,
678
- DevToolsTreeNode_UserTreeNode as UserTreeNode,
679
- DevToolsTreeNode_TreeNode as TreeNode,
680
- };
681
- }
682
-
683
617
  declare type CustomEvent<TRoomEvent extends Json> = {
684
618
  connectionId: number;
685
619
  event: TRoomEvent;
@@ -792,6 +726,128 @@ declare type BroadcastOptions = {
792
726
  */
793
727
  shouldQueueEventIfNotReady: boolean;
794
728
  };
729
+ declare type SubscribeFn<TPresence extends JsonObject, _TStorage extends LsonObject, TUserMeta extends BaseUserMeta, TRoomEvent extends Json> = {
730
+ /**
731
+ * Subscribe to the current user presence updates.
732
+ *
733
+ * @param listener the callback that is called every time the current user presence is updated with {@link Room.updatePresence}.
734
+ *
735
+ * @returns Unsubscribe function.
736
+ *
737
+ * @example
738
+ * room.subscribe("my-presence", (presence) => {
739
+ * // Do something
740
+ * });
741
+ */
742
+ (type: "my-presence", listener: Callback<TPresence>): () => void;
743
+ /**
744
+ * Subscribe to the other users updates.
745
+ *
746
+ * @param listener the callback that is called when a user enters or leaves the room or when a user update its presence.
747
+ *
748
+ * @returns Unsubscribe function.
749
+ *
750
+ * @example
751
+ * room.subscribe("others", (others) => {
752
+ * // Do something
753
+ * });
754
+ *
755
+ */
756
+ (type: "others", listener: (others: Others<TPresence, TUserMeta>, event: OthersEvent<TPresence, TUserMeta>) => void): () => void;
757
+ /**
758
+ * Subscribe to events broadcasted by {@link Room.broadcastEvent}
759
+ *
760
+ * @param listener the callback that is called when a user calls {@link Room.broadcastEvent}
761
+ *
762
+ * @returns Unsubscribe function.
763
+ *
764
+ * @example
765
+ * room.subscribe("event", ({ event, connectionId }) => {
766
+ * // Do something
767
+ * });
768
+ *
769
+ */
770
+ (type: "event", listener: Callback<CustomEvent<TRoomEvent>>): () => void;
771
+ /**
772
+ * Subscribe to errors thrown in the room.
773
+ *
774
+ * @returns Unsubscribe function.
775
+ *
776
+ */
777
+ (type: "error", listener: ErrorCallback): () => void;
778
+ /**
779
+ * Subscribe to connection state updates.
780
+ *
781
+ * @returns Unsubscribe function.
782
+ *
783
+ */
784
+ (type: "connection", listener: Callback<ConnectionStatus>): () => void;
785
+ /**
786
+ * Subscribes to changes made on a Live structure. Returns an unsubscribe function.
787
+ * In a future version, we will also expose what exactly changed in the Live structure.
788
+ *
789
+ * @param callback The callback this called when the Live structure changes.
790
+ *
791
+ * @returns Unsubscribe function.
792
+ *
793
+ * @example
794
+ * const liveMap = new LiveMap(); // Could also be LiveList or LiveObject
795
+ * const unsubscribe = room.subscribe(liveMap, (liveMap) => { });
796
+ * unsubscribe();
797
+ */
798
+ <L extends LiveStructure>(liveStructure: L, callback: (node: L) => void): () => void;
799
+ /**
800
+ * Subscribes to changes made on a Live structure and all the nested data
801
+ * structures. Returns an unsubscribe function. In a future version, we
802
+ * will also expose what exactly changed in the Live structure.
803
+ *
804
+ * @param callback The callback this called when the Live structure, or any
805
+ * of its nested values, changes.
806
+ *
807
+ * @returns Unsubscribe function.
808
+ *
809
+ * @example
810
+ * const liveMap = new LiveMap(); // Could also be LiveList or LiveObject
811
+ * const unsubscribe = room.subscribe(liveMap, (updates) => { }, { isDeep: true });
812
+ * unsubscribe();
813
+ */
814
+ <L extends LiveStructure>(liveStructure: L, callback: StorageCallback, options: {
815
+ isDeep: true;
816
+ }): () => void;
817
+ /**
818
+ * Subscribe to the current user's history changes.
819
+ *
820
+ * @returns Unsubscribe function.
821
+ *
822
+ * @example
823
+ * room.subscribe("history", ({ canUndo, canRedo }) => {
824
+ * // Do something
825
+ * });
826
+ */
827
+ (type: "history", listener: Callback<HistoryEvent>): () => void;
828
+ /**
829
+ * Subscribe to storage status changes.
830
+ *
831
+ * @returns Unsubscribe function.
832
+ *
833
+ * @example
834
+ * room.subscribe("storage-status", (status) => {
835
+ * switch(status) {
836
+ * case "not-loaded":
837
+ * break;
838
+ * case "loading":
839
+ * break;
840
+ * case "synchronizing":
841
+ * break;
842
+ * case "synchronized":
843
+ * break;
844
+ * default:
845
+ * break;
846
+ * }
847
+ * });
848
+ */
849
+ (type: "storage-status", listener: Callback<StorageStatus>): () => void;
850
+ };
795
851
  declare type Room<TPresence extends JsonObject, TStorage extends LsonObject, TUserMeta extends BaseUserMeta, TRoomEvent extends Json> = {
796
852
  /**
797
853
  * The id of the room.
@@ -803,128 +859,7 @@ declare type Room<TPresence extends JsonObject, TStorage extends LsonObject, TUs
803
859
  */
804
860
  isSelfAware(): boolean;
805
861
  getConnectionState(): ConnectionStatus;
806
- readonly subscribe: {
807
- /**
808
- * Subscribe to the current user presence updates.
809
- *
810
- * @param listener the callback that is called every time the current user presence is updated with {@link Room.updatePresence}.
811
- *
812
- * @returns Unsubscribe function.
813
- *
814
- * @example
815
- * room.subscribe("my-presence", (presence) => {
816
- * // Do something
817
- * });
818
- */
819
- (type: "my-presence", listener: Callback<TPresence>): () => void;
820
- /**
821
- * Subscribe to the other users updates.
822
- *
823
- * @param listener the callback that is called when a user enters or leaves the room or when a user update its presence.
824
- *
825
- * @returns Unsubscribe function.
826
- *
827
- * @example
828
- * room.subscribe("others", (others) => {
829
- * // Do something
830
- * });
831
- *
832
- */
833
- (type: "others", listener: (others: Others<TPresence, TUserMeta>, event: OthersEvent<TPresence, TUserMeta>) => void): () => void;
834
- /**
835
- * Subscribe to events broadcasted by {@link Room.broadcastEvent}
836
- *
837
- * @param listener the callback that is called when a user calls {@link Room.broadcastEvent}
838
- *
839
- * @returns Unsubscribe function.
840
- *
841
- * @example
842
- * room.subscribe("event", ({ event, connectionId }) => {
843
- * // Do something
844
- * });
845
- *
846
- */
847
- (type: "event", listener: Callback<CustomEvent<TRoomEvent>>): () => void;
848
- /**
849
- * Subscribe to errors thrown in the room.
850
- *
851
- * @returns Unsubscribe function.
852
- *
853
- */
854
- (type: "error", listener: ErrorCallback): () => void;
855
- /**
856
- * Subscribe to connection state updates.
857
- *
858
- * @returns Unsubscribe function.
859
- *
860
- */
861
- (type: "connection", listener: Callback<ConnectionStatus>): () => void;
862
- /**
863
- * Subscribes to changes made on a Live structure. Returns an unsubscribe function.
864
- * In a future version, we will also expose what exactly changed in the Live structure.
865
- *
866
- * @param callback The callback this called when the Live structure changes.
867
- *
868
- * @returns Unsubscribe function.
869
- *
870
- * @example
871
- * const liveMap = new LiveMap(); // Could also be LiveList or LiveObject
872
- * const unsubscribe = room.subscribe(liveMap, (liveMap) => { });
873
- * unsubscribe();
874
- */
875
- <L extends LiveStructure>(liveStructure: L, callback: (node: L) => void): () => void;
876
- /**
877
- * Subscribes to changes made on a Live structure and all the nested data
878
- * structures. Returns an unsubscribe function. In a future version, we
879
- * will also expose what exactly changed in the Live structure.
880
- *
881
- * @param callback The callback this called when the Live structure, or any
882
- * of its nested values, changes.
883
- *
884
- * @returns Unsubscribe function.
885
- *
886
- * @example
887
- * const liveMap = new LiveMap(); // Could also be LiveList or LiveObject
888
- * const unsubscribe = room.subscribe(liveMap, (updates) => { }, { isDeep: true });
889
- * unsubscribe();
890
- */
891
- <L extends LiveStructure>(liveStructure: L, callback: StorageCallback, options: {
892
- isDeep: true;
893
- }): () => void;
894
- /**
895
- * Subscribe to the current user's history changes.
896
- *
897
- * @returns Unsubscribe function.
898
- *
899
- * @example
900
- * room.subscribe("history", ({ canUndo, canRedo }) => {
901
- * // Do something
902
- * });
903
- */
904
- (type: "history", listener: Callback<HistoryEvent>): () => void;
905
- /**
906
- * Subscribe to storage status changes.
907
- *
908
- * @returns Unsubscribe function.
909
- *
910
- * @example
911
- * room.subscribe("storage-status", (status) => {
912
- * switch(status) {
913
- * case "not-loaded":
914
- * break;
915
- * case "loading":
916
- * break;
917
- * case "synchronizing":
918
- * break;
919
- * case "synchronized":
920
- * break;
921
- * default:
922
- * break;
923
- * }
924
- * });
925
- */
926
- (type: "storage-status", listener: Callback<StorageStatus>): () => void;
927
- };
862
+ readonly subscribe: SubscribeFn<TPresence, TStorage, TUserMeta, TRoomEvent>;
928
863
  /**
929
864
  * Room's history contains functions that let you undo and redo operation made on by the current client on the presence and storage.
930
865
  */
@@ -1004,24 +939,25 @@ declare type Room<TPresence extends JsonObject, TStorage extends LsonObject, TUs
1004
939
  */
1005
940
  getStorageSnapshot(): LiveObject<TStorage> | null;
1006
941
  readonly events: {
1007
- customEvent: Observable<{
942
+ readonly customEvent: Observable<{
1008
943
  connectionId: number;
1009
944
  event: TRoomEvent;
1010
945
  }>;
1011
- me: Observable<TPresence>;
1012
- others: Observable<{
946
+ readonly me: Observable<TPresence>;
947
+ readonly others: Observable<{
1013
948
  others: Others<TPresence, TUserMeta>;
1014
949
  event: OthersEvent<TPresence, TUserMeta>;
1015
950
  }>;
1016
- error: Observable<Error>;
1017
- connection: Observable<ConnectionStatus>;
1018
- storage: Observable<StorageUpdate[]>;
1019
- history: Observable<HistoryEvent>;
951
+ readonly error: Observable<Error>;
952
+ readonly connection: Observable<ConnectionStatus>;
953
+ readonly storage: Observable<StorageUpdate[]>;
954
+ readonly history: Observable<HistoryEvent>;
1020
955
  /**
1021
956
  * Subscribe to the storage loaded event. Will fire at most once during the
1022
957
  * lifetime of a Room.
1023
958
  */
1024
- storageDidLoad: Observable<void>;
959
+ readonly storageDidLoad: Observable<void>;
960
+ readonly storageStatus: Observable<StorageStatus>;
1025
961
  };
1026
962
  /**
1027
963
  * Batches modifications made during the given function.
@@ -1054,7 +990,7 @@ declare type Room<TPresence extends JsonObject, TStorage extends LsonObject, TUs
1054
990
  declare type Polyfills = {
1055
991
  atob?: (data: string) => string;
1056
992
  fetch?: typeof fetch;
1057
- WebSocket?: any;
993
+ WebSocket?: IWebSocket;
1058
994
  };
1059
995
  declare type RoomInitializers<TPresence extends JsonObject, TStorage extends LsonObject> = Resolve<{
1060
996
  /**
@@ -1329,6 +1265,79 @@ declare function asPos(str: string): Pos;
1329
1265
  */
1330
1266
  declare function shallow(a: unknown, b: unknown): boolean;
1331
1267
 
1268
+ declare type AppOnlyAuthToken = {
1269
+ appId: string;
1270
+ roomId?: never;
1271
+ scopes: string[];
1272
+ };
1273
+ declare type RoomAuthToken = {
1274
+ appId: string;
1275
+ roomId: string;
1276
+ scopes: string[];
1277
+ actor: number;
1278
+ maxConnectionsPerRoom?: number;
1279
+ info?: Json;
1280
+ groupIds?: string[];
1281
+ } & ({
1282
+ id: string;
1283
+ anonymousId?: never;
1284
+ } | {
1285
+ id?: never;
1286
+ anonymousId: string;
1287
+ });
1288
+ declare type AuthToken = AppOnlyAuthToken | RoomAuthToken;
1289
+ declare function isAppOnlyAuthToken(data: JsonObject): data is AppOnlyAuthToken;
1290
+ declare function isRoomAuthToken(data: JsonObject): data is RoomAuthToken;
1291
+ declare function isAuthToken(data: JsonObject): data is AuthToken;
1292
+
1293
+ declare enum ClientMsgCode {
1294
+ UPDATE_PRESENCE = 100,
1295
+ BROADCAST_EVENT = 103,
1296
+ FETCH_STORAGE = 200,
1297
+ UPDATE_STORAGE = 201
1298
+ }
1299
+ /**
1300
+ * Messages that can be sent from the client to the server.
1301
+ */
1302
+ declare type ClientMsg<TPresence extends JsonObject, TRoomEvent extends Json> = BroadcastEventClientMsg<TRoomEvent> | UpdatePresenceClientMsg<TPresence> | UpdateStorageClientMsg | FetchStorageClientMsg;
1303
+ declare type BroadcastEventClientMsg<TRoomEvent extends Json> = {
1304
+ type: ClientMsgCode.BROADCAST_EVENT;
1305
+ event: TRoomEvent;
1306
+ };
1307
+ declare type UpdatePresenceClientMsg<TPresence extends JsonObject> = {
1308
+ readonly type: ClientMsgCode.UPDATE_PRESENCE;
1309
+ /**
1310
+ * Set this to any number to signify that this is a Full Presence™
1311
+ * update, not a patch.
1312
+ *
1313
+ * The numeric value itself no longer has specific meaning. Historically,
1314
+ * this field was intended so that clients could ignore these broadcasted
1315
+ * full presence messages, but it turned out that getting a full presence
1316
+ * "keyframe" from time to time was useful.
1317
+ *
1318
+ * So nowadays, the presence (pun intended) of this `targetActor` field
1319
+ * is a backward-compatible way of expressing that the `data` contains
1320
+ * all presence fields, and isn't a partial "patch".
1321
+ */
1322
+ readonly targetActor: number;
1323
+ readonly data: TPresence;
1324
+ } | {
1325
+ readonly type: ClientMsgCode.UPDATE_PRESENCE;
1326
+ /**
1327
+ * Absence of the `targetActor` field signifies that this is a Partial
1328
+ * Presence™ "patch".
1329
+ */
1330
+ readonly targetActor?: undefined;
1331
+ readonly data: Partial<TPresence>;
1332
+ };
1333
+ declare type UpdateStorageClientMsg = {
1334
+ readonly type: ClientMsgCode.UPDATE_STORAGE;
1335
+ readonly ops: Op[];
1336
+ };
1337
+ declare type FetchStorageClientMsg = {
1338
+ readonly type: ClientMsgCode.FETCH_STORAGE;
1339
+ };
1340
+
1332
1341
  declare type IdTuple<T> = [id: string, value: T];
1333
1342
  declare enum CrdtType {
1334
1343
  OBJECT = 0,
@@ -1594,15 +1603,46 @@ declare type PlainLsonList = {
1594
1603
  };
1595
1604
  declare type PlainLson = PlainLsonObject | PlainLsonMap | PlainLsonList | Json;
1596
1605
 
1597
- declare enum WebsocketCloseCodes {
1598
- CLOSE_ABNORMAL = 1006,
1599
- INVALID_MESSAGE_FORMAT = 4000,
1600
- NOT_ALLOWED = 4001,
1601
- MAX_NUMBER_OF_MESSAGES_PER_SECONDS = 4002,
1602
- MAX_NUMBER_OF_CONCURRENT_CONNECTIONS = 4003,
1603
- MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP = 4004,
1604
- MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM = 4005,
1605
- CLOSE_WITHOUT_RETRY = 4999
1606
+ declare type JsonTreeNode = {
1607
+ readonly type: "Json";
1608
+ readonly id: string;
1609
+ readonly key: string;
1610
+ readonly payload: Json;
1611
+ };
1612
+ declare type LiveTreeNode<TName extends `Live${string}` = `Live${string}`> = {
1613
+ readonly type: TName;
1614
+ readonly id: string;
1615
+ readonly key: string;
1616
+ readonly payload: LsonTreeNode[];
1617
+ };
1618
+ declare type LsonTreeNode = LiveTreeNode | JsonTreeNode;
1619
+ declare type UserTreeNode = {
1620
+ readonly type: "User";
1621
+ readonly id: string;
1622
+ readonly key: string;
1623
+ readonly payload: {
1624
+ readonly connectionId: number;
1625
+ readonly id?: string;
1626
+ readonly info?: Json;
1627
+ readonly presence: JsonObject;
1628
+ readonly isReadOnly: boolean;
1629
+ };
1630
+ };
1631
+ declare type TreeNode = LsonTreeNode | UserTreeNode;
1632
+
1633
+ type DevToolsTreeNode_JsonTreeNode = JsonTreeNode;
1634
+ type DevToolsTreeNode_LiveTreeNode<TName extends `Live${string}` = `Live${string}`> = LiveTreeNode<TName>;
1635
+ type DevToolsTreeNode_LsonTreeNode = LsonTreeNode;
1636
+ type DevToolsTreeNode_UserTreeNode = UserTreeNode;
1637
+ type DevToolsTreeNode_TreeNode = TreeNode;
1638
+ declare namespace DevToolsTreeNode {
1639
+ export {
1640
+ DevToolsTreeNode_JsonTreeNode as JsonTreeNode,
1641
+ DevToolsTreeNode_LiveTreeNode as LiveTreeNode,
1642
+ DevToolsTreeNode_LsonTreeNode as LsonTreeNode,
1643
+ DevToolsTreeNode_UserTreeNode as UserTreeNode,
1644
+ DevToolsTreeNode_TreeNode as TreeNode,
1645
+ };
1606
1646
  }
1607
1647
 
1608
1648
  /**
@@ -1739,4 +1779,4 @@ declare type EnsureJson<T> = [
1739
1779
  [K in keyof T]: EnsureJson<T[K]>;
1740
1780
  };
1741
1781
 
1742
- export { AckOp, AppOnlyAuthToken, AuthToken, BaseUserMeta, BroadcastEventClientMsg, BroadcastOptions, BroadcastedEventServerMsg, Client, ClientMsg, ClientMsgCode, ConnectionStatus, CrdtType, CreateChildOp, CreateListOp, CreateMapOp, CreateObjectOp, CreateOp, CreateRegisterOp, CreateRootObjectOp, DeleteCrdtOp, DeleteObjectKeyOp, DevToolsTreeNode as DevTools, protocol as DevToolsMsg, EnsureJson, FetchStorageClientMsg, History, IdTuple, Immutable, InitialDocumentStateServerMsg, Json, JsonArray, JsonObject, JsonScalar, LiveList, LiveMap, LiveNode, LiveObject, LiveStructure, Lson, LsonObject, NodeMap, Op, OpCode, Others, ParentToChildNodeMap, PlainLson, PlainLsonFields, PlainLsonList, PlainLsonMap, PlainLsonObject, RejectedStorageOpServerMsg, Resolve, Room, RoomAuthToken, RoomInitializers, RoomStateServerMsg, SerializedChild, SerializedCrdt, SerializedList, SerializedMap, SerializedObject, SerializedRegister, SerializedRootObject, ServerMsg, ServerMsgCode, SetParentKeyOp, StorageStatus, StorageUpdate, ToImmutable, ToJson, UpdateObjectOp, UpdatePresenceClientMsg, UpdatePresenceServerMsg, UpdateStorageClientMsg, UpdateStorageServerMsg, User, UserJoinServerMsg, UserLeftServerMsg, WebsocketCloseCodes, asArrayWithLegacyMethods, asPos, assert, assertNever, b64decode, createClient, deprecate, deprecateIf, errorIf, freeze, isAppOnlyAuthToken, isAuthToken, isChildCrdt, isJsonArray, isJsonObject, isJsonScalar, isPlainObject, isRoomAuthToken, isRootCrdt, legacy_patchImmutableObject, lsonToJson, makePosition, nn, patchLiveObjectKey, shallow, throwUsageError, tryParseJson };
1782
+ export { AckOp, AppOnlyAuthToken, AuthToken, BaseUserMeta, BroadcastEventClientMsg, BroadcastOptions, BroadcastedEventServerMsg, Client, ClientMsg, ClientMsgCode, ConnectionStatus, CrdtType, CreateChildOp, CreateListOp, CreateMapOp, CreateObjectOp, CreateOp, CreateRegisterOp, CreateRootObjectOp, DeleteCrdtOp, DeleteObjectKeyOp, DevToolsTreeNode as DevTools, protocol as DevToolsMsg, EnsureJson, FetchStorageClientMsg, History, IWebSocket, IWebSocketCloseEvent, IWebSocketEvent, IWebSocketInstance, IWebSocketMessageEvent, IdTuple, Immutable, InitialDocumentStateServerMsg, Json, JsonArray, JsonObject, JsonScalar, LiveList, LiveMap, LiveNode, LiveObject, LiveStructure, Lson, LsonObject, NodeMap, Op, OpCode, Others, ParentToChildNodeMap, PlainLson, PlainLsonFields, PlainLsonList, PlainLsonMap, PlainLsonObject, RejectedStorageOpServerMsg, Resolve, Room, RoomAuthToken, RoomInitializers, RoomStateServerMsg, SerializedChild, SerializedCrdt, SerializedList, SerializedMap, SerializedObject, SerializedRegister, SerializedRootObject, ServerMsg, ServerMsgCode, SetParentKeyOp, StorageStatus, StorageUpdate, ToImmutable, ToJson, UpdateObjectOp, UpdatePresenceClientMsg, UpdatePresenceServerMsg, UpdateStorageClientMsg, UpdateStorageServerMsg, User, UserJoinServerMsg, UserLeftServerMsg, WebsocketCloseCodes, asArrayWithLegacyMethods, asPos, assert, assertNever, b64decode, createClient, deprecate, deprecateIf, errorIf, freeze, isAppOnlyAuthToken, isAuthToken, isChildCrdt, isJsonArray, isJsonObject, isJsonScalar, isPlainObject, isRoomAuthToken, isRootCrdt, legacy_patchImmutableObject, lsonToJson, makePosition, nn, patchLiveObjectKey, shallow, throwUsageError, tryParseJson };
package/dist/index.js CHANGED
@@ -117,7 +117,7 @@ var onMessageFromPanel = eventSource.observable;
117
117
  // src/devtools/index.ts
118
118
  var VERSION = true ? (
119
119
  /* istanbul ignore next */
120
- "1.0.7"
120
+ "1.0.8"
121
121
  ) : "dev";
122
122
  var _devtoolsSetupHasRun = false;
123
123
  function setupDevTools(getAllRooms) {
@@ -3237,7 +3237,7 @@ var DerivedRef = class extends ImmutableRef {
3237
3237
  }
3238
3238
  };
3239
3239
 
3240
- // src/types/WebsocketCloseCodes.ts
3240
+ // src/types/IWebSocket.ts
3241
3241
  var WebsocketCloseCodes = /* @__PURE__ */ ((WebsocketCloseCodes2) => {
3242
3242
  WebsocketCloseCodes2[WebsocketCloseCodes2["CLOSE_ABNORMAL"] = 1006] = "CLOSE_ABNORMAL";
3243
3243
  WebsocketCloseCodes2[WebsocketCloseCodes2["INVALID_MESSAGE_FORMAT"] = 4e3] = "INVALID_MESSAGE_FORMAT";
@@ -3273,8 +3273,10 @@ function userToTreeNode(key, user) {
3273
3273
  payload: user
3274
3274
  };
3275
3275
  }
3276
- function makeStateMachine(config, initialPresence, initialStorage) {
3276
+ function createRoom(options, config) {
3277
3277
  var _a;
3278
+ const initialPresence = typeof options.initialPresence === "function" ? options.initialPresence(config.roomId) : options.initialPresence;
3279
+ const initialStorage = typeof options.initialStorage === "function" ? options.initialStorage(config.roomId) : options.initialStorage;
3278
3280
  const context = {
3279
3281
  token: null,
3280
3282
  lastConnectionId: null,
@@ -3385,7 +3387,7 @@ function makeStateMachine(config, initialPresence, initialStorage) {
3385
3387
  authenticationSuccess(prevToken.parsed, socket);
3386
3388
  return void 0;
3387
3389
  } else {
3388
- return auth(config.roomId).then(({ token }) => {
3390
+ void auth(config.roomId).then(({ token }) => {
3389
3391
  if (context.connection.current.status !== "authenticating") {
3390
3392
  return;
3391
3393
  }
@@ -3398,13 +3400,16 @@ function makeStateMachine(config, initialPresence, initialStorage) {
3398
3400
  er instanceof Error ? er : new Error(String(er))
3399
3401
  )
3400
3402
  );
3403
+ return void 0;
3401
3404
  }
3402
3405
  },
3403
3406
  send(messageOrMessages) {
3404
3407
  if (context.socket === null) {
3405
3408
  throw new Error("Can't send message if socket is null");
3406
3409
  }
3407
- context.socket.send(JSON.stringify(messageOrMessages));
3410
+ if (context.socket.readyState === context.socket.OPEN) {
3411
+ context.socket.send(JSON.stringify(messageOrMessages));
3412
+ }
3408
3413
  },
3409
3414
  scheduleFlush: (delay) => setTimeout(tryFlushing, delay),
3410
3415
  scheduleReconnect: (delay) => setTimeout(connect, delay),
@@ -3632,7 +3637,7 @@ function makeStateMachine(config, initialPresence, initialStorage) {
3632
3637
  updateConnection({ status: "authenticating" }, batchUpdates);
3633
3638
  effects.authenticate(auth, createWebSocket);
3634
3639
  }
3635
- function updatePresence(patch, options) {
3640
+ function updatePresence(patch, options2) {
3636
3641
  const oldValues = {};
3637
3642
  if (context.buffer.me === null) {
3638
3643
  context.buffer.me = {
@@ -3650,7 +3655,7 @@ function makeStateMachine(config, initialPresence, initialStorage) {
3650
3655
  }
3651
3656
  context.me.patch(patch);
3652
3657
  if (context.activeBatch) {
3653
- if (options == null ? void 0 : options.addToHistory) {
3658
+ if (options2 == null ? void 0 : options2.addToHistory) {
3654
3659
  context.activeBatch.reverseOps.unshift({
3655
3660
  type: "presence",
3656
3661
  data: oldValues
@@ -3660,7 +3665,7 @@ function makeStateMachine(config, initialPresence, initialStorage) {
3660
3665
  } else {
3661
3666
  tryFlushing();
3662
3667
  batchUpdates(() => {
3663
- if (options == null ? void 0 : options.addToHistory) {
3668
+ if (options2 == null ? void 0 : options2.addToHistory) {
3664
3669
  addToUndoStack(
3665
3670
  [{ type: "presence", data: oldValues }],
3666
3671
  doNotBatchUpdates
@@ -3824,6 +3829,9 @@ function makeStateMachine(config, initialPresence, initialStorage) {
3824
3829
  clearTimeout(context.timers.pongTimeout);
3825
3830
  return;
3826
3831
  }
3832
+ if (typeof event.data !== "string") {
3833
+ return;
3834
+ }
3827
3835
  const messages = parseServerMessages(event.data);
3828
3836
  if (messages === null || messages.length === 0) {
3829
3837
  return;
@@ -4116,10 +4124,10 @@ ${Array.from(traces).join("\n\n")}`
4116
4124
  }
4117
4125
  return messages;
4118
4126
  }
4119
- function broadcastEvent(event, options = {
4127
+ function broadcastEvent(event, options2 = {
4120
4128
  shouldQueueEventIfNotReady: false
4121
4129
  }) {
4122
- if (context.socket === null && !options.shouldQueueEventIfNotReady) {
4130
+ if (context.socket === null && !options2.shouldQueueEventIfNotReady) {
4123
4131
  return;
4124
4132
  }
4125
4133
  context.buffer.messages.push({
@@ -4150,7 +4158,7 @@ ${Array.from(traces).join("\n\n")}`
4150
4158
  if (root !== void 0) {
4151
4159
  return root;
4152
4160
  } else {
4153
- startLoadingStorage();
4161
+ void startLoadingStorage();
4154
4162
  return null;
4155
4163
  }
4156
4164
  }
@@ -4256,7 +4264,7 @@ ${Array.from(traces).join("\n\n")}`
4256
4264
  _addToRealUndoStack(historyOps, batchUpdates);
4257
4265
  }
4258
4266
  }
4259
- function simulateSocketClose() {
4267
+ function simulateCloseWebsocket() {
4260
4268
  if (context.socket) {
4261
4269
  context.socket = null;
4262
4270
  }
@@ -4285,119 +4293,75 @@ ${Array.from(traces).join("\n\n")}`
4285
4293
  context.others,
4286
4294
  (others) => others.map((other, index) => userToTreeNode(`Other ${index}`, other))
4287
4295
  );
4296
+ const events = {
4297
+ customEvent: eventHub.customEvent.observable,
4298
+ others: eventHub.others.observable,
4299
+ me: eventHub.me.observable,
4300
+ error: eventHub.error.observable,
4301
+ connection: eventHub.connection.observable,
4302
+ storage: eventHub.storage.observable,
4303
+ history: eventHub.history.observable,
4304
+ storageDidLoad: eventHub.storageDidLoad.observable,
4305
+ storageStatus: eventHub.storageStatus.observable
4306
+ };
4288
4307
  return {
4289
- // Internal
4290
- get state() {
4291
- return context;
4308
+ /* NOTE: Exposing __internal here only to allow testing implementation details in unit tests */
4309
+ __internal: {
4310
+ get buffer() {
4311
+ return context.buffer;
4312
+ },
4313
+ // prettier-ignore
4314
+ get numRetries() {
4315
+ return context.numRetries;
4316
+ },
4317
+ // prettier-ignore
4318
+ onClose,
4319
+ onMessage,
4320
+ authenticationSuccess,
4321
+ onNavigatorOnline,
4322
+ simulateCloseWebsocket,
4323
+ simulateSendCloseEvent,
4324
+ onVisibilityChange,
4325
+ getUndoStack: () => context.undoStack,
4326
+ getItemsCount: () => context.nodes.size,
4327
+ connect,
4328
+ disconnect,
4329
+ // Support for the Liveblocks browser extension
4330
+ getSelf_forDevTools: () => selfAsTreeNode.current,
4331
+ getOthers_forDevTools: () => others_forDevTools.current
4292
4332
  },
4293
- onClose,
4294
- onMessage,
4295
- authenticationSuccess,
4296
- heartbeat,
4297
- onNavigatorOnline,
4298
- // Internal DevTools
4299
- simulateSocketClose,
4300
- simulateSendCloseEvent,
4301
- onVisibilityChange,
4302
- getUndoStack: () => context.undoStack,
4303
- getItemsCount: () => context.nodes.size,
4304
- // Core
4305
- connect,
4306
- disconnect,
4333
+ id: config.roomId,
4334
+ subscribe: makeClassicSubscribeFn(events),
4307
4335
  reconnect,
4308
4336
  // Presence
4309
4337
  updatePresence,
4310
4338
  broadcastEvent,
4311
4339
  // Storage
4312
4340
  batch,
4313
- undo,
4314
- redo,
4315
- canUndo,
4316
- canRedo,
4317
- pauseHistory,
4318
- resumeHistory,
4341
+ history: {
4342
+ undo,
4343
+ redo,
4344
+ canUndo,
4345
+ canRedo,
4346
+ pause: pauseHistory,
4347
+ resume: resumeHistory
4348
+ },
4319
4349
  getStorage,
4320
4350
  getStorageSnapshot,
4321
4351
  getStorageStatus,
4322
- events: {
4323
- customEvent: eventHub.customEvent.observable,
4324
- others: eventHub.others.observable,
4325
- me: eventHub.me.observable,
4326
- error: eventHub.error.observable,
4327
- connection: eventHub.connection.observable,
4328
- storage: eventHub.storage.observable,
4329
- history: eventHub.history.observable,
4330
- storageDidLoad: eventHub.storageDidLoad.observable,
4331
- storageStatus: eventHub.storageStatus.observable
4332
- },
4352
+ events,
4333
4353
  // Core
4334
4354
  getConnectionState: () => context.connection.current.status,
4335
4355
  isSelfAware: () => isConnectionSelfAware(context.connection.current),
4336
4356
  getSelf: () => self.current,
4337
4357
  // Presence
4338
4358
  getPresence: () => context.me.current,
4339
- getOthers: () => context.others.current,
4340
- // Support for the Liveblocks browser extension
4341
- getSelf_forDevTools: () => selfAsTreeNode.current,
4342
- getOthers_forDevTools: () => others_forDevTools.current
4359
+ getOthers: () => context.others.current
4343
4360
  };
4344
4361
  }
4345
- function createRoom(options, config) {
4346
- const { initialPresence, initialStorage } = options;
4347
- const machine = makeStateMachine(
4348
- config,
4349
- typeof initialPresence === "function" ? initialPresence(config.roomId) : initialPresence,
4350
- typeof initialStorage === "function" ? initialStorage(config.roomId) : initialStorage
4351
- );
4352
- const room = {
4353
- id: config.roomId,
4354
- /////////////
4355
- // Core //
4356
- /////////////
4357
- getConnectionState: machine.getConnectionState,
4358
- isSelfAware: machine.isSelfAware,
4359
- getSelf: machine.getSelf,
4360
- reconnect: machine.reconnect,
4361
- subscribe: makeClassicSubscribeFn(machine),
4362
- //////////////
4363
- // Presence //
4364
- //////////////
4365
- getPresence: machine.getPresence,
4366
- updatePresence: machine.updatePresence,
4367
- getOthers: machine.getOthers,
4368
- broadcastEvent: machine.broadcastEvent,
4369
- //////////////
4370
- // Storage //
4371
- //////////////
4372
- getStorage: machine.getStorage,
4373
- getStorageSnapshot: machine.getStorageSnapshot,
4374
- getStorageStatus: machine.getStorageStatus,
4375
- events: machine.events,
4376
- batch: machine.batch,
4377
- history: {
4378
- undo: machine.undo,
4379
- redo: machine.redo,
4380
- canUndo: machine.canUndo,
4381
- canRedo: machine.canRedo,
4382
- pause: machine.pauseHistory,
4383
- resume: machine.resumeHistory
4384
- },
4385
- __internal: {
4386
- connect: machine.connect,
4387
- disconnect: machine.disconnect,
4388
- onNavigatorOnline: machine.onNavigatorOnline,
4389
- onVisibilityChange: machine.onVisibilityChange,
4390
- simulateCloseWebsocket: machine.simulateSocketClose,
4391
- simulateSendCloseEvent: machine.simulateSendCloseEvent,
4392
- getSelf_forDevTools: machine.getSelf_forDevTools,
4393
- getOthers_forDevTools: machine.getOthers_forDevTools
4394
- }
4395
- };
4396
- return room;
4397
- }
4398
- function makeClassicSubscribeFn(machine) {
4362
+ function makeClassicSubscribeFn(events) {
4399
4363
  function subscribeToLiveStructureDeeply(node, callback) {
4400
- return machine.events.storage.subscribe((updates) => {
4364
+ return events.storage.subscribe((updates) => {
4401
4365
  const relatedUpdates = updates.filter(
4402
4366
  (update) => isSameNodeOrChildOf(update.node, node)
4403
4367
  );
@@ -4407,7 +4371,7 @@ function makeClassicSubscribeFn(machine) {
4407
4371
  });
4408
4372
  }
4409
4373
  function subscribeToLiveStructureShallowly(node, callback) {
4410
- return machine.events.storage.subscribe((updates) => {
4374
+ return events.storage.subscribe((updates) => {
4411
4375
  for (const update of updates) {
4412
4376
  if (update.node._id === node._id) {
4413
4377
  callback(update.node);
@@ -4423,33 +4387,31 @@ function makeClassicSubscribeFn(machine) {
4423
4387
  const callback = second;
4424
4388
  switch (first) {
4425
4389
  case "event":
4426
- return machine.events.customEvent.subscribe(
4390
+ return events.customEvent.subscribe(
4427
4391
  callback
4428
4392
  );
4429
4393
  case "my-presence":
4430
- return machine.events.me.subscribe(callback);
4394
+ return events.me.subscribe(callback);
4431
4395
  case "others": {
4432
4396
  const cb = callback;
4433
- return machine.events.others.subscribe(
4397
+ return events.others.subscribe(
4434
4398
  ({ others, event }) => cb(others, event)
4435
4399
  );
4436
4400
  }
4437
4401
  case "error":
4438
- return machine.events.error.subscribe(callback);
4402
+ return events.error.subscribe(callback);
4439
4403
  case "connection":
4440
- return machine.events.connection.subscribe(
4404
+ return events.connection.subscribe(
4441
4405
  callback
4442
4406
  );
4443
4407
  case "storage":
4444
- return machine.events.storage.subscribe(
4408
+ return events.storage.subscribe(
4445
4409
  callback
4446
4410
  );
4447
4411
  case "history":
4448
- return machine.events.history.subscribe(
4449
- callback
4450
- );
4412
+ return events.history.subscribe(callback);
4451
4413
  case "storage-status":
4452
- return machine.events.storageStatus.subscribe(
4414
+ return events.storageStatus.subscribe(
4453
4415
  callback
4454
4416
  );
4455
4417
  default:
@@ -4459,7 +4421,7 @@ function makeClassicSubscribeFn(machine) {
4459
4421
  if (second === void 0 || typeof first === "function") {
4460
4422
  if (typeof first === "function") {
4461
4423
  const storageCallback = first;
4462
- return machine.events.storage.subscribe(storageCallback);
4424
+ return events.storage.subscribe(storageCallback);
4463
4425
  } else {
4464
4426
  throw new Error("Please specify a listener callback");
4465
4427
  }
@@ -4474,7 +4436,7 @@ function makeClassicSubscribeFn(machine) {
4474
4436
  return subscribeToLiveStructureShallowly(node, nodeCallback);
4475
4437
  }
4476
4438
  }
4477
- throw new Error(`"${first}" is not a valid event name`);
4439
+ throw new Error(`"${String(first)}" is not a valid event name`);
4478
4440
  }
4479
4441
  return subscribe;
4480
4442
  }
@@ -4501,7 +4463,7 @@ function prepareCreateWebSocket(liveblocksServer, WebSocketPolyfill) {
4501
4463
  // @ts-ignore (__PACKAGE_VERSION__ will be injected by the build script)
4502
4464
  true ? (
4503
4465
  /* istanbul ignore next */
4504
- "1.0.7"
4466
+ "1.0.8"
4505
4467
  ) : "dev"}`
4506
4468
  );
4507
4469
  };
@@ -4567,7 +4529,9 @@ function fetchAuthEndpoint(fetch2, endpoint, body) {
4567
4529
  data = yield res.json();
4568
4530
  } catch (er) {
4569
4531
  throw new AuthenticationError(
4570
- `Expected a JSON response when doing a POST request on "${endpoint}". ${er}`
4532
+ `Expected a JSON response when doing a POST request on "${endpoint}". ${String(
4533
+ er
4534
+ )}`
4571
4535
  );
4572
4536
  }
4573
4537
  if (!isPlainObject(data) || typeof data.token !== "string") {
@@ -4591,6 +4555,10 @@ var AuthenticationError = class extends Error {
4591
4555
  var MIN_THROTTLE = 16;
4592
4556
  var MAX_THROTTLE = 1e3;
4593
4557
  var DEFAULT_THROTTLE = 100;
4558
+ function getServerFromClientOptions(clientOptions) {
4559
+ const rawOptions = clientOptions;
4560
+ return typeof rawOptions.liveblocksServer === "string" ? rawOptions.liveblocksServer : "wss://api.liveblocks.io/v6";
4561
+ }
4594
4562
  function createClient(options) {
4595
4563
  const clientOptions = options;
4596
4564
  const throttleDelay = getThrottleDelayFromOptions(clientOptions);
@@ -4619,11 +4587,7 @@ function createClient(options) {
4619
4587
  throttleDelay,
4620
4588
  polyfills: clientOptions.polyfills,
4621
4589
  unstable_batchedUpdates: options2 == null ? void 0 : options2.unstable_batchedUpdates,
4622
- liveblocksServer: (
4623
- // TODO Patch this using public but marked internal fields?
4624
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
4625
- (clientOptions == null ? void 0 : clientOptions.liveblocksServer) || "wss://api.liveblocks.io/v6"
4626
- ),
4590
+ liveblocksServer: getServerFromClientOptions(clientOptions),
4627
4591
  authentication: prepareAuthentication(clientOptions, roomId)
4628
4592
  }
4629
4593
  );
@@ -4864,7 +4828,9 @@ function patchLiveObjectKey(liveObject, key, prev, next) {
4864
4828
  const nonSerializableValue = findNonSerializableValue(next);
4865
4829
  if (nonSerializableValue) {
4866
4830
  error(
4867
- `New state path: '${nonSerializableValue.path}' value: '${nonSerializableValue.value}' is not serializable.
4831
+ `New state path: '${nonSerializableValue.path}' value: '${String(
4832
+ nonSerializableValue.value
4833
+ )}' is not serializable.
4868
4834
  Only serializable value can be synced with Liveblocks.`
4869
4835
  );
4870
4836
  return;
@@ -4927,7 +4893,7 @@ function legacy_patchImmutableNode(state, path, update) {
4927
4893
  if (pathItem === void 0) {
4928
4894
  switch (update.type) {
4929
4895
  case "LiveObject": {
4930
- if (state === null || typeof state !== "object" || Array.isArray(state)) {
4896
+ if (!isJsonObject(state)) {
4931
4897
  throw new Error(
4932
4898
  "Internal: received update on LiveObject but state was not an object"
4933
4899
  );
@@ -4993,7 +4959,7 @@ function legacy_patchImmutableNode(state, path, update) {
4993
4959
  return newState;
4994
4960
  }
4995
4961
  case "LiveMap": {
4996
- if (state === null || typeof state !== "object" || Array.isArray(state)) {
4962
+ if (!isJsonObject(state)) {
4997
4963
  throw new Error(
4998
4964
  "Internal: received update on LiveMap but state was not an object"
4999
4965
  );
@@ -5021,12 +4987,13 @@ function legacy_patchImmutableNode(state, path, update) {
5021
4987
  update
5022
4988
  );
5023
4989
  return newArray;
5024
- } else if (state !== null && typeof state === "object") {
4990
+ } else if (isJsonObject(state)) {
5025
4991
  const node = state[pathItem];
5026
4992
  if (node === void 0) {
5027
4993
  return state;
5028
4994
  } else {
5029
- return __spreadProps(__spreadValues({}, state), {
4995
+ const stateAsObj = state;
4996
+ return __spreadProps(__spreadValues({}, stateAsObj), {
5030
4997
  [pathItem]: legacy_patchImmutableNode(node, path, update)
5031
4998
  });
5032
4999
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liveblocks/core",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "Shared code and foundational internals for Liveblocks",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -23,6 +23,7 @@
23
23
  "format": "eslint --fix src/; prettier --write src/",
24
24
  "lint": "eslint src/",
25
25
  "test": "jest --silent --verbose --color=always",
26
+ "test:types": "tsd",
26
27
  "test:watch": "jest --silent --verbose --color=always --watch",
27
28
  "test:e2e": "jest --silent --verbose --color=always --config=./jest.config.e2e.js",
28
29
  "test:deps": "depcruise src --exclude __tests__ --config",