@liveblocks/client 0.13.1 → 0.14.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/lib/cjs/room.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Others, Presence, ClientOptions, Room, MyPresenceCallback, OthersEventCallback, AuthEndpoint, EventCallback, User, Connection, ErrorCallback, AuthenticationToken, ConnectionCallback, StorageCallback, StorageUpdate } from "./types";
1
+ import { Others, Presence, ClientOptions, Room, MyPresenceCallback, OthersEventCallback, AuthEndpoint, EventCallback, User, Connection, ErrorCallback, AuthenticationToken, ConnectionCallback, StorageCallback, StorageUpdate, BroadcastOptions } from "./types";
2
2
  import { ClientMessage, Op } from "./live";
3
3
  import { LiveMap } from "./LiveMap";
4
4
  import { LiveObject } from "./LiveObject";
@@ -11,6 +11,7 @@ declare type HistoryItem = Array<Op | {
11
11
  declare type IdFactory = () => string;
12
12
  export declare type State = {
13
13
  connection: Connection;
14
+ lastConnectionId: number | null;
14
15
  socket: WebSocket | null;
15
16
  lastFlushTime: number;
16
17
  buffer: {
@@ -62,6 +63,7 @@ export declare type State = {
62
63
  nodes: Set<AbstractCrdt>;
63
64
  };
64
65
  };
66
+ offlineOperations: Map<string, Op>;
65
67
  };
66
68
  export declare type Effects = {
67
69
  authenticate(): void;
@@ -89,6 +91,12 @@ export declare function makeStateMachine(state: State, context: Context, mockedE
89
91
  authenticationSuccess: (token: AuthenticationToken, socket: WebSocket) => void;
90
92
  heartbeat: () => void;
91
93
  onNavigatorOnline: () => void;
94
+ simulateSocketClose: () => void;
95
+ simulateSendCloseEvent: (event: {
96
+ code: number;
97
+ wasClean: boolean;
98
+ reason: any;
99
+ }) => void;
92
100
  onVisibilityChange: (visibilityState: VisibilityState) => void;
93
101
  getUndoStack: () => HistoryItem[];
94
102
  getItemsCount: () => number;
@@ -118,7 +126,7 @@ export declare function makeStateMachine(state: State, context: Context, mockedE
118
126
  updatePresence: <T_4 extends Presence>(overrides: Partial<T_4>, options?: {
119
127
  addToHistory: boolean;
120
128
  } | undefined) => void;
121
- broadcastEvent: (event: any) => void;
129
+ broadcastEvent: (event: any, options?: BroadcastOptions) => void;
122
130
  batch: (callback: () => void) => void;
123
131
  undo: () => void;
124
132
  redo: () => void;
package/lib/cjs/room.js CHANGED
@@ -58,6 +58,9 @@ function makeOthers(presenceMap) {
58
58
  get count() {
59
59
  return array.length;
60
60
  },
61
+ [Symbol.iterator]() {
62
+ return array[Symbol.iterator]();
63
+ },
61
64
  map(callback) {
62
65
  return array.map(callback);
63
66
  },
@@ -129,18 +132,23 @@ function makeStateMachine(state, context, mockedEffects) {
129
132
  };
130
133
  return genericSubscribe(cb);
131
134
  }
132
- function createRootFromMessage(message) {
133
- state.root = load(message.items);
135
+ function createOrUpdateRootFromMessage(message) {
136
+ if (message.items.length === 0) {
137
+ throw new Error("Internal error: cannot load storage without items");
138
+ }
139
+ if (state.root) {
140
+ updateRoot(message.items);
141
+ }
142
+ else {
143
+ state.root = load(message.items);
144
+ }
134
145
  for (const key in state.defaultStorageRoot) {
135
146
  if (state.root.get(key) == null) {
136
147
  state.root.set(key, state.defaultStorageRoot[key]);
137
148
  }
138
149
  }
139
150
  }
140
- function load(items) {
141
- if (items.length === 0) {
142
- throw new Error("Internal error: cannot load storage without items");
143
- }
151
+ function buildRootAndParentToChildren(items) {
144
152
  const parentToChildren = new Map();
145
153
  let root = null;
146
154
  for (const tuple of items) {
@@ -161,6 +169,23 @@ function makeStateMachine(state, context, mockedEffects) {
161
169
  if (root == null) {
162
170
  throw new Error("Root can't be null");
163
171
  }
172
+ return [root, parentToChildren];
173
+ }
174
+ function updateRoot(items) {
175
+ if (!state.root) {
176
+ return;
177
+ }
178
+ const currentItems = new Map();
179
+ state.items.forEach((liveCrdt, id) => {
180
+ currentItems.set(id, liveCrdt._toSerializedCrdt());
181
+ });
182
+ // Get operations that represent the diff between 2 states.
183
+ const ops = (0, utils_1.getTreesDiffOperations)(currentItems, new Map(items));
184
+ const result = apply(ops, false);
185
+ notify(result.updates);
186
+ }
187
+ function load(items) {
188
+ const [root, parentToChildren] = buildRootAndParentToChildren(items);
164
189
  return LiveObject_1.LiveObject._deserialize(root, parentToChildren, {
165
190
  addItem,
166
191
  deleteItem,
@@ -249,7 +274,10 @@ function makeStateMachine(state, context, mockedEffects) {
249
274
  state.connection.state === "connecting") {
250
275
  return state.connection.id;
251
276
  }
252
- throw new Error("Internal. Tried to get connection id but connection is not open");
277
+ else if (state.lastConnectionId !== null) {
278
+ return state.lastConnectionId;
279
+ }
280
+ throw new Error("Internal. Tried to get connection id but connection was never open");
253
281
  }
254
282
  function generateId() {
255
283
  return `${getConnectionId()}:${state.clock++}`;
@@ -257,7 +285,7 @@ function makeStateMachine(state, context, mockedEffects) {
257
285
  function generateOpId() {
258
286
  return `${getConnectionId()}:${state.opClock++}`;
259
287
  }
260
- function apply(item) {
288
+ function apply(item, isLocal) {
261
289
  const result = {
262
290
  reverse: [],
263
291
  updates: { nodes: new Set(), presence: false },
@@ -284,7 +312,11 @@ function makeStateMachine(state, context, mockedEffects) {
284
312
  result.updates.presence = true;
285
313
  }
286
314
  else {
287
- const applyOpResult = applyOp(op);
315
+ // Ops applied after undo/redo don't have an opId.
316
+ if (isLocal && !op.opId) {
317
+ op.opId = generateOpId();
318
+ }
319
+ const applyOpResult = applyOp(op, isLocal);
288
320
  if (applyOpResult.modified) {
289
321
  result.updates.nodes.add(applyOpResult.modified);
290
322
  result.reverse.unshift(...applyOpResult.reverse);
@@ -293,7 +325,10 @@ function makeStateMachine(state, context, mockedEffects) {
293
325
  }
294
326
  return result;
295
327
  }
296
- function applyOp(op) {
328
+ function applyOp(op, isLocal) {
329
+ if (op.opId) {
330
+ state.offlineOperations.delete(op.opId);
331
+ }
297
332
  switch (op.type) {
298
333
  case live_1.OpType.DeleteObjectKey:
299
334
  case live_1.OpType.UpdateObject:
@@ -302,7 +337,7 @@ function makeStateMachine(state, context, mockedEffects) {
302
337
  if (item == null) {
303
338
  return { modified: false };
304
339
  }
305
- return item._apply(op);
340
+ return item._apply(op, isLocal);
306
341
  }
307
342
  case live_1.OpType.SetParentKey: {
308
343
  const item = state.items.get(op.id);
@@ -330,28 +365,28 @@ function makeStateMachine(state, context, mockedEffects) {
330
365
  if (parent == null || getItem(op.id) != null) {
331
366
  return { modified: false };
332
367
  }
333
- return parent._attachChild(op.id, op.parentKey, new LiveObject_1.LiveObject(op.data));
368
+ return parent._attachChild(op.id, op.parentKey, new LiveObject_1.LiveObject(op.data), isLocal);
334
369
  }
335
370
  case live_1.OpType.CreateList: {
336
371
  const parent = state.items.get(op.parentId);
337
372
  if (parent == null || getItem(op.id) != null) {
338
373
  return { modified: false };
339
374
  }
340
- return parent._attachChild(op.id, op.parentKey, new LiveList_1.LiveList());
375
+ return parent._attachChild(op.id, op.parentKey, new LiveList_1.LiveList(), isLocal);
341
376
  }
342
377
  case live_1.OpType.CreateRegister: {
343
378
  const parent = state.items.get(op.parentId);
344
379
  if (parent == null || getItem(op.id) != null) {
345
380
  return { modified: false };
346
381
  }
347
- return parent._attachChild(op.id, op.parentKey, new LiveRegister_1.LiveRegister(op.data));
382
+ return parent._attachChild(op.id, op.parentKey, new LiveRegister_1.LiveRegister(op.data), isLocal);
348
383
  }
349
384
  case live_1.OpType.CreateMap: {
350
385
  const parent = state.items.get(op.parentId);
351
386
  if (parent == null || getItem(op.id) != null) {
352
387
  return { modified: false };
353
388
  }
354
- return parent._attachChild(op.id, op.parentKey, new LiveMap_1.LiveMap());
389
+ return parent._attachChild(op.id, op.parentKey, new LiveMap_1.LiveMap(), isLocal);
355
390
  }
356
391
  }
357
392
  return { modified: false };
@@ -443,7 +478,9 @@ See v0.13 release notes for more information.
443
478
  state.socket = socket;
444
479
  }
445
480
  function authenticationFailure(error) {
446
- console.error(error);
481
+ if (process.env.NODE_ENV !== "production") {
482
+ console.error("Call to authentication endpoint failed", error);
483
+ }
447
484
  updateConnection({ state: "unavailable" });
448
485
  state.numberOfRetry++;
449
486
  state.timeoutHandles.reconnect = effects.scheduleReconnect(getRetryDelay());
@@ -571,12 +608,13 @@ See v0.13 release notes for more information.
571
608
  break;
572
609
  }
573
610
  case live_1.ServerMessageType.InitialStorageState: {
574
- createRootFromMessage(subMessage);
611
+ createOrUpdateRootFromMessage(subMessage);
612
+ applyAndSendOfflineOps();
575
613
  _getInitialStateResolver === null || _getInitialStateResolver === void 0 ? void 0 : _getInitialStateResolver();
576
614
  break;
577
615
  }
578
616
  case live_1.ServerMessageType.UpdateStorage: {
579
- const applyResult = apply(subMessage.ops);
617
+ const applyResult = apply(subMessage.ops, false);
580
618
  for (const node of applyResult.updates.nodes) {
581
619
  updates.nodes.add(node);
582
620
  }
@@ -609,13 +647,20 @@ See v0.13 release notes for more information.
609
647
  updateConnection({ state: "failed" });
610
648
  const error = new LiveblocksError(event.reason, event.code);
611
649
  for (const listener of state.listeners.error) {
650
+ if (process.env.NODE_ENV !== "production") {
651
+ console.error(`Connection to Liveblocks websocket server closed. Reason: ${error.message} (code: ${error.code})`);
652
+ }
612
653
  listener(error);
613
654
  }
614
655
  }
615
656
  else if (event.wasClean === false) {
616
- updateConnection({ state: "unavailable" });
617
657
  state.numberOfRetry++;
618
- state.timeoutHandles.reconnect = effects.scheduleReconnect(getRetryDelay());
658
+ const delay = getRetryDelay();
659
+ if (process.env.NODE_ENV !== "production") {
660
+ console.warn(`Connection to Liveblocks websocket server closed (code: ${event.code}). Retrying in ${delay}ms.`);
661
+ }
662
+ updateConnection({ state: "unavailable" });
663
+ state.timeoutHandles.reconnect = effects.scheduleReconnect(delay);
619
664
  }
620
665
  else {
621
666
  updateConnection({ state: "closed" });
@@ -639,6 +684,10 @@ See v0.13 release notes for more information.
639
684
  if (state.connection.state === "connecting") {
640
685
  updateConnection(Object.assign(Object.assign({}, state.connection), { state: "open" }));
641
686
  state.numberOfRetry = 0;
687
+ state.lastConnectionId = state.connection.id;
688
+ if (state.root) {
689
+ state.buffer.messages.push({ type: live_1.ClientMessageType.FetchStorage });
690
+ }
642
691
  tryFlushing();
643
692
  }
644
693
  else {
@@ -678,11 +727,29 @@ See v0.13 release notes for more information.
678
727
  clearInterval(state.intervalHandles.heartbeat);
679
728
  connect();
680
729
  }
681
- function tryFlushing() {
682
- if (state.socket == null) {
730
+ function applyAndSendOfflineOps() {
731
+ if (state.offlineOperations.size === 0) {
683
732
  return;
684
733
  }
685
- if (state.socket.readyState !== WebSocket.OPEN) {
734
+ const messages = [];
735
+ const ops = Array.from(state.offlineOperations.values());
736
+ const result = apply(ops, true);
737
+ messages.push({
738
+ type: live_1.ClientMessageType.UpdateStorage,
739
+ ops: ops,
740
+ });
741
+ notify(result.updates);
742
+ effects.send(messages);
743
+ }
744
+ function tryFlushing() {
745
+ const storageOps = state.buffer.storageOperations;
746
+ if (storageOps.length > 0) {
747
+ storageOps.forEach((op) => {
748
+ state.offlineOperations.set(op.opId, op);
749
+ });
750
+ }
751
+ if (state.socket == null || state.socket.readyState !== WebSocket.OPEN) {
752
+ state.buffer.storageOperations = [];
686
753
  return;
687
754
  }
688
755
  const now = Date.now();
@@ -757,8 +824,10 @@ See v0.13 release notes for more information.
757
824
  function getOthers() {
758
825
  return state.others;
759
826
  }
760
- function broadcastEvent(event) {
761
- if (state.socket == null) {
827
+ function broadcastEvent(event, options = {
828
+ shouldQueueEventIfNotReady: false,
829
+ }) {
830
+ if (state.socket == null && options.shouldQueueEventIfNotReady == false) {
762
831
  return;
763
832
  }
764
833
  state.buffer.messages.push({
@@ -800,7 +869,7 @@ See v0.13 release notes for more information.
800
869
  return;
801
870
  }
802
871
  state.isHistoryPaused = false;
803
- const result = apply(historyItem);
872
+ const result = apply(historyItem, true);
804
873
  notify(result.updates);
805
874
  state.redoStack.push(result.reverse);
806
875
  for (const op of historyItem) {
@@ -819,7 +888,7 @@ See v0.13 release notes for more information.
819
888
  return;
820
889
  }
821
890
  state.isHistoryPaused = false;
822
- const result = apply(historyItem);
891
+ const result = apply(historyItem, true);
823
892
  notify(result.updates);
824
893
  state.undoStack.push(result.reverse);
825
894
  for (const op of historyItem) {
@@ -871,6 +940,16 @@ See v0.13 release notes for more information.
871
940
  }
872
941
  state.pausedHistory = [];
873
942
  }
943
+ function simulateSocketClose() {
944
+ if (state.socket) {
945
+ state.socket.close();
946
+ }
947
+ }
948
+ function simulateSendCloseEvent(event) {
949
+ if (state.socket) {
950
+ onClose(event);
951
+ }
952
+ }
874
953
  return {
875
954
  // Internal
876
955
  onOpen,
@@ -879,6 +958,9 @@ See v0.13 release notes for more information.
879
958
  authenticationSuccess,
880
959
  heartbeat,
881
960
  onNavigatorOnline,
961
+ // Internal dev tools
962
+ simulateSocketClose,
963
+ simulateSendCloseEvent,
882
964
  // onWakeUp,
883
965
  onVisibilityChange,
884
966
  getUndoStack: () => state.undoStack,
@@ -911,6 +993,7 @@ exports.makeStateMachine = makeStateMachine;
911
993
  function defaultState(me, defaultStorageRoot) {
912
994
  return {
913
995
  connection: { state: "closed" },
996
+ lastConnectionId: null,
914
997
  socket: null,
915
998
  listeners: {
916
999
  event: [],
@@ -955,6 +1038,7 @@ function defaultState(me, defaultStorageRoot) {
955
1038
  updates: { nodes: new Set(), presence: false, others: [] },
956
1039
  reverseOps: [],
957
1040
  },
1041
+ offlineOperations: new Map(),
958
1042
  };
959
1043
  }
960
1044
  exports.defaultState = defaultState;
@@ -1001,6 +1085,11 @@ function createRoom(name, options) {
1001
1085
  pause: machine.pauseHistory,
1002
1086
  resume: machine.resumeHistory,
1003
1087
  },
1088
+ // @ts-ignore
1089
+ internalDevTools: {
1090
+ closeWebsocket: machine.simulateSocketClose,
1091
+ sendCloseEvent: machine.simulateSendCloseEvent,
1092
+ },
1004
1093
  };
1005
1094
  return {
1006
1095
  connect: machine.connect,
@@ -28,6 +28,14 @@ export declare type LiveListUpdates<TItem = any> = {
28
28
  type: "LiveList";
29
29
  node: LiveList<TItem>;
30
30
  };
31
+ export declare type BroadcastOptions = {
32
+ /**
33
+ * Whether or not event is queued if the connection is currently closed.
34
+ *
35
+ * ❗ We are not sure if we want to support this option in the future so it might be deprecated to be replaced by something else
36
+ */
37
+ shouldQueueEventIfNotReady: boolean;
38
+ };
31
39
  export declare type StorageUpdate = LiveMapUpdates | LiveObjectUpdates | LiveListUpdates;
32
40
  export declare type StorageCallback = (updates: StorageUpdate[]) => void;
33
41
  export declare type Client = {
@@ -65,6 +73,10 @@ export interface Others<TPresence extends Presence = Presence> {
65
73
  * Number of other users in the room.
66
74
  */
67
75
  readonly count: number;
76
+ /**
77
+ * Returns a new Iterator object that contains the users.
78
+ */
79
+ [Symbol.iterator](): IterableIterator<User<TPresence>>;
68
80
  /**
69
81
  * Returns the array of connected users in room.
70
82
  */
@@ -423,7 +435,7 @@ export declare type Room = {
423
435
  * }
424
436
  * });
425
437
  */
426
- broadcastEvent: (event: any) => void;
438
+ broadcastEvent: (event: any, options?: BroadcastOptions) => void;
427
439
  /**
428
440
  * Get the room's storage asynchronously.
429
441
  * The storage's root is a {@link LiveObject}.
@@ -1,8 +1,9 @@
1
1
  import { AbstractCrdt, Doc } from "./AbstractCrdt";
2
- import { SerializedCrdtWithId } from "./live";
2
+ import { SerializedCrdtWithId, Op, SerializedCrdt } from "./live";
3
3
  export declare function remove<T>(array: T[], item: T): void;
4
4
  export declare function isSameNodeOrChildOf(node: AbstractCrdt, parent: AbstractCrdt): boolean;
5
5
  export declare function deserialize(entry: SerializedCrdtWithId, parentToChildren: Map<string, SerializedCrdtWithId[]>, doc: Doc): AbstractCrdt;
6
6
  export declare function isCrdt(obj: any): obj is AbstractCrdt;
7
7
  export declare function selfOrRegisterValue(obj: AbstractCrdt): any;
8
8
  export declare function selfOrRegister(obj: any): AbstractCrdt;
9
+ export declare function getTreesDiffOperations(currentItems: Map<string, SerializedCrdt>, newItems: Map<string, SerializedCrdt>): Op[];
package/lib/cjs/utils.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.selfOrRegister = exports.selfOrRegisterValue = exports.isCrdt = exports.deserialize = exports.isSameNodeOrChildOf = exports.remove = void 0;
3
+ exports.getTreesDiffOperations = exports.selfOrRegister = exports.selfOrRegisterValue = exports.isCrdt = exports.deserialize = exports.isSameNodeOrChildOf = exports.remove = void 0;
4
4
  const live_1 = require("./live");
5
5
  const LiveList_1 = require("./LiveList");
6
6
  const LiveMap_1 = require("./LiveMap");
@@ -73,3 +73,78 @@ function selfOrRegister(obj) {
73
73
  }
74
74
  }
75
75
  exports.selfOrRegister = selfOrRegister;
76
+ function getTreesDiffOperations(currentItems, newItems) {
77
+ const ops = [];
78
+ currentItems.forEach((_, id) => {
79
+ if (!newItems.get(id)) {
80
+ // Delete crdt
81
+ ops.push({
82
+ type: live_1.OpType.DeleteCrdt,
83
+ id: id,
84
+ });
85
+ }
86
+ });
87
+ newItems.forEach((crdt, id) => {
88
+ const currentCrdt = currentItems.get(id);
89
+ if (currentCrdt) {
90
+ if (crdt.type === live_1.CrdtType.Object) {
91
+ if (JSON.stringify(crdt.data) !==
92
+ JSON.stringify(currentCrdt.data)) {
93
+ ops.push({
94
+ type: live_1.OpType.UpdateObject,
95
+ id: id,
96
+ data: crdt.data,
97
+ });
98
+ }
99
+ }
100
+ if (crdt.parentKey !== currentCrdt.parentKey) {
101
+ ops.push({
102
+ type: live_1.OpType.SetParentKey,
103
+ id: id,
104
+ parentKey: crdt.parentKey,
105
+ });
106
+ }
107
+ }
108
+ else {
109
+ // new Crdt
110
+ switch (crdt.type) {
111
+ case live_1.CrdtType.Register:
112
+ ops.push({
113
+ type: live_1.OpType.CreateRegister,
114
+ id: id,
115
+ parentId: crdt.parentId,
116
+ parentKey: crdt.parentKey,
117
+ data: crdt.data,
118
+ });
119
+ break;
120
+ case live_1.CrdtType.List:
121
+ ops.push({
122
+ type: live_1.OpType.CreateList,
123
+ id: id,
124
+ parentId: crdt.parentId,
125
+ parentKey: crdt.parentKey,
126
+ });
127
+ break;
128
+ case live_1.CrdtType.Object:
129
+ ops.push({
130
+ type: live_1.OpType.CreateObject,
131
+ id: id,
132
+ parentId: crdt.parentId,
133
+ parentKey: crdt.parentKey,
134
+ data: crdt.data,
135
+ });
136
+ break;
137
+ case live_1.CrdtType.Map:
138
+ ops.push({
139
+ type: live_1.OpType.CreateMap,
140
+ id: id,
141
+ parentId: crdt.parentId,
142
+ parentKey: crdt.parentKey,
143
+ });
144
+ break;
145
+ }
146
+ }
147
+ });
148
+ return ops;
149
+ }
150
+ exports.getTreesDiffOperations = getTreesDiffOperations;
@@ -1,4 +1,4 @@
1
- import { Op } from "./live";
1
+ import { Op, SerializedCrdt } from "./live";
2
2
  export declare type ApplyResult = {
3
3
  reverse: Op[];
4
4
  modified: AbstractCrdt;
@@ -33,7 +33,7 @@ export declare abstract class AbstractCrdt {
33
33
  /**
34
34
  * INTERNAL
35
35
  */
36
- _apply(op: Op): ApplyResult;
36
+ _apply(op: Op, isLocal: boolean): ApplyResult;
37
37
  /**
38
38
  * INTERNAL
39
39
  */
@@ -45,7 +45,7 @@ export declare abstract class AbstractCrdt {
45
45
  /**
46
46
  * INTERNAL
47
47
  */
48
- abstract _attachChild(id: string, key: string, crdt: AbstractCrdt): ApplyResult;
48
+ abstract _attachChild(id: string, key: string, crdt: AbstractCrdt, isLocal: boolean): ApplyResult;
49
49
  /**
50
50
  * INTERNAL
51
51
  */
@@ -57,5 +57,9 @@ export declare abstract class AbstractCrdt {
57
57
  /**
58
58
  * INTERNAL
59
59
  */
60
- abstract _serialize(parentId: string, parentKey: string): Op[];
60
+ abstract _serialize(parentId: string, parentKey: string, doc?: Doc): Op[];
61
+ /**
62
+ * INTERNAL
63
+ */
64
+ abstract _toSerializedCrdt(): SerializedCrdt;
61
65
  }
@@ -45,12 +45,12 @@ export class AbstractCrdt {
45
45
  /**
46
46
  * INTERNAL
47
47
  */
48
- _apply(op) {
48
+ _apply(op, isLocal) {
49
49
  switch (op.type) {
50
50
  case OpType.DeleteCrdt: {
51
51
  if (this._parent != null && this._parentKey != null) {
52
52
  const parent = this._parent;
53
- const reverse = this._serialize(this._parent._id, this._parentKey);
53
+ const reverse = this._serialize(this._parent._id, this._parentKey, __classPrivateFieldGet(this, _AbstractCrdt_doc, "f"));
54
54
  this._parent._detachChild(this);
55
55
  return { modified: parent, reverse };
56
56
  }
@@ -1,5 +1,5 @@
1
1
  import { AbstractCrdt, Doc, ApplyResult } from "./AbstractCrdt";
2
- import { SerializedList, SerializedCrdtWithId, Op } from "./live";
2
+ import { SerializedList, SerializedCrdtWithId, Op, SerializedCrdt } from "./live";
3
3
  /**
4
4
  * The LiveList class represents an ordered collection of items that is synchorinized across clients.
5
5
  */
@@ -13,7 +13,7 @@ export declare class LiveList<T> extends AbstractCrdt {
13
13
  /**
14
14
  * INTERNAL
15
15
  */
16
- _serialize(parentId?: string, parentKey?: string): Op[];
16
+ _serialize(parentId?: string, parentKey?: string, doc?: Doc): Op[];
17
17
  /**
18
18
  * INTERNAL
19
19
  */
@@ -25,7 +25,7 @@ export declare class LiveList<T> extends AbstractCrdt {
25
25
  /**
26
26
  * INTERNAL
27
27
  */
28
- _attachChild(id: string, key: string, child: AbstractCrdt): ApplyResult;
28
+ _attachChild(id: string, key: string, child: AbstractCrdt, isLocal: boolean): ApplyResult;
29
29
  /**
30
30
  * INTERNAL
31
31
  */
@@ -37,7 +37,11 @@ export declare class LiveList<T> extends AbstractCrdt {
37
37
  /**
38
38
  * INTERNAL
39
39
  */
40
- _apply(op: Op): ApplyResult;
40
+ _apply(op: Op, isLocal: boolean): ApplyResult;
41
+ /**
42
+ * INTERNAL
43
+ */
44
+ _toSerializedCrdt(): SerializedCrdt;
41
45
  /**
42
46
  * Returns the number of elements.
43
47
  */
@@ -64,6 +68,7 @@ export declare class LiveList<T> extends AbstractCrdt {
64
68
  * @param index The index of the element to delete
65
69
  */
66
70
  delete(index: number): void;
71
+ clear(): void;
67
72
  /**
68
73
  * Returns an Array of all the elements in the LiveList.
69
74
  */