@liveblocks/client 0.16.4 → 0.16.5

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/internal.mjs CHANGED
@@ -1,320 +1,148 @@
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';
1
+ import { L as LiveObject, b as LiveList, h as LiveMap, j as LiveRegister, A as AbstractCrdt, k as findNonSerializableValue } from "./shared.mjs";
2
+
3
+ export { C as ClientMessageType, l as CrdtType, O as OpType, S as ServerMessageType, n as deprecate, f as deprecateIf, o as errorIf, t as throwUsageError } from "./shared.mjs";
3
4
 
4
5
  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;
6
+ const result = {};
7
+ for (const key in obj) {
8
+ const val = obj[key];
9
+ void 0 !== val && (result[key] = lsonToJson(val));
10
+ }
11
+ return result;
23
12
  }
13
+
24
14
  function lsonListToJson(value) {
25
- return value.map(lsonToJson);
26
- }
27
- function liveListToJson(value) {
28
- return lsonListToJson(value.toArray());
15
+ return value.map(lsonToJson);
29
16
  }
17
+
30
18
  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;
19
+ if (value instanceof LiveObject) return lsonObjectToJson(value.toObject());
20
+ if (value instanceof LiveList) return function(value) {
21
+ return lsonListToJson(value.toArray());
22
+ }(value);
23
+ if (value instanceof LiveMap) return function(map) {
24
+ const result = {};
25
+ for (const [key, value] of map.entries()) result[key] = lsonToJson(value);
26
+ return result;
27
+ }(value);
28
+ if (value instanceof LiveRegister) return value.data;
29
+ if (value instanceof AbstractCrdt) throw new Error("Unhandled subclass of AbstractCrdt encountered");
30
+ return Array.isArray(value) ? lsonListToJson(value) : isPlainObject(value) ? lsonObjectToJson(value) : value;
60
31
  }
32
+
61
33
  function isPlainObject(obj) {
62
- return (obj !== null && Object.prototype.toString.call(obj) === "[object Object]");
34
+ return null !== obj && "[object Object]" === Object.prototype.toString.call(obj);
63
35
  }
36
+
64
37
  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
- }
38
+ if (null == obj) return obj;
39
+ if (Array.isArray(obj)) return new LiveList(obj.map(anyToCrdt));
40
+ if (isPlainObject(obj)) {
41
+ const init = {};
42
+ for (const key in obj) init[key] = anyToCrdt(obj[key]);
43
+ return new LiveObject(init);
44
+ }
45
+ return obj;
158
46
  }
47
+
159
48
  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
- }
49
+ if ("production" !== process.env.NODE_ENV) {
50
+ const nonSerializableValue = findNonSerializableValue(next);
51
+ if (nonSerializableValue) return void console.error(`New state path: '${nonSerializableValue.path}' value: '${nonSerializableValue.value}' is not serializable.\nOnly serializable value can be synced with Liveblocks.`);
52
+ }
53
+ const value = liveObject.get(key);
54
+ if (void 0 === next) liveObject.delete(key); else if (void 0 === value) liveObject.set(key, anyToCrdt(next)); else {
55
+ if (prev === next) return;
56
+ value instanceof LiveList && Array.isArray(prev) && Array.isArray(next) ? function(liveList, prev, next) {
57
+ let i = 0, prevEnd = prev.length - 1, nextEnd = next.length - 1, prevNode = prev[0], nextNode = next[0];
58
+ outer: {
59
+ for (;prevNode === nextNode; ) {
60
+ if (++i, i > prevEnd || i > nextEnd) break outer;
61
+ prevNode = prev[i], nextNode = next[i];
62
+ }
63
+ for (prevNode = prev[prevEnd], nextNode = next[nextEnd]; prevNode === nextNode; ) {
64
+ if (prevEnd--, nextEnd--, i > prevEnd || i > nextEnd) break outer;
65
+ prevNode = prev[prevEnd], nextNode = next[nextEnd];
66
+ }
67
+ }
68
+ if (i > prevEnd) {
69
+ if (i <= nextEnd) for (;i <= nextEnd; ) liveList.insert(anyToCrdt(next[i]), i),
70
+ i++;
71
+ } else if (i > nextEnd) {
72
+ let localI = i;
73
+ for (;localI <= prevEnd; ) liveList.delete(i), localI++;
74
+ } else {
75
+ for (;i <= prevEnd && i <= nextEnd; ) {
76
+ prevNode = prev[i], nextNode = next[i];
77
+ const liveListNode = liveList.get(i);
78
+ liveListNode instanceof LiveObject && isPlainObject(prevNode) && isPlainObject(nextNode) ? patchLiveObject(liveListNode, prevNode, nextNode) : liveList.set(i, anyToCrdt(nextNode)),
79
+ i++;
80
+ }
81
+ for (;i <= nextEnd; ) liveList.insert(anyToCrdt(next[i]), i), i++;
82
+ let localI = i;
83
+ for (;localI <= prevEnd; ) liveList.delete(i), localI++;
84
+ }
85
+ }(value, prev, next) : value instanceof LiveObject && isPlainObject(prev) && isPlainObject(next) ? patchLiveObject(value, prev, next) : liveObject.set(key, anyToCrdt(next));
86
+ }
190
87
  }
88
+
191
89
  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;
90
+ const updates = {};
91
+ for (const key in next) patchLiveObjectKey(root, key, prev[key], next[key]);
92
+ for (const key in prev) void 0 === next[key] && root.delete(key);
93
+ Object.keys(updates).length > 0 && root.update(updates);
217
94
  }
95
+
218
96
  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);
97
+ return updates.reduce(((state, update) => function(state, update) {
98
+ const path = function(node) {
99
+ const path = [];
100
+ for (;null != node._parentKey && null != node._parent; ) node._parent instanceof LiveList ? path.push(node._parent._indexOfPosition(node._parentKey)) : path.push(node._parentKey),
101
+ node = node._parent;
102
+ return path;
103
+ }(update.node);
104
+ return patchImmutableNode(state, path, update);
105
+ }(state, update)), state);
224
106
  }
107
+
225
108
  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
- }
109
+ var _a, _b, _c, _d;
110
+ const pathItem = path.pop();
111
+ if (void 0 === pathItem) switch (update.type) {
112
+ case "LiveObject":
113
+ {
114
+ if ("object" != typeof state) throw new Error("Internal: received update on LiveObject but state was not an object");
115
+ const newState = Object.assign({}, state);
116
+ for (const key in update.updates) if ("update" === (null === (_a = update.updates[key]) || void 0 === _a ? void 0 : _a.type)) {
117
+ const val = update.node.get(key);
118
+ void 0 !== val && (newState[key] = lsonToJson(val));
119
+ } else "delete" === (null === (_b = update.updates[key]) || void 0 === _b ? void 0 : _b.type) && delete newState[key];
120
+ return newState;
121
+ }
122
+
123
+ case "LiveList":
124
+ {
125
+ if (!1 === Array.isArray(state)) throw new Error("Internal: received update on LiveList but state was not an array");
126
+ let newState = state.map((x => x));
127
+ for (const listUpdate of update.updates) "set" === listUpdate.type ? newState = newState.map(((item, index) => index === listUpdate.index ? listUpdate.item : item)) : "insert" === listUpdate.type ? listUpdate.index === newState.length ? newState.push(lsonToJson(listUpdate.item)) : newState = [ ...newState.slice(0, listUpdate.index), lsonToJson(listUpdate.item), ...newState.slice(listUpdate.index) ] : "delete" === listUpdate.type ? newState.splice(listUpdate.index, 1) : "move" === listUpdate.type && (newState = listUpdate.previousIndex > listUpdate.index ? [ ...newState.slice(0, listUpdate.index), lsonToJson(listUpdate.item), ...newState.slice(listUpdate.index, listUpdate.previousIndex), ...newState.slice(listUpdate.previousIndex + 1) ] : [ ...newState.slice(0, listUpdate.previousIndex), ...newState.slice(listUpdate.previousIndex + 1, listUpdate.index + 1), lsonToJson(listUpdate.item), ...newState.slice(listUpdate.index + 1) ]);
128
+ return newState;
129
+ }
130
+
131
+ case "LiveMap":
132
+ {
133
+ if ("object" != typeof state) throw new Error("Internal: received update on LiveMap but state was not an object");
134
+ const newState = Object.assign({}, state);
135
+ for (const key in update.updates) "update" === (null === (_c = update.updates[key]) || void 0 === _c ? void 0 : _c.type) ? newState[key] = lsonToJson(update.node.get(key)) : "delete" === (null === (_d = update.updates[key]) || void 0 === _d ? void 0 : _d.type) && delete newState[key];
136
+ return newState;
137
+ }
138
+ }
139
+ if (Array.isArray(state)) {
140
+ const newArray = [ ...state ];
141
+ return newArray[pathItem] = patchImmutableNode(state[pathItem], path, update), newArray;
142
+ }
143
+ return Object.assign(Object.assign({}, state), {
144
+ [pathItem]: patchImmutableNode(state[pathItem], path, update)
145
+ });
318
146
  }
319
147
 
320
148
  export { lsonToJson, patchImmutableObject, patchLiveObjectKey };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liveblocks/client",
3
- "version": "0.16.4",
3
+ "version": "0.16.5",
4
4
  "description": "A client that lets you interact with Liveblocks servers.",
5
5
  "main": "./index.js",
6
6
  "module": "./index.mjs",
@@ -31,17 +31,16 @@
31
31
  },
32
32
  "scripts": {
33
33
  "build": "rollup -c && cp ./package.json ./README.md ./lib",
34
+ "format": "eslint --fix src/ test/ && prettier --write src/ test/",
34
35
  "lint": "eslint src/ test/",
35
36
  "test": "jest --watch",
36
37
  "test-ci": "jest"
37
38
  },
38
39
  "license": "Apache-2.0",
39
40
  "devDependencies": {
40
- "@babel/core": "^7.12.16",
41
- "@babel/plugin-proposal-class-properties": "^7.16.7",
42
- "@babel/plugin-proposal-private-methods": "^7.16.11",
43
- "@babel/preset-env": "^7.12.16",
44
- "@babel/preset-typescript": "^7.12.16",
41
+ "@babel/core": "^7.17.10",
42
+ "@babel/preset-env": "^7.17.10",
43
+ "@babel/preset-typescript": "^7.16.7",
45
44
  "@rollup/plugin-babel": "^5.3.1",
46
45
  "@rollup/plugin-node-resolve": "^13.1.3",
47
46
  "@rollup/plugin-replace": "^4.0.0",
@@ -51,8 +50,9 @@
51
50
  "@types/ws": "^8.2.2",
52
51
  "@typescript-eslint/eslint-plugin": "^5.17.0",
53
52
  "@typescript-eslint/parser": "^5.17.0",
54
- "babel-jest": "^26.6.3",
55
53
  "eslint": "^8.12.0",
54
+ "eslint-plugin-import": "^2.26.0",
55
+ "eslint-plugin-simple-import-sort": "^7.0.0",
56
56
  "jest": "^26.6.3",
57
57
  "jest-each": "^27.5.1",
58
58
  "msw": "^0.39.1",
@@ -60,6 +60,7 @@
60
60
  "rollup": "^2.68.0",
61
61
  "rollup-plugin-command": "^1.1.3",
62
62
  "rollup-plugin-dts": "^4.1.0",
63
+ "rollup-plugin-terser": "^7.0.2",
63
64
  "typescript": "^4.4.0",
64
65
  "whatwg-fetch": "^3.6.2",
65
66
  "ws": "^8.5.0"
package/shared.d.ts CHANGED
@@ -22,7 +22,11 @@ declare type JsonObject = {
22
22
  */
23
23
  declare class LiveMap<TKey extends string = string, TValue extends Lson = Lson> extends AbstractCrdt {
24
24
  private _map;
25
- constructor(entries?: readonly (readonly [TKey, TValue])[] | null | undefined);
25
+ constructor(entries?: readonly (readonly [TKey, TValue])[] | undefined);
26
+ /**
27
+ * @deprecated Please call as `new LiveMap()` or `new LiveMap([])` instead.
28
+ */
29
+ constructor(entries: null);
26
30
  /**
27
31
  * Returns a specified element from the LiveMap.
28
32
  * @param key The key of the element to return.
@@ -394,7 +398,15 @@ declare type ClientOptions = {
394
398
  publicApiKey?: never;
395
399
  authEndpoint: AuthEndpoint;
396
400
  });
397
- declare type ConnectionState = "closed" | "authenticating" | "unavailable" | "failed" | "open" | "connecting";
401
+ declare type Connection = {
402
+ state: "closed" | "authenticating" | "unavailable" | "failed";
403
+ } | {
404
+ state: "open" | "connecting";
405
+ id: number;
406
+ userId?: string;
407
+ userInfo?: any;
408
+ };
409
+ declare type ConnectionState = Connection["state"];
398
410
  declare type OthersEvent<T extends Presence = Presence> = {
399
411
  type: "leave";
400
412
  user: User<T>;
@@ -738,7 +750,7 @@ declare abstract class AbstractCrdt {
738
750
  declare class LiveObject<O extends LsonObject = LsonObject> extends AbstractCrdt {
739
751
  private _map;
740
752
  private _propToLastUpdate;
741
- constructor(object?: O);
753
+ constructor(obj?: O);
742
754
  private _applyUpdate;
743
755
  private _applyDeleteObjectKey;
744
756
  /**