@liveblocks/core 0.18.3

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 ADDED
@@ -0,0 +1,1372 @@
1
+ /**
2
+ * Helper function that can be used to implement exhaustive switch statements
3
+ * with TypeScript. Example usage:
4
+ *
5
+ * type Fruit = "🍎" | "🍌";
6
+ *
7
+ * switch (fruit) {
8
+ * case "🍎":
9
+ * case "🍌":
10
+ * return doSomething();
11
+ *
12
+ * default:
13
+ * return assertNever(fruit, "Unknown fruit");
14
+ * }
15
+ *
16
+ * If now the Fruit union is extended (i.e. add "🍒"), TypeScript will catch
17
+ * this *statically*, rather than at runtime, and force you to handle the
18
+ * 🍒 case.
19
+ */
20
+ declare function assertNever(_value: never, errmsg: string): never;
21
+ /**
22
+ * Asserts that a given value is non-nullable. This is similar to TypeScript's
23
+ * `!` operator, but will throw an error at runtime (dev-mode only) indicating
24
+ * an incorrect assumption.
25
+ *
26
+ * Instead of:
27
+ *
28
+ * foo!.bar
29
+ *
30
+ * Use:
31
+ *
32
+ * nn(foo).bar
33
+ *
34
+ */
35
+ declare function nn<T>(value: T, errmsg?: string): NonNullable<T>;
36
+
37
+ declare type Callback<T> = (event: T) => void;
38
+ declare type UnsubscribeCallback = () => void;
39
+ declare type Observable<T> = {
40
+ subscribe(callback: Callback<T>): UnsubscribeCallback;
41
+ subscribeOnce(callback: Callback<T>): UnsubscribeCallback;
42
+ };
43
+
44
+ declare type ReadonlyArrayWithLegacyMethods<T> = readonly T[] & {
45
+ /**
46
+ * @deprecated Prefer the normal .length property on arrays.
47
+ */
48
+ readonly count: number;
49
+ /**
50
+ * @deprecated Calling .toArray() is no longer needed
51
+ */
52
+ readonly toArray: () => readonly T[];
53
+ };
54
+ declare function asArrayWithLegacyMethods<T>(arr: readonly T[]): ReadonlyArrayWithLegacyMethods<T>;
55
+
56
+ /**
57
+ * The LiveMap class is similar to a JavaScript Map that is synchronized on all clients.
58
+ * Keys should be a string, and values should be serializable to JSON.
59
+ * If multiple clients update the same property simultaneously, the last modification received by the Liveblocks servers is the winner.
60
+ */
61
+ declare class LiveMap<TKey extends string, TValue extends Lson> extends AbstractCrdt {
62
+ constructor(entries?: readonly (readonly [TKey, TValue])[] | undefined);
63
+ /**
64
+ * Returns a specified element from the LiveMap.
65
+ * @param key The key of the element to return.
66
+ * @returns The element associated with the specified key, or undefined if the key can't be found in the LiveMap.
67
+ */
68
+ get(key: TKey): TValue | undefined;
69
+ /**
70
+ * Adds or updates an element with a specified key and a value.
71
+ * @param key The key of the element to add. Should be a string.
72
+ * @param value The value of the element to add. Should be serializable to JSON.
73
+ */
74
+ set(key: TKey, value: TValue): void;
75
+ /**
76
+ * Returns the number of elements in the LiveMap.
77
+ */
78
+ get size(): number;
79
+ /**
80
+ * Returns a boolean indicating whether an element with the specified key exists or not.
81
+ * @param key The key of the element to test for presence.
82
+ */
83
+ has(key: TKey): boolean;
84
+ /**
85
+ * Removes the specified element by key.
86
+ * @param key The key of the element to remove.
87
+ * @returns true if an element existed and has been removed, or false if the element does not exist.
88
+ */
89
+ delete(key: TKey): boolean;
90
+ /**
91
+ * Returns a new Iterator object that contains the [key, value] pairs for each element.
92
+ */
93
+ entries(): IterableIterator<[TKey, TValue]>;
94
+ /**
95
+ * Same function object as the initial value of the entries method.
96
+ */
97
+ [Symbol.iterator](): IterableIterator<[TKey, TValue]>;
98
+ /**
99
+ * Returns a new Iterator object that contains the keys for each element.
100
+ */
101
+ keys(): IterableIterator<TKey>;
102
+ /**
103
+ * Returns a new Iterator object that contains the values for each element.
104
+ */
105
+ values(): IterableIterator<TValue>;
106
+ /**
107
+ * Executes a provided function once per each key/value pair in the Map object, in insertion order.
108
+ * @param callback Function to execute for each entry in the map.
109
+ */
110
+ forEach(callback: (value: TValue, key: TKey, map: LiveMap<TKey, TValue>) => void): void;
111
+ toImmutable(): ReadonlyMap<TKey, ToImmutable<TValue>>;
112
+ }
113
+
114
+ /**
115
+ * The LiveObject class is similar to a JavaScript object that is synchronized on all clients.
116
+ * Keys should be a string, and values should be serializable to JSON.
117
+ * If multiple clients update the same property simultaneously, the last modification received by the Liveblocks servers is the winner.
118
+ */
119
+ declare class LiveObject<O extends LsonObject> extends AbstractCrdt {
120
+ constructor(obj?: O);
121
+ /**
122
+ * Transform the LiveObject into a javascript object
123
+ */
124
+ toObject(): O;
125
+ /**
126
+ * Adds or updates a property with a specified key and a value.
127
+ * @param key The key of the property to add
128
+ * @param value The value of the property to add
129
+ */
130
+ set<TKey extends keyof O>(key: TKey, value: O[TKey]): void;
131
+ /**
132
+ * Returns a specified property from the LiveObject.
133
+ * @param key The key of the property to get
134
+ */
135
+ get<TKey extends keyof O>(key: TKey): O[TKey];
136
+ /**
137
+ * Deletes a key from the LiveObject
138
+ * @param key The key of the property to delete
139
+ */
140
+ delete(key: keyof O): void;
141
+ /**
142
+ * Adds or updates multiple properties at once with an object.
143
+ * @param patch The object used to overrides properties
144
+ */
145
+ update(patch: Partial<O>): void;
146
+ toImmutable(): ToImmutable<O>;
147
+ }
148
+
149
+ /**
150
+ * Represents an indefinitely deep arbitrary JSON data structure. There are
151
+ * four types that make up the Json family:
152
+ *
153
+ * - Json any legal JSON value
154
+ * - JsonScalar any legal JSON leaf value (no lists or objects)
155
+ * - JsonArray a JSON value whose outer type is an array
156
+ * - JsonObject a JSON value whose outer type is an object
157
+ *
158
+ */
159
+ declare type Json = JsonScalar | JsonArray | JsonObject;
160
+ declare type JsonScalar = string | number | boolean | null;
161
+ declare type JsonArray = Json[];
162
+ declare type JsonObject = {
163
+ [key: string]: Json | undefined;
164
+ };
165
+ declare function isJsonScalar(data: Json): data is JsonScalar;
166
+ declare function isJsonArray(data: Json): data is JsonArray;
167
+ declare function isJsonObject(data: Json): data is JsonObject;
168
+
169
+ /**
170
+ * INTERNAL
171
+ */
172
+ declare class LiveRegister<TValue extends Json> extends AbstractCrdt {
173
+ constructor(data: TValue);
174
+ get data(): TValue;
175
+ }
176
+
177
+ declare type LiveStructure = LiveObject<LsonObject> | LiveList<Lson> | LiveMap<string, Lson>;
178
+ /**
179
+ * Think of Lson as a sibling of the Json data tree, except that the nested
180
+ * data structure can contain a mix of Json values and LiveStructure instances.
181
+ */
182
+ declare type Lson = Json | LiveStructure;
183
+ /**
184
+ * LiveNode is the internal tree for managing Live data structures. The key
185
+ * difference with Lson is that all the Json values get represented in
186
+ * a LiveRegister node.
187
+ */
188
+ declare type LiveNode = LiveStructure | LiveRegister<Json>;
189
+ /**
190
+ * A mapping of keys to Lson values. A Lson value is any valid JSON
191
+ * value or a Live storage data structure (LiveMap, LiveList, etc.)
192
+ */
193
+ declare type LsonObject = {
194
+ [key: string]: Lson | undefined;
195
+ };
196
+ /**
197
+ * Helper type to convert any valid Lson type to the equivalent Json type.
198
+ *
199
+ * Examples:
200
+ *
201
+ * ToJson<42> // 42
202
+ * ToJson<'hi'> // 'hi'
203
+ * ToJson<number> // number
204
+ * ToJson<string> // string
205
+ * ToJson<string | LiveList<number>> // string | number[]
206
+ * ToJson<LiveMap<string, LiveList<number>>>
207
+ * // { [key: string]: number[] }
208
+ * ToJson<LiveObject<{ a: number, b: LiveList<string>, c?: number }>>
209
+ * // { a: null, b: string[], c?: number }
210
+ *
211
+ */
212
+ declare type ToJson<T extends Lson | LsonObject> = T extends Json ? T : T extends LsonObject ? {
213
+ [K in keyof T]: ToJson<Exclude<T[K], undefined>> | (undefined extends T[K] ? undefined : never);
214
+ } : T extends LiveList<infer I> ? ToJson<I>[] : T extends LiveObject<infer O> ? ToJson<O> : T extends LiveMap<infer KS, infer V> ? {
215
+ [K in KS]: ToJson<V>;
216
+ } : never;
217
+
218
+ /**
219
+ * Represents an indefinitely deep arbitrary immutable data
220
+ * structure, as returned by the .toImmutable().
221
+ */
222
+
223
+ declare type Immutable = Scalar | ImmutableList | ImmutableObject | ImmutableMap;
224
+ declare type Scalar = string | number | boolean | null;
225
+ declare type ImmutableList = readonly Immutable[];
226
+ declare type ImmutableObject = {
227
+ readonly [key: string]: Immutable | undefined;
228
+ };
229
+ declare type ImmutableMap = ReadonlyMap<string, Immutable>;
230
+ /**
231
+ * Helper type to convert any valid Lson type to the equivalent Json type.
232
+ *
233
+ * Examples:
234
+ *
235
+ * ToImmutable<42> // 42
236
+ * ToImmutable<'hi'> // 'hi'
237
+ * ToImmutable<number> // number
238
+ * ToImmutable<string> // string
239
+ * ToImmutable<string | LiveList<number>> // string | readonly number[]
240
+ * ToImmutable<LiveMap<string, LiveList<number>>>
241
+ * // { readonly [key: string]: readonly number[] }
242
+ * ToImmutable<LiveObject<{ a: number, b: LiveList<string>, c?: number }>>
243
+ * // { readonly a: null, readonly b: readonly string[], readonly c?: number }
244
+ *
245
+ */
246
+ declare type ToImmutable<L extends Lson | LsonObject> = L extends LiveList<infer I> ? readonly ToImmutable<I>[] : L extends LiveObject<infer O> ? ToImmutable<O> : L extends LiveMap<infer K, infer V> ? ReadonlyMap<K, ToImmutable<V>> : L extends LsonObject ? {
247
+ readonly [K in keyof L]: ToImmutable<Exclude<L[K], undefined>> | (undefined extends L[K] ? undefined : never);
248
+ } : L extends Json ? L : never;
249
+
250
+ declare abstract class AbstractCrdt {
251
+ get roomId(): string | null;
252
+ /**
253
+ * Return an immutable snapshot of this Live node and its children.
254
+ */
255
+ toImmutable(): Immutable;
256
+ }
257
+
258
+ /**
259
+ * The LiveList class represents an ordered collection of items that is synchronized across clients.
260
+ */
261
+ declare class LiveList<TItem extends Lson> extends AbstractCrdt {
262
+ constructor(items?: TItem[]);
263
+ /**
264
+ * Returns the number of elements.
265
+ */
266
+ get length(): number;
267
+ /**
268
+ * Adds one element to the end of the LiveList.
269
+ * @param element The element to add to the end of the LiveList.
270
+ */
271
+ push(element: TItem): void;
272
+ /**
273
+ * Inserts one element at a specified index.
274
+ * @param element The element to insert.
275
+ * @param index The index at which you want to insert the element.
276
+ */
277
+ insert(element: TItem, index: number): void;
278
+ /**
279
+ * Move one element from one index to another.
280
+ * @param index The index of the element to move
281
+ * @param targetIndex The index where the element should be after moving.
282
+ */
283
+ move(index: number, targetIndex: number): void;
284
+ /**
285
+ * Deletes an element at the specified index
286
+ * @param index The index of the element to delete
287
+ */
288
+ delete(index: number): void;
289
+ clear(): void;
290
+ set(index: number, item: TItem): void;
291
+ /**
292
+ * Returns an Array of all the elements in the LiveList.
293
+ */
294
+ toArray(): TItem[];
295
+ /**
296
+ * Tests whether all elements pass the test implemented by the provided function.
297
+ * @param predicate Function to test for each element, taking two arguments (the element and its index).
298
+ * @returns true if the predicate function returns a truthy value for every element. Otherwise, false.
299
+ */
300
+ every(predicate: (value: TItem, index: number) => unknown): boolean;
301
+ /**
302
+ * Creates an array with all elements that pass the test implemented by the provided function.
303
+ * @param predicate Function to test each element of the LiveList. Return a value that coerces to true to keep the element, or to false otherwise.
304
+ * @returns An array with the elements that pass the test.
305
+ */
306
+ filter(predicate: (value: TItem, index: number) => unknown): TItem[];
307
+ /**
308
+ * Returns the first element that satisfies the provided testing function.
309
+ * @param predicate Function to execute on each value.
310
+ * @returns The value of the first element in the LiveList that satisfies the provided testing function. Otherwise, undefined is returned.
311
+ */
312
+ find(predicate: (value: TItem, index: number) => unknown): TItem | undefined;
313
+ /**
314
+ * Returns the index of the first element in the LiveList that satisfies the provided testing function.
315
+ * @param predicate Function to execute on each value until the function returns true, indicating that the satisfying element was found.
316
+ * @returns The index of the first element in the LiveList that passes the test. Otherwise, -1.
317
+ */
318
+ findIndex(predicate: (value: TItem, index: number) => unknown): number;
319
+ /**
320
+ * Executes a provided function once for each element.
321
+ * @param callbackfn Function to execute on each element.
322
+ */
323
+ forEach(callbackfn: (value: TItem, index: number) => void): void;
324
+ /**
325
+ * Get the element at the specified index.
326
+ * @param index The index on the element to get.
327
+ * @returns The element at the specified index or undefined.
328
+ */
329
+ get(index: number): TItem | undefined;
330
+ /**
331
+ * Returns the first index at which a given element can be found in the LiveList, or -1 if it is not present.
332
+ * @param searchElement Element to locate.
333
+ * @param fromIndex The index to start the search at.
334
+ * @returns The first index of the element in the LiveList; -1 if not found.
335
+ */
336
+ indexOf(searchElement: TItem, fromIndex?: number): number;
337
+ /**
338
+ * Returns the last index at which a given element can be found in the LiveList, or -1 if it is not present. The LiveLsit is searched backwards, starting at fromIndex.
339
+ * @param searchElement Element to locate.
340
+ * @param fromIndex The index at which to start searching backwards.
341
+ * @returns
342
+ */
343
+ lastIndexOf(searchElement: TItem, fromIndex?: number): number;
344
+ /**
345
+ * Creates an array populated with the results of calling a provided function on every element.
346
+ * @param callback Function that is called for every element.
347
+ * @returns An array with each element being the result of the callback function.
348
+ */
349
+ map<U>(callback: (value: TItem, index: number) => U): U[];
350
+ /**
351
+ * Tests whether at least one element in the LiveList passes the test implemented by the provided function.
352
+ * @param predicate Function to test for each element.
353
+ * @returns true if the callback function returns a truthy value for at least one element. Otherwise, false.
354
+ */
355
+ some(predicate: (value: TItem, index: number) => unknown): boolean;
356
+ [Symbol.iterator](): IterableIterator<TItem>;
357
+ toImmutable(): readonly ToImmutable<TItem>[];
358
+ }
359
+
360
+ declare type BaseUserMeta = {
361
+ /**
362
+ * The id of the user that has been set in the authentication endpoint.
363
+ * Useful to get additional information about the connected user.
364
+ */
365
+ id?: string;
366
+ /**
367
+ * Additional user information that has been set in the authentication endpoint.
368
+ */
369
+ info?: Json;
370
+ };
371
+
372
+ declare enum OpCode {
373
+ INIT = 0,
374
+ SET_PARENT_KEY = 1,
375
+ CREATE_LIST = 2,
376
+ UPDATE_OBJECT = 3,
377
+ CREATE_OBJECT = 4,
378
+ DELETE_CRDT = 5,
379
+ DELETE_OBJECT_KEY = 6,
380
+ CREATE_MAP = 7,
381
+ CREATE_REGISTER = 8
382
+ }
383
+ /**
384
+ * These operations are the payload for {@link UpdateStorageServerMsg} messages
385
+ * only.
386
+ */
387
+ declare type Op = CreateOp | UpdateObjectOp | DeleteCrdtOp | SetParentKeyOp | DeleteObjectKeyOp;
388
+ declare type CreateOp = CreateRootObjectOp | CreateChildOp;
389
+ declare type CreateChildOp = CreateObjectOp | CreateRegisterOp | CreateMapOp | CreateListOp;
390
+ declare type UpdateObjectOp = {
391
+ opId?: string;
392
+ id: string;
393
+ type: OpCode.UPDATE_OBJECT;
394
+ data: Partial<JsonObject>;
395
+ };
396
+ declare type CreateObjectOp = {
397
+ opId?: string;
398
+ id: string;
399
+ intent?: "set";
400
+ deletedId?: string;
401
+ type: OpCode.CREATE_OBJECT;
402
+ parentId: string;
403
+ parentKey: string;
404
+ data: JsonObject;
405
+ };
406
+ declare type CreateRootObjectOp = {
407
+ opId?: string;
408
+ id: string;
409
+ type: OpCode.CREATE_OBJECT;
410
+ data: JsonObject;
411
+ parentId?: never;
412
+ parentKey?: never;
413
+ };
414
+ declare type CreateListOp = {
415
+ opId?: string;
416
+ id: string;
417
+ intent?: "set";
418
+ deletedId?: string;
419
+ type: OpCode.CREATE_LIST;
420
+ parentId: string;
421
+ parentKey: string;
422
+ };
423
+ declare type CreateMapOp = {
424
+ opId?: string;
425
+ id: string;
426
+ intent?: "set";
427
+ deletedId?: string;
428
+ type: OpCode.CREATE_MAP;
429
+ parentId: string;
430
+ parentKey: string;
431
+ };
432
+ declare type CreateRegisterOp = {
433
+ opId?: string;
434
+ id: string;
435
+ intent?: "set";
436
+ deletedId?: string;
437
+ type: OpCode.CREATE_REGISTER;
438
+ parentId: string;
439
+ parentKey: string;
440
+ data: Json;
441
+ };
442
+ declare type DeleteCrdtOp = {
443
+ opId?: string;
444
+ id: string;
445
+ type: OpCode.DELETE_CRDT;
446
+ };
447
+ declare type SetParentKeyOp = {
448
+ opId?: string;
449
+ id: string;
450
+ type: OpCode.SET_PARENT_KEY;
451
+ parentKey: string;
452
+ };
453
+ declare type DeleteObjectKeyOp = {
454
+ opId?: string;
455
+ id: string;
456
+ type: OpCode.DELETE_OBJECT_KEY;
457
+ key: string;
458
+ };
459
+
460
+ declare enum ClientMsgCode {
461
+ UPDATE_PRESENCE = 100,
462
+ BROADCAST_EVENT = 103,
463
+ FETCH_STORAGE = 200,
464
+ UPDATE_STORAGE = 201
465
+ }
466
+ /**
467
+ * Messages that can be sent from the client to the server.
468
+ */
469
+ declare type ClientMsg<TPresence extends JsonObject, TRoomEvent extends Json> = BroadcastEventClientMsg<TRoomEvent> | UpdatePresenceClientMsg<TPresence> | UpdateStorageClientMsg | FetchStorageClientMsg;
470
+ declare type BroadcastEventClientMsg<TRoomEvent extends Json> = {
471
+ type: ClientMsgCode.BROADCAST_EVENT;
472
+ event: TRoomEvent;
473
+ };
474
+ declare type UpdatePresenceClientMsg<TPresence extends JsonObject> = {
475
+ type: ClientMsgCode.UPDATE_PRESENCE;
476
+ /**
477
+ * Set this to any number to signify that this is a Full Presence™
478
+ * update, not a patch.
479
+ *
480
+ * The numeric value itself no longer has specific meaning. Historically,
481
+ * this field was intended so that clients could ignore these broadcasted
482
+ * full presence messages, but it turned out that getting a full presence
483
+ * "keyframe" from time to time was useful.
484
+ *
485
+ * So nowadays, the presence (pun intended) of this `targetActor` field
486
+ * is a backward-compatible way of expressing that the `data` contains
487
+ * all presence fields, and isn't a partial "patch".
488
+ */
489
+ targetActor: number;
490
+ data: TPresence;
491
+ } | {
492
+ type: ClientMsgCode.UPDATE_PRESENCE;
493
+ /**
494
+ * Absence of the `targetActor` field signifies that this is a Partial
495
+ * Presence™ "patch".
496
+ */
497
+ targetActor?: undefined;
498
+ data: Partial<TPresence>;
499
+ };
500
+ declare type UpdateStorageClientMsg = {
501
+ type: ClientMsgCode.UPDATE_STORAGE;
502
+ ops: Op[];
503
+ };
504
+ declare type FetchStorageClientMsg = {
505
+ type: ClientMsgCode.FETCH_STORAGE;
506
+ };
507
+
508
+ declare type IdTuple<T> = [id: string, value: T];
509
+ declare enum CrdtType {
510
+ OBJECT = 0,
511
+ LIST = 1,
512
+ MAP = 2,
513
+ REGISTER = 3
514
+ }
515
+ declare type SerializedCrdt = SerializedRootObject | SerializedChild;
516
+ declare type SerializedChild = SerializedObject | SerializedList | SerializedMap | SerializedRegister;
517
+ declare type SerializedRootObject = {
518
+ type: CrdtType.OBJECT;
519
+ data: JsonObject;
520
+ parentId?: never;
521
+ parentKey?: never;
522
+ };
523
+ declare type SerializedObject = {
524
+ type: CrdtType.OBJECT;
525
+ parentId: string;
526
+ parentKey: string;
527
+ data: JsonObject;
528
+ };
529
+ declare type SerializedList = {
530
+ type: CrdtType.LIST;
531
+ parentId: string;
532
+ parentKey: string;
533
+ };
534
+ declare type SerializedMap = {
535
+ type: CrdtType.MAP;
536
+ parentId: string;
537
+ parentKey: string;
538
+ };
539
+ declare type SerializedRegister = {
540
+ type: CrdtType.REGISTER;
541
+ parentId: string;
542
+ parentKey: string;
543
+ data: Json;
544
+ };
545
+ declare function isRootCrdt(crdt: SerializedCrdt): crdt is SerializedRootObject;
546
+ declare function isChildCrdt(crdt: SerializedCrdt): crdt is SerializedChild;
547
+
548
+ /**
549
+ * Lookup table for nodes (= SerializedCrdt values) by their IDs.
550
+ */
551
+ declare type NodeMap = Map<string, // Node ID
552
+ SerializedCrdt>;
553
+ /**
554
+ * Reverse lookup table for all child nodes (= list of SerializedCrdt values)
555
+ * by their parent node's IDs.
556
+ */
557
+ declare type ParentToChildNodeMap = Map<string, // Parent's node ID
558
+ IdTuple<SerializedChild>[]>;
559
+
560
+ declare enum ServerMsgCode {
561
+ UPDATE_PRESENCE = 100,
562
+ USER_JOINED = 101,
563
+ USER_LEFT = 102,
564
+ BROADCASTED_EVENT = 103,
565
+ ROOM_STATE = 104,
566
+ INITIAL_STORAGE_STATE = 200,
567
+ UPDATE_STORAGE = 201
568
+ }
569
+ /**
570
+ * Messages that can be sent from the server to the client.
571
+ */
572
+ declare type ServerMsg<TPresence extends JsonObject, TUserMeta extends BaseUserMeta, TRoomEvent extends Json> = UpdatePresenceServerMsg<TPresence> | UserJoinServerMsg<TUserMeta> | UserLeftServerMsg | BroadcastedEventServerMsg<TRoomEvent> | RoomStateServerMsg<TUserMeta> | InitialDocumentStateServerMsg | UpdateStorageServerMsg;
573
+ /**
574
+ * Sent by the WebSocket server and broadcasted to all clients to announce that
575
+ * a User updated their presence. For example, when a user moves their cursor.
576
+ *
577
+ * In most cases, the data payload will only include the fields from the
578
+ * Presence that have been changed since the last announcement. However, after
579
+ * a new user joins a room, a "full presence" will be announced so the newly
580
+ * connected user will get each other's user full presence at least once. In
581
+ * those cases, the `targetActor` field indicates the newly connected client,
582
+ * so all other existing clients can ignore this broadcasted message.
583
+ */
584
+ declare type UpdatePresenceServerMsg<TPresence extends JsonObject> = {
585
+ type: ServerMsgCode.UPDATE_PRESENCE;
586
+ /**
587
+ * The User whose Presence has changed.
588
+ */
589
+ actor: number;
590
+ /**
591
+ * When set, signifies that this is a Full Presence™ update, not a patch.
592
+ *
593
+ * The numeric value itself no longer has specific meaning. Historically,
594
+ * this field was intended so that clients could ignore these broadcasted
595
+ * full presence messages, but it turned out that getting a full presence
596
+ * "keyframe" from time to time was useful.
597
+ *
598
+ * So nowadays, the presence (pun intended) of this `targetActor` field
599
+ * is a backward-compatible way of expressing that the `data` contains
600
+ * all presence fields, and isn't a partial "patch".
601
+ */
602
+ targetActor: number;
603
+ /**
604
+ * The partial or full Presence of a User. If the `targetActor` field is set,
605
+ * this will be the full Presence, otherwise it only contain the fields that
606
+ * have changed since the last broadcast.
607
+ */
608
+ data: TPresence;
609
+ } | {
610
+ type: ServerMsgCode.UPDATE_PRESENCE;
611
+ /**
612
+ * The User whose Presence has changed.
613
+ */
614
+ actor: number;
615
+ /**
616
+ * Not set for partial presence updates.
617
+ */
618
+ targetActor?: undefined;
619
+ /**
620
+ * A partial Presence patch to apply to the User. It will only contain the
621
+ * fields that have changed since the last broadcast.
622
+ */
623
+ data: Partial<TPresence>;
624
+ };
625
+ /**
626
+ * Sent by the WebSocket server and broadcasted to all clients to announce that
627
+ * a new User has joined the Room.
628
+ */
629
+ declare type UserJoinServerMsg<TUserMeta extends BaseUserMeta> = {
630
+ type: ServerMsgCode.USER_JOINED;
631
+ actor: number;
632
+ /**
633
+ * The id of the User that has been set in the authentication endpoint.
634
+ * Useful to get additional information about the connected user.
635
+ */
636
+ id: TUserMeta["id"];
637
+ /**
638
+ * Additional user information that has been set in the authentication
639
+ * endpoint.
640
+ */
641
+ info: TUserMeta["info"];
642
+ };
643
+ /**
644
+ * Sent by the WebSocket server and broadcasted to all clients to announce that
645
+ * a new User has left the Room.
646
+ */
647
+ declare type UserLeftServerMsg = {
648
+ type: ServerMsgCode.USER_LEFT;
649
+ actor: number;
650
+ };
651
+ /**
652
+ * Sent by the WebSocket server and broadcasted to all clients to announce that
653
+ * a User broadcasted an Event to everyone in the Room.
654
+ */
655
+ declare type BroadcastedEventServerMsg<TRoomEvent extends Json> = {
656
+ type: ServerMsgCode.BROADCASTED_EVENT;
657
+ /**
658
+ * The User who broadcasted the Event.
659
+ */
660
+ actor: number;
661
+ /**
662
+ * The arbitrary payload of the Event. This can be any JSON value. Clients
663
+ * will have to manually verify/decode this event.
664
+ */
665
+ event: TRoomEvent;
666
+ };
667
+ /**
668
+ * Sent by the WebSocket server to a single client in response to the client
669
+ * joining the Room, to provide the initial state of the Room. The payload
670
+ * includes a list of all other Users that already are in the Room.
671
+ */
672
+ declare type RoomStateServerMsg<TUserMeta extends BaseUserMeta> = {
673
+ type: ServerMsgCode.ROOM_STATE;
674
+ users: {
675
+ [actor: number]: TUserMeta;
676
+ };
677
+ };
678
+ /**
679
+ * Sent by the WebSocket server to a single client in response to the client
680
+ * joining the Room, to provide the initial Storage state of the Room. The
681
+ * payload includes the entire Storage document.
682
+ */
683
+ declare type InitialDocumentStateServerMsg = {
684
+ type: ServerMsgCode.INITIAL_STORAGE_STATE;
685
+ items: IdTuple<SerializedCrdt>[];
686
+ };
687
+ /**
688
+ * Sent by the WebSocket server and broadcasted to all clients to announce that
689
+ * a change occurred in the Storage document.
690
+ *
691
+ * The payload of this message contains a list of Ops (aka incremental
692
+ * mutations to make to the initially loaded document).
693
+ */
694
+ declare type UpdateStorageServerMsg = {
695
+ type: ServerMsgCode.UPDATE_STORAGE;
696
+ ops: Op[];
697
+ };
698
+
699
+ /**
700
+ * This helper type is effectively a no-op, but will force TypeScript to
701
+ * "evaluate" any named helper types in its definition. This can sometimes make
702
+ * API signatures clearer in IDEs.
703
+ *
704
+ * For example, in:
705
+ *
706
+ * type Payload<T> = { data: T };
707
+ *
708
+ * let r1: Payload<string>;
709
+ * let r2: Resolve<Payload<string>>;
710
+ *
711
+ * The inferred type of `r1` is going to be `Payload<string>` which shows up in
712
+ * editor hints, and it may be unclear what's inside if you don't know the
713
+ * definition of `Payload`.
714
+ *
715
+ * The inferred type of `r2` is going to be `{ data: string }`, which may be
716
+ * more helpful.
717
+ *
718
+ * This trick comes from:
719
+ * https://effectivetypescript.com/2022/02/25/gentips-4-display/
720
+ */
721
+ declare type Resolve<T> = T extends (...args: unknown[]) => unknown ? T : {
722
+ [K in keyof T]: T[K];
723
+ };
724
+ declare type CustomEvent<TRoomEvent extends Json> = {
725
+ connectionId: number;
726
+ event: TRoomEvent;
727
+ };
728
+ declare type UpdateDelta = {
729
+ type: "update";
730
+ } | {
731
+ type: "delete";
732
+ };
733
+ /**
734
+ * A LiveMap notification that is sent in-client to any subscribers whenever
735
+ * one or more of the values inside the LiveMap instance have changed.
736
+ */
737
+ declare type LiveMapUpdates<TKey extends string, TValue extends Lson> = {
738
+ type: "LiveMap";
739
+ node: LiveMap<TKey, TValue>;
740
+ updates: {
741
+ [key: string]: UpdateDelta;
742
+ };
743
+ };
744
+ declare type LiveObjectUpdateDelta<O extends {
745
+ [key: string]: unknown;
746
+ }> = {
747
+ [K in keyof O]?: UpdateDelta | undefined;
748
+ };
749
+ /**
750
+ * A LiveObject notification that is sent in-client to any subscribers whenever
751
+ * one or more of the entries inside the LiveObject instance have changed.
752
+ */
753
+ declare type LiveObjectUpdates<TData extends LsonObject> = {
754
+ type: "LiveObject";
755
+ node: LiveObject<TData>;
756
+ updates: LiveObjectUpdateDelta<TData>;
757
+ };
758
+ declare type LiveListUpdateDelta = {
759
+ index: number;
760
+ item: Lson;
761
+ type: "insert";
762
+ } | {
763
+ index: number;
764
+ type: "delete";
765
+ } | {
766
+ index: number;
767
+ previousIndex: number;
768
+ item: Lson;
769
+ type: "move";
770
+ } | {
771
+ index: number;
772
+ item: Lson;
773
+ type: "set";
774
+ };
775
+ /**
776
+ * A LiveList notification that is sent in-client to any subscribers whenever
777
+ * one or more of the items inside the LiveList instance have changed.
778
+ */
779
+ declare type LiveListUpdates<TItem extends Lson> = {
780
+ type: "LiveList";
781
+ node: LiveList<TItem>;
782
+ updates: LiveListUpdateDelta[];
783
+ };
784
+ declare type BroadcastOptions = {
785
+ /**
786
+ * Whether or not event is queued if the connection is currently closed.
787
+ *
788
+ * ❗ We are not sure if we want to support this option in the future so it might be deprecated to be replaced by something else
789
+ */
790
+ shouldQueueEventIfNotReady: boolean;
791
+ };
792
+ /**
793
+ * The payload of notifications sent (in-client) when LiveStructures change.
794
+ * Messages of this kind are not originating from the network, but are 100%
795
+ * in-client.
796
+ */
797
+ declare type StorageUpdate = LiveMapUpdates<string, Lson> | LiveObjectUpdates<LsonObject> | LiveListUpdates<Lson>;
798
+ declare type StorageCallback = (updates: StorageUpdate[]) => void;
799
+ declare type RoomInitializers<TPresence extends JsonObject, TStorage extends LsonObject> = Resolve<{
800
+ /**
801
+ * The initial Presence to use and announce when you enter the Room. The
802
+ * Presence is available on all users in the Room (me & others).
803
+ */
804
+ initialPresence: TPresence | ((roomId: string) => TPresence);
805
+ /**
806
+ * The initial Storage to use when entering a new Room.
807
+ */
808
+ initialStorage?: TStorage | ((roomId: string) => TStorage);
809
+ /**
810
+ * Whether or not the room connects to Liveblock servers. Default is true.
811
+ *
812
+ * Usually set to false when the client is used from the server to not call
813
+ * the authentication endpoint or connect via WebSocket.
814
+ */
815
+ shouldInitiallyConnect?: boolean;
816
+ }>;
817
+ declare type Client = {
818
+ /**
819
+ * Gets a room. Returns null if {@link Client.enter} has not been called previously.
820
+ *
821
+ * @param roomId The id of the room
822
+ */
823
+ getRoom<TPresence extends JsonObject, TStorage extends LsonObject = LsonObject, TUserMeta extends BaseUserMeta = BaseUserMeta, TRoomEvent extends Json = never>(roomId: string): Room<TPresence, TStorage, TUserMeta, TRoomEvent> | null;
824
+ /**
825
+ * Enters a room and returns it.
826
+ * @param roomId The id of the room
827
+ * @param options Optional. You can provide initializers for the Presence or Storage when entering the Room.
828
+ */
829
+ enter<TPresence extends JsonObject, TStorage extends LsonObject = LsonObject, TUserMeta extends BaseUserMeta = BaseUserMeta, TRoomEvent extends Json = never>(roomId: string, options: RoomInitializers<TPresence, TStorage>): Room<TPresence, TStorage, TUserMeta, TRoomEvent>;
830
+ /**
831
+ * Leaves a room.
832
+ * @param roomId The id of the room
833
+ */
834
+ leave(roomId: string): void;
835
+ };
836
+ /**
837
+ * Represents all the other users connected in the room. Treated as immutable.
838
+ */
839
+ declare type Others<TPresence extends JsonObject, TUserMeta extends BaseUserMeta> = ReadonlyArrayWithLegacyMethods<User<TPresence, TUserMeta>>;
840
+ /**
841
+ * Represents a user connected in a room. Treated as immutable.
842
+ */
843
+ declare type User<TPresence extends JsonObject, TUserMeta extends BaseUserMeta> = {
844
+ /**
845
+ * The connection id of the user. It is unique and increment at every new connection.
846
+ */
847
+ readonly connectionId: number;
848
+ /**
849
+ * The id of the user that has been set in the authentication endpoint.
850
+ * Useful to get additional information about the connected user.
851
+ */
852
+ readonly id: TUserMeta["id"];
853
+ /**
854
+ * Additional user information that has been set in the authentication endpoint.
855
+ */
856
+ readonly info: TUserMeta["info"];
857
+ /**
858
+ * The user presence.
859
+ */
860
+ readonly presence: TPresence;
861
+ };
862
+ declare type AuthEndpointCallback = (room: string) => Promise<{
863
+ token: string;
864
+ }>;
865
+ declare type AuthEndpoint = string | AuthEndpointCallback;
866
+ declare type Polyfills = {
867
+ atob?: (data: string) => string;
868
+ fetch?: typeof fetch;
869
+ WebSocket?: any;
870
+ };
871
+ /**
872
+ * The authentication endpoint that is called to ensure that the current user has access to a room.
873
+ * Can be an url or a callback if you need to add additional headers.
874
+ */
875
+ declare type ClientOptions = {
876
+ throttle?: number;
877
+ polyfills?: Polyfills;
878
+ /**
879
+ * Backward-compatible way to set `polyfills.fetch`.
880
+ */
881
+ fetchPolyfill?: Polyfills["fetch"];
882
+ /**
883
+ * Backward-compatible way to set `polyfills.WebSocket`.
884
+ */
885
+ WebSocketPolyfill?: Polyfills["WebSocket"];
886
+ } & ({
887
+ publicApiKey: string;
888
+ authEndpoint?: never;
889
+ } | {
890
+ publicApiKey?: never;
891
+ authEndpoint: AuthEndpoint;
892
+ });
893
+ declare type Connection = {
894
+ state: "closed";
895
+ } | {
896
+ state: "authenticating";
897
+ } | {
898
+ state: "connecting";
899
+ id: number;
900
+ userId?: string;
901
+ userInfo?: Json;
902
+ } | {
903
+ state: "open";
904
+ id: number;
905
+ userId?: string;
906
+ userInfo?: Json;
907
+ } | {
908
+ state: "unavailable";
909
+ } | {
910
+ state: "failed";
911
+ };
912
+ declare type ConnectionState = Connection["state"];
913
+ declare type OthersEvent<TPresence extends JsonObject, TUserMeta extends BaseUserMeta> = {
914
+ type: "leave";
915
+ user: User<TPresence, TUserMeta>;
916
+ } | {
917
+ type: "enter";
918
+ user: User<TPresence, TUserMeta>;
919
+ } | {
920
+ type: "update";
921
+ user: User<TPresence, TUserMeta>;
922
+ updates: Partial<TPresence>;
923
+ } | {
924
+ type: "reset";
925
+ };
926
+ interface History {
927
+ /**
928
+ * Undoes the last operation executed by the current client.
929
+ * It does not impact operations made by other clients.
930
+ *
931
+ * @example
932
+ * room.updatePresence({ selectedId: "xx" }, { addToHistory: true });
933
+ * room.updatePresence({ selectedId: "yy" }, { addToHistory: true });
934
+ * room.history.undo();
935
+ * // room.getPresence() equals { selectedId: "xx" }
936
+ */
937
+ undo: () => void;
938
+ /**
939
+ * Redoes the last operation executed by the current client.
940
+ * It does not impact operations made by other clients.
941
+ *
942
+ * @example
943
+ * room.updatePresence({ selectedId: "xx" }, { addToHistory: true });
944
+ * room.updatePresence({ selectedId: "yy" }, { addToHistory: true });
945
+ * room.history.undo();
946
+ * // room.getPresence() equals { selectedId: "xx" }
947
+ * room.history.redo();
948
+ * // room.getPresence() equals { selectedId: "yy" }
949
+ */
950
+ redo: () => void;
951
+ /**
952
+ * Returns whether there are any operations to undo.
953
+ *
954
+ * @example
955
+ * room.updatePresence({ selectedId: "xx" }, { addToHistory: true });
956
+ * // room.history.canUndo() is true
957
+ * room.history.undo();
958
+ * // room.history.canUndo() is false
959
+ */
960
+ canUndo: () => boolean;
961
+ /**
962
+ * Returns whether there are any operations to redo.
963
+ *
964
+ * @example
965
+ * room.updatePresence({ selectedId: "xx" }, { addToHistory: true });
966
+ * room.history.undo();
967
+ * // room.history.canRedo() is true
968
+ * room.history.redo();
969
+ * // room.history.canRedo() is false
970
+ */
971
+ canRedo: () => boolean;
972
+ /**
973
+ * All future modifications made on the Room will be merged together to create a single history item until resume is called.
974
+ *
975
+ * @example
976
+ * room.updatePresence({ cursor: { x: 0, y: 0 } }, { addToHistory: true });
977
+ * room.history.pause();
978
+ * room.updatePresence({ cursor: { x: 1, y: 1 } }, { addToHistory: true });
979
+ * room.updatePresence({ cursor: { x: 2, y: 2 } }, { addToHistory: true });
980
+ * room.history.resume();
981
+ * room.history.undo();
982
+ * // room.getPresence() equals { cursor: { x: 0, y: 0 } }
983
+ */
984
+ pause: () => void;
985
+ /**
986
+ * Resumes history. Modifications made on the Room are not merged into a single history item anymore.
987
+ *
988
+ * @example
989
+ * room.updatePresence({ cursor: { x: 0, y: 0 } }, { addToHistory: true });
990
+ * room.history.pause();
991
+ * room.updatePresence({ cursor: { x: 1, y: 1 } }, { addToHistory: true });
992
+ * room.updatePresence({ cursor: { x: 2, y: 2 } }, { addToHistory: true });
993
+ * room.history.resume();
994
+ * room.history.undo();
995
+ * // room.getPresence() equals { cursor: { x: 0, y: 0 } }
996
+ */
997
+ resume: () => void;
998
+ }
999
+ interface HistoryEvent {
1000
+ canUndo: boolean;
1001
+ canRedo: boolean;
1002
+ }
1003
+ declare type Room<TPresence extends JsonObject, TStorage extends LsonObject, TUserMeta extends BaseUserMeta, TRoomEvent extends Json> = {
1004
+ /**
1005
+ * The id of the room.
1006
+ */
1007
+ readonly id: string;
1008
+ /**
1009
+ * A client is considered "self aware" if it knows its own
1010
+ * metadata and connection ID (from the auth server).
1011
+ */
1012
+ isSelfAware(): boolean;
1013
+ getConnectionState(): ConnectionState;
1014
+ readonly subscribe: {
1015
+ /**
1016
+ * Subscribe to the current user presence updates.
1017
+ *
1018
+ * @param listener the callback that is called every time the current user presence is updated with {@link Room.updatePresence}.
1019
+ *
1020
+ * @returns Unsubscribe function.
1021
+ *
1022
+ * @example
1023
+ * room.subscribe("my-presence", (presence) => {
1024
+ * // Do something
1025
+ * });
1026
+ */
1027
+ (type: "my-presence", listener: Callback<TPresence>): () => void;
1028
+ /**
1029
+ * Subscribe to the other users updates.
1030
+ *
1031
+ * @param listener the callback that is called when a user enters or leaves the room or when a user update its presence.
1032
+ *
1033
+ * @returns Unsubscribe function.
1034
+ *
1035
+ * @example
1036
+ * room.subscribe("others", (others) => {
1037
+ * // Do something
1038
+ * });
1039
+ *
1040
+ */
1041
+ (type: "others", listener: (others: Others<TPresence, TUserMeta>, event: OthersEvent<TPresence, TUserMeta>) => void): () => void;
1042
+ /**
1043
+ * Subscribe to events broadcasted by {@link Room.broadcastEvent}
1044
+ *
1045
+ * @param listener the callback that is called when a user calls {@link Room.broadcastEvent}
1046
+ *
1047
+ * @returns Unsubscribe function.
1048
+ *
1049
+ * @example
1050
+ * room.subscribe("event", ({ event, connectionId }) => {
1051
+ * // Do something
1052
+ * });
1053
+ *
1054
+ */
1055
+ (type: "event", listener: Callback<CustomEvent<TRoomEvent>>): () => void;
1056
+ /**
1057
+ * Subscribe to errors thrown in the room.
1058
+ *
1059
+ * @returns Unsubscribe function.
1060
+ *
1061
+ */
1062
+ (type: "error", listener: ErrorCallback): () => void;
1063
+ /**
1064
+ * Subscribe to connection state updates.
1065
+ *
1066
+ * @returns Unsubscribe function.
1067
+ *
1068
+ */
1069
+ (type: "connection", listener: Callback<ConnectionState>): () => void;
1070
+ /**
1071
+ * Subscribes to changes made on a Live structure. Returns an unsubscribe function.
1072
+ * In a future version, we will also expose what exactly changed in the Live structure.
1073
+ *
1074
+ * @param callback The callback this called when the Live structure changes.
1075
+ *
1076
+ * @returns Unsubscribe function.
1077
+ *
1078
+ * @example
1079
+ * const liveMap = new LiveMap(); // Could also be LiveList or LiveObject
1080
+ * const unsubscribe = room.subscribe(liveMap, (liveMap) => { });
1081
+ * unsubscribe();
1082
+ */
1083
+ <L extends LiveStructure>(liveStructure: L, callback: (node: L) => void): () => void;
1084
+ /**
1085
+ * Subscribes to changes made on a Live structure and all the nested data
1086
+ * structures. Returns an unsubscribe function. In a future version, we
1087
+ * will also expose what exactly changed in the Live structure.
1088
+ *
1089
+ * @param callback The callback this called when the Live structure, or any
1090
+ * of its nested values, changes.
1091
+ *
1092
+ * @returns Unsubscribe function.
1093
+ *
1094
+ * @example
1095
+ * const liveMap = new LiveMap(); // Could also be LiveList or LiveObject
1096
+ * const unsubscribe = room.subscribe(liveMap, (updates) => { }, { isDeep: true });
1097
+ * unsubscribe();
1098
+ */
1099
+ <L extends LiveStructure>(liveStructure: L, callback: StorageCallback, options: {
1100
+ isDeep: true;
1101
+ }): () => void;
1102
+ /**
1103
+ * Subscribe to the current user's history changes.
1104
+ *
1105
+ * @returns Unsubscribe function.
1106
+ *
1107
+ * @example
1108
+ * room.subscribe("history", ({ canUndo, canRedo }) => {
1109
+ * // Do something
1110
+ * });
1111
+ *
1112
+ */
1113
+ (type: "history", listener: Callback<HistoryEvent>): () => void;
1114
+ };
1115
+ /**
1116
+ * Room's history contains functions that let you undo and redo operation made on by the current client on the presence and storage.
1117
+ */
1118
+ readonly history: History;
1119
+ /**
1120
+ * Gets the current user.
1121
+ * Returns null if not it is not yet connected to the room.
1122
+ *
1123
+ * @example
1124
+ * const user = room.getSelf();
1125
+ */
1126
+ getSelf(): User<TPresence, TUserMeta> | null;
1127
+ /**
1128
+ * Gets the presence of the current user.
1129
+ *
1130
+ * @example
1131
+ * const presence = room.getPresence();
1132
+ */
1133
+ getPresence(): TPresence;
1134
+ /**
1135
+ * Gets all the other users in the room.
1136
+ *
1137
+ * @example
1138
+ * const others = room.getOthers();
1139
+ */
1140
+ getOthers(): Others<TPresence, TUserMeta>;
1141
+ /**
1142
+ * Updates the presence of the current user. Only pass the properties you want to update. No need to send the full presence.
1143
+ * @param patch A partial object that contains the properties you want to update.
1144
+ * @param options Optional object to configure the behavior of updatePresence.
1145
+ *
1146
+ * @example
1147
+ * room.updatePresence({ x: 0 });
1148
+ * room.updatePresence({ y: 0 });
1149
+ *
1150
+ * const presence = room.getPresence();
1151
+ * // presence is equivalent to { x: 0, y: 0 }
1152
+ */
1153
+ updatePresence(patch: Partial<TPresence>, options?: {
1154
+ /**
1155
+ * Whether or not the presence should have an impact on the undo/redo history.
1156
+ */
1157
+ addToHistory: boolean;
1158
+ }): void;
1159
+ /**
1160
+ * Broadcasts an event to other users in the room. Event broadcasted to the room can be listened with {@link Room.subscribe}("event").
1161
+ * @param {any} event the event to broadcast. Should be serializable to JSON
1162
+ *
1163
+ * @example
1164
+ * // On client A
1165
+ * room.broadcastEvent({ type: "EMOJI", emoji: "🔥" });
1166
+ *
1167
+ * // On client B
1168
+ * room.subscribe("event", ({ event }) => {
1169
+ * if(event.type === "EMOJI") {
1170
+ * // Do something
1171
+ * }
1172
+ * });
1173
+ */
1174
+ broadcastEvent(event: TRoomEvent, options?: BroadcastOptions): void;
1175
+ /**
1176
+ * Get the room's storage asynchronously.
1177
+ * The storage's root is a {@link LiveObject}.
1178
+ *
1179
+ * @example
1180
+ * const { root } = await room.getStorage();
1181
+ */
1182
+ getStorage(): Promise<{
1183
+ root: LiveObject<TStorage>;
1184
+ }>;
1185
+ /**
1186
+ * Get the room's storage synchronously.
1187
+ * The storage's root is a {@link LiveObject}.
1188
+ *
1189
+ * @example
1190
+ * const root = room.getStorageSnapshot();
1191
+ */
1192
+ getStorageSnapshot(): LiveObject<TStorage> | null;
1193
+ readonly events: {
1194
+ customEvent: Observable<{
1195
+ connectionId: number;
1196
+ event: TRoomEvent;
1197
+ }>;
1198
+ me: Observable<TPresence>;
1199
+ others: Observable<{
1200
+ others: Others<TPresence, TUserMeta>;
1201
+ event: OthersEvent<TPresence, TUserMeta>;
1202
+ }>;
1203
+ error: Observable<Error>;
1204
+ connection: Observable<ConnectionState>;
1205
+ storage: Observable<StorageUpdate[]>;
1206
+ history: Observable<HistoryEvent>;
1207
+ /**
1208
+ * Subscribe to the storage loaded event. Will fire at most once during the
1209
+ * lifetime of a Room.
1210
+ */
1211
+ storageDidLoad: Observable<void>;
1212
+ };
1213
+ /**
1214
+ * Batches modifications made during the given function.
1215
+ * All the modifications are sent to other clients in a single message.
1216
+ * All the subscribers are called only after the batch is over.
1217
+ * All the modifications are merged in a single history item (undo/redo).
1218
+ *
1219
+ * @example
1220
+ * const { root } = await room.getStorage();
1221
+ * room.batch(() => {
1222
+ * root.set("x", 0);
1223
+ * room.updatePresence({ cursor: { x: 100, y: 100 }});
1224
+ * });
1225
+ */
1226
+ batch<T>(fn: () => T): T;
1227
+ };
1228
+ declare enum WebsocketCloseCodes {
1229
+ CLOSE_ABNORMAL = 1006,
1230
+ INVALID_MESSAGE_FORMAT = 4000,
1231
+ NOT_ALLOWED = 4001,
1232
+ MAX_NUMBER_OF_MESSAGES_PER_SECONDS = 4002,
1233
+ MAX_NUMBER_OF_CONCURRENT_CONNECTIONS = 4003,
1234
+ MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP = 4004,
1235
+ MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM = 4005,
1236
+ CLOSE_WITHOUT_RETRY = 4999
1237
+ }
1238
+
1239
+ declare type AppOnlyAuthToken = {
1240
+ appId: string;
1241
+ roomId?: never;
1242
+ scopes: string[];
1243
+ };
1244
+ declare type RoomAuthToken = {
1245
+ appId: string;
1246
+ roomId: string;
1247
+ scopes: string[];
1248
+ actor: number;
1249
+ maxConnectionsPerRoom?: number;
1250
+ id?: string;
1251
+ info?: Json;
1252
+ };
1253
+ declare type AuthToken = AppOnlyAuthToken | RoomAuthToken;
1254
+ declare function isAppOnlyAuthToken(data: JsonObject): data is AppOnlyAuthToken;
1255
+ declare function isRoomAuthToken(data: JsonObject): data is RoomAuthToken;
1256
+ declare function isAuthToken(data: JsonObject): data is AuthToken;
1257
+
1258
+ /**
1259
+ * Displays a deprecation warning in the dev console. Only in dev mode, and
1260
+ * only once per message/key. In production, this is a no-op.
1261
+ */
1262
+ declare function deprecate(message: string, key?: string): void;
1263
+ /**
1264
+ * Conditionally displays a deprecation warning in the dev
1265
+ * console if the first argument is truthy. Only in dev mode, and
1266
+ * only once per message/key. In production, this is a no-op.
1267
+ */
1268
+ declare function deprecateIf(condition: unknown, message: string, key?: string): void;
1269
+ /**
1270
+ * Throws a deprecation error in the dev console.
1271
+ *
1272
+ * Only triggers in dev mode. In production, this is a no-op.
1273
+ */
1274
+ declare function throwUsageError(message: string): void;
1275
+ /**
1276
+ * Conditionally throws a usage error in the dev console if the first argument
1277
+ * is truthy. Use this to "escalate" usage patterns that in previous versions
1278
+ * we already warned about with deprecation warnings.
1279
+ *
1280
+ * Only has effect in dev mode. In production, this is a no-op.
1281
+ */
1282
+ declare function errorIf(condition: unknown, message: string): void;
1283
+
1284
+ declare function lsonToJson(value: Lson): Json;
1285
+ declare function patchLiveObjectKey<O extends LsonObject, K extends keyof O, V extends Lson>(liveObject: LiveObject<O>, key: K, prev?: V, next?: V): void;
1286
+ declare function legacy_patchImmutableObject<S extends JsonObject>(state: S, updates: StorageUpdate[]): S;
1287
+
1288
+ declare function makePosition(before?: string, after?: string): string;
1289
+ declare function comparePosition(posA: string, posB: string): number;
1290
+
1291
+ /**
1292
+ * Freezes the given argument, but only in development builds. In production
1293
+ * builds, this is a no-op for performance reasons.
1294
+ */
1295
+ declare const freeze: typeof Object.freeze;
1296
+ declare function isPlainObject(blob: unknown): blob is {
1297
+ [key: string]: unknown;
1298
+ };
1299
+ /**
1300
+ * Alternative to JSON.parse() that will not throw in production. If the passed
1301
+ * string cannot be parsed, this will return `undefined`.
1302
+ */
1303
+ declare function tryParseJson(rawMessage: string): Json | undefined;
1304
+ /**
1305
+ * Decode base64 string.
1306
+ */
1307
+ declare function b64decode(b64value: string): string;
1308
+
1309
+ /**
1310
+ * Create a client that will be responsible to communicate with liveblocks servers.
1311
+ *
1312
+ * @example
1313
+ * const client = createClient({
1314
+ * authEndpoint: "/api/auth"
1315
+ * });
1316
+ *
1317
+ * // It's also possible to use a function to call your authentication endpoint.
1318
+ * // Useful to add additional headers or use an API wrapper (like Firebase functions)
1319
+ * const client = createClient({
1320
+ * authEndpoint: async (room) => {
1321
+ * const response = await fetch("/api/auth", {
1322
+ * method: "POST",
1323
+ * headers: {
1324
+ * Authentication: "token",
1325
+ * "Content-Type": "application/json"
1326
+ * },
1327
+ * body: JSON.stringify({ room })
1328
+ * });
1329
+ *
1330
+ * return await response.json(); // should be: { token: "..." }
1331
+ * }
1332
+ * });
1333
+ */
1334
+ declare function createClient(options: ClientOptions): Client;
1335
+
1336
+ /**
1337
+ * Shallowly compares two given values.
1338
+ *
1339
+ * - Two simple values are considered equal if they're strictly equal
1340
+ * - Two arrays are considered equal if their members are strictly equal
1341
+ * - Two objects are considered equal if their values are strictly equal
1342
+ *
1343
+ * Testing goes one level deep.
1344
+ */
1345
+ declare function shallow(a: unknown, b: unknown): boolean;
1346
+
1347
+ /**
1348
+ * PRIVATE / INTERNAL APIS
1349
+ * -----------------------
1350
+ *
1351
+ * This module is intended for internal use only, PLEASE DO NOT RELY ON ANY OF
1352
+ * THE EXPORTS IN HERE. These are implementation details that can change at any
1353
+ * time and without announcement. This module purely exists to share code
1354
+ * between the several Liveblocks packages.
1355
+ *
1356
+ * But since you're so deep inside Liveblocks code... we're hiring!
1357
+ * https://join.team/liveblocks ;)
1358
+ */
1359
+
1360
+ /**
1361
+ * Helper type to help users adopt to Lson types from interface definitions.
1362
+ * You should only use this to wrap interfaces you don't control. For more
1363
+ * information, see
1364
+ * https://liveblocks.io/docs/guides/limits#lson-constraint-and-interfaces
1365
+ */
1366
+ declare type EnsureJson<T> = [
1367
+ unknown
1368
+ ] extends [T] ? T : T extends (...args: unknown[]) => unknown ? T : {
1369
+ [K in keyof T]: EnsureJson<T[K]>;
1370
+ };
1371
+
1372
+ export { AppOnlyAuthToken, AuthToken, BaseUserMeta, BroadcastEventClientMsg, BroadcastOptions, BroadcastedEventServerMsg, Client, ClientMsg, ClientMsgCode, CrdtType, CreateChildOp, CreateListOp, CreateMapOp, CreateObjectOp, CreateOp, CreateRegisterOp, CreateRootObjectOp, DeleteCrdtOp, DeleteObjectKeyOp, EnsureJson, FetchStorageClientMsg, History, IdTuple, Immutable, InitialDocumentStateServerMsg, Json, JsonObject, LiveList, LiveMap, LiveNode, LiveObject, LiveStructure, Lson, LsonObject, NodeMap, Op, OpCode, Others, ParentToChildNodeMap, Resolve, Room, RoomAuthToken, RoomInitializers, RoomStateServerMsg, SerializedChild, SerializedCrdt, SerializedList, SerializedMap, SerializedObject, SerializedRegister, SerializedRootObject, ServerMsg, ServerMsgCode, SetParentKeyOp, StorageUpdate, ToImmutable, ToJson, UpdateObjectOp, UpdatePresenceClientMsg, UpdatePresenceServerMsg, UpdateStorageClientMsg, UpdateStorageServerMsg, User, UserJoinServerMsg, UserLeftServerMsg, WebsocketCloseCodes, asArrayWithLegacyMethods, assertNever, b64decode, comparePosition, createClient, deprecate, deprecateIf, errorIf, freeze, isAppOnlyAuthToken, isAuthToken, isChildCrdt, isJsonArray, isJsonObject, isJsonScalar, isPlainObject, isRoomAuthToken, isRootCrdt, legacy_patchImmutableObject, lsonToJson, makePosition, nn, patchLiveObjectKey, shallow, throwUsageError, tryParseJson };