@liveblocks/client 0.13.2 → 0.15.0-alpha.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.
- package/lib/cjs/AbstractCrdt.d.ts +13 -7
- package/lib/cjs/AbstractCrdt.js +2 -5
- package/lib/cjs/LiveList.d.ts +17 -6
- package/lib/cjs/LiveList.js +140 -15
- package/lib/cjs/LiveMap.d.ts +12 -4
- package/lib/cjs/LiveMap.js +57 -7
- package/lib/cjs/LiveObject.d.ts +22 -8
- package/lib/cjs/LiveObject.js +109 -24
- package/lib/cjs/LiveRegister.d.ts +13 -5
- package/lib/cjs/LiveRegister.js +23 -4
- package/lib/cjs/{immutable/index.d.ts → immutable.d.ts} +5 -3
- package/lib/cjs/{immutable/index.js → immutable.js} +77 -19
- package/lib/cjs/index.d.ts +2 -1
- package/lib/cjs/index.js +8 -1
- package/lib/cjs/live.d.ts +7 -0
- package/lib/cjs/room.d.ts +11 -3
- package/lib/cjs/room.js +150 -76
- package/lib/cjs/types.d.ts +33 -1
- package/lib/cjs/utils.d.ts +4 -1
- package/lib/cjs/utils.js +101 -1
- package/lib/esm/AbstractCrdt.d.ts +13 -7
- package/lib/esm/AbstractCrdt.js +2 -5
- package/lib/esm/LiveList.d.ts +17 -6
- package/lib/esm/LiveList.js +141 -16
- package/lib/esm/LiveMap.d.ts +12 -4
- package/lib/esm/LiveMap.js +57 -7
- package/lib/esm/LiveObject.d.ts +22 -8
- package/lib/esm/LiveObject.js +109 -24
- package/lib/esm/LiveRegister.d.ts +13 -5
- package/lib/esm/LiveRegister.js +24 -5
- package/lib/esm/{immutable/index.d.ts → immutable.d.ts} +5 -3
- package/lib/esm/{immutable/index.js → immutable.js} +75 -19
- package/lib/esm/index.d.ts +2 -1
- package/lib/esm/index.js +1 -0
- package/lib/esm/live.d.ts +7 -0
- package/lib/esm/room.d.ts +11 -3
- package/lib/esm/room.js +151 -77
- package/lib/esm/types.d.ts +33 -1
- package/lib/esm/utils.d.ts +4 -1
- package/lib/esm/utils.js +99 -1
- package/package.json +1 -1
package/lib/esm/LiveObject.js
CHANGED
|
@@ -35,13 +35,14 @@ export class LiveObject extends AbstractCrdt {
|
|
|
35
35
|
/**
|
|
36
36
|
* INTERNAL
|
|
37
37
|
*/
|
|
38
|
-
_serialize(parentId, parentKey) {
|
|
38
|
+
_serialize(parentId, parentKey, doc) {
|
|
39
39
|
if (this._id == null) {
|
|
40
40
|
throw new Error("Cannot serialize item is not attached");
|
|
41
41
|
}
|
|
42
42
|
const ops = [];
|
|
43
43
|
const op = {
|
|
44
44
|
id: this._id,
|
|
45
|
+
opId: doc === null || doc === void 0 ? void 0 : doc.generateOpId(),
|
|
45
46
|
type: OpType.CreateObject,
|
|
46
47
|
parentId,
|
|
47
48
|
parentKey,
|
|
@@ -50,7 +51,7 @@ export class LiveObject extends AbstractCrdt {
|
|
|
50
51
|
ops.push(op);
|
|
51
52
|
for (const [key, value] of __classPrivateFieldGet(this, _LiveObject_map, "f")) {
|
|
52
53
|
if (value instanceof AbstractCrdt) {
|
|
53
|
-
ops.push(...value._serialize(this._id, key));
|
|
54
|
+
ops.push(...value._serialize(this._id, key, doc));
|
|
54
55
|
}
|
|
55
56
|
else {
|
|
56
57
|
op.data[key] = value;
|
|
@@ -67,7 +68,13 @@ export class LiveObject extends AbstractCrdt {
|
|
|
67
68
|
}
|
|
68
69
|
const object = new LiveObject(item.data);
|
|
69
70
|
object._attach(id, doc);
|
|
70
|
-
|
|
71
|
+
return this._deserializeChildren(object, parentToChildren, doc);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* INTERNAL
|
|
75
|
+
*/
|
|
76
|
+
static _deserializeChildren(object, parentToChildren, doc) {
|
|
77
|
+
const children = parentToChildren.get(object._id);
|
|
71
78
|
if (children == null) {
|
|
72
79
|
return object;
|
|
73
80
|
}
|
|
@@ -96,7 +103,7 @@ export class LiveObject extends AbstractCrdt {
|
|
|
96
103
|
/**
|
|
97
104
|
* INTERNAL
|
|
98
105
|
*/
|
|
99
|
-
_attachChild(id, key, child) {
|
|
106
|
+
_attachChild(id, key, child, isLocal) {
|
|
100
107
|
if (this._doc == null) {
|
|
101
108
|
throw new Error("Can't attach child if doc is not present");
|
|
102
109
|
}
|
|
@@ -123,19 +130,45 @@ export class LiveObject extends AbstractCrdt {
|
|
|
123
130
|
__classPrivateFieldGet(this, _LiveObject_map, "f").set(key, child);
|
|
124
131
|
child._setParentLink(this, key);
|
|
125
132
|
child._attach(id, this._doc);
|
|
126
|
-
return {
|
|
133
|
+
return {
|
|
134
|
+
reverse,
|
|
135
|
+
modified: {
|
|
136
|
+
node: this,
|
|
137
|
+
type: "LiveObject",
|
|
138
|
+
updates: { [key]: { type: "update" } },
|
|
139
|
+
},
|
|
140
|
+
};
|
|
127
141
|
}
|
|
128
142
|
/**
|
|
129
143
|
* INTERNAL
|
|
130
144
|
*/
|
|
131
145
|
_detachChild(child) {
|
|
132
|
-
for (const [key, value] of __classPrivateFieldGet(this, _LiveObject_map, "f")) {
|
|
133
|
-
if (value === child) {
|
|
134
|
-
__classPrivateFieldGet(this, _LiveObject_map, "f").delete(key);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
146
|
if (child) {
|
|
147
|
+
const reverse = this._serialize(this._id, child._parentKey, this._doc);
|
|
148
|
+
for (const [key, value] of __classPrivateFieldGet(this, _LiveObject_map, "f")) {
|
|
149
|
+
if (value === child) {
|
|
150
|
+
__classPrivateFieldGet(this, _LiveObject_map, "f").delete(key);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
138
153
|
child._detach();
|
|
154
|
+
const storageUpdate = {
|
|
155
|
+
node: this,
|
|
156
|
+
type: "LiveObject",
|
|
157
|
+
updates: {
|
|
158
|
+
[child._parentKey]: { type: "delete" },
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
return { modified: storageUpdate, reverse };
|
|
162
|
+
}
|
|
163
|
+
return { modified: false };
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* INTERNAL
|
|
167
|
+
*/
|
|
168
|
+
_detachChildren() {
|
|
169
|
+
for (const [key, value] of __classPrivateFieldGet(this, _LiveObject_map, "f")) {
|
|
170
|
+
__classPrivateFieldGet(this, _LiveObject_map, "f").delete(key);
|
|
171
|
+
value._detach();
|
|
139
172
|
}
|
|
140
173
|
}
|
|
141
174
|
/**
|
|
@@ -152,14 +185,32 @@ export class LiveObject extends AbstractCrdt {
|
|
|
152
185
|
/**
|
|
153
186
|
* INTERNAL
|
|
154
187
|
*/
|
|
155
|
-
_apply(op) {
|
|
188
|
+
_apply(op, isLocal) {
|
|
156
189
|
if (op.type === OpType.UpdateObject) {
|
|
157
|
-
return __classPrivateFieldGet(this, _LiveObject_instances, "m", _LiveObject_applyUpdate).call(this, op);
|
|
190
|
+
return __classPrivateFieldGet(this, _LiveObject_instances, "m", _LiveObject_applyUpdate).call(this, op, isLocal);
|
|
158
191
|
}
|
|
159
192
|
else if (op.type === OpType.DeleteObjectKey) {
|
|
160
193
|
return __classPrivateFieldGet(this, _LiveObject_instances, "m", _LiveObject_applyDeleteObjectKey).call(this, op);
|
|
161
194
|
}
|
|
162
|
-
return super._apply(op);
|
|
195
|
+
return super._apply(op, isLocal);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* INTERNAL
|
|
199
|
+
*/
|
|
200
|
+
_toSerializedCrdt() {
|
|
201
|
+
var _a;
|
|
202
|
+
return {
|
|
203
|
+
type: CrdtType.Object,
|
|
204
|
+
parentId: (_a = this._parent) === null || _a === void 0 ? void 0 : _a._id,
|
|
205
|
+
parentKey: this._parentKey,
|
|
206
|
+
data: this.toObject(),
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* INTERNAL
|
|
211
|
+
*/
|
|
212
|
+
_getType() {
|
|
213
|
+
return "LiveObject";
|
|
163
214
|
}
|
|
164
215
|
/**
|
|
165
216
|
* Transform the LiveObject into a javascript object
|
|
@@ -215,7 +266,20 @@ export class LiveObject extends AbstractCrdt {
|
|
|
215
266
|
];
|
|
216
267
|
}
|
|
217
268
|
__classPrivateFieldGet(this, _LiveObject_map, "f").delete(keyAsString);
|
|
218
|
-
|
|
269
|
+
const storageUpdates = new Map();
|
|
270
|
+
storageUpdates.set(this._id, {
|
|
271
|
+
node: this,
|
|
272
|
+
type: "LiveObject",
|
|
273
|
+
updates: { [key]: { type: "delete" } },
|
|
274
|
+
});
|
|
275
|
+
this._doc.dispatch([
|
|
276
|
+
{
|
|
277
|
+
type: OpType.DeleteObjectKey,
|
|
278
|
+
key: keyAsString,
|
|
279
|
+
id: this._id,
|
|
280
|
+
opId: this._doc.generateOpId(),
|
|
281
|
+
},
|
|
282
|
+
], reverse, storageUpdates);
|
|
219
283
|
}
|
|
220
284
|
/**
|
|
221
285
|
* Adds or updates multiple properties at once with an object.
|
|
@@ -245,6 +309,7 @@ export class LiveObject extends AbstractCrdt {
|
|
|
245
309
|
type: OpType.UpdateObject,
|
|
246
310
|
data: {},
|
|
247
311
|
};
|
|
312
|
+
const updateDelta = {};
|
|
248
313
|
for (const key in overrides) {
|
|
249
314
|
__classPrivateFieldGet(this, _LiveObject_propToLastUpdate, "f").set(key, opId);
|
|
250
315
|
const oldValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
|
|
@@ -262,12 +327,13 @@ export class LiveObject extends AbstractCrdt {
|
|
|
262
327
|
if (newValue instanceof AbstractCrdt) {
|
|
263
328
|
newValue._setParentLink(this, key);
|
|
264
329
|
newValue._attach(this._doc.generateId(), this._doc);
|
|
265
|
-
ops.push(...newValue._serialize(this._id, key));
|
|
330
|
+
ops.push(...newValue._serialize(this._id, key, this._doc));
|
|
266
331
|
}
|
|
267
332
|
else {
|
|
268
333
|
updatedProps[key] = newValue;
|
|
269
334
|
}
|
|
270
335
|
__classPrivateFieldGet(this, _LiveObject_map, "f").set(key, newValue);
|
|
336
|
+
updateDelta[key] = { type: "update" };
|
|
271
337
|
}
|
|
272
338
|
if (Object.keys(reverseUpdateOp.data).length !== 0) {
|
|
273
339
|
reverseOps.unshift(reverseUpdateOp);
|
|
@@ -280,10 +346,16 @@ export class LiveObject extends AbstractCrdt {
|
|
|
280
346
|
data: updatedProps,
|
|
281
347
|
});
|
|
282
348
|
}
|
|
283
|
-
|
|
349
|
+
const storageUpdates = new Map();
|
|
350
|
+
storageUpdates.set(this._id, {
|
|
351
|
+
node: this,
|
|
352
|
+
type: "LiveObject",
|
|
353
|
+
updates: updateDelta,
|
|
354
|
+
});
|
|
355
|
+
this._doc.dispatch(ops, reverseOps, storageUpdates);
|
|
284
356
|
}
|
|
285
357
|
}
|
|
286
|
-
_LiveObject_map = new WeakMap(), _LiveObject_propToLastUpdate = new WeakMap(), _LiveObject_instances = new WeakSet(), _LiveObject_applyUpdate = function _LiveObject_applyUpdate(op) {
|
|
358
|
+
_LiveObject_map = new WeakMap(), _LiveObject_propToLastUpdate = new WeakMap(), _LiveObject_instances = new WeakSet(), _LiveObject_applyUpdate = function _LiveObject_applyUpdate(op, isLocal) {
|
|
287
359
|
let isModified = false;
|
|
288
360
|
const reverse = [];
|
|
289
361
|
const reverseUpdate = {
|
|
@@ -305,11 +377,7 @@ _LiveObject_map = new WeakMap(), _LiveObject_propToLastUpdate = new WeakMap(), _
|
|
|
305
377
|
reverse.push({ type: OpType.DeleteObjectKey, id: this._id, key });
|
|
306
378
|
}
|
|
307
379
|
}
|
|
308
|
-
let
|
|
309
|
-
if (op.opId == null) {
|
|
310
|
-
isLocal = true;
|
|
311
|
-
op.opId = this._doc.generateOpId();
|
|
312
|
-
}
|
|
380
|
+
let updateDelta = {};
|
|
313
381
|
for (const key in op.data) {
|
|
314
382
|
if (isLocal) {
|
|
315
383
|
__classPrivateFieldGet(this, _LiveObject_propToLastUpdate, "f").set(key, op.opId);
|
|
@@ -332,12 +400,22 @@ _LiveObject_map = new WeakMap(), _LiveObject_propToLastUpdate = new WeakMap(), _
|
|
|
332
400
|
oldValue._detach();
|
|
333
401
|
}
|
|
334
402
|
isModified = true;
|
|
403
|
+
updateDelta[key] = { type: "update" };
|
|
335
404
|
__classPrivateFieldGet(this, _LiveObject_map, "f").set(key, op.data[key]);
|
|
336
405
|
}
|
|
337
406
|
if (Object.keys(reverseUpdate.data).length !== 0) {
|
|
338
407
|
reverse.unshift(reverseUpdate);
|
|
339
408
|
}
|
|
340
|
-
return isModified
|
|
409
|
+
return isModified
|
|
410
|
+
? {
|
|
411
|
+
modified: {
|
|
412
|
+
node: this,
|
|
413
|
+
type: "LiveObject",
|
|
414
|
+
updates: updateDelta,
|
|
415
|
+
},
|
|
416
|
+
reverse,
|
|
417
|
+
}
|
|
418
|
+
: { modified: false };
|
|
341
419
|
}, _LiveObject_applyDeleteObjectKey = function _LiveObject_applyDeleteObjectKey(op) {
|
|
342
420
|
const key = op.key;
|
|
343
421
|
// If property does not exist, exit without notifying
|
|
@@ -360,5 +438,12 @@ _LiveObject_map = new WeakMap(), _LiveObject_propToLastUpdate = new WeakMap(), _
|
|
|
360
438
|
];
|
|
361
439
|
}
|
|
362
440
|
__classPrivateFieldGet(this, _LiveObject_map, "f").delete(key);
|
|
363
|
-
return {
|
|
441
|
+
return {
|
|
442
|
+
modified: {
|
|
443
|
+
node: this,
|
|
444
|
+
type: "LiveObject",
|
|
445
|
+
updates: { [op.key]: { type: "delete" } },
|
|
446
|
+
},
|
|
447
|
+
reverse,
|
|
448
|
+
};
|
|
364
449
|
};
|
|
@@ -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,16 @@ export declare class LiveRegister<TValue = any> extends AbstractCrdt {
|
|
|
14
14
|
/**
|
|
15
15
|
* INTERNAL
|
|
16
16
|
*/
|
|
17
|
-
_serialize(parentId: string, parentKey: string): Op[];
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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;
|
|
23
|
+
_detachChild(crdt: AbstractCrdt): ApplyResult;
|
|
24
|
+
_apply(op: Op, isLocal: boolean): ApplyResult;
|
|
25
|
+
/**
|
|
26
|
+
* INTERNAL
|
|
27
|
+
*/
|
|
28
|
+
_getType(): string;
|
|
21
29
|
}
|
package/lib/esm/LiveRegister.js
CHANGED
|
@@ -11,7 +11,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
11
11
|
};
|
|
12
12
|
var _LiveRegister_data;
|
|
13
13
|
import { AbstractCrdt } from "./AbstractCrdt";
|
|
14
|
-
import { CrdtType, OpType } from "./live";
|
|
14
|
+
import { CrdtType, OpType, } from "./live";
|
|
15
15
|
/**
|
|
16
16
|
* INTERNAL
|
|
17
17
|
*/
|
|
@@ -38,13 +38,14 @@ export class LiveRegister extends AbstractCrdt {
|
|
|
38
38
|
/**
|
|
39
39
|
* INTERNAL
|
|
40
40
|
*/
|
|
41
|
-
_serialize(parentId, parentKey) {
|
|
41
|
+
_serialize(parentId, parentKey, doc) {
|
|
42
42
|
if (this._id == null || parentId == null || parentKey == null) {
|
|
43
43
|
throw new Error("Cannot serialize register if parentId or parentKey is undefined");
|
|
44
44
|
}
|
|
45
45
|
return [
|
|
46
46
|
{
|
|
47
47
|
type: OpType.CreateRegister,
|
|
48
|
+
opId: doc === null || doc === void 0 ? void 0 : doc.generateOpId(),
|
|
48
49
|
id: this._id,
|
|
49
50
|
parentId,
|
|
50
51
|
parentKey,
|
|
@@ -52,14 +53,32 @@ export class LiveRegister extends AbstractCrdt {
|
|
|
52
53
|
},
|
|
53
54
|
];
|
|
54
55
|
}
|
|
55
|
-
|
|
56
|
+
/**
|
|
57
|
+
* INTERNAL
|
|
58
|
+
*/
|
|
59
|
+
_toSerializedCrdt() {
|
|
60
|
+
var _a;
|
|
61
|
+
return {
|
|
62
|
+
type: CrdtType.Register,
|
|
63
|
+
parentId: (_a = this._parent) === null || _a === void 0 ? void 0 : _a._id,
|
|
64
|
+
parentKey: this._parentKey,
|
|
65
|
+
data: this.data,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
_attachChild(id, key, crdt, isLocal) {
|
|
56
69
|
throw new Error("Method not implemented.");
|
|
57
70
|
}
|
|
58
71
|
_detachChild(crdt) {
|
|
59
72
|
throw new Error("Method not implemented.");
|
|
60
73
|
}
|
|
61
|
-
_apply(op) {
|
|
62
|
-
return super._apply(op);
|
|
74
|
+
_apply(op, isLocal) {
|
|
75
|
+
return super._apply(op, isLocal);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* INTERNAL
|
|
79
|
+
*/
|
|
80
|
+
_getType() {
|
|
81
|
+
return "LiveRegister";
|
|
63
82
|
}
|
|
64
83
|
}
|
|
65
84
|
_LiveRegister_data = new WeakMap();
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { LiveList } from "
|
|
2
|
-
import { LiveObject } from "
|
|
3
|
-
import { StorageUpdate } from "
|
|
1
|
+
import { LiveList } from "./LiveList";
|
|
2
|
+
import { LiveObject } from "./LiveObject";
|
|
3
|
+
import { StorageUpdate } from "./types";
|
|
4
4
|
export declare function liveObjectToJson(liveObject: LiveObject<any>): any;
|
|
5
|
+
export declare function liveNodeToJson(value: any): any;
|
|
5
6
|
export declare function patchLiveList<T>(liveList: LiveList<T>, prev: Array<T>, next: Array<T>): void;
|
|
7
|
+
export declare function patchLiveObjectKey<T>(liveObject: LiveObject<T>, key: keyof T, prev: any, next: any): void;
|
|
6
8
|
export declare function patchLiveObject<T extends Record<string, any>>(root: LiveObject<T>, prev: T, next: T): void;
|
|
7
9
|
export declare function patchImmutableObject<T>(state: T, updates: StorageUpdate[]): T;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { LiveList } from "
|
|
2
|
-
import { LiveMap } from "
|
|
3
|
-
import { LiveObject } from "
|
|
1
|
+
import { LiveList } from "./LiveList";
|
|
2
|
+
import { LiveMap } from "./LiveMap";
|
|
3
|
+
import { LiveObject } from "./LiveObject";
|
|
4
|
+
import { LiveRegister } from "./LiveRegister";
|
|
4
5
|
export function liveObjectToJson(liveObject) {
|
|
5
6
|
const result = {};
|
|
6
7
|
const obj = liveObject.toObject();
|
|
@@ -20,7 +21,7 @@ function liveMapToJson(map) {
|
|
|
20
21
|
function liveListToJson(value) {
|
|
21
22
|
return value.toArray().map(liveNodeToJson);
|
|
22
23
|
}
|
|
23
|
-
function liveNodeToJson(value) {
|
|
24
|
+
export function liveNodeToJson(value) {
|
|
24
25
|
if (value instanceof LiveObject) {
|
|
25
26
|
return liveObjectToJson(value);
|
|
26
27
|
}
|
|
@@ -30,6 +31,9 @@ function liveNodeToJson(value) {
|
|
|
30
31
|
else if (value instanceof LiveMap) {
|
|
31
32
|
return liveMapToJson(value);
|
|
32
33
|
}
|
|
34
|
+
else if (value instanceof LiveRegister) {
|
|
35
|
+
return value.data;
|
|
36
|
+
}
|
|
33
37
|
return value;
|
|
34
38
|
}
|
|
35
39
|
function isPlainObject(obj) {
|
|
@@ -127,21 +131,35 @@ export function patchLiveList(liveList, prev, next) {
|
|
|
127
131
|
}
|
|
128
132
|
}
|
|
129
133
|
}
|
|
134
|
+
export function patchLiveObjectKey(liveObject, key, prev, next) {
|
|
135
|
+
const value = liveObject.get(key);
|
|
136
|
+
if (next === undefined) {
|
|
137
|
+
liveObject.delete(key);
|
|
138
|
+
}
|
|
139
|
+
else if (value === undefined) {
|
|
140
|
+
liveObject.set(key, anyToCrdt(next));
|
|
141
|
+
}
|
|
142
|
+
else if (prev === next) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
else if (value instanceof LiveList &&
|
|
146
|
+
Array.isArray(prev) &&
|
|
147
|
+
Array.isArray(next)) {
|
|
148
|
+
patchLiveList(value, prev, next);
|
|
149
|
+
}
|
|
150
|
+
else if (value instanceof LiveObject &&
|
|
151
|
+
isPlainObject(prev) &&
|
|
152
|
+
isPlainObject(next)) {
|
|
153
|
+
patchLiveObject(value, prev, next);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
liveObject.set(key, anyToCrdt(next));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
130
159
|
export function patchLiveObject(root, prev, next) {
|
|
131
160
|
const updates = {};
|
|
132
161
|
for (const key in next) {
|
|
133
|
-
|
|
134
|
-
continue;
|
|
135
|
-
}
|
|
136
|
-
else if (Array.isArray(prev[key]) && Array.isArray(next[key])) {
|
|
137
|
-
patchLiveList(root.get(key), prev[key], next[key]);
|
|
138
|
-
}
|
|
139
|
-
else if (isPlainObject(prev[key]) && isPlainObject(next[key])) {
|
|
140
|
-
patchLiveObject(root.get(key), prev[key], next[key]);
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
updates[key] = anyToCrdt(next[key]);
|
|
144
|
-
}
|
|
162
|
+
patchLiveObjectKey(root, key, prev[key], next[key]);
|
|
145
163
|
}
|
|
146
164
|
for (const key in prev) {
|
|
147
165
|
if (next[key] === undefined) {
|
|
@@ -173,6 +191,7 @@ function patchImmutableObjectWithUpdate(state, update) {
|
|
|
173
191
|
return patchImmutableNode(state, path, update);
|
|
174
192
|
}
|
|
175
193
|
function patchImmutableNode(state, path, update) {
|
|
194
|
+
var _a, _b, _c, _d;
|
|
176
195
|
const pathItem = path.pop();
|
|
177
196
|
if (pathItem === undefined) {
|
|
178
197
|
switch (update.type) {
|
|
@@ -180,19 +199,56 @@ function patchImmutableNode(state, path, update) {
|
|
|
180
199
|
if (typeof state !== "object") {
|
|
181
200
|
throw new Error("Internal: received update on LiveObject but state was not an object");
|
|
182
201
|
}
|
|
183
|
-
|
|
202
|
+
let newState = Object.assign({}, state);
|
|
203
|
+
for (const key in update.updates) {
|
|
204
|
+
if (((_a = update.updates[key]) === null || _a === void 0 ? void 0 : _a.type) === "update") {
|
|
205
|
+
newState[key] = liveNodeToJson(update.node.get(key));
|
|
206
|
+
}
|
|
207
|
+
else if (((_b = update.updates[key]) === null || _b === void 0 ? void 0 : _b.type) === "delete") {
|
|
208
|
+
delete newState[key];
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return newState;
|
|
184
212
|
}
|
|
185
213
|
case "LiveList": {
|
|
186
214
|
if (Array.isArray(state) === false) {
|
|
187
215
|
throw new Error("Internal: received update on LiveList but state was not an array");
|
|
188
216
|
}
|
|
189
|
-
|
|
217
|
+
let newState = state.map((x) => x);
|
|
218
|
+
const newArray = update.node.toArray();
|
|
219
|
+
for (const listUpdate of update.updates) {
|
|
220
|
+
if (listUpdate.type === "insert") {
|
|
221
|
+
if (listUpdate.index === newState.length) {
|
|
222
|
+
newState.push(liveNodeToJson(newArray[listUpdate.index]));
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
newState = [
|
|
226
|
+
...newState.slice(0, listUpdate.index),
|
|
227
|
+
liveNodeToJson(newArray[listUpdate.index]),
|
|
228
|
+
...newState.slice(listUpdate.index),
|
|
229
|
+
];
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
else if (listUpdate.type === "delete") {
|
|
233
|
+
newState.splice(listUpdate.index, 1);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return newState;
|
|
190
237
|
}
|
|
191
238
|
case "LiveMap": {
|
|
192
239
|
if (typeof state !== "object") {
|
|
193
240
|
throw new Error("Internal: received update on LiveMap but state was not an object");
|
|
194
241
|
}
|
|
195
|
-
|
|
242
|
+
let newState = Object.assign({}, state);
|
|
243
|
+
for (const key in update.updates) {
|
|
244
|
+
if (((_c = update.updates[key]) === null || _c === void 0 ? void 0 : _c.type) === "update") {
|
|
245
|
+
newState[key] = liveNodeToJson(update.node.get(key));
|
|
246
|
+
}
|
|
247
|
+
else if (((_d = update.updates[key]) === null || _d === void 0 ? void 0 : _d.type) === "delete") {
|
|
248
|
+
delete newState[key];
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return newState;
|
|
196
252
|
}
|
|
197
253
|
}
|
|
198
254
|
}
|
package/lib/esm/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { LiveObject } from "./LiveObject";
|
|
2
2
|
export { LiveMap } from "./LiveMap";
|
|
3
3
|
export { LiveList } from "./LiveList";
|
|
4
|
-
export type { Others, Presence, Room, Client, User } from "./types";
|
|
4
|
+
export type { Others, Presence, Room, Client, User, BroadcastOptions, } from "./types";
|
|
5
5
|
export { createClient } from "./client";
|
|
6
|
+
export { liveObjectToJson, liveNodeToJson, patchLiveList, patchImmutableObject, patchLiveObject, patchLiveObjectKey, } from "./immutable";
|
package/lib/esm/index.js
CHANGED
|
@@ -2,3 +2,4 @@ export { LiveObject } from "./LiveObject";
|
|
|
2
2
|
export { LiveMap } from "./LiveMap";
|
|
3
3
|
export { LiveList } from "./LiveList";
|
|
4
4
|
export { createClient } from "./client";
|
|
5
|
+
export { liveObjectToJson, liveNodeToJson, patchLiveList, patchImmutableObject, patchLiveObject, patchLiveObjectKey, } from "./immutable";
|
package/lib/esm/live.d.ts
CHANGED
|
@@ -122,6 +122,7 @@ export declare type UpdateObjectOp = {
|
|
|
122
122
|
};
|
|
123
123
|
};
|
|
124
124
|
export declare type CreateObjectOp = {
|
|
125
|
+
opId?: string;
|
|
125
126
|
id: string;
|
|
126
127
|
type: OpType.CreateObject;
|
|
127
128
|
parentId?: string;
|
|
@@ -131,18 +132,21 @@ export declare type CreateObjectOp = {
|
|
|
131
132
|
};
|
|
132
133
|
};
|
|
133
134
|
export declare type CreateListOp = {
|
|
135
|
+
opId?: string;
|
|
134
136
|
id: string;
|
|
135
137
|
type: OpType.CreateList;
|
|
136
138
|
parentId: string;
|
|
137
139
|
parentKey: string;
|
|
138
140
|
};
|
|
139
141
|
export declare type CreateMapOp = {
|
|
142
|
+
opId?: string;
|
|
140
143
|
id: string;
|
|
141
144
|
type: OpType.CreateMap;
|
|
142
145
|
parentId: string;
|
|
143
146
|
parentKey: string;
|
|
144
147
|
};
|
|
145
148
|
export declare type CreateRegisterOp = {
|
|
149
|
+
opId?: string;
|
|
146
150
|
id: string;
|
|
147
151
|
type: OpType.CreateRegister;
|
|
148
152
|
parentId: string;
|
|
@@ -150,15 +154,18 @@ export declare type CreateRegisterOp = {
|
|
|
150
154
|
data: any;
|
|
151
155
|
};
|
|
152
156
|
export declare type DeleteCrdtOp = {
|
|
157
|
+
opId?: string;
|
|
153
158
|
id: string;
|
|
154
159
|
type: OpType.DeleteCrdt;
|
|
155
160
|
};
|
|
156
161
|
export declare type SetParentKeyOp = {
|
|
162
|
+
opId?: string;
|
|
157
163
|
id: string;
|
|
158
164
|
type: OpType.SetParentKey;
|
|
159
165
|
parentKey: string;
|
|
160
166
|
};
|
|
161
167
|
export declare type DeleteObjectKeyOp = {
|
|
168
|
+
opId?: string;
|
|
162
169
|
id: string;
|
|
163
170
|
type: OpType.DeleteObjectKey;
|
|
164
171
|
key: string;
|
package/lib/esm/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: {
|
|
@@ -59,9 +60,10 @@ export declare type State = {
|
|
|
59
60
|
updates: {
|
|
60
61
|
others: [];
|
|
61
62
|
presence: boolean;
|
|
62
|
-
|
|
63
|
+
storageUpdates: Map<string, StorageUpdate>;
|
|
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;
|