@liveblocks/client 0.17.0-beta1 → 0.17.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/README.md CHANGED
@@ -18,7 +18,8 @@
18
18
  </a>
19
19
  </p>
20
20
 
21
- A client that lets you interact with [Liveblocks](https://liveblocks.io) servers.
21
+ A client that lets you interact with [Liveblocks](https://liveblocks.io)
22
+ servers.
22
23
 
23
24
  ## Installation
24
25
 
@@ -28,25 +29,33 @@ npm install @liveblocks/client
28
29
 
29
30
  ## Documentation
30
31
 
31
- - [Read the documentation](https://liveblocks.io/docs) to start using Liveblocks.
32
- - Explore the [API Reference](https://liveblocks.io/docs/api-reference/liveblocks-client).
32
+ - [Read the documentation](https://liveblocks.io/docs) to start using
33
+ Liveblocks.
34
+ - Explore the
35
+ [API Reference](https://liveblocks.io/docs/api-reference/liveblocks-client).
33
36
 
34
37
  ## Examples
35
38
 
36
- - Browse our gallery of collaborative UI patterns. [View examples gallery](https://liveblocks.io/examples)
37
- - Explore and clone any of our open-source examples. [View code examples](https://github.com/liveblocks/liveblocks/tree/main/examples)
39
+ - Browse our gallery of collaborative UI patterns.
40
+ [View examples gallery](https://liveblocks.io/examples)
41
+ - Explore and clone any of our open-source examples.
42
+ [View code examples](https://github.com/liveblocks/liveblocks/tree/main/examples)
38
43
 
39
44
  ## Releases
40
45
 
41
- For changelog, visit [https://github.com/liveblocks/liveblocks/releases](https://github.com/liveblocks/liveblocks/releases).
46
+ For changelog, visit
47
+ [https://github.com/liveblocks/liveblocks/releases](https://github.com/liveblocks/liveblocks/releases).
42
48
 
43
49
  ## Community
44
50
 
45
- - [Discord](https://discord.gg/X4YWJuH9VY) - To get involved with the Liveblocks community, ask questions and share tips.
46
- - [Twitter](https://twitter.com/liveblocks) - To receive updates, announcements, blog posts, and general Liveblocks tips.
51
+ - [Discord](https://discord.gg/X4YWJuH9VY) - To get involved with the Liveblocks
52
+ community, ask questions and share tips.
53
+ - [Twitter](https://twitter.com/liveblocks) - To receive updates, announcements,
54
+ blog posts, and general Liveblocks tips.
47
55
 
48
56
  ## License
49
57
 
50
- Licensed under the Apache License 2.0, Copyright © 2021-present [Liveblocks](https://liveblocks.io).
58
+ Licensed under the Apache License 2.0, Copyright © 2021-present
59
+ [Liveblocks](https://liveblocks.io).
51
60
 
52
61
  See [LICENSE](../../LICENSE) for more information.
package/index.js CHANGED
@@ -413,7 +413,9 @@ function makeStateMachine(state, context, mockedEffects) {
413
413
  );
414
414
  var ws = WebSocketPolyfill || WebSocket;
415
415
  return function (token) {
416
- return new ws(liveblocksServer + "/?token=" + token);
416
+ return new ws(
417
+ liveblocksServer + "/?token=" + token + "&version=0.17.0"
418
+ );
417
419
  };
418
420
  })(
419
421
  context.liveblocksServer,
package/index.mjs CHANGED
@@ -336,7 +336,8 @@ function makeStateMachine(state, context, mockedEffects) {
336
336
  "To use Liveblocks client in a non-dom environment, you need to provide a WebSocket polyfill."
337
337
  );
338
338
  const ws = WebSocketPolyfill || WebSocket;
339
- return (token) => new ws(`${liveblocksServer}/?token=${token}`);
339
+ return (token) =>
340
+ new ws(`${liveblocksServer}/?token=${token}&version=0.17.0`);
340
341
  })(
341
342
  context.liveblocksServer,
342
343
  null !==
package/internal.d.ts CHANGED
@@ -123,14 +123,14 @@ declare enum ClientMsgCode {
123
123
  /**
124
124
  * Messages that can be sent from the client to the server.
125
125
  */
126
- declare type ClientMsg<TPresence extends JsonObject, TEvent extends Json> =
127
- | BroadcastEventClientMsg<TEvent>
126
+ declare type ClientMsg<TPresence extends JsonObject, TRoomEvent extends Json> =
127
+ | BroadcastEventClientMsg<TRoomEvent>
128
128
  | UpdatePresenceClientMsg<TPresence>
129
129
  | UpdateStorageClientMsg
130
130
  | FetchStorageClientMsg;
131
- declare type BroadcastEventClientMsg<TEvent extends Json> = {
131
+ declare type BroadcastEventClientMsg<TRoomEvent extends Json> = {
132
132
  type: ClientMsgCode.BROADCAST_EVENT;
133
- event: TEvent;
133
+ event: TRoomEvent;
134
134
  };
135
135
  declare type UpdatePresenceClientMsg<TPresence extends JsonObject> = {
136
136
  type: ClientMsgCode.UPDATE_PRESENCE;
@@ -220,12 +220,12 @@ declare enum ServerMsgCode {
220
220
  declare type ServerMsg<
221
221
  TPresence extends JsonObject,
222
222
  TUserMeta extends BaseUserMeta,
223
- TEvent extends Json
223
+ TRoomEvent extends Json
224
224
  > =
225
225
  | UpdatePresenceServerMsg<TPresence>
226
226
  | UserJoinServerMsg<TUserMeta>
227
227
  | UserLeftServerMsg
228
- | BroadcastedEventServerMsg<TEvent>
228
+ | BroadcastedEventServerMsg<TRoomEvent>
229
229
  | RoomStateServerMsg<TUserMeta>
230
230
  | InitialDocumentStateServerMsg
231
231
  | UpdateStorageServerMsg;
@@ -289,7 +289,7 @@ declare type UserLeftServerMsg = {
289
289
  * Sent by the WebSocket server and broadcasted to all clients to announce that
290
290
  * a User broadcasted an Event to everyone in the Room.
291
291
  */
292
- declare type BroadcastedEventServerMsg<TEvent extends Json> = {
292
+ declare type BroadcastedEventServerMsg<TRoomEvent extends Json> = {
293
293
  type: ServerMsgCode.BROADCASTED_EVENT;
294
294
  /**
295
295
  * The User who broadcasted the Event.
@@ -299,7 +299,7 @@ declare type BroadcastedEventServerMsg<TEvent extends Json> = {
299
299
  * The arbitrary payload of the Event. This can be any JSON value. Clients
300
300
  * will have to manually verify/decode this event.
301
301
  */
302
- event: TEvent;
302
+ event: TRoomEvent;
303
303
  };
304
304
  /**
305
305
  * Sent by the WebSocket server to a single client in response to the client
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liveblocks/client",
3
- "version": "0.17.0-beta1",
3
+ "version": "0.17.0",
4
4
  "description": "A client that lets you interact with Liveblocks servers.",
5
5
  "main": "./index.js",
6
6
  "module": "./index.mjs",
package/shared.d.ts CHANGED
@@ -303,12 +303,12 @@ declare type OthersEventCallback<
303
303
  others: Others<TPresence, TUserMeta>,
304
304
  event: OthersEvent<TPresence, TUserMeta>
305
305
  ) => void;
306
- declare type EventCallback<TEvent extends Json> = ({
306
+ declare type EventCallback<TRoomEvent extends Json> = ({
307
307
  connectionId,
308
308
  event,
309
309
  }: {
310
310
  connectionId: number;
311
- event: TEvent;
311
+ event: TRoomEvent;
312
312
  }) => void;
313
313
  declare type ErrorCallback = (error: Error) => void;
314
314
  declare type ConnectionCallback = (state: ConnectionState) => void;
@@ -426,12 +426,12 @@ declare type Client = {
426
426
  */
427
427
  getRoom<
428
428
  TPresence extends JsonObject,
429
- TStorage extends LsonObject,
430
- TUserMeta extends BaseUserMeta,
431
- TEvent extends Json
429
+ TStorage extends LsonObject = LsonObject,
430
+ TUserMeta extends BaseUserMeta = BaseUserMeta,
431
+ TRoomEvent extends Json = never
432
432
  >(
433
433
  roomId: string
434
- ): Room<TPresence, TStorage, TUserMeta, TEvent> | null;
434
+ ): Room<TPresence, TStorage, TUserMeta, TRoomEvent> | null;
435
435
  /**
436
436
  * Enters a room and returns it.
437
437
  * @param roomId The id of the room
@@ -439,13 +439,13 @@ declare type Client = {
439
439
  */
440
440
  enter<
441
441
  TPresence extends JsonObject,
442
- TStorage extends LsonObject,
443
- TUserMeta extends BaseUserMeta,
444
- TEvent extends Json
442
+ TStorage extends LsonObject = LsonObject,
443
+ TUserMeta extends BaseUserMeta = BaseUserMeta,
444
+ TRoomEvent extends Json = never
445
445
  >(
446
446
  roomId: string,
447
447
  options?: RoomInitializers<TPresence, TStorage>
448
- ): Room<TPresence, TStorage, TUserMeta, TEvent>;
448
+ ): Room<TPresence, TStorage, TUserMeta, TRoomEvent>;
449
449
  /**
450
450
  * Leaves a room.
451
451
  * @param roomId The id of the room
@@ -635,7 +635,7 @@ declare type Room<
635
635
  TPresence extends JsonObject,
636
636
  TStorage extends LsonObject,
637
637
  TUserMeta extends BaseUserMeta,
638
- TEvent extends Json
638
+ TRoomEvent extends Json
639
639
  > = {
640
640
  /**
641
641
  * The id of the room.
@@ -678,7 +678,7 @@ declare type Room<
678
678
  * // Do something
679
679
  * });
680
680
  */
681
- (type: "event", listener: EventCallback<TEvent>): () => void;
681
+ (type: "event", listener: EventCallback<TRoomEvent>): () => void;
682
682
  /**
683
683
  * Subscribe to errors thrown in the room.
684
684
  */
@@ -789,7 +789,7 @@ declare type Room<
789
789
  * }
790
790
  * });
791
791
  */
792
- broadcastEvent: (event: TEvent, options?: BroadcastOptions) => void;
792
+ broadcastEvent: (event: TRoomEvent, options?: BroadcastOptions) => void;
793
793
  /**
794
794
  * Get the room's storage asynchronously.
795
795
  * The storage's root is a {@link LiveObject}.
package/shared.js CHANGED
@@ -945,14 +945,14 @@ var LiveList = (function (_AbstractCrdt) {
945
945
  var parentKey = nn(child._parentKey),
946
946
  reverse = child._serialize(nn(this._id), parentKey, this._doc),
947
947
  indexToDelete = this._items.indexOf(child);
948
- return (
949
- this._items.splice(indexToDelete, 1),
950
- child._detach(),
951
- {
952
- modified: makeUpdate(this, [deleteDelta(indexToDelete)]),
953
- reverse: reverse,
954
- }
955
- );
948
+ return -1 === indexToDelete
949
+ ? { modified: !1 }
950
+ : (this._items.splice(indexToDelete, 1),
951
+ child._detach(),
952
+ {
953
+ modified: makeUpdate(this, [deleteDelta(indexToDelete)]),
954
+ reverse: reverse,
955
+ });
956
956
  }
957
957
  return { modified: !1 };
958
958
  }),
@@ -1448,10 +1448,12 @@ var LiveMap = (function (_AbstractCrdt) {
1448
1448
  var _this;
1449
1449
  if (
1450
1450
  (((_this = _AbstractCrdt.call(this) || this)._map = void 0),
1451
+ (_this.unacknowledgedSet = void 0),
1451
1452
  errorIf(
1452
1453
  null === entries,
1453
1454
  "Support for calling `new LiveMap(null)` will be removed in @liveblocks/client 0.18. Please call as `new LiveMap()`, or `new LiveMap([])`."
1454
1455
  ),
1456
+ (_this.unacknowledgedSet = new Map()),
1455
1457
  entries)
1456
1458
  ) {
1457
1459
  for (
@@ -1531,14 +1533,24 @@ var LiveMap = (function (_AbstractCrdt) {
1531
1533
  isLiveNode(_value3) && _value3._attach(doc.generateId(), doc);
1532
1534
  }
1533
1535
  }),
1534
- (_proto._attachChild = function (op) {
1536
+ (_proto._attachChild = function (op, source) {
1535
1537
  var _updates;
1536
1538
  if (null == this._doc)
1537
1539
  throw new Error("Can't attach child if doc is not present");
1538
1540
  var id = op.id,
1539
- key = op.parentKey,
1541
+ parentKey = op.parentKey,
1542
+ opId = op.opId,
1543
+ key = parentKey,
1540
1544
  child = creationOpToLiveNode(op);
1541
1545
  if (void 0 !== this._doc.getItem(id)) return { modified: !1 };
1546
+ if (source === exports.OpSource.ACK) {
1547
+ var lastUpdateOpId = this.unacknowledgedSet.get(key);
1548
+ if (lastUpdateOpId === opId)
1549
+ return this.unacknowledgedSet.delete(key), { modified: !1 };
1550
+ if (null != lastUpdateOpId) return { modified: !1 };
1551
+ } else
1552
+ source === exports.OpSource.REMOTE &&
1553
+ this.unacknowledgedSet.delete(key);
1542
1554
  var reverse,
1543
1555
  previousValue = this._map.get(key);
1544
1556
  if (previousValue) {
@@ -1637,7 +1649,9 @@ var LiveMap = (function (_AbstractCrdt) {
1637
1649
  ((_updates3 = {}),
1638
1650
  (_updates3[key] = { type: "update" }),
1639
1651
  _updates3),
1640
- }),
1652
+ });
1653
+ var ops = item._serialize(this._id, key, this._doc);
1654
+ this.unacknowledgedSet.set(key, nn(ops[0].opId)),
1641
1655
  this._doc.dispatch(
1642
1656
  item._serialize(this._id, key, this._doc),
1643
1657
  oldValue
package/shared.mjs CHANGED
@@ -693,14 +693,14 @@ class LiveList extends AbstractCrdt {
693
693
  const parentKey = nn(child._parentKey),
694
694
  reverse = child._serialize(nn(this._id), parentKey, this._doc),
695
695
  indexToDelete = this._items.indexOf(child);
696
- return (
697
- this._items.splice(indexToDelete, 1),
698
- child._detach(),
699
- {
700
- modified: makeUpdate(this, [deleteDelta(indexToDelete)]),
701
- reverse: reverse,
702
- }
703
- );
696
+ return -1 === indexToDelete
697
+ ? { modified: !1 }
698
+ : (this._items.splice(indexToDelete, 1),
699
+ child._detach(),
700
+ {
701
+ modified: makeUpdate(this, [deleteDelta(indexToDelete)]),
702
+ reverse: reverse,
703
+ });
704
704
  }
705
705
  return { modified: !1 };
706
706
  }
@@ -1152,6 +1152,7 @@ class LiveMap extends AbstractCrdt {
1152
1152
  null === entries,
1153
1153
  "Support for calling `new LiveMap(null)` will be removed in @liveblocks/client 0.18. Please call as `new LiveMap()`, or `new LiveMap([])`."
1154
1154
  ),
1155
+ (this.unacknowledgedSet = new Map()),
1155
1156
  entries)
1156
1157
  ) {
1157
1158
  const mappedEntries = [];
@@ -1196,12 +1197,19 @@ class LiveMap extends AbstractCrdt {
1196
1197
  for (const [_key, value] of this._map)
1197
1198
  isLiveNode(value) && value._attach(doc.generateId(), doc);
1198
1199
  }
1199
- _attachChild(op) {
1200
+ _attachChild(op, source) {
1200
1201
  if (null == this._doc)
1201
1202
  throw new Error("Can't attach child if doc is not present");
1202
- const { id: id, parentKey: key } = op,
1203
+ const { id: id, parentKey: parentKey, opId: opId } = op,
1204
+ key = parentKey,
1203
1205
  child = creationOpToLiveNode(op);
1204
1206
  if (void 0 !== this._doc.getItem(id)) return { modified: !1 };
1207
+ if (source === OpSource.ACK) {
1208
+ const lastUpdateOpId = this.unacknowledgedSet.get(key);
1209
+ if (lastUpdateOpId === opId)
1210
+ return this.unacknowledgedSet.delete(key), { modified: !1 };
1211
+ if (null != lastUpdateOpId) return { modified: !1 };
1212
+ } else source === OpSource.REMOTE && this.unacknowledgedSet.delete(key);
1205
1213
  const previousValue = this._map.get(key);
1206
1214
  let reverse;
1207
1215
  if (previousValue) {
@@ -1272,7 +1280,9 @@ class LiveMap extends AbstractCrdt {
1272
1280
  node: this,
1273
1281
  type: "LiveMap",
1274
1282
  updates: { [key]: { type: "update" } },
1275
- }),
1283
+ });
1284
+ const ops = item._serialize(this._id, key, this._doc);
1285
+ this.unacknowledgedSet.set(key, nn(ops[0].opId)),
1276
1286
  this._doc.dispatch(
1277
1287
  item._serialize(this._id, key, this._doc),
1278
1288
  oldValue