@liveblocks/client 0.16.3 → 0.16.4
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/index.d.ts +3 -727
- package/index.js +85 -2861
- package/index.mjs +1324 -0
- package/internal.d.ts +18 -56
- package/internal.js +321 -148
- package/internal.mjs +320 -0
- package/package.json +17 -16
- package/shared.d.ts +771 -0
- package/shared.js +2482 -0
- package/shared.mjs +1947 -0
- package/esm/index.js +0 -3068
- package/esm/index.mjs +0 -3068
- package/esm/internal.js +0 -150
- package/esm/internal.mjs +0 -150
package/internal.mjs
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import { L as LiveObject, b as LiveList, h as LiveMap, j as LiveRegister, A as AbstractCrdt, k as findNonSerializableValue } from './shared.mjs';
|
|
2
|
+
export { C as ClientMessageType, l as CrdtType, O as OpType, S as ServerMessageType, n as deprecate, f as deprecateIf } from './shared.mjs';
|
|
3
|
+
|
|
4
|
+
function lsonObjectToJson(obj) {
|
|
5
|
+
const result = {};
|
|
6
|
+
for (const key in obj) {
|
|
7
|
+
const val = obj[key];
|
|
8
|
+
if (val !== undefined) {
|
|
9
|
+
result[key] = lsonToJson(val);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return result;
|
|
13
|
+
}
|
|
14
|
+
function liveObjectToJson(liveObject) {
|
|
15
|
+
return lsonObjectToJson(liveObject.toObject());
|
|
16
|
+
}
|
|
17
|
+
function liveMapToJson(map) {
|
|
18
|
+
const result = {};
|
|
19
|
+
for (const [key, value] of map.entries()) {
|
|
20
|
+
result[key] = lsonToJson(value);
|
|
21
|
+
}
|
|
22
|
+
return result;
|
|
23
|
+
}
|
|
24
|
+
function lsonListToJson(value) {
|
|
25
|
+
return value.map(lsonToJson);
|
|
26
|
+
}
|
|
27
|
+
function liveListToJson(value) {
|
|
28
|
+
return lsonListToJson(value.toArray());
|
|
29
|
+
}
|
|
30
|
+
function lsonToJson(value) {
|
|
31
|
+
// ^^^^^^^^^^^^
|
|
32
|
+
// FIXME: Remove me later. This requires the
|
|
33
|
+
// addition of a concrete LiveStructure type first.
|
|
34
|
+
// Check for LiveStructure datastructures first
|
|
35
|
+
if (value instanceof LiveObject) {
|
|
36
|
+
return liveObjectToJson(value);
|
|
37
|
+
}
|
|
38
|
+
else if (value instanceof LiveList) {
|
|
39
|
+
return liveListToJson(value);
|
|
40
|
+
}
|
|
41
|
+
else if (value instanceof LiveMap) {
|
|
42
|
+
return liveMapToJson(value);
|
|
43
|
+
}
|
|
44
|
+
else if (value instanceof LiveRegister) {
|
|
45
|
+
return value.data;
|
|
46
|
+
}
|
|
47
|
+
else if (value instanceof AbstractCrdt) {
|
|
48
|
+
// This code path should never be taken
|
|
49
|
+
throw new Error("Unhandled subclass of AbstractCrdt encountered");
|
|
50
|
+
}
|
|
51
|
+
// Then for composite Lson values
|
|
52
|
+
if (Array.isArray(value)) {
|
|
53
|
+
return lsonListToJson(value);
|
|
54
|
+
}
|
|
55
|
+
else if (isPlainObject(value)) {
|
|
56
|
+
return lsonObjectToJson(value);
|
|
57
|
+
}
|
|
58
|
+
// Finally, if value is an LsonScalar, then it's also a valid JsonScalar
|
|
59
|
+
return value;
|
|
60
|
+
}
|
|
61
|
+
function isPlainObject(obj) {
|
|
62
|
+
return (obj !== null && Object.prototype.toString.call(obj) === "[object Object]");
|
|
63
|
+
}
|
|
64
|
+
function anyToCrdt(obj) {
|
|
65
|
+
// ^^^ AbstractCrdt?
|
|
66
|
+
if (obj == null) {
|
|
67
|
+
return obj;
|
|
68
|
+
}
|
|
69
|
+
if (Array.isArray(obj)) {
|
|
70
|
+
return new LiveList(obj.map(anyToCrdt));
|
|
71
|
+
}
|
|
72
|
+
if (isPlainObject(obj)) {
|
|
73
|
+
const init = {};
|
|
74
|
+
for (const key in obj) {
|
|
75
|
+
init[key] = anyToCrdt(obj[key]);
|
|
76
|
+
}
|
|
77
|
+
return new LiveObject(init);
|
|
78
|
+
}
|
|
79
|
+
return obj;
|
|
80
|
+
}
|
|
81
|
+
function patchLiveList(liveList, prev, next) {
|
|
82
|
+
let i = 0;
|
|
83
|
+
let prevEnd = prev.length - 1;
|
|
84
|
+
let nextEnd = next.length - 1;
|
|
85
|
+
let prevNode = prev[0];
|
|
86
|
+
let nextNode = next[0];
|
|
87
|
+
/**
|
|
88
|
+
* For A,B,C => A,B,C,D
|
|
89
|
+
* i = 3, prevEnd = 2, nextEnd = 3
|
|
90
|
+
*
|
|
91
|
+
* For A,B,C => B,C
|
|
92
|
+
* i = 2, prevEnd = 2, nextEnd = 1
|
|
93
|
+
*
|
|
94
|
+
* For B,C => A,B,C
|
|
95
|
+
* i = 0, pre
|
|
96
|
+
*/
|
|
97
|
+
outer: {
|
|
98
|
+
while (prevNode === nextNode) {
|
|
99
|
+
++i;
|
|
100
|
+
if (i > prevEnd || i > nextEnd) {
|
|
101
|
+
break outer;
|
|
102
|
+
}
|
|
103
|
+
prevNode = prev[i];
|
|
104
|
+
nextNode = next[i];
|
|
105
|
+
}
|
|
106
|
+
prevNode = prev[prevEnd];
|
|
107
|
+
nextNode = next[nextEnd];
|
|
108
|
+
while (prevNode === nextNode) {
|
|
109
|
+
prevEnd--;
|
|
110
|
+
nextEnd--;
|
|
111
|
+
if (i > prevEnd || i > nextEnd) {
|
|
112
|
+
break outer;
|
|
113
|
+
}
|
|
114
|
+
prevNode = prev[prevEnd];
|
|
115
|
+
nextNode = next[nextEnd];
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (i > prevEnd) {
|
|
119
|
+
if (i <= nextEnd) {
|
|
120
|
+
while (i <= nextEnd) {
|
|
121
|
+
liveList.insert(anyToCrdt(next[i]), i);
|
|
122
|
+
i++;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
else if (i > nextEnd) {
|
|
127
|
+
let localI = i;
|
|
128
|
+
while (localI <= prevEnd) {
|
|
129
|
+
liveList.delete(i);
|
|
130
|
+
localI++;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
while (i <= prevEnd && i <= nextEnd) {
|
|
135
|
+
prevNode = prev[i];
|
|
136
|
+
nextNode = next[i];
|
|
137
|
+
const liveListNode = liveList.get(i);
|
|
138
|
+
if (liveListNode instanceof LiveObject &&
|
|
139
|
+
isPlainObject(prevNode) &&
|
|
140
|
+
isPlainObject(nextNode)) {
|
|
141
|
+
patchLiveObject(liveListNode, prevNode, nextNode);
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
liveList.set(i, anyToCrdt(nextNode));
|
|
145
|
+
}
|
|
146
|
+
i++;
|
|
147
|
+
}
|
|
148
|
+
while (i <= nextEnd) {
|
|
149
|
+
liveList.insert(anyToCrdt(next[i]), i);
|
|
150
|
+
i++;
|
|
151
|
+
}
|
|
152
|
+
let localI = i;
|
|
153
|
+
while (localI <= prevEnd) {
|
|
154
|
+
liveList.delete(i);
|
|
155
|
+
localI++;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function patchLiveObjectKey(liveObject, key, prev, next) {
|
|
160
|
+
if (process.env.NODE_ENV !== "production") {
|
|
161
|
+
const nonSerializableValue = findNonSerializableValue(next);
|
|
162
|
+
if (nonSerializableValue) {
|
|
163
|
+
console.error(`New state path: '${nonSerializableValue.path}' value: '${nonSerializableValue.value}' is not serializable.\nOnly serializable value can be synced with Liveblocks.`);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
const value = liveObject.get(key);
|
|
168
|
+
if (next === undefined) {
|
|
169
|
+
liveObject.delete(key);
|
|
170
|
+
}
|
|
171
|
+
else if (value === undefined) {
|
|
172
|
+
liveObject.set(key, anyToCrdt(next));
|
|
173
|
+
}
|
|
174
|
+
else if (prev === next) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
else if (value instanceof LiveList &&
|
|
178
|
+
Array.isArray(prev) &&
|
|
179
|
+
Array.isArray(next)) {
|
|
180
|
+
patchLiveList(value, prev, next);
|
|
181
|
+
}
|
|
182
|
+
else if (value instanceof LiveObject &&
|
|
183
|
+
isPlainObject(prev) &&
|
|
184
|
+
isPlainObject(next)) {
|
|
185
|
+
patchLiveObject(value, prev, next);
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
liveObject.set(key, anyToCrdt(next));
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function patchLiveObject(root, prev, next) {
|
|
192
|
+
const updates = {};
|
|
193
|
+
for (const key in next) {
|
|
194
|
+
patchLiveObjectKey(root, key, prev[key], next[key]);
|
|
195
|
+
}
|
|
196
|
+
for (const key in prev) {
|
|
197
|
+
if (next[key] === undefined) {
|
|
198
|
+
root.delete(key);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
if (Object.keys(updates).length > 0) {
|
|
202
|
+
root.update(updates);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function getParentsPath(node) {
|
|
206
|
+
const path = [];
|
|
207
|
+
while (node._parentKey != null && node._parent != null) {
|
|
208
|
+
if (node._parent instanceof LiveList) {
|
|
209
|
+
path.push(node._parent._indexOfPosition(node._parentKey));
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
path.push(node._parentKey);
|
|
213
|
+
}
|
|
214
|
+
node = node._parent;
|
|
215
|
+
}
|
|
216
|
+
return path;
|
|
217
|
+
}
|
|
218
|
+
function patchImmutableObject(state, updates) {
|
|
219
|
+
return updates.reduce((state, update) => patchImmutableObjectWithUpdate(state, update), state);
|
|
220
|
+
}
|
|
221
|
+
function patchImmutableObjectWithUpdate(state, update) {
|
|
222
|
+
const path = getParentsPath(update.node);
|
|
223
|
+
return patchImmutableNode(state, path, update);
|
|
224
|
+
}
|
|
225
|
+
function patchImmutableNode(state, path, update) {
|
|
226
|
+
var _a, _b, _c, _d;
|
|
227
|
+
const pathItem = path.pop();
|
|
228
|
+
if (pathItem === undefined) {
|
|
229
|
+
switch (update.type) {
|
|
230
|
+
case "LiveObject": {
|
|
231
|
+
if (typeof state !== "object") {
|
|
232
|
+
throw new Error("Internal: received update on LiveObject but state was not an object");
|
|
233
|
+
}
|
|
234
|
+
const newState = Object.assign({}, state);
|
|
235
|
+
for (const key in update.updates) {
|
|
236
|
+
if (((_a = update.updates[key]) === null || _a === void 0 ? void 0 : _a.type) === "update") {
|
|
237
|
+
const val = update.node.get(key);
|
|
238
|
+
if (val !== undefined) {
|
|
239
|
+
newState[key] = lsonToJson(val);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
else if (((_b = update.updates[key]) === null || _b === void 0 ? void 0 : _b.type) === "delete") {
|
|
243
|
+
delete newState[key];
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return newState;
|
|
247
|
+
}
|
|
248
|
+
case "LiveList": {
|
|
249
|
+
if (Array.isArray(state) === false) {
|
|
250
|
+
throw new Error("Internal: received update on LiveList but state was not an array");
|
|
251
|
+
}
|
|
252
|
+
let newState = state.map((x) => x);
|
|
253
|
+
for (const listUpdate of update.updates) {
|
|
254
|
+
if (listUpdate.type === "set") {
|
|
255
|
+
newState = newState.map((item, index) => index === listUpdate.index ? listUpdate.item : item);
|
|
256
|
+
}
|
|
257
|
+
else if (listUpdate.type === "insert") {
|
|
258
|
+
if (listUpdate.index === newState.length) {
|
|
259
|
+
newState.push(lsonToJson(listUpdate.item));
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
newState = [
|
|
263
|
+
...newState.slice(0, listUpdate.index),
|
|
264
|
+
lsonToJson(listUpdate.item),
|
|
265
|
+
...newState.slice(listUpdate.index),
|
|
266
|
+
];
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
else if (listUpdate.type === "delete") {
|
|
270
|
+
newState.splice(listUpdate.index, 1);
|
|
271
|
+
}
|
|
272
|
+
else if (listUpdate.type === "move") {
|
|
273
|
+
if (listUpdate.previousIndex > listUpdate.index) {
|
|
274
|
+
newState = [
|
|
275
|
+
...newState.slice(0, listUpdate.index),
|
|
276
|
+
lsonToJson(listUpdate.item),
|
|
277
|
+
...newState.slice(listUpdate.index, listUpdate.previousIndex),
|
|
278
|
+
...newState.slice(listUpdate.previousIndex + 1),
|
|
279
|
+
];
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
newState = [
|
|
283
|
+
...newState.slice(0, listUpdate.previousIndex),
|
|
284
|
+
...newState.slice(listUpdate.previousIndex + 1, listUpdate.index + 1),
|
|
285
|
+
lsonToJson(listUpdate.item),
|
|
286
|
+
...newState.slice(listUpdate.index + 1),
|
|
287
|
+
];
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return newState;
|
|
292
|
+
}
|
|
293
|
+
case "LiveMap": {
|
|
294
|
+
if (typeof state !== "object") {
|
|
295
|
+
throw new Error("Internal: received update on LiveMap but state was not an object");
|
|
296
|
+
}
|
|
297
|
+
const newState = Object.assign({}, state);
|
|
298
|
+
for (const key in update.updates) {
|
|
299
|
+
if (((_c = update.updates[key]) === null || _c === void 0 ? void 0 : _c.type) === "update") {
|
|
300
|
+
newState[key] = lsonToJson(update.node.get(key));
|
|
301
|
+
}
|
|
302
|
+
else if (((_d = update.updates[key]) === null || _d === void 0 ? void 0 : _d.type) === "delete") {
|
|
303
|
+
delete newState[key];
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return newState;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
if (Array.isArray(state)) {
|
|
311
|
+
const newArray = [...state];
|
|
312
|
+
newArray[pathItem] = patchImmutableNode(state[pathItem], path, update);
|
|
313
|
+
return newArray;
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
return Object.assign(Object.assign({}, state), { [pathItem]: patchImmutableNode(state[pathItem], path, update) });
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export { lsonToJson, patchImmutableObject, patchLiveObjectKey };
|
package/package.json
CHANGED
|
@@ -1,27 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liveblocks/client",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.4",
|
|
4
4
|
"description": "A client that lets you interact with Liveblocks servers.",
|
|
5
5
|
"main": "./index.js",
|
|
6
|
+
"module": "./index.mjs",
|
|
6
7
|
"types": "./index.d.ts",
|
|
7
|
-
"files": [
|
|
8
|
-
"**"
|
|
9
|
-
],
|
|
10
8
|
"exports": {
|
|
11
|
-
"./package.json": "./package.json",
|
|
12
|
-
".": {
|
|
13
|
-
"types": "./index.d.ts",
|
|
14
|
-
"module": "./esm/index.js",
|
|
15
|
-
"import": "./esm/index.mjs",
|
|
16
|
-
"default": "./index.js"
|
|
17
|
-
},
|
|
18
9
|
"./internal": {
|
|
19
10
|
"types": "./internal.d.ts",
|
|
20
|
-
"
|
|
21
|
-
"import": "./
|
|
22
|
-
|
|
11
|
+
"require": "./internal.js",
|
|
12
|
+
"import": "./internal.mjs"
|
|
13
|
+
},
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./index.d.ts",
|
|
16
|
+
"require": "./index.js",
|
|
17
|
+
"import": "./index.mjs"
|
|
23
18
|
}
|
|
24
19
|
},
|
|
20
|
+
"files": [
|
|
21
|
+
"**"
|
|
22
|
+
],
|
|
25
23
|
"keywords": [
|
|
26
24
|
"liveblocks",
|
|
27
25
|
"multiplayer",
|
|
@@ -33,6 +31,7 @@
|
|
|
33
31
|
},
|
|
34
32
|
"scripts": {
|
|
35
33
|
"build": "rollup -c && cp ./package.json ./README.md ./lib",
|
|
34
|
+
"lint": "eslint src/ test/",
|
|
36
35
|
"test": "jest --watch",
|
|
37
36
|
"test-ci": "jest"
|
|
38
37
|
},
|
|
@@ -45,6 +44,7 @@
|
|
|
45
44
|
"@babel/preset-typescript": "^7.12.16",
|
|
46
45
|
"@rollup/plugin-babel": "^5.3.1",
|
|
47
46
|
"@rollup/plugin-node-resolve": "^13.1.3",
|
|
47
|
+
"@rollup/plugin-replace": "^4.0.0",
|
|
48
48
|
"@rollup/plugin-typescript": "^8.3.1",
|
|
49
49
|
"@types/jest": "^26.0.21",
|
|
50
50
|
"@types/node-fetch": "^2.6.1",
|
|
@@ -58,8 +58,8 @@
|
|
|
58
58
|
"msw": "^0.39.1",
|
|
59
59
|
"node-fetch": "2.6.7",
|
|
60
60
|
"rollup": "^2.68.0",
|
|
61
|
+
"rollup-plugin-command": "^1.1.3",
|
|
61
62
|
"rollup-plugin-dts": "^4.1.0",
|
|
62
|
-
"rollup-plugin-esbuild": "^4.8.2",
|
|
63
63
|
"typescript": "^4.4.0",
|
|
64
64
|
"whatwg-fetch": "^3.6.2",
|
|
65
65
|
"ws": "^8.5.0"
|
|
@@ -68,5 +68,6 @@
|
|
|
68
68
|
"type": "git",
|
|
69
69
|
"url": "https://github.com/liveblocks/liveblocks.git",
|
|
70
70
|
"directory": "packages/liveblocks-client"
|
|
71
|
-
}
|
|
71
|
+
},
|
|
72
|
+
"sideEffects": false
|
|
72
73
|
}
|