@liveblocks/client 0.15.0-alpha.1 → 0.15.0-alpha.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.
@@ -17,6 +17,7 @@ const AbstractCrdt_1 = require("./AbstractCrdt");
17
17
  const utils_1 = require("./utils");
18
18
  const live_1 = require("./live");
19
19
  const position_1 = require("./position");
20
+ const LiveRegister_1 = require("./LiveRegister");
20
21
  /**
21
22
  * The LiveList class represents an ordered collection of items that is synchorinized across clients.
22
23
  */
@@ -132,7 +133,13 @@ class LiveList extends AbstractCrdt_1.AbstractCrdt {
132
133
  modified: {
133
134
  node: this,
134
135
  type: "LiveList",
135
- updates: [{ index: newIndex, type: "insert" }],
136
+ updates: [
137
+ {
138
+ index: newIndex,
139
+ type: "insert",
140
+ item: child instanceof LiveRegister_1.LiveRegister ? child.data : child,
141
+ },
142
+ ],
136
143
  },
137
144
  };
138
145
  }
@@ -141,7 +148,7 @@ class LiveList extends AbstractCrdt_1.AbstractCrdt {
141
148
  */
142
149
  _detachChild(child) {
143
150
  if (child) {
144
- const reverse = this._serialize(this._id, child._parentKey, this._doc);
151
+ const reverse = child._serialize(this._id, child._parentKey, this._doc);
145
152
  const indexToDelete = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((item) => item[0] === child);
146
153
  __classPrivateFieldGet(this, _LiveList_items, "f").splice(indexToDelete, 1);
147
154
  child._detach();
@@ -160,6 +167,7 @@ class LiveList extends AbstractCrdt_1.AbstractCrdt {
160
167
  _setChildKey(key, child, previousKey) {
161
168
  var _a;
162
169
  child._setParentLink(this, key);
170
+ const previousIndex = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((entry) => entry[0]._id === child._id);
163
171
  const index = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((entry) => entry[1] === key);
164
172
  // Assign a temporary position until we get the fix from the backend
165
173
  if (index !== -1) {
@@ -170,12 +178,22 @@ class LiveList extends AbstractCrdt_1.AbstractCrdt {
170
178
  item[1] = key;
171
179
  }
172
180
  __classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => (0, position_1.compare)(itemA[1], itemB[1]));
173
- const newIndex = this._indexOfPosition(key);
181
+ const newIndex = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((entry) => entry[0]._id === child._id);
182
+ const updatesDelta = newIndex === previousIndex
183
+ ? []
184
+ : [
185
+ {
186
+ index: newIndex,
187
+ item: child instanceof LiveRegister_1.LiveRegister ? child.data : child,
188
+ previousIndex: previousIndex,
189
+ type: "move",
190
+ },
191
+ ];
174
192
  return {
175
193
  modified: {
176
194
  node: this,
177
195
  type: "LiveList",
178
- updates: [{ index: newIndex, type: "insert" }],
196
+ updates: updatesDelta,
179
197
  },
180
198
  reverse: [
181
199
  {
@@ -229,7 +247,7 @@ class LiveList extends AbstractCrdt_1.AbstractCrdt {
229
247
  */
230
248
  insert(element, index) {
231
249
  if (index < 0 || index > __classPrivateFieldGet(this, _LiveList_items, "f").length) {
232
- throw new Error(`Cannot delete list item at index "${index}". index should be between 0 and ${__classPrivateFieldGet(this, _LiveList_items, "f").length}`);
250
+ throw new Error(`Cannot insert list item at index "${index}". index should be between 0 and ${__classPrivateFieldGet(this, _LiveList_items, "f").length}`);
233
251
  }
234
252
  let before = __classPrivateFieldGet(this, _LiveList_items, "f")[index - 1] ? __classPrivateFieldGet(this, _LiveList_items, "f")[index - 1][1] : undefined;
235
253
  let after = __classPrivateFieldGet(this, _LiveList_items, "f")[index] ? __classPrivateFieldGet(this, _LiveList_items, "f")[index][1] : undefined;
@@ -246,7 +264,13 @@ class LiveList extends AbstractCrdt_1.AbstractCrdt {
246
264
  storageUpdates.set(this._id, {
247
265
  node: this,
248
266
  type: "LiveList",
249
- updates: [{ index: newIndex, type: "insert" }],
267
+ updates: [
268
+ {
269
+ index: newIndex,
270
+ item: value instanceof LiveRegister_1.LiveRegister ? value.data : value,
271
+ type: "insert",
272
+ },
273
+ ],
250
274
  });
251
275
  this._doc.dispatch(value._serialize(this._id, position, this._doc), [{ type: live_1.OpType.DeleteCrdt, id }], storageUpdates);
252
276
  }
@@ -296,8 +320,12 @@ class LiveList extends AbstractCrdt_1.AbstractCrdt {
296
320
  node: this,
297
321
  type: "LiveList",
298
322
  updates: [
299
- { index: index, type: "delete" },
300
- { index: newIndex, type: "insert" },
323
+ {
324
+ index: newIndex,
325
+ previousIndex: index,
326
+ item: item[0],
327
+ type: "move",
328
+ },
301
329
  ],
302
330
  });
303
331
  this._doc.dispatch([
@@ -138,7 +138,7 @@ class LiveMap extends AbstractCrdt_1.AbstractCrdt {
138
138
  * INTERNAL
139
139
  */
140
140
  _detachChild(child) {
141
- const reverse = this._serialize(this._id, child._parentKey, this._doc);
141
+ const reverse = child._serialize(this._id, child._parentKey, this._doc);
142
142
  for (const [key, value] of __classPrivateFieldGet(this, _LiveMap_map, "f")) {
143
143
  if (value === child) {
144
144
  __classPrivateFieldGet(this, _LiveMap_map, "f").delete(key);
@@ -147,7 +147,7 @@ class LiveObject extends AbstractCrdt_1.AbstractCrdt {
147
147
  */
148
148
  _detachChild(child) {
149
149
  if (child) {
150
- const reverse = this._serialize(this._id, child._parentKey, this._doc);
150
+ const reverse = child._serialize(this._id, child._parentKey, this._doc);
151
151
  for (const [key, value] of __classPrivateFieldGet(this, _LiveObject_map, "f")) {
152
152
  if (value === child) {
153
153
  __classPrivateFieldGet(this, _LiveObject_map, "f").delete(key);
@@ -106,8 +106,10 @@ function patchLiveList(liveList, prev, next) {
106
106
  }
107
107
  }
108
108
  else if (i > nextEnd) {
109
- while (i <= prevEnd) {
110
- liveList.delete(i++);
109
+ let localI = i;
110
+ while (localI <= prevEnd) {
111
+ liveList.delete(i);
112
+ localI++;
111
113
  }
112
114
  }
113
115
  else {
@@ -224,16 +226,15 @@ function patchImmutableNode(state, path, update) {
224
226
  throw new Error("Internal: received update on LiveList but state was not an array");
225
227
  }
226
228
  let newState = state.map((x) => x);
227
- const newArray = update.node.toArray();
228
229
  for (const listUpdate of update.updates) {
229
230
  if (listUpdate.type === "insert") {
230
231
  if (listUpdate.index === newState.length) {
231
- newState.push(liveNodeToJson(newArray[listUpdate.index]));
232
+ newState.push(liveNodeToJson(listUpdate.item));
232
233
  }
233
234
  else {
234
235
  newState = [
235
236
  ...newState.slice(0, listUpdate.index),
236
- liveNodeToJson(newArray[listUpdate.index]),
237
+ liveNodeToJson(listUpdate.item),
237
238
  ...newState.slice(listUpdate.index),
238
239
  ];
239
240
  }
@@ -241,6 +242,24 @@ function patchImmutableNode(state, path, update) {
241
242
  else if (listUpdate.type === "delete") {
242
243
  newState.splice(listUpdate.index, 1);
243
244
  }
245
+ else if (listUpdate.type === "move") {
246
+ if (listUpdate.previousIndex > listUpdate.index) {
247
+ newState = [
248
+ ...newState.slice(0, listUpdate.index),
249
+ liveNodeToJson(listUpdate.item),
250
+ ...newState.slice(listUpdate.index, listUpdate.previousIndex),
251
+ ...newState.slice(listUpdate.previousIndex + 1),
252
+ ];
253
+ }
254
+ else {
255
+ newState = [
256
+ ...newState.slice(0, listUpdate.previousIndex),
257
+ ...newState.slice(listUpdate.previousIndex + 1, listUpdate.index + 1),
258
+ liveNodeToJson(listUpdate.item),
259
+ ...newState.slice(listUpdate.index + 1),
260
+ ];
261
+ }
262
+ }
244
263
  }
245
264
  return newState;
246
265
  }
@@ -1,3 +1,4 @@
1
+ import { AbstractCrdt } from "./AbstractCrdt";
1
2
  import type { LiveList } from "./LiveList";
2
3
  import type { LiveMap } from "./LiveMap";
3
4
  import type { LiveObject } from "./LiveObject";
@@ -34,14 +35,18 @@ export declare type LiveObjectUpdates<TData = any> = {
34
35
  node: LiveObject<TData>;
35
36
  updates: LiveObjectUpdateDelta<TData>;
36
37
  };
37
- export declare type ListUpdateDelta = {
38
+ export declare type LiveListUpdateDelta = {
39
+ index: number;
40
+ item: AbstractCrdt;
38
41
  type: "insert";
39
42
  } | {
43
+ index: number;
40
44
  type: "delete";
41
- };
42
- export declare type LiveListUpdateDelta = {
45
+ } | {
43
46
  index: number;
44
- type: "insert" | "delete";
47
+ previousIndex: number;
48
+ item: AbstractCrdt;
49
+ type: "move";
45
50
  };
46
51
  export declare type LiveListUpdates<TItem = any> = {
47
52
  type: "LiveList";
@@ -14,6 +14,7 @@ import { AbstractCrdt } from "./AbstractCrdt";
14
14
  import { deserialize, selfOrRegister, selfOrRegisterValue } from "./utils";
15
15
  import { OpType, CrdtType, } from "./live";
16
16
  import { makePosition, compare } from "./position";
17
+ import { LiveRegister } from "./LiveRegister";
17
18
  /**
18
19
  * The LiveList class represents an ordered collection of items that is synchorinized across clients.
19
20
  */
@@ -129,7 +130,13 @@ export class LiveList extends AbstractCrdt {
129
130
  modified: {
130
131
  node: this,
131
132
  type: "LiveList",
132
- updates: [{ index: newIndex, type: "insert" }],
133
+ updates: [
134
+ {
135
+ index: newIndex,
136
+ type: "insert",
137
+ item: child instanceof LiveRegister ? child.data : child,
138
+ },
139
+ ],
133
140
  },
134
141
  };
135
142
  }
@@ -138,7 +145,7 @@ export class LiveList extends AbstractCrdt {
138
145
  */
139
146
  _detachChild(child) {
140
147
  if (child) {
141
- const reverse = this._serialize(this._id, child._parentKey, this._doc);
148
+ const reverse = child._serialize(this._id, child._parentKey, this._doc);
142
149
  const indexToDelete = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((item) => item[0] === child);
143
150
  __classPrivateFieldGet(this, _LiveList_items, "f").splice(indexToDelete, 1);
144
151
  child._detach();
@@ -157,6 +164,7 @@ export class LiveList extends AbstractCrdt {
157
164
  _setChildKey(key, child, previousKey) {
158
165
  var _a;
159
166
  child._setParentLink(this, key);
167
+ const previousIndex = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((entry) => entry[0]._id === child._id);
160
168
  const index = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((entry) => entry[1] === key);
161
169
  // Assign a temporary position until we get the fix from the backend
162
170
  if (index !== -1) {
@@ -167,12 +175,22 @@ export class LiveList extends AbstractCrdt {
167
175
  item[1] = key;
168
176
  }
169
177
  __classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => compare(itemA[1], itemB[1]));
170
- const newIndex = this._indexOfPosition(key);
178
+ const newIndex = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((entry) => entry[0]._id === child._id);
179
+ const updatesDelta = newIndex === previousIndex
180
+ ? []
181
+ : [
182
+ {
183
+ index: newIndex,
184
+ item: child instanceof LiveRegister ? child.data : child,
185
+ previousIndex: previousIndex,
186
+ type: "move",
187
+ },
188
+ ];
171
189
  return {
172
190
  modified: {
173
191
  node: this,
174
192
  type: "LiveList",
175
- updates: [{ index: newIndex, type: "insert" }],
193
+ updates: updatesDelta,
176
194
  },
177
195
  reverse: [
178
196
  {
@@ -226,7 +244,7 @@ export class LiveList extends AbstractCrdt {
226
244
  */
227
245
  insert(element, index) {
228
246
  if (index < 0 || index > __classPrivateFieldGet(this, _LiveList_items, "f").length) {
229
- throw new Error(`Cannot delete list item at index "${index}". index should be between 0 and ${__classPrivateFieldGet(this, _LiveList_items, "f").length}`);
247
+ throw new Error(`Cannot insert list item at index "${index}". index should be between 0 and ${__classPrivateFieldGet(this, _LiveList_items, "f").length}`);
230
248
  }
231
249
  let before = __classPrivateFieldGet(this, _LiveList_items, "f")[index - 1] ? __classPrivateFieldGet(this, _LiveList_items, "f")[index - 1][1] : undefined;
232
250
  let after = __classPrivateFieldGet(this, _LiveList_items, "f")[index] ? __classPrivateFieldGet(this, _LiveList_items, "f")[index][1] : undefined;
@@ -243,7 +261,13 @@ export class LiveList extends AbstractCrdt {
243
261
  storageUpdates.set(this._id, {
244
262
  node: this,
245
263
  type: "LiveList",
246
- updates: [{ index: newIndex, type: "insert" }],
264
+ updates: [
265
+ {
266
+ index: newIndex,
267
+ item: value instanceof LiveRegister ? value.data : value,
268
+ type: "insert",
269
+ },
270
+ ],
247
271
  });
248
272
  this._doc.dispatch(value._serialize(this._id, position, this._doc), [{ type: OpType.DeleteCrdt, id }], storageUpdates);
249
273
  }
@@ -293,8 +317,12 @@ export class LiveList extends AbstractCrdt {
293
317
  node: this,
294
318
  type: "LiveList",
295
319
  updates: [
296
- { index: index, type: "delete" },
297
- { index: newIndex, type: "insert" },
320
+ {
321
+ index: newIndex,
322
+ previousIndex: index,
323
+ item: item[0],
324
+ type: "move",
325
+ },
298
326
  ],
299
327
  });
300
328
  this._doc.dispatch([
@@ -135,7 +135,7 @@ export class LiveMap extends AbstractCrdt {
135
135
  * INTERNAL
136
136
  */
137
137
  _detachChild(child) {
138
- const reverse = this._serialize(this._id, child._parentKey, this._doc);
138
+ const reverse = child._serialize(this._id, child._parentKey, this._doc);
139
139
  for (const [key, value] of __classPrivateFieldGet(this, _LiveMap_map, "f")) {
140
140
  if (value === child) {
141
141
  __classPrivateFieldGet(this, _LiveMap_map, "f").delete(key);
@@ -144,7 +144,7 @@ export class LiveObject extends AbstractCrdt {
144
144
  */
145
145
  _detachChild(child) {
146
146
  if (child) {
147
- const reverse = this._serialize(this._id, child._parentKey, this._doc);
147
+ const reverse = child._serialize(this._id, child._parentKey, this._doc);
148
148
  for (const [key, value] of __classPrivateFieldGet(this, _LiveObject_map, "f")) {
149
149
  if (value === child) {
150
150
  __classPrivateFieldGet(this, _LiveObject_map, "f").delete(key);
@@ -101,8 +101,10 @@ export function patchLiveList(liveList, prev, next) {
101
101
  }
102
102
  }
103
103
  else if (i > nextEnd) {
104
- while (i <= prevEnd) {
105
- liveList.delete(i++);
104
+ let localI = i;
105
+ while (localI <= prevEnd) {
106
+ liveList.delete(i);
107
+ localI++;
106
108
  }
107
109
  }
108
110
  else {
@@ -215,16 +217,15 @@ function patchImmutableNode(state, path, update) {
215
217
  throw new Error("Internal: received update on LiveList but state was not an array");
216
218
  }
217
219
  let newState = state.map((x) => x);
218
- const newArray = update.node.toArray();
219
220
  for (const listUpdate of update.updates) {
220
221
  if (listUpdate.type === "insert") {
221
222
  if (listUpdate.index === newState.length) {
222
- newState.push(liveNodeToJson(newArray[listUpdate.index]));
223
+ newState.push(liveNodeToJson(listUpdate.item));
223
224
  }
224
225
  else {
225
226
  newState = [
226
227
  ...newState.slice(0, listUpdate.index),
227
- liveNodeToJson(newArray[listUpdate.index]),
228
+ liveNodeToJson(listUpdate.item),
228
229
  ...newState.slice(listUpdate.index),
229
230
  ];
230
231
  }
@@ -232,6 +233,24 @@ function patchImmutableNode(state, path, update) {
232
233
  else if (listUpdate.type === "delete") {
233
234
  newState.splice(listUpdate.index, 1);
234
235
  }
236
+ else if (listUpdate.type === "move") {
237
+ if (listUpdate.previousIndex > listUpdate.index) {
238
+ newState = [
239
+ ...newState.slice(0, listUpdate.index),
240
+ liveNodeToJson(listUpdate.item),
241
+ ...newState.slice(listUpdate.index, listUpdate.previousIndex),
242
+ ...newState.slice(listUpdate.previousIndex + 1),
243
+ ];
244
+ }
245
+ else {
246
+ newState = [
247
+ ...newState.slice(0, listUpdate.previousIndex),
248
+ ...newState.slice(listUpdate.previousIndex + 1, listUpdate.index + 1),
249
+ liveNodeToJson(listUpdate.item),
250
+ ...newState.slice(listUpdate.index + 1),
251
+ ];
252
+ }
253
+ }
235
254
  }
236
255
  return newState;
237
256
  }
@@ -1,3 +1,4 @@
1
+ import { AbstractCrdt } from "./AbstractCrdt";
1
2
  import type { LiveList } from "./LiveList";
2
3
  import type { LiveMap } from "./LiveMap";
3
4
  import type { LiveObject } from "./LiveObject";
@@ -34,14 +35,18 @@ export declare type LiveObjectUpdates<TData = any> = {
34
35
  node: LiveObject<TData>;
35
36
  updates: LiveObjectUpdateDelta<TData>;
36
37
  };
37
- export declare type ListUpdateDelta = {
38
+ export declare type LiveListUpdateDelta = {
39
+ index: number;
40
+ item: AbstractCrdt;
38
41
  type: "insert";
39
42
  } | {
43
+ index: number;
40
44
  type: "delete";
41
- };
42
- export declare type LiveListUpdateDelta = {
45
+ } | {
43
46
  index: number;
44
- type: "insert" | "delete";
47
+ previousIndex: number;
48
+ item: AbstractCrdt;
49
+ type: "move";
45
50
  };
46
51
  export declare type LiveListUpdates<TItem = any> = {
47
52
  type: "LiveList";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liveblocks/client",
3
- "version": "0.15.0-alpha.1",
3
+ "version": "0.15.0-alpha.2",
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
+ }