@liveblocks/client 0.13.2 → 0.14.0-beta.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 +8 -4
- package/lib/cjs/AbstractCrdt.js +2 -2
- package/lib/cjs/LiveList.d.ts +8 -4
- package/lib/cjs/LiveList.js +36 -9
- package/lib/cjs/LiveMap.d.ts +7 -3
- package/lib/cjs/LiveMap.js +23 -5
- package/lib/cjs/LiveObject.d.ts +17 -7
- package/lib/cjs/LiveObject.js +45 -15
- package/lib/cjs/LiveRegister.d.ts +8 -4
- package/lib/cjs/LiveRegister.js +17 -4
- package/lib/cjs/live.d.ts +7 -0
- package/lib/cjs/room.d.ts +8 -0
- package/lib/cjs/room.js +97 -22
- package/lib/cjs/utils.d.ts +2 -1
- package/lib/cjs/utils.js +76 -1
- package/lib/esm/AbstractCrdt.d.ts +8 -4
- package/lib/esm/AbstractCrdt.js +2 -2
- package/lib/esm/LiveList.d.ts +8 -4
- package/lib/esm/LiveList.js +37 -10
- package/lib/esm/LiveMap.d.ts +7 -3
- package/lib/esm/LiveMap.js +23 -5
- package/lib/esm/LiveObject.d.ts +17 -7
- package/lib/esm/LiveObject.js +45 -15
- package/lib/esm/LiveRegister.d.ts +8 -4
- package/lib/esm/LiveRegister.js +18 -5
- package/lib/esm/live.d.ts +7 -0
- package/lib/esm/room.d.ts +8 -0
- package/lib/esm/room.js +98 -23
- package/lib/esm/utils.d.ts +2 -1
- package/lib/esm/utils.js +75 -1
- package/package.json +2 -2
- package/lib/cjs/immutable/index.d.ts +0 -7
- package/lib/cjs/immutable/index.js +0 -214
- package/lib/esm/immutable/index.d.ts +0 -7
- package/lib/esm/immutable/index.js +0 -207
package/lib/esm/utils.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CrdtType, } from "./live";
|
|
1
|
+
import { CrdtType, OpType, } from "./live";
|
|
2
2
|
import { LiveList } from "./LiveList";
|
|
3
3
|
import { LiveMap } from "./LiveMap";
|
|
4
4
|
import { LiveObject } from "./LiveObject";
|
|
@@ -64,3 +64,77 @@ export function selfOrRegister(obj) {
|
|
|
64
64
|
return new LiveRegister(obj);
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
|
+
export function getTreesDiffOperations(currentItems, newItems) {
|
|
68
|
+
const ops = [];
|
|
69
|
+
currentItems.forEach((_, id) => {
|
|
70
|
+
if (!newItems.get(id)) {
|
|
71
|
+
// Delete crdt
|
|
72
|
+
ops.push({
|
|
73
|
+
type: OpType.DeleteCrdt,
|
|
74
|
+
id: id,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
newItems.forEach((crdt, id) => {
|
|
79
|
+
const currentCrdt = currentItems.get(id);
|
|
80
|
+
if (currentCrdt) {
|
|
81
|
+
if (crdt.type === CrdtType.Object) {
|
|
82
|
+
if (JSON.stringify(crdt.data) !==
|
|
83
|
+
JSON.stringify(currentCrdt.data)) {
|
|
84
|
+
ops.push({
|
|
85
|
+
type: OpType.UpdateObject,
|
|
86
|
+
id: id,
|
|
87
|
+
data: crdt.data,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (crdt.parentKey !== currentCrdt.parentKey) {
|
|
92
|
+
ops.push({
|
|
93
|
+
type: OpType.SetParentKey,
|
|
94
|
+
id: id,
|
|
95
|
+
parentKey: crdt.parentKey,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
// new Crdt
|
|
101
|
+
switch (crdt.type) {
|
|
102
|
+
case CrdtType.Register:
|
|
103
|
+
ops.push({
|
|
104
|
+
type: OpType.CreateRegister,
|
|
105
|
+
id: id,
|
|
106
|
+
parentId: crdt.parentId,
|
|
107
|
+
parentKey: crdt.parentKey,
|
|
108
|
+
data: crdt.data,
|
|
109
|
+
});
|
|
110
|
+
break;
|
|
111
|
+
case CrdtType.List:
|
|
112
|
+
ops.push({
|
|
113
|
+
type: OpType.CreateList,
|
|
114
|
+
id: id,
|
|
115
|
+
parentId: crdt.parentId,
|
|
116
|
+
parentKey: crdt.parentKey,
|
|
117
|
+
});
|
|
118
|
+
break;
|
|
119
|
+
case CrdtType.Object:
|
|
120
|
+
ops.push({
|
|
121
|
+
type: OpType.CreateObject,
|
|
122
|
+
id: id,
|
|
123
|
+
parentId: crdt.parentId,
|
|
124
|
+
parentKey: crdt.parentKey,
|
|
125
|
+
data: crdt.data,
|
|
126
|
+
});
|
|
127
|
+
break;
|
|
128
|
+
case CrdtType.Map:
|
|
129
|
+
ops.push({
|
|
130
|
+
type: OpType.CreateMap,
|
|
131
|
+
id: id,
|
|
132
|
+
parentId: crdt.parentId,
|
|
133
|
+
parentKey: crdt.parentKey,
|
|
134
|
+
});
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
return ops;
|
|
140
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liveblocks/client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0-beta.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./lib/cjs/index.js",
|
|
6
6
|
"module": "./lib/esm/index.js",
|
|
@@ -38,4 +38,4 @@
|
|
|
38
38
|
"url": "https://github.com/liveblocks/liveblocks.git",
|
|
39
39
|
"directory": "packages/liveblocks"
|
|
40
40
|
}
|
|
41
|
-
}
|
|
41
|
+
}
|
|
@@ -1,7 +0,0 @@
|
|
|
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;
|
|
@@ -1,214 +0,0 @@
|
|
|
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,7 +0,0 @@
|
|
|
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;
|
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
import { LiveList } from "../LiveList";
|
|
2
|
-
import { LiveMap } from "../LiveMap";
|
|
3
|
-
import { LiveObject } from "../LiveObject";
|
|
4
|
-
export function liveObjectToJson(liveObject) {
|
|
5
|
-
const result = {};
|
|
6
|
-
const obj = liveObject.toObject();
|
|
7
|
-
for (const key in obj) {
|
|
8
|
-
result[key] = liveNodeToJson(obj[key]);
|
|
9
|
-
}
|
|
10
|
-
return result;
|
|
11
|
-
}
|
|
12
|
-
function liveMapToJson(map) {
|
|
13
|
-
const result = {};
|
|
14
|
-
const obj = Object.fromEntries(map);
|
|
15
|
-
for (const key in obj) {
|
|
16
|
-
result[key] = liveNodeToJson(obj[key]);
|
|
17
|
-
}
|
|
18
|
-
return result;
|
|
19
|
-
}
|
|
20
|
-
function liveListToJson(value) {
|
|
21
|
-
return value.toArray().map(liveNodeToJson);
|
|
22
|
-
}
|
|
23
|
-
function liveNodeToJson(value) {
|
|
24
|
-
if (value instanceof LiveObject) {
|
|
25
|
-
return liveObjectToJson(value);
|
|
26
|
-
}
|
|
27
|
-
else if (value instanceof LiveList) {
|
|
28
|
-
return liveListToJson(value);
|
|
29
|
-
}
|
|
30
|
-
else if (value instanceof LiveMap) {
|
|
31
|
-
return liveMapToJson(value);
|
|
32
|
-
}
|
|
33
|
-
return value;
|
|
34
|
-
}
|
|
35
|
-
function isPlainObject(obj) {
|
|
36
|
-
return Object.prototype.toString.call(obj) === "[object Object]";
|
|
37
|
-
}
|
|
38
|
-
function anyToCrdt(obj) {
|
|
39
|
-
if (obj == null) {
|
|
40
|
-
return obj;
|
|
41
|
-
}
|
|
42
|
-
if (Array.isArray(obj)) {
|
|
43
|
-
return new LiveList(obj.map(anyToCrdt));
|
|
44
|
-
}
|
|
45
|
-
if (isPlainObject(obj)) {
|
|
46
|
-
const init = {};
|
|
47
|
-
for (const key in obj) {
|
|
48
|
-
init[key] = anyToCrdt(obj[key]);
|
|
49
|
-
}
|
|
50
|
-
return new LiveObject(init);
|
|
51
|
-
}
|
|
52
|
-
return obj;
|
|
53
|
-
}
|
|
54
|
-
export function patchLiveList(liveList, prev, next) {
|
|
55
|
-
let i = 0;
|
|
56
|
-
let prevEnd = prev.length - 1;
|
|
57
|
-
let nextEnd = next.length - 1;
|
|
58
|
-
let prevNode = prev[0];
|
|
59
|
-
let nextNode = next[0];
|
|
60
|
-
/**
|
|
61
|
-
* For A,B,C => A,B,C,D
|
|
62
|
-
* i = 3, prevEnd = 2, nextEnd = 3
|
|
63
|
-
*
|
|
64
|
-
* For A,B,C => B,C
|
|
65
|
-
* i = 2, prevEnd = 2, nextEnd = 1
|
|
66
|
-
*
|
|
67
|
-
* For B,C => A,B,C
|
|
68
|
-
* i = 0, pre
|
|
69
|
-
*/
|
|
70
|
-
outer: {
|
|
71
|
-
while (prevNode === nextNode) {
|
|
72
|
-
++i;
|
|
73
|
-
if (i > prevEnd || i > nextEnd) {
|
|
74
|
-
break outer;
|
|
75
|
-
}
|
|
76
|
-
prevNode = prev[i];
|
|
77
|
-
nextNode = next[i];
|
|
78
|
-
}
|
|
79
|
-
prevNode = prev[prevEnd];
|
|
80
|
-
nextNode = next[nextEnd];
|
|
81
|
-
while (prevNode === nextNode) {
|
|
82
|
-
prevEnd--;
|
|
83
|
-
nextEnd--;
|
|
84
|
-
if (i > prevEnd || i > nextEnd) {
|
|
85
|
-
break outer;
|
|
86
|
-
}
|
|
87
|
-
prevNode = prev[prevEnd];
|
|
88
|
-
nextNode = next[nextEnd];
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
if (i > prevEnd) {
|
|
92
|
-
if (i <= nextEnd) {
|
|
93
|
-
while (i <= nextEnd) {
|
|
94
|
-
liveList.insert(anyToCrdt(next[i]), i);
|
|
95
|
-
i++;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
else if (i > nextEnd) {
|
|
100
|
-
while (i <= prevEnd) {
|
|
101
|
-
liveList.delete(i++);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
while (i <= prevEnd && i <= nextEnd) {
|
|
106
|
-
prevNode = prev[i];
|
|
107
|
-
nextNode = next[i];
|
|
108
|
-
const liveListNode = liveList.get(i);
|
|
109
|
-
if (liveListNode instanceof LiveObject &&
|
|
110
|
-
isPlainObject(prevNode) &&
|
|
111
|
-
isPlainObject(nextNode)) {
|
|
112
|
-
patchLiveObject(liveListNode, prevNode, nextNode);
|
|
113
|
-
}
|
|
114
|
-
else {
|
|
115
|
-
liveList.delete(i);
|
|
116
|
-
liveList.insert(anyToCrdt(nextNode), i);
|
|
117
|
-
}
|
|
118
|
-
i++;
|
|
119
|
-
}
|
|
120
|
-
while (i <= nextEnd) {
|
|
121
|
-
liveList.insert(anyToCrdt(next[i]), i);
|
|
122
|
-
i++;
|
|
123
|
-
}
|
|
124
|
-
while (i <= prevEnd) {
|
|
125
|
-
liveList.delete(i);
|
|
126
|
-
i++;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
export function patchLiveObject(root, prev, next) {
|
|
131
|
-
const updates = {};
|
|
132
|
-
for (const key in next) {
|
|
133
|
-
if (prev[key] === next[key]) {
|
|
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
|
-
}
|
|
145
|
-
}
|
|
146
|
-
for (const key in prev) {
|
|
147
|
-
if (next[key] === undefined) {
|
|
148
|
-
root.delete(key);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
if (Object.keys(updates).length > 0) {
|
|
152
|
-
root.update(updates);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
function getParentsPath(node) {
|
|
156
|
-
const path = [];
|
|
157
|
-
while (node._parentKey != null && node._parent != null) {
|
|
158
|
-
if (node._parent instanceof LiveList) {
|
|
159
|
-
path.push(node._parent._indexOfPosition(node._parentKey));
|
|
160
|
-
}
|
|
161
|
-
else {
|
|
162
|
-
path.push(node._parentKey);
|
|
163
|
-
}
|
|
164
|
-
node = node._parent;
|
|
165
|
-
}
|
|
166
|
-
return path;
|
|
167
|
-
}
|
|
168
|
-
export function patchImmutableObject(state, updates) {
|
|
169
|
-
return updates.reduce((state, update) => patchImmutableObjectWithUpdate(state, update), state);
|
|
170
|
-
}
|
|
171
|
-
function patchImmutableObjectWithUpdate(state, update) {
|
|
172
|
-
const path = getParentsPath(update.node);
|
|
173
|
-
return patchImmutableNode(state, path, update);
|
|
174
|
-
}
|
|
175
|
-
function patchImmutableNode(state, path, update) {
|
|
176
|
-
const pathItem = path.pop();
|
|
177
|
-
if (pathItem === undefined) {
|
|
178
|
-
switch (update.type) {
|
|
179
|
-
case "LiveObject": {
|
|
180
|
-
if (typeof state !== "object") {
|
|
181
|
-
throw new Error("Internal: received update on LiveObject but state was not an object");
|
|
182
|
-
}
|
|
183
|
-
return liveObjectToJson(update.node);
|
|
184
|
-
}
|
|
185
|
-
case "LiveList": {
|
|
186
|
-
if (Array.isArray(state) === false) {
|
|
187
|
-
throw new Error("Internal: received update on LiveList but state was not an array");
|
|
188
|
-
}
|
|
189
|
-
return liveListToJson(update.node);
|
|
190
|
-
}
|
|
191
|
-
case "LiveMap": {
|
|
192
|
-
if (typeof state !== "object") {
|
|
193
|
-
throw new Error("Internal: received update on LiveMap but state was not an object");
|
|
194
|
-
}
|
|
195
|
-
return liveMapToJson(update.node);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
if (Array.isArray(state)) {
|
|
200
|
-
const newArray = [...state];
|
|
201
|
-
newArray[pathItem] = patchImmutableNode(state[pathItem], path, update);
|
|
202
|
-
return newArray;
|
|
203
|
-
}
|
|
204
|
-
else {
|
|
205
|
-
return Object.assign(Object.assign({}, state), { [pathItem]: patchImmutableNode(state[pathItem], path, update) });
|
|
206
|
-
}
|
|
207
|
-
}
|