@liveblocks/client 0.12.1 → 0.13.0

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.
Files changed (44) hide show
  1. package/README.md +34 -6
  2. package/lib/cjs/AbstractCrdt.d.ts +61 -0
  3. package/lib/cjs/AbstractCrdt.js +98 -0
  4. package/lib/cjs/LiveList.d.ts +133 -0
  5. package/lib/cjs/LiveList.js +374 -0
  6. package/lib/cjs/LiveMap.d.ts +83 -0
  7. package/lib/cjs/LiveMap.js +272 -0
  8. package/lib/cjs/LiveObject.d.ts +61 -0
  9. package/lib/cjs/LiveObject.js +330 -0
  10. package/lib/cjs/LiveRegister.d.ts +21 -0
  11. package/lib/cjs/LiveRegister.js +69 -0
  12. package/lib/cjs/index.d.ts +3 -1
  13. package/lib/cjs/index.js +7 -5
  14. package/lib/cjs/room.d.ts +50 -9
  15. package/lib/cjs/room.js +476 -85
  16. package/lib/cjs/types.d.ts +174 -40
  17. package/lib/cjs/utils.d.ts +7 -0
  18. package/lib/cjs/utils.js +64 -1
  19. package/lib/esm/AbstractCrdt.d.ts +61 -0
  20. package/lib/esm/AbstractCrdt.js +94 -0
  21. package/lib/esm/LiveList.d.ts +133 -0
  22. package/lib/esm/LiveList.js +370 -0
  23. package/lib/esm/LiveMap.d.ts +83 -0
  24. package/lib/esm/LiveMap.js +268 -0
  25. package/lib/esm/LiveObject.d.ts +61 -0
  26. package/lib/esm/LiveObject.js +326 -0
  27. package/lib/esm/LiveRegister.d.ts +21 -0
  28. package/lib/esm/LiveRegister.js +65 -0
  29. package/lib/esm/index.d.ts +3 -1
  30. package/lib/esm/index.js +3 -1
  31. package/lib/esm/room.d.ts +50 -9
  32. package/lib/esm/room.js +478 -84
  33. package/lib/esm/types.d.ts +174 -40
  34. package/lib/esm/utils.d.ts +7 -0
  35. package/lib/esm/utils.js +58 -0
  36. package/package.json +3 -3
  37. package/lib/cjs/doc.d.ts +0 -347
  38. package/lib/cjs/doc.js +0 -1349
  39. package/lib/cjs/storage.d.ts +0 -21
  40. package/lib/cjs/storage.js +0 -68
  41. package/lib/esm/doc.d.ts +0 -347
  42. package/lib/esm/doc.js +0 -1342
  43. package/lib/esm/storage.d.ts +0 -21
  44. package/lib/esm/storage.js +0 -65
@@ -1,4 +1,6 @@
1
- import { LiveObject } from "./doc";
1
+ import type { LiveList } from "./LiveList";
2
+ import type { LiveMap } from "./LiveMap";
3
+ import type { LiveObject } from "./LiveObject";
2
4
  export declare type MyPresenceCallback<T extends Presence = Presence> = (me: T) => void;
3
5
  export declare type OthersEventCallback<T extends Presence = Presence> = (others: Others<T>, event: OthersEvent<T>) => void;
4
6
  export declare type EventCallback = ({ connectionId, event, }: {
@@ -14,17 +16,31 @@ export declare type RoomEventCallbackMap = {
14
16
  error: ErrorCallback;
15
17
  connection: ConnectionCallback;
16
18
  };
19
+ export declare type LiveMapUpdates<TKey extends string = string, TValue = any> = {
20
+ type: "LiveMap";
21
+ node: LiveMap<TKey, TValue>;
22
+ };
23
+ export declare type LiveObjectUpdates<TData = any> = {
24
+ type: "LiveObject";
25
+ node: LiveObject<TData>;
26
+ };
27
+ export declare type LiveListUpdates<TItem = any> = {
28
+ type: "LiveList";
29
+ node: LiveList<TItem>;
30
+ };
31
+ export declare type StorageUpdate = LiveMapUpdates | LiveObjectUpdates | LiveListUpdates;
32
+ export declare type StorageCallback = (updates: StorageUpdate[]) => void;
17
33
  export declare type Client = {
18
34
  /**
19
35
  * Gets a room. Returns null if {@link Client.enter} has not been called previously.
20
36
  *
21
- * @param roomId - The id of the room
37
+ * @param roomId The id of the room
22
38
  */
23
39
  getRoom(roomId: string): Room | null;
24
40
  /**
25
41
  * Enters a room and returns it.
26
- * @param roomId - The id of the room
27
- * @param defaultPresence - Optional. Should be serializable to JSON. If omitted, an empty object will be used.
42
+ * @param roomId The id of the room
43
+ * @param defaultPresence Optional. Should be serializable to JSON. If omitted, an empty object will be used.
28
44
  */
29
45
  enter<TStorageRoot extends Record<string, any> = Record<string, any>>(roomId: string, options?: {
30
46
  defaultPresence?: Presence;
@@ -32,7 +48,7 @@ export declare type Client = {
32
48
  }): Room;
33
49
  /**
34
50
  * Leaves a room.
35
- * @param roomId - The id of the room
51
+ * @param roomId The id of the room
36
52
  */
37
53
  leave(roomId: string): void;
38
54
  };
@@ -131,85 +147,192 @@ export declare type Room = {
131
147
  /**
132
148
  * Subscribe to the current user presence updates.
133
149
  *
134
- * @param listener - the callback that is called every time the current user presence is updated with {@link Room.updatePresence}.
150
+ * @param listener the callback that is called every time the current user presence is updated with {@link Room.updatePresence}.
135
151
  *
136
152
  * @example
137
153
  * room.subscribe("my-presence", (presence) => {
138
154
  * // Do something
139
155
  * });
140
156
  */
141
- <T extends Presence>(type: "my-presence", listener: MyPresenceCallback<T>): void;
157
+ <T extends Presence>(type: "my-presence", listener: MyPresenceCallback<T>): () => void;
142
158
  /**
143
159
  * Subscribe to the other users updates.
144
160
  *
145
- * @param listener - the callback that is called when a user enters or leaves the room or when a user update its presence.
161
+ * @param listener the callback that is called when a user enters or leaves the room or when a user update its presence.
146
162
  *
147
163
  * @example
148
164
  * room.subscribe("others", (others) => {
149
165
  * // Do something
150
166
  * });
151
167
  */
152
- <T extends Presence>(type: "others", listener: OthersEventCallback<T>): void;
168
+ <T extends Presence>(type: "others", listener: OthersEventCallback<T>): () => void;
153
169
  /**
154
170
  * Subscribe to events broadcasted by {@link Room.broadcastEvent}
155
171
  *
156
- * @param listener - the callback that is called when a user calls {@link Room.broadcastEvent}
172
+ * @param listener the callback that is called when a user calls {@link Room.broadcastEvent}
157
173
  *
158
174
  * @example
159
175
  * room.subscribe("event", ({ event, connectionId }) => {
160
176
  * // Do something
161
177
  * });
162
178
  */
163
- (type: "event", listener: EventCallback): void;
179
+ (type: "event", listener: EventCallback): () => void;
164
180
  /**
165
181
  * Subscribe to errors thrown in the room.
166
182
  */
167
- (type: "error", listener: ErrorCallback): void;
183
+ (type: "error", listener: ErrorCallback): () => void;
168
184
  /**
169
185
  * Subscribe to connection state updates.
170
186
  */
171
- (type: "connection", listener: ConnectionCallback): void;
172
- };
173
- unsubscribe: {
187
+ (type: "connection", listener: ConnectionCallback): () => void;
174
188
  /**
175
- * Unsubscribe to the current user presence updates.
189
+ * Subscribes to changes made on a {@link LiveMap}. Returns an unsubscribe function.
190
+ * In a future version, we will also expose what exactly changed in the {@link LiveMap}.
176
191
  *
177
- * @param listener - the callback that has been used with {@link Room.subscribe}("my-presence").
192
+ * @param listener the callback this called when the {@link LiveMap} changes.
193
+ *
194
+ * @returns Unsubscribe function.
178
195
  *
179
196
  * @example
180
- * const onPresenceChange = (presence) => { };
181
- * room.subscribe("my-presence", onPresenceChange);
182
- * room.unsubscribe("my-presence", onPresenceChange);
197
+ * const liveMap = new LiveMap();
198
+ * const unsubscribe = room.subscribe(liveMap, (liveMap) => { });
199
+ * unsubscribe();
183
200
  */
184
- <T extends Presence>(type: "my-presence", listener: MyPresenceCallback<T>): void;
201
+ <TKey extends string, TValue>(liveMap: LiveMap<TKey, TValue>, listener: (liveMap: LiveMap<TKey, TValue>) => void): () => void;
185
202
  /**
186
- * Unsubscribe to the other users updates.
203
+ * Subscribes to changes made on a {@link LiveObject}. Returns an unsubscribe function.
204
+ * In a future version, we will also expose what exactly changed in the {@link LiveObject}.
187
205
  *
188
- * @param listener - the callback that has been used with {@link Room.subscribe}("others").
206
+ * @param listener the callback this called when the {@link LiveObject} changes.
207
+ *
208
+ * @returns Unsubscribe function.
189
209
  *
190
210
  * @example
191
- * const onOthersChange = (presence) => { };
192
- * room.subscribe("others", onOthersChange);
193
- * room.unsubscribe("others", onOthersChange);
211
+ * const liveObject = new LiveObject();
212
+ * const unsubscribe = room.subscribe(liveObject, (liveObject) => { });
213
+ * unsubscribe();
194
214
  */
195
- <T extends Presence>(type: "others", listener: OthersEventCallback<T>): void;
215
+ <TData>(liveObject: LiveObject<TData>, callback: (liveObject: LiveObject<TData>) => void): () => void;
216
+ /**
217
+ * Subscribes to changes made on a {@link LiveList}. Returns an unsubscribe function.
218
+ * In a future version, we will also expose what exactly changed in the {@link LiveList}.
219
+ *
220
+ * @param listener the callback this called when the {@link LiveList} changes.
221
+ *
222
+ * @returns Unsubscribe function.
223
+ *
224
+ * @example
225
+ * const liveList = new LiveList();
226
+ * const unsubscribe = room.subscribe(liveList, (liveList) => { });
227
+ * unsubscribe();
228
+ */
229
+ <TItem>(liveList: LiveList<TItem>, callback: (liveList: LiveList<TItem>) => void): () => void;
230
+ /**
231
+ * Subscribes to changes made on a {@link LiveMap} and all the nested data structures. Returns an unsubscribe function.
232
+ * In a future version, we will also expose what exactly changed in the {@link LiveMap}.
233
+ *
234
+ * @param listener the callback this called when the {@link LiveMap} changes.
235
+ *
236
+ * @returns Unsubscribe function.
237
+ *
238
+ * @example
239
+ * const liveMap = new LiveMap();
240
+ * const unsubscribe = room.subscribe(liveMap, (liveMap) => { }, { isDeep: true });
241
+ * unsubscribe();
242
+ */
243
+ <TKey extends string, TValue>(liveMap: LiveMap<TKey, TValue>, callback: (updates: StorageUpdate[]) => void, options: {
244
+ isDeep: true;
245
+ }): () => void;
246
+ /**
247
+ * Subscribes to changes made on a {@link LiveObject} and all the nested data structures. Returns an unsubscribe function.
248
+ * In a future version, we will also expose what exactly changed in the {@link LiveObject}.
249
+ *
250
+ * @param listener the callback this called when the {@link LiveObject} changes.
251
+ *
252
+ * @returns Unsubscribe function.
253
+ *
254
+ * @example
255
+ * const liveObject = new LiveObject();
256
+ * const unsubscribe = room.subscribe(liveObject, (liveObject) => { }, { isDeep: true });
257
+ * unsubscribe();
258
+ */
259
+ <TData>(liveObject: LiveObject<TData>, callback: (updates: StorageUpdate[]) => void, options: {
260
+ isDeep: true;
261
+ }): () => void;
196
262
  /**
197
- * Unsubscribe to events broadcasted by {@link Room.broadcastEvent}
263
+ * Subscribes to changes made on a {@link LiveList} and all the nested data structures. Returns an unsubscribe function.
264
+ * In a future version, we will also expose what exactly changed in the {@link LiveList}.
198
265
  *
199
- * @param listener - the callback that has been used with {@link Room.unsubscribe}("event").
266
+ * @param listener the callback this called when the {@link LiveList} changes.
267
+ *
268
+ * @returns Unsubscribe function.
200
269
  *
201
270
  * @example
202
- * const onEvent = ({ event, connectionId }) => { };
203
- * room.subscribe("event", onEvent);
204
- * room.unsubscribe("event", onEvent);
271
+ * const liveList = new LiveList();
272
+ * const unsubscribe = room.subscribe(liveList, (liveList) => { }, { isDeep: true });
273
+ * unsubscribe();
274
+ */
275
+ <TItem>(liveList: LiveList<TItem>, callback: (updates: StorageUpdate[]) => void, options: {
276
+ isDeep: true;
277
+ }): () => void;
278
+ };
279
+ /**
280
+ * Room's history contains function that let you undo and redo operation made on by the current client on the presence and storage.
281
+ */
282
+ history: {
283
+ /**
284
+ * Undoes the last operation executed by the current client.
285
+ * It does not impact operations made by other clients.
286
+ */
287
+ undo: () => void;
288
+ /**
289
+ * Redoes the last operation executed by the current client.
290
+ * It does not impact operations made by other clients.
291
+ */
292
+ redo: () => void;
293
+ /**
294
+ * All future modifications made on the Room will be merged together to create a single history item until resume is called.
295
+ */
296
+ pause: () => void;
297
+ /**
298
+ * Resumes history. Modifications made on the Room are not merged into a single history item anymore.
299
+ */
300
+ resume: () => void;
301
+ };
302
+ /**
303
+ * @deprecated use the callback returned by subscribe instead.
304
+ * See v0.13 release notes for more information.
305
+ * Will be removed in a future version.
306
+ */
307
+ unsubscribe: {
308
+ /**
309
+ * @deprecated use the callback returned by subscribe instead.
310
+ * See v0.13 release notes for more information.
311
+ * Will be removed in a future version.
312
+ */
313
+ <T extends Presence>(type: "my-presence", listener: MyPresenceCallback<T>): void;
314
+ /**
315
+ * @deprecated use the callback returned by subscribe instead.
316
+ * See v0.13 release notes for more information.
317
+ * Will be removed in a future version.
318
+ */
319
+ <T extends Presence>(type: "others", listener: OthersEventCallback<T>): void;
320
+ /**
321
+ * @deprecated use the callback returned by subscribe instead.
322
+ * See v0.13 release notes for more information.
323
+ * Will be removed in a future version.
205
324
  */
206
325
  (type: "event", listener: EventCallback): void;
207
326
  /**
208
- * Unsubscribe to errors thrown in the room.
327
+ * @deprecated use the callback returned by subscribe instead.
328
+ * See v0.13 release notes for more information.
329
+ * Will be removed in a future version.
209
330
  */
210
331
  (type: "error", listener: ErrorCallback): void;
211
332
  /**
212
- * Unsubscribe to connection state updates.
333
+ * @deprecated use the callback returned by subscribe instead.
334
+ * See v0.13 release notes for more information.
335
+ * Will be removed in a future version.
213
336
  */
214
337
  (type: "connection", listener: ConnectionCallback): void;
215
338
  };
@@ -237,7 +360,8 @@ export declare type Room = {
237
360
  getOthers: <T extends Presence>() => Others<T>;
238
361
  /**
239
362
  * Updates the presence of the current user. Only pass the properties you want to update. No need to send the full presence.
240
- * @param {Partial<T>} overrides - A partial object that contains the properties you want to update.
363
+ * @param overrides A partial object that contains the properties you want to update.
364
+ * @param overrides Optional object to configure the behavior of updatePresence.
241
365
  *
242
366
  * @example
243
367
  * room.updatePresence({ x: 0 });
@@ -246,10 +370,15 @@ export declare type Room = {
246
370
  * const presence = room.getPresence();
247
371
  * // presence is equivalent to { x: 0, y: 0 }
248
372
  */
249
- updatePresence: <T extends Presence>(overrides: Partial<T>) => void;
373
+ updatePresence: <T extends Presence>(overrides: Partial<T>, options?: {
374
+ /**
375
+ * Whether or not the presence should have an impact on the undo/redo history.
376
+ */
377
+ addToHistory: boolean;
378
+ }) => void;
250
379
  /**
251
- * Broadcast an event to other users in the room. Event broadcasted to the room can be listened with {@link Room.subscribe}("event").
252
- * @param {any} event - the event to broadcast. Should be serializable to JSON
380
+ * Broadcasts an event to other users in the room. Event broadcasted to the room can be listened with {@link Room.subscribe}("event").
381
+ * @param {any} event the event to broadcast. Should be serializable to JSON
253
382
  *
254
383
  * @example
255
384
  * // On client A
@@ -266,7 +395,12 @@ export declare type Room = {
266
395
  getStorage: <TRoot>() => Promise<{
267
396
  root: LiveObject<TRoot>;
268
397
  }>;
269
- undo: () => void;
270
- redo: () => void;
398
+ /**
399
+ * Batches modifications made during the given function.
400
+ * All the modifications are sent to other clients in a single message.
401
+ * All the subscribers are called only after the batch is over.
402
+ * All the modifications are merged in a single history item (undo/redo).
403
+ */
404
+ batch: (fn: () => void) => void;
271
405
  };
272
406
  export {};
@@ -1 +1,8 @@
1
+ import { AbstractCrdt, Doc } from "./AbstractCrdt";
2
+ import { SerializedCrdtWithId } from "./live";
1
3
  export declare function remove<T>(array: T[], item: T): void;
4
+ export declare function isSameNodeOrChildOf(node: AbstractCrdt, parent: AbstractCrdt): boolean;
5
+ export declare function deserialize(entry: SerializedCrdtWithId, parentToChildren: Map<string, SerializedCrdtWithId[]>, doc: Doc): AbstractCrdt;
6
+ export declare function isCrdt(obj: any): obj is AbstractCrdt;
7
+ export declare function selfOrRegisterValue(obj: AbstractCrdt): any;
8
+ export declare function selfOrRegister(obj: any): AbstractCrdt;
package/lib/esm/utils.js CHANGED
@@ -1,3 +1,8 @@
1
+ import { CrdtType, } from "./live";
2
+ import { LiveList } from "./LiveList";
3
+ import { LiveMap } from "./LiveMap";
4
+ import { LiveObject } from "./LiveObject";
5
+ import { LiveRegister } from "./LiveRegister";
1
6
  export function remove(array, item) {
2
7
  for (let i = 0; i < array.length; i++) {
3
8
  if (array[i] === item) {
@@ -6,3 +11,56 @@ export function remove(array, item) {
6
11
  }
7
12
  }
8
13
  }
14
+ export function isSameNodeOrChildOf(node, parent) {
15
+ if (node === parent) {
16
+ return true;
17
+ }
18
+ if (node._parent) {
19
+ return isSameNodeOrChildOf(node._parent, parent);
20
+ }
21
+ return false;
22
+ }
23
+ export function deserialize(entry, parentToChildren, doc) {
24
+ switch (entry[1].type) {
25
+ case CrdtType.Object: {
26
+ return LiveObject._deserialize(entry, parentToChildren, doc);
27
+ }
28
+ case CrdtType.List: {
29
+ return LiveList._deserialize(entry, parentToChildren, doc);
30
+ }
31
+ case CrdtType.Map: {
32
+ return LiveMap._deserialize(entry, parentToChildren, doc);
33
+ }
34
+ case CrdtType.Register: {
35
+ return LiveRegister._deserialize(entry, parentToChildren, doc);
36
+ }
37
+ default: {
38
+ throw new Error("Unexpected CRDT type");
39
+ }
40
+ }
41
+ }
42
+ export function isCrdt(obj) {
43
+ return (obj instanceof LiveObject ||
44
+ obj instanceof LiveMap ||
45
+ obj instanceof LiveList ||
46
+ obj instanceof LiveRegister);
47
+ }
48
+ export function selfOrRegisterValue(obj) {
49
+ if (obj instanceof LiveRegister) {
50
+ return obj.data;
51
+ }
52
+ return obj;
53
+ }
54
+ export function selfOrRegister(obj) {
55
+ if (obj instanceof LiveObject ||
56
+ obj instanceof LiveMap ||
57
+ obj instanceof LiveList) {
58
+ return obj;
59
+ }
60
+ else if (obj instanceof LiveRegister) {
61
+ throw new Error("Internal error. LiveRegister should not be created from selfOrRegister");
62
+ }
63
+ else {
64
+ return new LiveRegister(obj);
65
+ }
66
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liveblocks/client",
3
- "version": "0.12.1",
3
+ "version": "0.13.0",
4
4
  "description": "",
5
5
  "main": "./lib/cjs/index.js",
6
6
  "module": "./lib/esm/index.js",
@@ -19,8 +19,8 @@
19
19
  "scripts": {
20
20
  "build-and-pack": "npm run build && npm pack",
21
21
  "build": "npm run build:esm && npm run build:cjs",
22
- "build:esm": "tsc -p tsconfig.json && rm ./lib/esm/*.test.js && rm ./lib/esm/*.test.d.ts",
23
- "build:cjs": "tsc -p tsconfig-cjs.json && rm ./lib/cjs/*.test.js && rm ./lib/cjs/*.test.d.ts",
22
+ "build:esm": "tsc -p tsconfig-esm.json",
23
+ "build:cjs": "tsc -p tsconfig-cjs.json",
24
24
  "test": "jest --watch"
25
25
  },
26
26
  "license": "Apache-2.0",