@liveblocks/client 0.13.2 → 0.14.1

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 (41) hide show
  1. package/lib/cjs/AbstractCrdt.d.ts +8 -4
  2. package/lib/cjs/AbstractCrdt.js +2 -2
  3. package/lib/cjs/LiveList.d.ts +9 -4
  4. package/lib/cjs/LiveList.js +58 -9
  5. package/lib/cjs/LiveMap.d.ts +7 -3
  6. package/lib/cjs/LiveMap.js +23 -5
  7. package/lib/cjs/LiveObject.d.ts +17 -7
  8. package/lib/cjs/LiveObject.js +45 -15
  9. package/lib/cjs/LiveRegister.d.ts +8 -4
  10. package/lib/cjs/LiveRegister.js +17 -4
  11. package/lib/cjs/client.js +50 -7
  12. package/lib/cjs/{immutable/index.d.ts → immutable.d.ts} +5 -3
  13. package/lib/cjs/{immutable/index.js → immutable.js} +98 -21
  14. package/lib/cjs/index.d.ts +1 -1
  15. package/lib/cjs/live.d.ts +7 -0
  16. package/lib/cjs/room.d.ts +17 -9
  17. package/lib/cjs/room.js +203 -81
  18. package/lib/cjs/types.d.ts +26 -1
  19. package/lib/cjs/utils.d.ts +2 -1
  20. package/lib/cjs/utils.js +76 -1
  21. package/lib/esm/AbstractCrdt.d.ts +8 -4
  22. package/lib/esm/AbstractCrdt.js +2 -2
  23. package/lib/esm/LiveList.d.ts +9 -4
  24. package/lib/esm/LiveList.js +59 -10
  25. package/lib/esm/LiveMap.d.ts +7 -3
  26. package/lib/esm/LiveMap.js +23 -5
  27. package/lib/esm/LiveObject.d.ts +17 -7
  28. package/lib/esm/LiveObject.js +45 -15
  29. package/lib/esm/LiveRegister.d.ts +8 -4
  30. package/lib/esm/LiveRegister.js +18 -5
  31. package/lib/esm/client.js +50 -7
  32. package/lib/esm/{immutable/index.d.ts → immutable.d.ts} +5 -3
  33. package/lib/esm/{immutable/index.js → immutable.js} +96 -21
  34. package/lib/esm/index.d.ts +1 -1
  35. package/lib/esm/live.d.ts +7 -0
  36. package/lib/esm/room.d.ts +17 -9
  37. package/lib/esm/room.js +203 -62
  38. package/lib/esm/types.d.ts +26 -1
  39. package/lib/esm/utils.d.ts +2 -1
  40. package/lib/esm/utils.js +75 -1
  41. package/package.json +6 -2
@@ -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
  }
@@ -48,12 +48,12 @@ class AbstractCrdt {
48
48
  /**
49
49
  * INTERNAL
50
50
  */
51
- _apply(op) {
51
+ _apply(op, isLocal) {
52
52
  switch (op.type) {
53
53
  case live_1.OpType.DeleteCrdt: {
54
54
  if (this._parent != null && this._parentKey != null) {
55
55
  const parent = this._parent;
56
- const reverse = this._serialize(this._parent._id, this._parentKey);
56
+ const reverse = this._serialize(this._parent._id, this._parentKey, __classPrivateFieldGet(this, _AbstractCrdt_doc, "f"));
57
57
  this._parent._detachChild(this);
58
58
  return { modified: parent, reverse };
59
59
  }
@@ -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
  */
@@ -54,7 +54,7 @@ class LiveList extends AbstractCrdt_1.AbstractCrdt {
54
54
  /**
55
55
  * INTERNAL
56
56
  */
57
- _serialize(parentId, parentKey) {
57
+ _serialize(parentId, parentKey, doc) {
58
58
  if (this._id == null) {
59
59
  throw new Error("Cannot serialize item is not attached");
60
60
  }
@@ -64,13 +64,14 @@ class LiveList extends AbstractCrdt_1.AbstractCrdt {
64
64
  const ops = [];
65
65
  const op = {
66
66
  id: this._id,
67
+ opId: doc === null || doc === void 0 ? void 0 : doc.generateOpId(),
67
68
  type: live_1.OpType.CreateList,
68
69
  parentId,
69
70
  parentKey,
70
71
  };
71
72
  ops.push(op);
72
73
  for (const [value, key] of __classPrivateFieldGet(this, _LiveList_items, "f")) {
73
- ops.push(...value._serialize(this._id, key));
74
+ ops.push(...value._serialize(this._id, key, doc));
74
75
  }
75
76
  return ops;
76
77
  }
@@ -95,7 +96,7 @@ class LiveList extends AbstractCrdt_1.AbstractCrdt {
95
96
  /**
96
97
  * INTERNAL
97
98
  */
98
- _attachChild(id, key, child) {
99
+ _attachChild(id, key, child, isLocal) {
99
100
  var _a;
100
101
  if (this._doc == null) {
101
102
  throw new Error("Can't attach child if doc is not present");
@@ -103,11 +104,24 @@ class LiveList extends AbstractCrdt_1.AbstractCrdt {
103
104
  child._attach(id, this._doc);
104
105
  child._setParentLink(this, key);
105
106
  const index = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((entry) => entry[1] === key);
106
- // Assign a temporary position until we get the fix from the backend
107
+ let newKey = key;
108
+ // If there is a conflict
107
109
  if (index !== -1) {
108
- __classPrivateFieldGet(this, _LiveList_items, "f")[index][1] = (0, position_1.makePosition)(key, (_a = __classPrivateFieldGet(this, _LiveList_items, "f")[index + 1]) === null || _a === void 0 ? void 0 : _a[1]);
110
+ if (isLocal) {
111
+ // If change is local => assign a temporary position to newly attached child
112
+ let before = __classPrivateFieldGet(this, _LiveList_items, "f")[index] ? __classPrivateFieldGet(this, _LiveList_items, "f")[index][1] : undefined;
113
+ let after = __classPrivateFieldGet(this, _LiveList_items, "f")[index + 1]
114
+ ? __classPrivateFieldGet(this, _LiveList_items, "f")[index + 1][1]
115
+ : undefined;
116
+ newKey = (0, position_1.makePosition)(before, after);
117
+ child._setParentLink(this, newKey);
118
+ }
119
+ else {
120
+ // If change is remote => assign a temporary position to existing child until we get the fix from the backend
121
+ __classPrivateFieldGet(this, _LiveList_items, "f")[index][1] = (0, position_1.makePosition)(key, (_a = __classPrivateFieldGet(this, _LiveList_items, "f")[index + 1]) === null || _a === void 0 ? void 0 : _a[1]);
122
+ }
109
123
  }
110
- __classPrivateFieldGet(this, _LiveList_items, "f").push([child, key]);
124
+ __classPrivateFieldGet(this, _LiveList_items, "f").push([child, newKey]);
111
125
  __classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => (0, position_1.compare)(itemA[1], itemB[1]));
112
126
  return { reverse: [{ type: live_1.OpType.DeleteCrdt, id }], modified: this };
113
127
  }
@@ -141,8 +155,19 @@ class LiveList extends AbstractCrdt_1.AbstractCrdt {
141
155
  /**
142
156
  * INTERNAL
143
157
  */
144
- _apply(op) {
145
- return super._apply(op);
158
+ _apply(op, isLocal) {
159
+ return super._apply(op, isLocal);
160
+ }
161
+ /**
162
+ * INTERNAL
163
+ */
164
+ _toSerializedCrdt() {
165
+ var _a;
166
+ return {
167
+ type: live_1.CrdtType.List,
168
+ parentId: (_a = this._parent) === null || _a === void 0 ? void 0 : _a._id,
169
+ parentKey: this._parentKey,
170
+ };
146
171
  }
147
172
  /**
148
173
  * Returns the number of elements.
@@ -176,7 +201,7 @@ class LiveList extends AbstractCrdt_1.AbstractCrdt {
176
201
  if (this._doc && this._id) {
177
202
  const id = this._doc.generateId();
178
203
  value._attach(id, this._doc);
179
- this._doc.dispatch(value._serialize(this._id, position), [{ type: live_1.OpType.DeleteCrdt, id }], [this]);
204
+ this._doc.dispatch(value._serialize(this._id, position, this._doc), [{ type: live_1.OpType.DeleteCrdt, id }], [this]);
180
205
  }
181
206
  }
182
207
  /**
@@ -222,6 +247,7 @@ class LiveList extends AbstractCrdt_1.AbstractCrdt {
222
247
  {
223
248
  type: live_1.OpType.SetParentKey,
224
249
  id: item[0]._id,
250
+ opId: this._doc.generateOpId(),
225
251
  parentKey: position,
226
252
  },
227
253
  ], [
@@ -250,12 +276,35 @@ class LiveList extends AbstractCrdt_1.AbstractCrdt {
250
276
  this._doc.dispatch([
251
277
  {
252
278
  id: childRecordId,
279
+ opId: this._doc.generateOpId(),
253
280
  type: live_1.OpType.DeleteCrdt,
254
281
  },
255
282
  ], item[0]._serialize(this._id, item[1]), [this]);
256
283
  }
257
284
  }
258
285
  }
286
+ clear() {
287
+ if (this._doc) {
288
+ let ops = [];
289
+ let reverseOps = [];
290
+ for (const item of __classPrivateFieldGet(this, _LiveList_items, "f")) {
291
+ item[0]._detach();
292
+ const childId = item[0]._id;
293
+ if (childId) {
294
+ ops.push({ id: childId, type: live_1.OpType.DeleteCrdt });
295
+ reverseOps.push(...item[0]._serialize(this._id, item[1]));
296
+ }
297
+ }
298
+ __classPrivateFieldSet(this, _LiveList_items, [], "f");
299
+ this._doc.dispatch(ops, reverseOps, [this]);
300
+ }
301
+ else {
302
+ for (const item of __classPrivateFieldGet(this, _LiveList_items, "f")) {
303
+ item[0]._detach();
304
+ }
305
+ __classPrivateFieldSet(this, _LiveList_items, [], "f");
306
+ }
307
+ }
259
308
  /**
260
309
  * Returns an Array of all the elements in the LiveList.
261
310
  */
@@ -1,5 +1,5 @@
1
1
  import { AbstractCrdt, Doc, ApplyResult } from "./AbstractCrdt";
2
- import { Op, SerializedCrdtWithId } from "./live";
2
+ import { Op, SerializedCrdtWithId, SerializedCrdt } from "./live";
3
3
  /**
4
4
  * The LiveMap class is similar to a JavaScript Map that is synchronized on all clients.
5
5
  * Keys should be a string, and values should be serializable to JSON.
@@ -11,7 +11,7 @@ export declare class LiveMap<TKey extends string, TValue> extends AbstractCrdt {
11
11
  /**
12
12
  * INTERNAL
13
13
  */
14
- _serialize(parentId?: string, parentKey?: string): Op[];
14
+ _serialize(parentId?: string, parentKey?: string, doc?: Doc): Op[];
15
15
  /**
16
16
  * INTERNAL
17
17
  */
@@ -23,7 +23,7 @@ export declare class LiveMap<TKey extends string, TValue> extends AbstractCrdt {
23
23
  /**
24
24
  * INTERNAL
25
25
  */
26
- _attachChild(id: string, key: TKey, child: AbstractCrdt): ApplyResult;
26
+ _attachChild(id: string, key: TKey, child: AbstractCrdt, isLocal: boolean): ApplyResult;
27
27
  /**
28
28
  * INTERNAL
29
29
  */
@@ -32,6 +32,10 @@ export declare class LiveMap<TKey extends string, TValue> extends AbstractCrdt {
32
32
  * INTERNAL
33
33
  */
34
34
  _detachChild(child: AbstractCrdt): void;
35
+ /**
36
+ * INTERNAL
37
+ */
38
+ _toSerializedCrdt(): SerializedCrdt;
35
39
  /**
36
40
  * Returns a specified element from the LiveMap.
37
41
  * @param key The key of the element to return.
@@ -41,7 +41,7 @@ class LiveMap extends AbstractCrdt_1.AbstractCrdt {
41
41
  /**
42
42
  * INTERNAL
43
43
  */
44
- _serialize(parentId, parentKey) {
44
+ _serialize(parentId, parentKey, doc) {
45
45
  if (this._id == null) {
46
46
  throw new Error("Cannot serialize item is not attached");
47
47
  }
@@ -51,13 +51,14 @@ class LiveMap extends AbstractCrdt_1.AbstractCrdt {
51
51
  const ops = [];
52
52
  const op = {
53
53
  id: this._id,
54
+ opId: doc === null || doc === void 0 ? void 0 : doc.generateOpId(),
54
55
  type: live_1.OpType.CreateMap,
55
56
  parentId,
56
57
  parentKey,
57
58
  };
58
59
  ops.push(op);
59
60
  for (const [key, value] of __classPrivateFieldGet(this, _LiveMap_map, "f")) {
60
- ops.push(...value._serialize(this._id, key));
61
+ ops.push(...value._serialize(this._id, key, doc));
61
62
  }
62
63
  return ops;
63
64
  }
@@ -99,7 +100,7 @@ class LiveMap extends AbstractCrdt_1.AbstractCrdt {
99
100
  /**
100
101
  * INTERNAL
101
102
  */
102
- _attachChild(id, key, child) {
103
+ _attachChild(id, key, child, isLocal) {
103
104
  if (this._doc == null) {
104
105
  throw new Error("Can't attach child if doc is not present");
105
106
  }
@@ -137,6 +138,17 @@ class LiveMap extends AbstractCrdt_1.AbstractCrdt {
137
138
  }
138
139
  child._detach();
139
140
  }
141
+ /**
142
+ * INTERNAL
143
+ */
144
+ _toSerializedCrdt() {
145
+ var _a;
146
+ return {
147
+ type: live_1.CrdtType.Map,
148
+ parentId: (_a = this._parent) === null || _a === void 0 ? void 0 : _a._id,
149
+ parentKey: this._parentKey,
150
+ };
151
+ }
140
152
  /**
141
153
  * Returns a specified element from the LiveMap.
142
154
  * @param key The key of the element to return.
@@ -165,7 +177,7 @@ class LiveMap extends AbstractCrdt_1.AbstractCrdt {
165
177
  if (this._doc && this._id) {
166
178
  const id = this._doc.generateId();
167
179
  item._attach(id, this._doc);
168
- this._doc.dispatch(item._serialize(this._id, key), oldValue
180
+ this._doc.dispatch(item._serialize(this._id, key, this._doc), oldValue
169
181
  ? oldValue._serialize(this._id, key)
170
182
  : [{ type: live_1.OpType.DeleteCrdt, id }], [this]);
171
183
  }
@@ -195,7 +207,13 @@ class LiveMap extends AbstractCrdt_1.AbstractCrdt {
195
207
  }
196
208
  item._detach();
197
209
  if (this._doc && item._id) {
198
- this._doc.dispatch([{ type: live_1.OpType.DeleteCrdt, id: item._id }], item._serialize(this._id, key), [this]);
210
+ this._doc.dispatch([
211
+ {
212
+ type: live_1.OpType.DeleteCrdt,
213
+ id: item._id,
214
+ opId: this._doc.generateOpId(),
215
+ },
216
+ ], item._serialize(this._id, key), [this]);
199
217
  }
200
218
  __classPrivateFieldGet(this, _LiveMap_map, "f").delete(key);
201
219
  return true;
@@ -1,5 +1,5 @@
1
1
  import { AbstractCrdt, Doc, ApplyResult } from "./AbstractCrdt";
2
- import { Op, SerializedCrdtWithId } from "./live";
2
+ import { Op, SerializedCrdt, SerializedCrdtWithId } from "./live";
3
3
  /**
4
4
  * The LiveObject class is similar to a JavaScript object that is synchronized on all clients.
5
5
  * Keys should be a string, and values should be serializable to JSON.
@@ -11,13 +11,15 @@ export declare class LiveObject<T extends Record<string, any> = Record<string, a
11
11
  /**
12
12
  * INTERNAL
13
13
  */
14
- _serialize(parentId?: string, parentKey?: string): Op[];
14
+ _serialize(parentId?: string, parentKey?: string, doc?: Doc): Op[];
15
15
  /**
16
16
  * INTERNAL
17
17
  */
18
- static _deserialize([id, item]: SerializedCrdtWithId, parentToChildren: Map<string, SerializedCrdtWithId[]>, doc: Doc): LiveObject<{
19
- [key: string]: any;
20
- }>;
18
+ static _deserialize([id, item]: SerializedCrdtWithId, parentToChildren: Map<string, SerializedCrdtWithId[]>, doc: Doc): LiveObject<Record<string, any>>;
19
+ /**
20
+ * INTERNAL
21
+ */
22
+ static _deserializeChildren(object: LiveObject, parentToChildren: Map<string, SerializedCrdtWithId[]>, doc: Doc): LiveObject<Record<string, any>>;
21
23
  /**
22
24
  * INTERNAL
23
25
  */
@@ -25,11 +27,15 @@ export declare class LiveObject<T extends Record<string, any> = Record<string, a
25
27
  /**
26
28
  * INTERNAL
27
29
  */
28
- _attachChild(id: string, key: keyof T, child: AbstractCrdt): ApplyResult;
30
+ _attachChild(id: string, key: keyof T, child: AbstractCrdt, isLocal: boolean): ApplyResult;
29
31
  /**
30
32
  * INTERNAL
31
33
  */
32
34
  _detachChild(child: AbstractCrdt): void;
35
+ /**
36
+ * INTERNAL
37
+ */
38
+ _detachChildren(): void;
33
39
  /**
34
40
  * INTERNAL
35
41
  */
@@ -37,7 +43,11 @@ export declare class LiveObject<T extends Record<string, any> = Record<string, a
37
43
  /**
38
44
  * INTERNAL
39
45
  */
40
- _apply(op: Op): ApplyResult;
46
+ _apply(op: Op, isLocal: boolean): ApplyResult;
47
+ /**
48
+ * INTERNAL
49
+ */
50
+ _toSerializedCrdt(): SerializedCrdt;
41
51
  /**
42
52
  * Transform the LiveObject into a javascript object
43
53
  */
@@ -38,13 +38,14 @@ class LiveObject extends AbstractCrdt_1.AbstractCrdt {
38
38
  /**
39
39
  * INTERNAL
40
40
  */
41
- _serialize(parentId, parentKey) {
41
+ _serialize(parentId, parentKey, doc) {
42
42
  if (this._id == null) {
43
43
  throw new Error("Cannot serialize item is not attached");
44
44
  }
45
45
  const ops = [];
46
46
  const op = {
47
47
  id: this._id,
48
+ opId: doc === null || doc === void 0 ? void 0 : doc.generateOpId(),
48
49
  type: live_1.OpType.CreateObject,
49
50
  parentId,
50
51
  parentKey,
@@ -53,7 +54,7 @@ class LiveObject extends AbstractCrdt_1.AbstractCrdt {
53
54
  ops.push(op);
54
55
  for (const [key, value] of __classPrivateFieldGet(this, _LiveObject_map, "f")) {
55
56
  if (value instanceof AbstractCrdt_1.AbstractCrdt) {
56
- ops.push(...value._serialize(this._id, key));
57
+ ops.push(...value._serialize(this._id, key, doc));
57
58
  }
58
59
  else {
59
60
  op.data[key] = value;
@@ -70,7 +71,13 @@ class LiveObject extends AbstractCrdt_1.AbstractCrdt {
70
71
  }
71
72
  const object = new LiveObject(item.data);
72
73
  object._attach(id, doc);
73
- const children = parentToChildren.get(id);
74
+ return this._deserializeChildren(object, parentToChildren, doc);
75
+ }
76
+ /**
77
+ * INTERNAL
78
+ */
79
+ static _deserializeChildren(object, parentToChildren, doc) {
80
+ const children = parentToChildren.get(object._id);
74
81
  if (children == null) {
75
82
  return object;
76
83
  }
@@ -99,7 +106,7 @@ class LiveObject extends AbstractCrdt_1.AbstractCrdt {
99
106
  /**
100
107
  * INTERNAL
101
108
  */
102
- _attachChild(id, key, child) {
109
+ _attachChild(id, key, child, isLocal) {
103
110
  if (this._doc == null) {
104
111
  throw new Error("Can't attach child if doc is not present");
105
112
  }
@@ -141,6 +148,15 @@ class LiveObject extends AbstractCrdt_1.AbstractCrdt {
141
148
  child._detach();
142
149
  }
143
150
  }
151
+ /**
152
+ * INTERNAL
153
+ */
154
+ _detachChildren() {
155
+ for (const [key, value] of __classPrivateFieldGet(this, _LiveObject_map, "f")) {
156
+ __classPrivateFieldGet(this, _LiveObject_map, "f").delete(key);
157
+ value._detach();
158
+ }
159
+ }
144
160
  /**
145
161
  * INTERNAL
146
162
  */
@@ -155,14 +171,26 @@ class LiveObject extends AbstractCrdt_1.AbstractCrdt {
155
171
  /**
156
172
  * INTERNAL
157
173
  */
158
- _apply(op) {
174
+ _apply(op, isLocal) {
159
175
  if (op.type === live_1.OpType.UpdateObject) {
160
- return __classPrivateFieldGet(this, _LiveObject_instances, "m", _LiveObject_applyUpdate).call(this, op);
176
+ return __classPrivateFieldGet(this, _LiveObject_instances, "m", _LiveObject_applyUpdate).call(this, op, isLocal);
161
177
  }
162
178
  else if (op.type === live_1.OpType.DeleteObjectKey) {
163
179
  return __classPrivateFieldGet(this, _LiveObject_instances, "m", _LiveObject_applyDeleteObjectKey).call(this, op);
164
180
  }
165
- return super._apply(op);
181
+ return super._apply(op, isLocal);
182
+ }
183
+ /**
184
+ * INTERNAL
185
+ */
186
+ _toSerializedCrdt() {
187
+ var _a;
188
+ return {
189
+ type: live_1.CrdtType.Object,
190
+ parentId: (_a = this._parent) === null || _a === void 0 ? void 0 : _a._id,
191
+ parentKey: this._parentKey,
192
+ data: this.toObject(),
193
+ };
166
194
  }
167
195
  /**
168
196
  * Transform the LiveObject into a javascript object
@@ -218,7 +246,14 @@ class LiveObject extends AbstractCrdt_1.AbstractCrdt {
218
246
  ];
219
247
  }
220
248
  __classPrivateFieldGet(this, _LiveObject_map, "f").delete(keyAsString);
221
- this._doc.dispatch([{ type: live_1.OpType.DeleteObjectKey, key: keyAsString, id: this._id }], reverse, [this]);
249
+ this._doc.dispatch([
250
+ {
251
+ type: live_1.OpType.DeleteObjectKey,
252
+ key: keyAsString,
253
+ id: this._id,
254
+ opId: this._doc.generateOpId(),
255
+ },
256
+ ], reverse, [this]);
222
257
  }
223
258
  /**
224
259
  * Adds or updates multiple properties at once with an object.
@@ -265,7 +300,7 @@ class LiveObject extends AbstractCrdt_1.AbstractCrdt {
265
300
  if (newValue instanceof AbstractCrdt_1.AbstractCrdt) {
266
301
  newValue._setParentLink(this, key);
267
302
  newValue._attach(this._doc.generateId(), this._doc);
268
- ops.push(...newValue._serialize(this._id, key));
303
+ ops.push(...newValue._serialize(this._id, key, this._doc));
269
304
  }
270
305
  else {
271
306
  updatedProps[key] = newValue;
@@ -287,7 +322,7 @@ class LiveObject extends AbstractCrdt_1.AbstractCrdt {
287
322
  }
288
323
  }
289
324
  exports.LiveObject = LiveObject;
290
- _LiveObject_map = new WeakMap(), _LiveObject_propToLastUpdate = new WeakMap(), _LiveObject_instances = new WeakSet(), _LiveObject_applyUpdate = function _LiveObject_applyUpdate(op) {
325
+ _LiveObject_map = new WeakMap(), _LiveObject_propToLastUpdate = new WeakMap(), _LiveObject_instances = new WeakSet(), _LiveObject_applyUpdate = function _LiveObject_applyUpdate(op, isLocal) {
291
326
  let isModified = false;
292
327
  const reverse = [];
293
328
  const reverseUpdate = {
@@ -309,11 +344,6 @@ _LiveObject_map = new WeakMap(), _LiveObject_propToLastUpdate = new WeakMap(), _
309
344
  reverse.push({ type: live_1.OpType.DeleteObjectKey, id: this._id, key });
310
345
  }
311
346
  }
312
- let isLocal = false;
313
- if (op.opId == null) {
314
- isLocal = true;
315
- op.opId = this._doc.generateOpId();
316
- }
317
347
  for (const key in op.data) {
318
348
  if (isLocal) {
319
349
  __classPrivateFieldGet(this, _LiveObject_propToLastUpdate, "f").set(key, op.opId);
@@ -1,5 +1,5 @@
1
1
  import { AbstractCrdt, Doc, ApplyResult } from "./AbstractCrdt";
2
- import { SerializedCrdtWithId, Op } from "./live";
2
+ import { SerializedCrdtWithId, Op, SerializedCrdt } from "./live";
3
3
  /**
4
4
  * INTERNAL
5
5
  */
@@ -14,8 +14,12 @@ export declare class LiveRegister<TValue = any> extends AbstractCrdt {
14
14
  /**
15
15
  * INTERNAL
16
16
  */
17
- _serialize(parentId: string, parentKey: string): Op[];
18
- _attachChild(id: string, key: string, crdt: AbstractCrdt): ApplyResult;
17
+ _serialize(parentId: string, parentKey: string, doc?: Doc): Op[];
18
+ /**
19
+ * INTERNAL
20
+ */
21
+ _toSerializedCrdt(): SerializedCrdt;
22
+ _attachChild(id: string, key: string, crdt: AbstractCrdt, isLocal: boolean): ApplyResult;
19
23
  _detachChild(crdt: AbstractCrdt): void;
20
- _apply(op: Op): ApplyResult;
24
+ _apply(op: Op, isLocal: boolean): ApplyResult;
21
25
  }
@@ -41,13 +41,14 @@ class LiveRegister extends AbstractCrdt_1.AbstractCrdt {
41
41
  /**
42
42
  * INTERNAL
43
43
  */
44
- _serialize(parentId, parentKey) {
44
+ _serialize(parentId, parentKey, doc) {
45
45
  if (this._id == null || parentId == null || parentKey == null) {
46
46
  throw new Error("Cannot serialize register if parentId or parentKey is undefined");
47
47
  }
48
48
  return [
49
49
  {
50
50
  type: live_1.OpType.CreateRegister,
51
+ opId: doc === null || doc === void 0 ? void 0 : doc.generateOpId(),
51
52
  id: this._id,
52
53
  parentId,
53
54
  parentKey,
@@ -55,14 +56,26 @@ class LiveRegister extends AbstractCrdt_1.AbstractCrdt {
55
56
  },
56
57
  ];
57
58
  }
58
- _attachChild(id, key, crdt) {
59
+ /**
60
+ * INTERNAL
61
+ */
62
+ _toSerializedCrdt() {
63
+ var _a;
64
+ return {
65
+ type: live_1.CrdtType.Register,
66
+ parentId: (_a = this._parent) === null || _a === void 0 ? void 0 : _a._id,
67
+ parentKey: this._parentKey,
68
+ data: this.data,
69
+ };
70
+ }
71
+ _attachChild(id, key, crdt, isLocal) {
59
72
  throw new Error("Method not implemented.");
60
73
  }
61
74
  _detachChild(crdt) {
62
75
  throw new Error("Method not implemented.");
63
76
  }
64
- _apply(op) {
65
- return super._apply(op);
77
+ _apply(op, isLocal) {
78
+ return super._apply(op, isLocal);
66
79
  }
67
80
  }
68
81
  exports.LiveRegister = LiveRegister;
package/lib/cjs/client.js CHANGED
@@ -29,11 +29,7 @@ const room_1 = require("./room");
29
29
  */
30
30
  function createClient(options) {
31
31
  const clientOptions = options;
32
- if (typeof clientOptions.throttle === "number") {
33
- if (clientOptions.throttle < 80 || clientOptions.throttle > 1000) {
34
- throw new Error("Liveblocks client throttle should be between 80 and 1000 ms");
35
- }
36
- }
32
+ const throttleDelay = getThrottleDelayFromOptions(options);
37
33
  const rooms = new Map();
38
34
  function getRoom(roomId) {
39
35
  const internalRoom = rooms.get(roomId);
@@ -44,9 +40,21 @@ function createClient(options) {
44
40
  if (internalRoom) {
45
41
  return internalRoom.room;
46
42
  }
47
- internalRoom = (0, room_1.createRoom)(roomId, Object.assign(Object.assign({}, clientOptions), options));
43
+ internalRoom = (0, room_1.createRoom)({
44
+ defaultPresence: options.defaultPresence,
45
+ defaultStorageRoot: options.defaultStorageRoot,
46
+ }, {
47
+ room: roomId,
48
+ throttleDelay,
49
+ WebSocketPolyfill: clientOptions.WebSocketPolyfill,
50
+ fetchPolyfill: clientOptions.fetchPolyfill,
51
+ liveblocksServer: clientOptions.liveblocksServer || "wss://liveblocks.net/v5",
52
+ authentication: prepareAuthentication(clientOptions),
53
+ });
48
54
  rooms.set(roomId, internalRoom);
49
- internalRoom.connect();
55
+ if (!options.DO_NOT_USE_withoutConnecting) {
56
+ internalRoom.connect();
57
+ }
50
58
  return internalRoom.room;
51
59
  }
52
60
  function leave(roomId) {
@@ -78,3 +86,38 @@ function createClient(options) {
78
86
  };
79
87
  }
80
88
  exports.createClient = createClient;
89
+ function getThrottleDelayFromOptions(options) {
90
+ if (options.throttle === undefined) {
91
+ return 100;
92
+ }
93
+ if (typeof options.throttle !== "number" ||
94
+ options.throttle < 80 ||
95
+ options.throttle > 1000) {
96
+ throw new Error("throttle should be a number between 80 and 1000.");
97
+ }
98
+ return options.throttle;
99
+ }
100
+ function prepareAuthentication(clientOptions) {
101
+ // TODO: throw descriptive errors for invalid options
102
+ if (typeof clientOptions.publicApiKey === "string") {
103
+ return {
104
+ type: "public",
105
+ publicApiKey: clientOptions.publicApiKey,
106
+ url: clientOptions.publicAuthorizeEndpoint ||
107
+ "https://liveblocks.io/api/public/authorize",
108
+ };
109
+ }
110
+ else if (typeof clientOptions.authEndpoint === "string") {
111
+ return {
112
+ type: "private",
113
+ url: clientOptions.authEndpoint,
114
+ };
115
+ }
116
+ else if (typeof clientOptions.authEndpoint === "function") {
117
+ return {
118
+ type: "custom",
119
+ callback: clientOptions.authEndpoint,
120
+ };
121
+ }
122
+ throw new Error("Invalid Liveblocks client options. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClient");
123
+ }