@liveblocks/client 0.12.3 → 0.13.2

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 (48) hide show
  1. package/README.md +34 -6
  2. package/lib/cjs/AbstractCrdt.d.ts +61 -0
  3. package/lib/cjs/AbstractCrdt.js +98 -0
  4. package/lib/cjs/LiveList.d.ts +133 -0
  5. package/lib/cjs/LiveList.js +374 -0
  6. package/lib/cjs/LiveMap.d.ts +83 -0
  7. package/lib/cjs/LiveMap.js +272 -0
  8. package/lib/cjs/LiveObject.d.ts +66 -0
  9. package/lib/cjs/LiveObject.js +368 -0
  10. package/lib/cjs/LiveRegister.d.ts +21 -0
  11. package/lib/cjs/LiveRegister.js +69 -0
  12. package/lib/cjs/immutable/index.d.ts +7 -0
  13. package/lib/cjs/immutable/index.js +214 -0
  14. package/lib/cjs/index.d.ts +3 -1
  15. package/lib/cjs/index.js +7 -5
  16. package/lib/cjs/room.d.ts +50 -9
  17. package/lib/cjs/room.js +477 -85
  18. package/lib/cjs/types.d.ts +220 -40
  19. package/lib/cjs/utils.d.ts +7 -0
  20. package/lib/cjs/utils.js +64 -1
  21. package/lib/esm/AbstractCrdt.d.ts +61 -0
  22. package/lib/esm/AbstractCrdt.js +94 -0
  23. package/lib/esm/LiveList.d.ts +133 -0
  24. package/lib/esm/LiveList.js +370 -0
  25. package/lib/esm/LiveMap.d.ts +83 -0
  26. package/lib/esm/LiveMap.js +268 -0
  27. package/lib/esm/LiveObject.d.ts +66 -0
  28. package/lib/esm/LiveObject.js +364 -0
  29. package/lib/esm/LiveRegister.d.ts +21 -0
  30. package/lib/esm/LiveRegister.js +65 -0
  31. package/lib/esm/immutable/index.d.ts +7 -0
  32. package/lib/esm/immutable/index.js +207 -0
  33. package/lib/esm/index.d.ts +3 -1
  34. package/lib/esm/index.js +3 -1
  35. package/lib/esm/room.d.ts +50 -9
  36. package/lib/esm/room.js +479 -84
  37. package/lib/esm/types.d.ts +220 -40
  38. package/lib/esm/utils.d.ts +7 -0
  39. package/lib/esm/utils.js +58 -0
  40. package/package.json +3 -3
  41. package/lib/cjs/doc.d.ts +0 -347
  42. package/lib/cjs/doc.js +0 -1349
  43. package/lib/cjs/storage.d.ts +0 -21
  44. package/lib/cjs/storage.js +0 -68
  45. package/lib/esm/doc.d.ts +0 -347
  46. package/lib/esm/doc.js +0 -1342
  47. package/lib/esm/storage.d.ts +0 -21
  48. package/lib/esm/storage.js +0 -65
@@ -0,0 +1,368 @@
1
+ "use strict";
2
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
+ if (kind === "m") throw new TypeError("Private method is not writable");
4
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7
+ };
8
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
+ };
13
+ var _LiveObject_instances, _LiveObject_map, _LiveObject_propToLastUpdate, _LiveObject_applyUpdate, _LiveObject_applyDeleteObjectKey;
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.LiveObject = void 0;
16
+ const AbstractCrdt_1 = require("./AbstractCrdt");
17
+ const utils_1 = require("./utils");
18
+ const live_1 = require("./live");
19
+ /**
20
+ * The LiveObject class is similar to a JavaScript object that is synchronized on all clients.
21
+ * Keys should be a string, and values should be serializable to JSON.
22
+ * If multiple clients update the same property simultaneously, the last modification received by the Liveblocks servers is the winner.
23
+ */
24
+ class LiveObject extends AbstractCrdt_1.AbstractCrdt {
25
+ constructor(object = {}) {
26
+ super();
27
+ _LiveObject_instances.add(this);
28
+ _LiveObject_map.set(this, void 0);
29
+ _LiveObject_propToLastUpdate.set(this, new Map());
30
+ for (const key in object) {
31
+ const value = object[key];
32
+ if (value instanceof AbstractCrdt_1.AbstractCrdt) {
33
+ value._setParentLink(this, key);
34
+ }
35
+ }
36
+ __classPrivateFieldSet(this, _LiveObject_map, new Map(Object.entries(object)), "f");
37
+ }
38
+ /**
39
+ * INTERNAL
40
+ */
41
+ _serialize(parentId, parentKey) {
42
+ if (this._id == null) {
43
+ throw new Error("Cannot serialize item is not attached");
44
+ }
45
+ const ops = [];
46
+ const op = {
47
+ id: this._id,
48
+ type: live_1.OpType.CreateObject,
49
+ parentId,
50
+ parentKey,
51
+ data: {},
52
+ };
53
+ ops.push(op);
54
+ for (const [key, value] of __classPrivateFieldGet(this, _LiveObject_map, "f")) {
55
+ if (value instanceof AbstractCrdt_1.AbstractCrdt) {
56
+ ops.push(...value._serialize(this._id, key));
57
+ }
58
+ else {
59
+ op.data[key] = value;
60
+ }
61
+ }
62
+ return ops;
63
+ }
64
+ /**
65
+ * INTERNAL
66
+ */
67
+ static _deserialize([id, item], parentToChildren, doc) {
68
+ if (item.type !== live_1.CrdtType.Object) {
69
+ throw new Error(`Tried to deserialize a record but item type is "${item.type}"`);
70
+ }
71
+ const object = new LiveObject(item.data);
72
+ object._attach(id, doc);
73
+ const children = parentToChildren.get(id);
74
+ if (children == null) {
75
+ return object;
76
+ }
77
+ for (const entry of children) {
78
+ const crdt = entry[1];
79
+ if (crdt.parentKey == null) {
80
+ throw new Error("Tried to deserialize a crdt but it does not have a parentKey and is not the root");
81
+ }
82
+ const child = (0, utils_1.deserialize)(entry, parentToChildren, doc);
83
+ child._setParentLink(object, crdt.parentKey);
84
+ __classPrivateFieldGet(object, _LiveObject_map, "f").set(crdt.parentKey, child);
85
+ }
86
+ return object;
87
+ }
88
+ /**
89
+ * INTERNAL
90
+ */
91
+ _attach(id, doc) {
92
+ super._attach(id, doc);
93
+ for (const [key, value] of __classPrivateFieldGet(this, _LiveObject_map, "f")) {
94
+ if (value instanceof AbstractCrdt_1.AbstractCrdt) {
95
+ value._attach(doc.generateId(), doc);
96
+ }
97
+ }
98
+ }
99
+ /**
100
+ * INTERNAL
101
+ */
102
+ _attachChild(id, key, child) {
103
+ if (this._doc == null) {
104
+ throw new Error("Can't attach child if doc is not present");
105
+ }
106
+ const previousValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
107
+ let reverse;
108
+ if ((0, utils_1.isCrdt)(previousValue)) {
109
+ reverse = previousValue._serialize(this._id, key);
110
+ previousValue._detach();
111
+ }
112
+ else if (previousValue === undefined) {
113
+ reverse = [
114
+ { type: live_1.OpType.DeleteObjectKey, id: this._id, key: key },
115
+ ];
116
+ }
117
+ else {
118
+ reverse = [
119
+ {
120
+ type: live_1.OpType.UpdateObject,
121
+ id: this._id,
122
+ data: { [key]: previousValue },
123
+ },
124
+ ];
125
+ }
126
+ __classPrivateFieldGet(this, _LiveObject_map, "f").set(key, child);
127
+ child._setParentLink(this, key);
128
+ child._attach(id, this._doc);
129
+ return { reverse, modified: this };
130
+ }
131
+ /**
132
+ * INTERNAL
133
+ */
134
+ _detachChild(child) {
135
+ for (const [key, value] of __classPrivateFieldGet(this, _LiveObject_map, "f")) {
136
+ if (value === child) {
137
+ __classPrivateFieldGet(this, _LiveObject_map, "f").delete(key);
138
+ }
139
+ }
140
+ if (child) {
141
+ child._detach();
142
+ }
143
+ }
144
+ /**
145
+ * INTERNAL
146
+ */
147
+ _detach() {
148
+ super._detach();
149
+ for (const value of __classPrivateFieldGet(this, _LiveObject_map, "f").values()) {
150
+ if ((0, utils_1.isCrdt)(value)) {
151
+ value._detach();
152
+ }
153
+ }
154
+ }
155
+ /**
156
+ * INTERNAL
157
+ */
158
+ _apply(op) {
159
+ if (op.type === live_1.OpType.UpdateObject) {
160
+ return __classPrivateFieldGet(this, _LiveObject_instances, "m", _LiveObject_applyUpdate).call(this, op);
161
+ }
162
+ else if (op.type === live_1.OpType.DeleteObjectKey) {
163
+ return __classPrivateFieldGet(this, _LiveObject_instances, "m", _LiveObject_applyDeleteObjectKey).call(this, op);
164
+ }
165
+ return super._apply(op);
166
+ }
167
+ /**
168
+ * Transform the LiveObject into a javascript object
169
+ */
170
+ toObject() {
171
+ return Object.fromEntries(__classPrivateFieldGet(this, _LiveObject_map, "f"));
172
+ }
173
+ /**
174
+ * Adds or updates a property with a specified key and a value.
175
+ * @param key The key of the property to add
176
+ * @param value The value of the property to add
177
+ */
178
+ set(key, value) {
179
+ // TODO: Find out why typescript complains
180
+ this.update({ [key]: value });
181
+ }
182
+ /**
183
+ * Returns a specified property from the LiveObject.
184
+ * @param key The key of the property to get
185
+ */
186
+ get(key) {
187
+ return __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
188
+ }
189
+ /**
190
+ * Deletes a key from the LiveObject
191
+ * @param key The key of the property to delete
192
+ */
193
+ delete(key) {
194
+ const keyAsString = key;
195
+ const oldValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(keyAsString);
196
+ if (oldValue === undefined) {
197
+ return;
198
+ }
199
+ if (this._doc == null || this._id == null) {
200
+ if (oldValue instanceof AbstractCrdt_1.AbstractCrdt) {
201
+ oldValue._detach();
202
+ }
203
+ __classPrivateFieldGet(this, _LiveObject_map, "f").delete(keyAsString);
204
+ return;
205
+ }
206
+ let reverse;
207
+ if (oldValue instanceof AbstractCrdt_1.AbstractCrdt) {
208
+ oldValue._detach();
209
+ reverse = oldValue._serialize(this._id, keyAsString);
210
+ }
211
+ else {
212
+ reverse = [
213
+ {
214
+ type: live_1.OpType.UpdateObject,
215
+ data: { [keyAsString]: oldValue },
216
+ id: this._id,
217
+ },
218
+ ];
219
+ }
220
+ __classPrivateFieldGet(this, _LiveObject_map, "f").delete(keyAsString);
221
+ this._doc.dispatch([{ type: live_1.OpType.DeleteObjectKey, key: keyAsString, id: this._id }], reverse, [this]);
222
+ }
223
+ /**
224
+ * Adds or updates multiple properties at once with an object.
225
+ * @param overrides The object used to overrides properties
226
+ */
227
+ update(overrides) {
228
+ if (this._doc == null || this._id == null) {
229
+ for (const key in overrides) {
230
+ const oldValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
231
+ if (oldValue instanceof AbstractCrdt_1.AbstractCrdt) {
232
+ oldValue._detach();
233
+ }
234
+ const newValue = overrides[key];
235
+ if (newValue instanceof AbstractCrdt_1.AbstractCrdt) {
236
+ newValue._setParentLink(this, key);
237
+ }
238
+ __classPrivateFieldGet(this, _LiveObject_map, "f").set(key, newValue);
239
+ }
240
+ return;
241
+ }
242
+ const ops = [];
243
+ const reverseOps = [];
244
+ const opId = this._doc.generateOpId();
245
+ const updatedProps = {};
246
+ const reverseUpdateOp = {
247
+ id: this._id,
248
+ type: live_1.OpType.UpdateObject,
249
+ data: {},
250
+ };
251
+ for (const key in overrides) {
252
+ __classPrivateFieldGet(this, _LiveObject_propToLastUpdate, "f").set(key, opId);
253
+ const oldValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
254
+ if (oldValue instanceof AbstractCrdt_1.AbstractCrdt) {
255
+ reverseOps.push(...oldValue._serialize(this._id, key));
256
+ oldValue._detach();
257
+ }
258
+ else if (oldValue === undefined) {
259
+ reverseOps.push({ type: live_1.OpType.DeleteObjectKey, id: this._id, key });
260
+ }
261
+ else {
262
+ reverseUpdateOp.data[key] = oldValue;
263
+ }
264
+ const newValue = overrides[key];
265
+ if (newValue instanceof AbstractCrdt_1.AbstractCrdt) {
266
+ newValue._setParentLink(this, key);
267
+ newValue._attach(this._doc.generateId(), this._doc);
268
+ ops.push(...newValue._serialize(this._id, key));
269
+ }
270
+ else {
271
+ updatedProps[key] = newValue;
272
+ }
273
+ __classPrivateFieldGet(this, _LiveObject_map, "f").set(key, newValue);
274
+ }
275
+ if (Object.keys(reverseUpdateOp.data).length !== 0) {
276
+ reverseOps.unshift(reverseUpdateOp);
277
+ }
278
+ if (Object.keys(updatedProps).length !== 0) {
279
+ ops.unshift({
280
+ opId,
281
+ id: this._id,
282
+ type: live_1.OpType.UpdateObject,
283
+ data: updatedProps,
284
+ });
285
+ }
286
+ this._doc.dispatch(ops, reverseOps, [this]);
287
+ }
288
+ }
289
+ exports.LiveObject = LiveObject;
290
+ _LiveObject_map = new WeakMap(), _LiveObject_propToLastUpdate = new WeakMap(), _LiveObject_instances = new WeakSet(), _LiveObject_applyUpdate = function _LiveObject_applyUpdate(op) {
291
+ let isModified = false;
292
+ const reverse = [];
293
+ const reverseUpdate = {
294
+ type: live_1.OpType.UpdateObject,
295
+ id: this._id,
296
+ data: {},
297
+ };
298
+ reverse.push(reverseUpdate);
299
+ for (const key in op.data) {
300
+ const oldValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
301
+ if (oldValue instanceof AbstractCrdt_1.AbstractCrdt) {
302
+ reverse.push(...oldValue._serialize(this._id, key));
303
+ oldValue._detach();
304
+ }
305
+ else if (oldValue !== undefined) {
306
+ reverseUpdate.data[key] = oldValue;
307
+ }
308
+ else if (oldValue === undefined) {
309
+ reverse.push({ type: live_1.OpType.DeleteObjectKey, id: this._id, key });
310
+ }
311
+ }
312
+ let isLocal = false;
313
+ if (op.opId == null) {
314
+ isLocal = true;
315
+ op.opId = this._doc.generateOpId();
316
+ }
317
+ for (const key in op.data) {
318
+ if (isLocal) {
319
+ __classPrivateFieldGet(this, _LiveObject_propToLastUpdate, "f").set(key, op.opId);
320
+ }
321
+ else if (__classPrivateFieldGet(this, _LiveObject_propToLastUpdate, "f").get(key) == null) {
322
+ // Not modified localy so we apply update
323
+ isModified = true;
324
+ }
325
+ else if (__classPrivateFieldGet(this, _LiveObject_propToLastUpdate, "f").get(key) === op.opId) {
326
+ // Acknowlegment from local operation
327
+ __classPrivateFieldGet(this, _LiveObject_propToLastUpdate, "f").delete(key);
328
+ continue;
329
+ }
330
+ else {
331
+ // Conflict, ignore remote operation
332
+ continue;
333
+ }
334
+ const oldValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
335
+ if ((0, utils_1.isCrdt)(oldValue)) {
336
+ oldValue._detach();
337
+ }
338
+ isModified = true;
339
+ __classPrivateFieldGet(this, _LiveObject_map, "f").set(key, op.data[key]);
340
+ }
341
+ if (Object.keys(reverseUpdate.data).length !== 0) {
342
+ reverse.unshift(reverseUpdate);
343
+ }
344
+ return isModified ? { modified: this, reverse } : { modified: false };
345
+ }, _LiveObject_applyDeleteObjectKey = function _LiveObject_applyDeleteObjectKey(op) {
346
+ const key = op.key;
347
+ // If property does not exist, exit without notifying
348
+ if (__classPrivateFieldGet(this, _LiveObject_map, "f").has(key) === false) {
349
+ return { modified: false };
350
+ }
351
+ const oldValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
352
+ let reverse = [];
353
+ if ((0, utils_1.isCrdt)(oldValue)) {
354
+ reverse = oldValue._serialize(this._id, op.key);
355
+ oldValue._detach();
356
+ }
357
+ else if (oldValue !== undefined) {
358
+ reverse = [
359
+ {
360
+ type: live_1.OpType.UpdateObject,
361
+ id: this._id,
362
+ data: { [key]: oldValue },
363
+ },
364
+ ];
365
+ }
366
+ __classPrivateFieldGet(this, _LiveObject_map, "f").delete(key);
367
+ return { modified: this, reverse };
368
+ };
@@ -0,0 +1,21 @@
1
+ import { AbstractCrdt, Doc, ApplyResult } from "./AbstractCrdt";
2
+ import { SerializedCrdtWithId, Op } from "./live";
3
+ /**
4
+ * INTERNAL
5
+ */
6
+ export declare class LiveRegister<TValue = any> extends AbstractCrdt {
7
+ #private;
8
+ constructor(data: TValue);
9
+ get data(): TValue;
10
+ /**
11
+ * INTERNAL
12
+ */
13
+ static _deserialize([id, item]: SerializedCrdtWithId, parentToChildren: Map<string, SerializedCrdtWithId[]>, doc: Doc): LiveRegister<any>;
14
+ /**
15
+ * INTERNAL
16
+ */
17
+ _serialize(parentId: string, parentKey: string): Op[];
18
+ _attachChild(id: string, key: string, crdt: AbstractCrdt): ApplyResult;
19
+ _detachChild(crdt: AbstractCrdt): void;
20
+ _apply(op: Op): ApplyResult;
21
+ }
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
+ if (kind === "m") throw new TypeError("Private method is not writable");
4
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7
+ };
8
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
+ };
13
+ var _LiveRegister_data;
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.LiveRegister = void 0;
16
+ const AbstractCrdt_1 = require("./AbstractCrdt");
17
+ const live_1 = require("./live");
18
+ /**
19
+ * INTERNAL
20
+ */
21
+ class LiveRegister extends AbstractCrdt_1.AbstractCrdt {
22
+ constructor(data) {
23
+ super();
24
+ _LiveRegister_data.set(this, void 0);
25
+ __classPrivateFieldSet(this, _LiveRegister_data, data, "f");
26
+ }
27
+ get data() {
28
+ return __classPrivateFieldGet(this, _LiveRegister_data, "f");
29
+ }
30
+ /**
31
+ * INTERNAL
32
+ */
33
+ static _deserialize([id, item], parentToChildren, doc) {
34
+ if (item.type !== live_1.CrdtType.Register) {
35
+ throw new Error(`Tried to deserialize a map but item type is "${item.type}"`);
36
+ }
37
+ const register = new LiveRegister(item.data);
38
+ register._attach(id, doc);
39
+ return register;
40
+ }
41
+ /**
42
+ * INTERNAL
43
+ */
44
+ _serialize(parentId, parentKey) {
45
+ if (this._id == null || parentId == null || parentKey == null) {
46
+ throw new Error("Cannot serialize register if parentId or parentKey is undefined");
47
+ }
48
+ return [
49
+ {
50
+ type: live_1.OpType.CreateRegister,
51
+ id: this._id,
52
+ parentId,
53
+ parentKey,
54
+ data: this.data,
55
+ },
56
+ ];
57
+ }
58
+ _attachChild(id, key, crdt) {
59
+ throw new Error("Method not implemented.");
60
+ }
61
+ _detachChild(crdt) {
62
+ throw new Error("Method not implemented.");
63
+ }
64
+ _apply(op) {
65
+ return super._apply(op);
66
+ }
67
+ }
68
+ exports.LiveRegister = LiveRegister;
69
+ _LiveRegister_data = new WeakMap();
@@ -0,0 +1,7 @@
1
+ import { LiveList } from "../LiveList";
2
+ import { LiveObject } from "../LiveObject";
3
+ import { StorageUpdate } from "../types";
4
+ export declare function liveObjectToJson(liveObject: LiveObject<any>): any;
5
+ export declare function patchLiveList<T>(liveList: LiveList<T>, prev: Array<T>, next: Array<T>): void;
6
+ export declare function patchLiveObject<T extends Record<string, any>>(root: LiveObject<T>, prev: T, next: T): void;
7
+ export declare function patchImmutableObject<T>(state: T, updates: StorageUpdate[]): T;
@@ -0,0 +1,214 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.patchImmutableObject = exports.patchLiveObject = exports.patchLiveList = exports.liveObjectToJson = void 0;
4
+ const LiveList_1 = require("../LiveList");
5
+ const LiveMap_1 = require("../LiveMap");
6
+ const LiveObject_1 = require("../LiveObject");
7
+ function liveObjectToJson(liveObject) {
8
+ const result = {};
9
+ const obj = liveObject.toObject();
10
+ for (const key in obj) {
11
+ result[key] = liveNodeToJson(obj[key]);
12
+ }
13
+ return result;
14
+ }
15
+ exports.liveObjectToJson = liveObjectToJson;
16
+ function liveMapToJson(map) {
17
+ const result = {};
18
+ const obj = Object.fromEntries(map);
19
+ for (const key in obj) {
20
+ result[key] = liveNodeToJson(obj[key]);
21
+ }
22
+ return result;
23
+ }
24
+ function liveListToJson(value) {
25
+ return value.toArray().map(liveNodeToJson);
26
+ }
27
+ function liveNodeToJson(value) {
28
+ if (value instanceof LiveObject_1.LiveObject) {
29
+ return liveObjectToJson(value);
30
+ }
31
+ else if (value instanceof LiveList_1.LiveList) {
32
+ return liveListToJson(value);
33
+ }
34
+ else if (value instanceof LiveMap_1.LiveMap) {
35
+ return liveMapToJson(value);
36
+ }
37
+ return value;
38
+ }
39
+ function isPlainObject(obj) {
40
+ return Object.prototype.toString.call(obj) === "[object Object]";
41
+ }
42
+ function anyToCrdt(obj) {
43
+ if (obj == null) {
44
+ return obj;
45
+ }
46
+ if (Array.isArray(obj)) {
47
+ return new LiveList_1.LiveList(obj.map(anyToCrdt));
48
+ }
49
+ if (isPlainObject(obj)) {
50
+ const init = {};
51
+ for (const key in obj) {
52
+ init[key] = anyToCrdt(obj[key]);
53
+ }
54
+ return new LiveObject_1.LiveObject(init);
55
+ }
56
+ return obj;
57
+ }
58
+ function patchLiveList(liveList, prev, next) {
59
+ let i = 0;
60
+ let prevEnd = prev.length - 1;
61
+ let nextEnd = next.length - 1;
62
+ let prevNode = prev[0];
63
+ let nextNode = next[0];
64
+ /**
65
+ * For A,B,C => A,B,C,D
66
+ * i = 3, prevEnd = 2, nextEnd = 3
67
+ *
68
+ * For A,B,C => B,C
69
+ * i = 2, prevEnd = 2, nextEnd = 1
70
+ *
71
+ * For B,C => A,B,C
72
+ * i = 0, pre
73
+ */
74
+ outer: {
75
+ while (prevNode === nextNode) {
76
+ ++i;
77
+ if (i > prevEnd || i > nextEnd) {
78
+ break outer;
79
+ }
80
+ prevNode = prev[i];
81
+ nextNode = next[i];
82
+ }
83
+ prevNode = prev[prevEnd];
84
+ nextNode = next[nextEnd];
85
+ while (prevNode === nextNode) {
86
+ prevEnd--;
87
+ nextEnd--;
88
+ if (i > prevEnd || i > nextEnd) {
89
+ break outer;
90
+ }
91
+ prevNode = prev[prevEnd];
92
+ nextNode = next[nextEnd];
93
+ }
94
+ }
95
+ if (i > prevEnd) {
96
+ if (i <= nextEnd) {
97
+ while (i <= nextEnd) {
98
+ liveList.insert(anyToCrdt(next[i]), i);
99
+ i++;
100
+ }
101
+ }
102
+ }
103
+ else if (i > nextEnd) {
104
+ while (i <= prevEnd) {
105
+ liveList.delete(i++);
106
+ }
107
+ }
108
+ else {
109
+ while (i <= prevEnd && i <= nextEnd) {
110
+ prevNode = prev[i];
111
+ nextNode = next[i];
112
+ const liveListNode = liveList.get(i);
113
+ if (liveListNode instanceof LiveObject_1.LiveObject &&
114
+ isPlainObject(prevNode) &&
115
+ isPlainObject(nextNode)) {
116
+ patchLiveObject(liveListNode, prevNode, nextNode);
117
+ }
118
+ else {
119
+ liveList.delete(i);
120
+ liveList.insert(anyToCrdt(nextNode), i);
121
+ }
122
+ i++;
123
+ }
124
+ while (i <= nextEnd) {
125
+ liveList.insert(anyToCrdt(next[i]), i);
126
+ i++;
127
+ }
128
+ while (i <= prevEnd) {
129
+ liveList.delete(i);
130
+ i++;
131
+ }
132
+ }
133
+ }
134
+ exports.patchLiveList = patchLiveList;
135
+ function patchLiveObject(root, prev, next) {
136
+ const updates = {};
137
+ for (const key in next) {
138
+ if (prev[key] === next[key]) {
139
+ continue;
140
+ }
141
+ else if (Array.isArray(prev[key]) && Array.isArray(next[key])) {
142
+ patchLiveList(root.get(key), prev[key], next[key]);
143
+ }
144
+ else if (isPlainObject(prev[key]) && isPlainObject(next[key])) {
145
+ patchLiveObject(root.get(key), prev[key], next[key]);
146
+ }
147
+ else {
148
+ updates[key] = anyToCrdt(next[key]);
149
+ }
150
+ }
151
+ for (const key in prev) {
152
+ if (next[key] === undefined) {
153
+ root.delete(key);
154
+ }
155
+ }
156
+ if (Object.keys(updates).length > 0) {
157
+ root.update(updates);
158
+ }
159
+ }
160
+ exports.patchLiveObject = patchLiveObject;
161
+ function getParentsPath(node) {
162
+ const path = [];
163
+ while (node._parentKey != null && node._parent != null) {
164
+ if (node._parent instanceof LiveList_1.LiveList) {
165
+ path.push(node._parent._indexOfPosition(node._parentKey));
166
+ }
167
+ else {
168
+ path.push(node._parentKey);
169
+ }
170
+ node = node._parent;
171
+ }
172
+ return path;
173
+ }
174
+ function patchImmutableObject(state, updates) {
175
+ return updates.reduce((state, update) => patchImmutableObjectWithUpdate(state, update), state);
176
+ }
177
+ exports.patchImmutableObject = patchImmutableObject;
178
+ function patchImmutableObjectWithUpdate(state, update) {
179
+ const path = getParentsPath(update.node);
180
+ return patchImmutableNode(state, path, update);
181
+ }
182
+ function patchImmutableNode(state, path, update) {
183
+ const pathItem = path.pop();
184
+ if (pathItem === undefined) {
185
+ switch (update.type) {
186
+ case "LiveObject": {
187
+ if (typeof state !== "object") {
188
+ throw new Error("Internal: received update on LiveObject but state was not an object");
189
+ }
190
+ return liveObjectToJson(update.node);
191
+ }
192
+ case "LiveList": {
193
+ if (Array.isArray(state) === false) {
194
+ throw new Error("Internal: received update on LiveList but state was not an array");
195
+ }
196
+ return liveListToJson(update.node);
197
+ }
198
+ case "LiveMap": {
199
+ if (typeof state !== "object") {
200
+ throw new Error("Internal: received update on LiveMap but state was not an object");
201
+ }
202
+ return liveMapToJson(update.node);
203
+ }
204
+ }
205
+ }
206
+ if (Array.isArray(state)) {
207
+ const newArray = [...state];
208
+ newArray[pathItem] = patchImmutableNode(state[pathItem], path, update);
209
+ return newArray;
210
+ }
211
+ else {
212
+ return Object.assign(Object.assign({}, state), { [pathItem]: patchImmutableNode(state[pathItem], path, update) });
213
+ }
214
+ }
@@ -1,3 +1,5 @@
1
- export { LiveObject, LiveList, LiveMap } from "./doc";
1
+ export { LiveObject } from "./LiveObject";
2
+ export { LiveMap } from "./LiveMap";
3
+ export { LiveList } from "./LiveList";
2
4
  export type { Others, Presence, Room, Client, User } from "./types";
3
5
  export { createClient } from "./client";