@liveblocks/core 1.19.0-test1 → 2.0.0-alpha2

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/dist/index.d.mts CHANGED
@@ -5,6 +5,19 @@
5
5
  declare function detectDupes(pkgName: string, pkgVersion: string | false, // false if not built yet
6
6
  pkgFormat: string | false): void;
7
7
 
8
+ declare type CustomAuthenticationResult = {
9
+ token: string;
10
+ error?: never;
11
+ } | {
12
+ token?: never;
13
+ error: "forbidden";
14
+ reason: string;
15
+ } | {
16
+ token?: never;
17
+ error: string;
18
+ reason: string;
19
+ };
20
+
8
21
  /**
9
22
  * Represents an indefinitely deep arbitrary JSON data structure. There are
10
23
  * four types that make up the Json family:
@@ -25,6 +38,217 @@ declare function isJsonScalar(data: Json): data is JsonScalar;
25
38
  declare function isJsonArray(data: Json): data is JsonArray;
26
39
  declare function isJsonObject(data: Json): data is JsonObject;
27
40
 
41
+ /**
42
+ * Represents some constraints for user info. Basically read this as: "any JSON
43
+ * object is fine, but _if_ it has a name field, it _must_ be a string."
44
+ * (Ditto for avatar.)
45
+ */
46
+ declare type IUserInfo = {
47
+ [key: string]: Json | undefined;
48
+ name?: string;
49
+ avatar?: string;
50
+ };
51
+ /**
52
+ * This type is used by clients to define the metadata for a user.
53
+ */
54
+ declare type BaseUserMeta = {
55
+ /**
56
+ * The id of the user that has been set in the authentication endpoint.
57
+ * Useful to get additional information about the connected user.
58
+ */
59
+ id?: string;
60
+ /**
61
+ * Additional user information that has been set in the authentication endpoint.
62
+ */
63
+ info?: IUserInfo;
64
+ };
65
+
66
+ declare type Callback<T> = (event: T) => void;
67
+ declare type UnsubscribeCallback = () => void;
68
+ declare type Observable<T> = {
69
+ /**
70
+ * Register a callback function to be called whenever the event source emits
71
+ * an event.
72
+ */
73
+ subscribe(callback: Callback<T>): UnsubscribeCallback;
74
+ /**
75
+ * Register a one-time callback function to be called whenever the event
76
+ * source emits an event. After the event fires, the callback is
77
+ * auto-unsubscribed.
78
+ */
79
+ subscribeOnce(callback: Callback<T>): UnsubscribeCallback;
80
+ /**
81
+ * Returns a promise that will resolve when an event is emitted by this
82
+ * event source. Optionally, specify a predicate that has to match. The first
83
+ * event matching that predicate will then resolve the promise.
84
+ */
85
+ waitUntil(predicate?: (event: T) => boolean): Promise<T>;
86
+ };
87
+ declare type EventSource<T> = Observable<T> & {
88
+ /**
89
+ * Notify all subscribers about the event.
90
+ */
91
+ notify(event: T): void;
92
+ /**
93
+ * Clear all registered event listeners. None of the registered functions
94
+ * will ever get called again. Be careful when using this API, because the
95
+ * subscribers may not have any idea they won't be notified anymore.
96
+ */
97
+ clear(): void;
98
+ /**
99
+ * Returns the number of active subscribers.
100
+ */
101
+ count(): number;
102
+ /**
103
+ * Pauses event delivery until unpaused. Any .notify() calls made while
104
+ * paused will get buffered into memory and emitted later.
105
+ */
106
+ pause(): void;
107
+ /**
108
+ * Emits all in-memory buffered events, and unpauses. Any .notify() calls
109
+ * made after this will be synchronously delivered again.
110
+ */
111
+ unpause(): void;
112
+ /**
113
+ * Observable instance, which can be used to subscribe to this event source
114
+ * in a readonly fashion. Safe to publicly expose.
115
+ */
116
+ observable: Observable<T>;
117
+ };
118
+ /**
119
+ * makeEventSource allows you to generate a subscribe/notify pair of functions
120
+ * to make subscribing easy and to get notified about events.
121
+ *
122
+ * The events are anonymous, so you can use it to define events, like so:
123
+ *
124
+ * const event1 = makeEventSource();
125
+ * const event2 = makeEventSource();
126
+ *
127
+ * event1.subscribe(foo);
128
+ * event1.subscribe(bar);
129
+ * event2.subscribe(qux);
130
+ *
131
+ * // Unsubscription is pretty standard
132
+ * const unsub = event2.subscribe(foo);
133
+ * unsub();
134
+ *
135
+ * event1.notify(); // Now foo and bar will get called
136
+ * event2.notify(); // Now qux will get called (but foo will not, since it's unsubscribed)
137
+ *
138
+ */
139
+ declare function makeEventSource<T>(): EventSource<T>;
140
+
141
+ interface IWebSocketEvent {
142
+ type: string;
143
+ }
144
+ interface IWebSocketCloseEvent extends IWebSocketEvent {
145
+ readonly code: WebsocketCloseCodes;
146
+ readonly wasClean: boolean;
147
+ readonly reason: string;
148
+ }
149
+ interface IWebSocketMessageEvent extends IWebSocketEvent {
150
+ readonly data: string | Buffer | ArrayBuffer | readonly Buffer[];
151
+ }
152
+ interface IWebSocketInstance {
153
+ readonly CONNECTING: number;
154
+ readonly OPEN: number;
155
+ readonly CLOSING: number;
156
+ readonly CLOSED: number;
157
+ readonly readyState: number;
158
+ addEventListener(type: "close", listener: (this: IWebSocketInstance, ev: IWebSocketCloseEvent) => unknown): void;
159
+ addEventListener(type: "message", listener: (this: IWebSocketInstance, ev: IWebSocketMessageEvent) => unknown): void;
160
+ addEventListener(type: "open" | "error", listener: (this: IWebSocketInstance, ev: IWebSocketEvent) => unknown): void;
161
+ removeEventListener(type: "close", listener: (this: IWebSocketInstance, ev: IWebSocketCloseEvent) => unknown): void;
162
+ removeEventListener(type: "message", listener: (this: IWebSocketInstance, ev: IWebSocketMessageEvent) => unknown): void;
163
+ removeEventListener(type: "open" | "error", listener: (this: IWebSocketInstance, ev: IWebSocketEvent) => unknown): void;
164
+ close(): void;
165
+ send(data: string): void;
166
+ }
167
+ /**
168
+ * Either the browser-based WebSocket API or Node.js' WebSocket API (from the
169
+ * 'ws' package).
170
+ *
171
+ * This type defines the minimal WebSocket API that Liveblocks needs from
172
+ * a WebSocket implementation, and is a minimal subset of the browser-based
173
+ * WebSocket APIs and Node.js' WebSocket API so that both implementations are
174
+ * assignable to this type.
175
+ */
176
+ interface IWebSocket {
177
+ new (address: string): IWebSocketInstance;
178
+ }
179
+ /**
180
+ * The following ranges will be respected by the client:
181
+ *
182
+ * 10xx: client will reauthorize (just like 41xx)
183
+ * 40xx: client will disconnect
184
+ * 41xx: client will reauthorize
185
+ * 42xx: client will retry without reauthorizing (currently not used)
186
+ *
187
+ */
188
+ declare enum WebsocketCloseCodes {
189
+ /** Normal close of connection, the connection fulfilled its purpose. */
190
+ CLOSE_NORMAL = 1000,
191
+ /** Unexpected error happened with the network/infra level. In spirit akin to HTTP 503 */
192
+ CLOSE_ABNORMAL = 1006,
193
+ /** Unexpected error happened. In spirit akin to HTTP 500 */
194
+ UNEXPECTED_CONDITION = 1011,
195
+ /** Please back off for now, but try again in a few moments */
196
+ TRY_AGAIN_LATER = 1013,
197
+ /** Message wasn't understood, disconnect */
198
+ INVALID_MESSAGE_FORMAT = 4000,
199
+ /** Server refused to allow connection. Re-authorizing won't help. Disconnect. In spirit akin to HTTP 403 */
200
+ NOT_ALLOWED = 4001,
201
+ /** Unused */
202
+ MAX_NUMBER_OF_MESSAGES_PER_SECONDS = 4002,
203
+ /** Unused */
204
+ MAX_NUMBER_OF_CONCURRENT_CONNECTIONS = 4003,
205
+ /** Unused */
206
+ MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP = 4004,
207
+ /** Room is full, disconnect */
208
+ MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM = 4005,
209
+ /** The room's ID was updated, disconnect */
210
+ ROOM_ID_UPDATED = 4006,
211
+ /** The server kicked the connection from the room. */
212
+ KICKED = 4100,
213
+ /** The auth token is expired, reauthorize to get a fresh one. In spirit akin to HTTP 401 */
214
+ TOKEN_EXPIRED = 4109,
215
+ /** Disconnect immediately */
216
+ CLOSE_WITHOUT_RETRY = 4999
217
+ }
218
+
219
+ /**
220
+ * Returns a human-readable status indicating the current connection status of
221
+ * a Room, as returned by `room.getStatus()`. Can be used to implement
222
+ * a connection status badge.
223
+ */
224
+ declare type Status = "initial" | "connecting" | "connected" | "reconnecting" | "disconnected";
225
+ /**
226
+ * Used to report about app-level reconnection issues.
227
+ *
228
+ * Normal (quick) reconnects won't be reported as a "lost connection". Instead,
229
+ * the application will only get an event if the reconnection attempts by the
230
+ * client are taking (much) longer than usual. Definitely a situation you want
231
+ * to inform your users about, for example, by throwing a toast message on
232
+ * screen, or show a "trying to reconnect" banner.
233
+ */
234
+ declare type LostConnectionEvent = "lost" | "restored" | "failed";
235
+ /**
236
+ * Arbitrary record that will be used as the authentication "authValue". It's the
237
+ * value that is returned by calling the authentication delegate, and will get
238
+ * passed to the connection factory delegate. This value will be remembered by
239
+ * the connection manager, but its value will not be interpreted, so it can be
240
+ * any value (except null).
241
+ */
242
+ declare type BaseAuthResult = NonNullable<Json>;
243
+ declare class LiveblocksError extends Error {
244
+ code: number;
245
+ }
246
+ declare type Delegates<T extends BaseAuthResult> = {
247
+ authenticate: () => Promise<T>;
248
+ createSocket: (authValue: T) => IWebSocketInstance;
249
+ canZombie: () => boolean;
250
+ };
251
+
28
252
  declare enum OpCode {
29
253
  INIT = 0,
30
254
  SET_PARENT_KEY = 1,
@@ -96,6 +320,25 @@ declare type AckOp = {
96
320
  readonly id: "ACK";
97
321
  readonly opId: string;
98
322
  };
323
+ /**
324
+ * Create an Op that can be used as an acknowledgement for the given opId, to
325
+ * send back to the originating client in cases where the server decided to
326
+ * ignore the Op and not forward it.
327
+ *
328
+ * Why?
329
+ * It's important for the client to receive an acknowledgement for this, so
330
+ * that it can correctly update its own unacknowledged Ops administration.
331
+ * Otherwise it could get in "synchronizing" state indefinitely.
332
+ *
333
+ * CLEVER HACK
334
+ * Introducing a new Op type for this would not be backward-compatible as
335
+ * receiving such Op would crash old clients :(
336
+ * So the clever backward-compatible hack pulled here is that we codify the
337
+ * acknowledgement as a "deletion Op" for the non-existing node id "ACK". In
338
+ * old clients such Op is accepted, but will effectively be a no-op as that
339
+ * node does not exist, but as a side-effect the Op will get acknowledged.
340
+ */
341
+ declare function ackOp(opId: string): AckOp;
99
342
  declare type SetParentKeyOp = {
100
343
  readonly opId?: string;
101
344
  readonly id: string;
@@ -184,56 +427,6 @@ declare type PlainLsonList = {
184
427
  };
185
428
  declare type PlainLson = PlainLsonObject | PlainLsonMap | PlainLsonList | Json;
186
429
 
187
- declare type LiveObjectUpdateDelta<O extends {
188
- [key: string]: unknown;
189
- }> = {
190
- [K in keyof O]?: UpdateDelta | undefined;
191
- };
192
- /**
193
- * A LiveObject notification that is sent in-client to any subscribers whenever
194
- * one or more of the entries inside the LiveObject instance have changed.
195
- */
196
- declare type LiveObjectUpdates<TData extends LsonObject> = {
197
- type: "LiveObject";
198
- node: LiveObject<TData>;
199
- updates: LiveObjectUpdateDelta<TData>;
200
- };
201
- /**
202
- * The LiveObject class is similar to a JavaScript object that is synchronized on all clients.
203
- * Keys should be a string, and values should be serializable to JSON.
204
- * If multiple clients update the same property simultaneously, the last modification received by the Liveblocks servers is the winner.
205
- */
206
- declare class LiveObject<O extends LsonObject> extends AbstractCrdt {
207
- constructor(obj?: O);
208
- /**
209
- * Transform the LiveObject into a javascript object
210
- */
211
- toObject(): O;
212
- /**
213
- * Adds or updates a property with a specified key and a value.
214
- * @param key The key of the property to add
215
- * @param value The value of the property to add
216
- */
217
- set<TKey extends keyof O>(key: TKey, value: O[TKey]): void;
218
- /**
219
- * Returns a specified property from the LiveObject.
220
- * @param key The key of the property to get
221
- */
222
- get<TKey extends keyof O>(key: TKey): O[TKey];
223
- /**
224
- * Deletes a key from the LiveObject
225
- * @param key The key of the property to delete
226
- */
227
- delete(key: keyof O): void;
228
- /**
229
- * Adds or updates multiple properties at once with an object.
230
- * @param patch The object used to overrides properties
231
- */
232
- update(patch: Partial<O>): void;
233
- toImmutable(): ToImmutable<O>;
234
- clone(): LiveObject<O>;
235
- }
236
-
237
430
  /**
238
431
  * Helper type to convert any valid Lson type to the equivalent Json type.
239
432
  *
@@ -531,165 +724,123 @@ declare type ToJson<T extends Lson | LsonObject> = T extends Json ? T : T extend
531
724
  [K in KS]: ToJson<V>;
532
725
  } : never;
533
726
 
534
- /**
535
- * This helper type is effectively a no-op, but will force TypeScript to
536
- * "evaluate" any named helper types in its definition. This can sometimes make
537
- * API signatures clearer in IDEs.
538
- *
539
- * For example, in:
540
- *
541
- * type Payload<T> = { data: T };
542
- *
543
- * let r1: Payload<string>;
544
- * let r2: Resolve<Payload<string>>;
545
- *
546
- * The inferred type of `r1` is going to be `Payload<string>` which shows up in
547
- * editor hints, and it may be unclear what's inside if you don't know the
548
- * definition of `Payload`.
549
- *
550
- * The inferred type of `r2` is going to be `{ data: string }`, which may be
551
- * more helpful.
552
- *
553
- * This trick comes from:
554
- * https://effectivetypescript.com/2022/02/25/gentips-4-display/
555
- */
556
- declare type Resolve<T> = T extends (...args: unknown[]) => unknown ? T : {
557
- [K in keyof T]: T[K];
558
- };
559
-
560
- declare type CustomAuthenticationResult = {
561
- token: string;
562
- error?: never;
563
- } | {
564
- token?: never;
565
- error: "forbidden";
566
- reason: string;
567
- } | {
568
- token?: never;
569
- error: string;
570
- reason: string;
727
+ declare type LiveObjectUpdateDelta<O extends {
728
+ [key: string]: unknown;
729
+ }> = {
730
+ [K in keyof O]?: UpdateDelta | undefined;
571
731
  };
572
-
573
732
  /**
574
- * Represents some constraints for user info. Basically read this as: "any JSON
575
- * object is fine, but _if_ it has a name field, it _must_ be a string."
576
- * (Ditto for avatar.)
733
+ * A LiveObject notification that is sent in-client to any subscribers whenever
734
+ * one or more of the entries inside the LiveObject instance have changed.
577
735
  */
578
- declare type IUserInfo = {
579
- [key: string]: Json | undefined;
580
- name?: string;
581
- avatar?: string;
736
+ declare type LiveObjectUpdates<TData extends LsonObject> = {
737
+ type: "LiveObject";
738
+ node: LiveObject<TData>;
739
+ updates: LiveObjectUpdateDelta<TData>;
582
740
  };
583
741
  /**
584
- * This type is used by clients to define the metadata for a user.
742
+ * The LiveObject class is similar to a JavaScript object that is synchronized on all clients.
743
+ * Keys should be a string, and values should be serializable to JSON.
744
+ * If multiple clients update the same property simultaneously, the last modification received by the Liveblocks servers is the winner.
585
745
  */
586
- declare type BaseUserMeta = {
746
+ declare class LiveObject<O extends LsonObject> extends AbstractCrdt {
747
+ constructor(obj?: O);
587
748
  /**
588
- * The id of the user that has been set in the authentication endpoint.
589
- * Useful to get additional information about the connected user.
749
+ * Transform the LiveObject into a javascript object
590
750
  */
591
- id?: string;
751
+ toObject(): O;
592
752
  /**
593
- * Additional user information that has been set in the authentication endpoint.
753
+ * Adds or updates a property with a specified key and a value.
754
+ * @param key The key of the property to add
755
+ * @param value The value of the property to add
594
756
  */
595
- info?: IUserInfo;
596
- };
597
-
598
- declare enum Permission {
599
- Read = "room:read",
600
- Write = "room:write",
601
- PresenceWrite = "room:presence:write",
602
- CommentsWrite = "comments:write",
603
- CommentsRead = "comments:read"
604
- }
605
- declare type LiveblocksPermissions = Record<string, Permission[]>;
606
- declare enum TokenKind {
607
- SECRET_LEGACY = "sec-legacy",
608
- ACCESS_TOKEN = "acc",
609
- ID_TOKEN = "id"
757
+ set<TKey extends keyof O>(key: TKey, value: O[TKey]): void;
758
+ /**
759
+ * Returns a specified property from the LiveObject.
760
+ * @param key The key of the property to get
761
+ */
762
+ get<TKey extends keyof O>(key: TKey): O[TKey];
763
+ /**
764
+ * Deletes a key from the LiveObject
765
+ * @param key The key of the property to delete
766
+ */
767
+ delete(key: keyof O): void;
768
+ /**
769
+ * Adds or updates multiple properties at once with an object.
770
+ * @param patch The object used to overrides properties
771
+ */
772
+ update(patch: Partial<O>): void;
773
+ toImmutable(): ToImmutable<O>;
774
+ clone(): LiveObject<O>;
610
775
  }
611
- declare type JwtMeta = {
612
- iat: number;
613
- exp: number;
614
- };
615
- /**
616
- * Legacy Secret Token.
617
- */
618
- declare type LegacySecretToken = {
619
- k: TokenKind.SECRET_LEGACY;
620
- roomId: string;
621
- scopes: string[];
622
- id?: string;
623
- info?: IUserInfo;
624
- [other: string]: Json | undefined;
625
- } & JwtMeta;
626
- /**
627
- * New authorization Access Token.
628
- */
629
- declare type AccessToken = {
630
- k: TokenKind.ACCESS_TOKEN;
631
- pid: string;
632
- uid: string;
633
- perms: LiveblocksPermissions;
634
- ui?: IUserInfo;
635
- } & JwtMeta;
636
- /**
637
- * New authorization ID Token.
638
- */
639
- declare type IDToken = {
640
- k: TokenKind.ID_TOKEN;
641
- pid: string;
642
- uid: string;
643
- gids?: string[];
644
- ui?: IUserInfo;
645
- } & JwtMeta;
646
- declare type AuthToken = AccessToken | IDToken | LegacySecretToken;
647
- declare type ParsedAuthToken = {
648
- readonly raw: string;
649
- readonly parsed: AuthToken;
650
- };
651
-
652
- declare type AuthValue = {
653
- type: "secret";
654
- token: ParsedAuthToken;
655
- } | {
656
- type: "public";
657
- publicApiKey: string;
658
- };
659
776
 
660
- declare type BaseMetadata = Record<string, string | boolean | number>;
661
-
662
- declare type CommentBodyBlockElement = CommentBodyParagraph;
663
- declare type CommentBodyInlineElement = CommentBodyText | CommentBodyMention | CommentBodyLink;
664
- declare type CommentBodyElement = CommentBodyBlockElement | CommentBodyInlineElement;
665
- declare type CommentBodyParagraph = {
666
- type: "paragraph";
667
- children: CommentBodyInlineElement[];
777
+ declare type DateToString<T> = {
778
+ [P in keyof T]: T[P] extends Date ? string : T[P] extends Date | null ? string | null : T[P] extends Date | undefined ? string | undefined : T[P];
668
779
  };
669
- declare type CommentBodyMention = {
670
- type: "mention";
780
+
781
+ declare type InboxNotificationThreadData = {
782
+ kind: "thread";
671
783
  id: string;
784
+ roomId: string;
785
+ threadId: string;
786
+ notifiedAt: Date;
787
+ readAt: Date | null;
672
788
  };
673
- declare type CommentBodyLink = {
674
- type: "link";
675
- url: string;
789
+ declare type InboxNotificationTextMentionData = {
790
+ kind: "textMention";
791
+ id: string;
792
+ roomId: string;
793
+ notifiedAt: Date;
794
+ readAt: Date | null;
795
+ createdBy: string;
796
+ mentionId: string;
797
+ };
798
+ declare type InboxNotificationTextMentionDataPlain = DateToString<InboxNotificationTextMentionData>;
799
+ declare type ActivityData = Record<string, string | boolean | number | undefined>;
800
+ declare type InboxNotificationActivity<K extends `$${string}` = `$${string}`> = {
801
+ id: string;
802
+ createdAt: Date;
803
+ data: K extends keyof DAD ? DAD[K] : ActivityData;
676
804
  };
677
- declare type CommentBodyText = {
678
- bold?: boolean;
679
- italic?: boolean;
680
- strikethrough?: boolean;
681
- code?: boolean;
682
- text: string;
805
+ declare type InboxNotificationCustomData<K extends `$${string}` = `$${string}`> = {
806
+ kind: `$${string}`;
807
+ id: string;
808
+ roomId?: string;
809
+ subjectId: string;
810
+ notifiedAt: Date;
811
+ readAt: Date | null;
812
+ activities: InboxNotificationActivity<K>[];
813
+ };
814
+ declare type InboxNotificationData = InboxNotificationThreadData | InboxNotificationCustomData | InboxNotificationTextMentionData;
815
+ declare type InboxNotificationThreadDataPlain = DateToString<InboxNotificationThreadData>;
816
+ declare type InboxNotificationCustomDataPlain = Omit<DateToString<InboxNotificationCustomData>, "activities"> & {
817
+ activities: DateToString<InboxNotificationActivity>[];
818
+ };
819
+ declare type InboxNotificationDataPlain = InboxNotificationThreadDataPlain | InboxNotificationCustomDataPlain | InboxNotificationTextMentionDataPlain;
820
+ declare type InboxNotificationDeleteInfo = {
821
+ type: "deletedInboxNotification";
822
+ id: string;
823
+ roomId: string;
824
+ deletedAt: Date;
683
825
  };
684
- declare type CommentBody = {
685
- version: 1;
686
- content: CommentBodyBlockElement[];
826
+
827
+ declare type BaseActivitiesData = {
828
+ [key: `$${string}`]: ActivityData;
687
829
  };
688
830
 
689
- declare type DateToString<T> = {
690
- [P in keyof T]: T[P] extends Date ? string : T[P];
831
+ declare type BaseRoomInfo = {
832
+ [key: string]: Json | undefined;
833
+ /**
834
+ * The name of the room.
835
+ */
836
+ name?: string;
837
+ /**
838
+ * The URL of the room.
839
+ */
840
+ url?: string;
691
841
  };
692
842
 
843
+ declare type BaseMetadata = Record<string, string | boolean | number | undefined>;
693
844
  declare type CommentReaction = {
694
845
  emoji: string;
695
846
  createdAt: Date;
@@ -716,8 +867,8 @@ declare type CommentData = {
716
867
  body?: never;
717
868
  deletedAt: Date;
718
869
  });
719
- declare type CommentDataPlain = Omit<DateToString<CommentData>, "reaction" | "body"> & {
720
- reactions: DateToString<CommentReaction[]>;
870
+ declare type CommentDataPlain = Omit<DateToString<CommentData>, "reactions" | "body"> & {
871
+ reactions: DateToString<CommentReaction>[];
721
872
  } & ({
722
873
  body: CommentBody;
723
874
  deletedAt?: never;
@@ -725,265 +876,139 @@ declare type CommentDataPlain = Omit<DateToString<CommentData>, "reaction" | "bo
725
876
  body?: never;
726
877
  deletedAt: string;
727
878
  });
728
-
729
- declare type CommentUserReaction = {
730
- emoji: string;
731
- createdAt: Date;
732
- userId: string;
879
+ declare type CommentBodyBlockElement = CommentBodyParagraph;
880
+ declare type CommentBodyInlineElement = CommentBodyText | CommentBodyMention | CommentBodyLink;
881
+ declare type CommentBodyElement = CommentBodyBlockElement | CommentBodyInlineElement;
882
+ declare type CommentBodyParagraph = {
883
+ type: "paragraph";
884
+ children: CommentBodyInlineElement[];
733
885
  };
734
- declare type CommentUserReactionPlain = DateToString<CommentUserReaction>;
735
-
736
- /**
737
- * Represents a thread of comments.
738
- */
739
- declare type ThreadData<TThreadMetadata extends BaseMetadata = never> = {
740
- type: "thread";
886
+ declare type CommentBodyMention = {
887
+ type: "mention";
741
888
  id: string;
742
- roomId: string;
743
- createdAt: Date;
744
- updatedAt?: Date;
745
- comments: CommentData[];
746
- metadata: [TThreadMetadata] extends [never] ? Record<string, never> : TThreadMetadata;
747
- };
748
- declare type ThreadDataPlain<TThreadMetadata extends BaseMetadata = never> = Omit<DateToString<ThreadData<TThreadMetadata>>, "comments" | "metadata"> & {
749
- comments: CommentDataPlain[];
750
- metadata: [TThreadMetadata] extends [never] ? Record<string, never> : TThreadMetadata;
751
889
  };
752
-
753
- declare type Options = {
754
- baseUrl: string;
755
- };
756
- declare type PartialNullable<T> = {
757
- [P in keyof T]?: T[P] | null | undefined;
758
- };
759
- declare type ThreadsFilterOptions<TThreadMetadata extends BaseMetadata> = {
760
- query?: {
761
- metadata?: Partial<TThreadMetadata>;
762
- };
890
+ declare type CommentBodyLink = {
891
+ type: "link";
892
+ url: string;
763
893
  };
764
- declare type CommentsApi<TThreadMetadata extends BaseMetadata> = {
765
- getThreads(options?: ThreadsFilterOptions<TThreadMetadata>): Promise<ThreadData<TThreadMetadata>[]>;
766
- createThread(options: {
767
- threadId: string;
768
- commentId: string;
769
- metadata: TThreadMetadata | undefined;
770
- body: CommentBody;
771
- }): Promise<ThreadData<TThreadMetadata>>;
772
- editThreadMetadata(options: {
773
- metadata: PartialNullable<TThreadMetadata>;
774
- threadId: string;
775
- }): Promise<TThreadMetadata>;
776
- createComment(options: {
777
- threadId: string;
778
- commentId: string;
779
- body: CommentBody;
780
- }): Promise<CommentData>;
781
- editComment(options: {
782
- threadId: string;
783
- commentId: string;
784
- body: CommentBody;
785
- }): Promise<CommentData>;
786
- deleteComment(options: {
787
- threadId: string;
788
- commentId: string;
789
- }): Promise<void>;
790
- addReaction(options: {
791
- threadId: string;
792
- commentId: string;
793
- emoji: string;
794
- }): Promise<CommentUserReaction>;
795
- removeReaction(options: {
796
- threadId: string;
797
- commentId: string;
798
- emoji: string;
799
- }): Promise<void>;
894
+ declare type CommentBodyText = {
895
+ bold?: boolean;
896
+ italic?: boolean;
897
+ strikethrough?: boolean;
898
+ code?: boolean;
899
+ text: string;
800
900
  };
801
- declare class CommentsApiError extends Error {
802
- message: string;
803
- status: number;
804
- details?: JsonObject | undefined;
805
- constructor(message: string, status: number, details?: JsonObject | undefined);
806
- }
807
- declare function createCommentsApi<TThreadMetadata extends BaseMetadata>(roomId: string, getAuthValue: () => Promise<AuthValue>, config: Options): CommentsApi<TThreadMetadata>;
808
-
809
- declare type Callback<T> = (event: T) => void;
810
- declare type UnsubscribeCallback = () => void;
811
- declare type Observable<T> = {
812
- /**
813
- * Register a callback function to be called whenever the event source emits
814
- * an event.
815
- */
816
- subscribe(callback: Callback<T>): UnsubscribeCallback;
817
- /**
818
- * Register a one-time callback function to be called whenever the event
819
- * source emits an event. After the event fires, the callback is
820
- * auto-unsubscribed.
821
- */
822
- subscribeOnce(callback: Callback<T>): UnsubscribeCallback;
823
- /**
824
- * Returns a promise that will resolve when an event is emitted by this
825
- * event source. Optionally, specify a predicate that has to match. The first
826
- * event matching that predicate will then resolve the promise.
827
- */
828
- waitUntil(predicate?: (event: T) => boolean): Promise<T>;
901
+ declare type CommentBody = {
902
+ version: 1;
903
+ content: CommentBodyBlockElement[];
829
904
  };
830
- declare type EventSource<T> = Observable<T> & {
831
- /**
832
- * Notify all subscribers about the event.
833
- */
834
- notify(event: T): void;
835
- /**
836
- * Clear all registered event listeners. None of the registered functions
837
- * will ever get called again. Be careful when using this API, because the
838
- * subscribers may not have any idea they won't be notified anymore.
839
- */
840
- clear(): void;
841
- /**
842
- * Returns the number of active subscribers.
843
- */
844
- count(): number;
845
- /**
846
- * Pauses event delivery until unpaused. Any .notify() calls made while
847
- * paused will get buffered into memory and emitted later.
848
- */
849
- pause(): void;
850
- /**
851
- * Emits all in-memory buffered events, and unpauses. Any .notify() calls
852
- * made after this will be synchronously delivered again.
853
- */
854
- unpause(): void;
855
- /**
856
- * Observable instance, which can be used to subscribe to this event source
857
- * in a readonly fashion. Safe to publicly expose.
858
- */
859
- observable: Observable<T>;
905
+ declare type CommentUserReaction = {
906
+ emoji: string;
907
+ createdAt: Date;
908
+ userId: string;
860
909
  };
910
+ declare type CommentUserReactionPlain = DateToString<CommentUserReaction>;
861
911
  /**
862
- * makeEventSource allows you to generate a subscribe/notify pair of functions
863
- * to make subscribing easy and to get notified about events.
864
- *
865
- * The events are anonymous, so you can use it to define events, like so:
866
- *
867
- * const event1 = makeEventSource();
868
- * const event2 = makeEventSource();
869
- *
870
- * event1.subscribe(foo);
871
- * event1.subscribe(bar);
872
- * event2.subscribe(qux);
873
- *
874
- * // Unsubscription is pretty standard
875
- * const unsub = event2.subscribe(foo);
876
- * unsub();
877
- *
878
- * event1.notify(); // Now foo and bar will get called
879
- * event2.notify(); // Now qux will get called (but foo will not, since it's unsubscribed)
880
- *
912
+ * Represents a thread of comments.
881
913
  */
882
- declare function makeEventSource<T>(): EventSource<T>;
883
-
884
- interface IWebSocketEvent {
885
- type: string;
886
- }
887
- interface IWebSocketCloseEvent extends IWebSocketEvent {
888
- readonly code: WebsocketCloseCodes;
889
- readonly wasClean: boolean;
890
- readonly reason: string;
891
- }
892
- interface IWebSocketMessageEvent extends IWebSocketEvent {
893
- readonly data: string | Buffer | ArrayBuffer | readonly Buffer[];
894
- }
895
- interface IWebSocketInstance {
896
- readonly CONNECTING: number;
897
- readonly OPEN: number;
898
- readonly CLOSING: number;
899
- readonly CLOSED: number;
900
- readonly readyState: number;
901
- addEventListener(type: "close", listener: (this: IWebSocketInstance, ev: IWebSocketCloseEvent) => unknown): void;
902
- addEventListener(type: "message", listener: (this: IWebSocketInstance, ev: IWebSocketMessageEvent) => unknown): void;
903
- addEventListener(type: "open" | "error", listener: (this: IWebSocketInstance, ev: IWebSocketEvent) => unknown): void;
904
- removeEventListener(type: "close", listener: (this: IWebSocketInstance, ev: IWebSocketCloseEvent) => unknown): void;
905
- removeEventListener(type: "message", listener: (this: IWebSocketInstance, ev: IWebSocketMessageEvent) => unknown): void;
906
- removeEventListener(type: "open" | "error", listener: (this: IWebSocketInstance, ev: IWebSocketEvent) => unknown): void;
907
- close(): void;
908
- send(data: string): void;
914
+ declare type ThreadData<M extends BaseMetadata = DM> = {
915
+ type: "thread";
916
+ id: string;
917
+ roomId: string;
918
+ createdAt: Date;
919
+ updatedAt?: Date;
920
+ comments: CommentData[];
921
+ metadata: M;
922
+ };
923
+ interface ThreadDataWithDeleteInfo<M extends BaseMetadata = DM> extends ThreadData<M> {
924
+ deletedAt?: Date;
909
925
  }
926
+ declare type ThreadDataPlain<M extends BaseMetadata> = Omit<DateToString<ThreadData<M>>, "comments" | "metadata"> & {
927
+ comments: CommentDataPlain[];
928
+ metadata: M;
929
+ };
930
+ declare type ThreadDeleteInfo = {
931
+ type: "deletedThread";
932
+ id: string;
933
+ roomId: string;
934
+ deletedAt: Date;
935
+ };
936
+ declare type StringOperators<T> = T | {
937
+ startsWith: string;
938
+ };
910
939
  /**
911
- * Either the browser-based WebSocket API or Node.js' WebSocket API (from the
912
- * 'ws' package).
940
+ * This type can be used to build a metadata query string (compatible
941
+ * with `@liveblocks/query-parser`) through a type-safe API.
913
942
  *
914
- * This type defines the minimal WebSocket API that Liveblocks needs from
915
- * a WebSocket implementation, and is a minimal subset of the browser-based
916
- * WebSocket APIs and Node.js' WebSocket API so that both implementations are
917
- * assignable to this type.
943
+ * In addition to exact values (`:` in query string), it adds:
944
+ * - to strings:
945
+ * - `startsWith` (`^` in query string)
918
946
  */
919
- interface IWebSocket {
920
- new (address: string): IWebSocketInstance;
947
+ declare type QueryMetadata<M extends BaseMetadata> = {
948
+ [K in keyof M]: string extends M[K] ? StringOperators<M[K]> : M[K];
949
+ };
950
+
951
+ declare global {
952
+ /**
953
+ * Namespace for user-defined Liveblocks types.
954
+ */
955
+ export interface Liveblocks {
956
+ [key: string]: unknown;
957
+ }
921
958
  }
959
+ declare type ExtendableTypes = "Presence" | "Storage" | "UserMeta" | "RoomEvent" | "ThreadMetadata" | "RoomInfo" | "ActivitiesData";
960
+ declare type ExtendedType<K extends ExtendableTypes, B, ErrorReason extends string = "does not match its requirements"> = unknown extends Liveblocks[K] ? B : Liveblocks[K] extends B ? Liveblocks[K] : `The type you provided for '${K}' ${ErrorReason}. To learn how to fix this, see https://liveblocks.io/docs/errors/${K}`;
961
+ declare type DP = ExtendedType<"Presence", JsonObject, "is not a valid JSON object">;
962
+ declare type DS = ExtendedType<"Storage", LsonObject, "is not a valid LSON value">;
963
+ declare type DU = ExtendedType<"UserMeta", BaseUserMeta>;
964
+ declare type DE = ExtendedType<"RoomEvent", Json, "is not a valid JSON value">;
965
+ declare type DM = ExtendedType<"ThreadMetadata", BaseMetadata>;
966
+ declare type DRI = ExtendedType<"RoomInfo", BaseRoomInfo>;
967
+ declare type DAD = ExtendedType<"ActivitiesData", BaseActivitiesData>;
968
+
922
969
  /**
923
- * The following ranges will be respected by the client:
924
- *
925
- * 40xx: client will disconnect
926
- * 41xx: client will reauthorize
927
- * 42xx: client will retry without reauthorizing (currently not used)
970
+ * Use this symbol to brand an object property as internal.
928
971
  *
972
+ * @example
973
+ * Object.defineProperty(
974
+ * {
975
+ * public,
976
+ * [kInternal]: {
977
+ * private
978
+ * },
979
+ * },
980
+ * kInternal,
981
+ * {
982
+ * enumerable: false,
983
+ * }
984
+ * );
929
985
  */
930
- declare enum WebsocketCloseCodes {
931
- /** Unexpected error happened with the network/infra level. In spirit akin to HTTP 503 */
932
- CLOSE_ABNORMAL = 1006,
933
- /** Unexpected error happened. In spirit akin to HTTP 500 */
934
- UNEXPECTED_CONDITION = 1011,
935
- /** Please back off for now, but try again in a few moments */
936
- TRY_AGAIN_LATER = 1013,
937
- /** Message wasn't understood, disconnect */
938
- INVALID_MESSAGE_FORMAT = 4000,
939
- /** Server refused to allow connection. Re-authorizing won't help. Disconnect. In spirit akin to HTTP 403 */
940
- NOT_ALLOWED = 4001,
941
- /** Unused */
942
- MAX_NUMBER_OF_MESSAGES_PER_SECONDS = 4002,
943
- /** Unused */
944
- MAX_NUMBER_OF_CONCURRENT_CONNECTIONS = 4003,
945
- /** Unused */
946
- MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP = 4004,
947
- /** Room is full, disconnect */
948
- MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM = 4005,
949
- /** The auth token is expired, reauthorize to get a fresh one. In spirit akin to HTTP 401 */
950
- TOKEN_EXPIRED = 4109,
951
- /** Disconnect immediately */
952
- CLOSE_WITHOUT_RETRY = 4999
953
- }
986
+ declare const kInternal: unique symbol;
954
987
 
955
988
  /**
956
- * Old connection statuses, here for backward-compatibility reasons only.
957
- */
958
- declare type LegacyConnectionStatus = "closed" | "authenticating" | "connecting" | "open" | "unavailable" | "failed";
959
- /**
960
- * Returns a human-readable status indicating the current connection status of
961
- * a Room, as returned by `room.getStatus()`. Can be used to implement
962
- * a connection status badge.
963
- */
964
- declare type Status = "initial" | "connecting" | "connected" | "reconnecting" | "disconnected";
965
- /**
966
- * Used to report about app-level reconnection issues.
989
+ * This helper type is effectively a no-op, but will force TypeScript to
990
+ * "evaluate" any named helper types in its definition. This can sometimes make
991
+ * API signatures clearer in IDEs.
967
992
  *
968
- * Normal (quick) reconnects won't be reported as a "lost connection". Instead,
969
- * the application will only get an event if the reconnection attempts by the
970
- * client are taking (much) longer than usual. Definitely a situation you want
971
- * to inform your users about, for example, by throwing a toast message on
972
- * screen, or show a "trying to reconnect" banner.
973
- */
974
- declare type LostConnectionEvent = "lost" | "restored" | "failed";
975
- /**
976
- * Arbitrary record that will be used as the authentication "authValue". It's the
977
- * value that is returned by calling the authentication delegate, and will get
978
- * passed to the connection factory delegate. This value will be remembered by
979
- * the connection manager, but its value will not be interpreted, so it can be
980
- * any value (except null).
993
+ * For example, in:
994
+ *
995
+ * type Payload<T> = { data: T };
996
+ *
997
+ * let r1: Payload<string>;
998
+ * let r2: Resolve<Payload<string>>;
999
+ *
1000
+ * The inferred type of `r1` is going to be `Payload<string>` which shows up in
1001
+ * editor hints, and it may be unclear what's inside if you don't know the
1002
+ * definition of `Payload`.
1003
+ *
1004
+ * The inferred type of `r2` is going to be `{ data: string }`, which may be
1005
+ * more helpful.
1006
+ *
1007
+ * This trick comes from:
1008
+ * https://effectivetypescript.com/2022/02/25/gentips-4-display/
981
1009
  */
982
- declare type BaseAuthResult = NonNullable<Json>;
983
- declare type Delegates<T extends BaseAuthResult> = {
984
- authenticate: () => Promise<T>;
985
- createSocket: (authValue: T) => IWebSocketInstance;
986
- canZombie: () => boolean;
1010
+ declare type Resolve<T> = T extends (...args: unknown[]) => unknown ? T : {
1011
+ [K in keyof T]: T[K];
987
1012
  };
988
1013
 
989
1014
  declare enum ClientMsgCode {
@@ -997,12 +1022,12 @@ declare enum ClientMsgCode {
997
1022
  /**
998
1023
  * Messages that can be sent from the client to the server.
999
1024
  */
1000
- declare type ClientMsg<TPresence extends JsonObject, TRoomEvent extends Json> = BroadcastEventClientMsg<TRoomEvent> | UpdatePresenceClientMsg<TPresence> | UpdateStorageClientMsg | FetchStorageClientMsg | FetchYDocClientMsg | UpdateYDocClientMsg;
1001
- declare type BroadcastEventClientMsg<TRoomEvent extends Json> = {
1025
+ declare type ClientMsg<P extends JsonObject, E extends Json> = BroadcastEventClientMsg<E> | UpdatePresenceClientMsg<P> | UpdateStorageClientMsg | FetchStorageClientMsg | FetchYDocClientMsg | UpdateYDocClientMsg;
1026
+ declare type BroadcastEventClientMsg<E extends Json> = {
1002
1027
  type: ClientMsgCode.BROADCAST_EVENT;
1003
- event: TRoomEvent;
1028
+ event: E;
1004
1029
  };
1005
- declare type UpdatePresenceClientMsg<TPresence extends JsonObject> = {
1030
+ declare type UpdatePresenceClientMsg<P extends JsonObject> = {
1006
1031
  readonly type: ClientMsgCode.UPDATE_PRESENCE;
1007
1032
  /**
1008
1033
  * Set this to any number to signify that this is a Full Presence™
@@ -1018,7 +1043,7 @@ declare type UpdatePresenceClientMsg<TPresence extends JsonObject> = {
1018
1043
  * all presence fields, and isn't a partial "patch".
1019
1044
  */
1020
1045
  readonly targetActor: number;
1021
- readonly data: TPresence;
1046
+ readonly data: P;
1022
1047
  } | {
1023
1048
  readonly type: ClientMsgCode.UPDATE_PRESENCE;
1024
1049
  /**
@@ -1026,7 +1051,7 @@ declare type UpdatePresenceClientMsg<TPresence extends JsonObject> = {
1026
1051
  * Presence™ "patch".
1027
1052
  */
1028
1053
  readonly targetActor?: undefined;
1029
- readonly data: Partial<TPresence>;
1054
+ readonly data: Partial<P>;
1030
1055
  };
1031
1056
  declare type UpdateStorageClientMsg = {
1032
1057
  readonly type: ClientMsgCode.UPDATE_STORAGE;
@@ -1107,7 +1132,7 @@ declare enum ServerMsgCode {
1107
1132
  /**
1108
1133
  * Messages that can be sent from the server to the client.
1109
1134
  */
1110
- declare type ServerMsg<TPresence extends JsonObject, TUserMeta extends BaseUserMeta, TRoomEvent extends Json> = UpdatePresenceServerMsg<TPresence> | UserJoinServerMsg<TUserMeta> | UserLeftServerMsg | BroadcastedEventServerMsg<TRoomEvent> | RoomStateServerMsg<TUserMeta> | InitialDocumentStateServerMsg | UpdateStorageServerMsg | RejectedStorageOpServerMsg | YDocUpdateServerMsg | CommentsEventServerMsg;
1135
+ declare type ServerMsg<P extends JsonObject, U extends BaseUserMeta, E extends Json> = UpdatePresenceServerMsg<P> | UserJoinServerMsg<U> | UserLeftServerMsg | BroadcastedEventServerMsg<E> | RoomStateServerMsg<U> | InitialDocumentStateServerMsg | UpdateStorageServerMsg | RejectedStorageOpServerMsg | YDocUpdateServerMsg | CommentsEventServerMsg;
1111
1136
  declare type CommentsEventServerMsg = ThreadCreatedEvent | ThreadMetadataUpdatedEvent | CommentCreatedEvent | CommentEditedEvent | CommentDeletedEvent | CommentReactionAdded | CommentReactionRemoved;
1112
1137
  declare type ThreadCreatedEvent = {
1113
1138
  type: ServerMsgCode.THREAD_CREATED;
@@ -1155,7 +1180,7 @@ declare type CommentReactionRemoved = {
1155
1180
  * those cases, the `targetActor` field indicates the newly connected client,
1156
1181
  * so all other existing clients can ignore this broadcasted message.
1157
1182
  */
1158
- declare type UpdatePresenceServerMsg<TPresence extends JsonObject> = {
1183
+ declare type UpdatePresenceServerMsg<P extends JsonObject> = {
1159
1184
  readonly type: ServerMsgCode.UPDATE_PRESENCE;
1160
1185
  /**
1161
1186
  * The User whose Presence has changed.
@@ -1179,7 +1204,7 @@ declare type UpdatePresenceServerMsg<TPresence extends JsonObject> = {
1179
1204
  * this will be the full Presence, otherwise it only contain the fields that
1180
1205
  * have changed since the last broadcast.
1181
1206
  */
1182
- readonly data: TPresence;
1207
+ readonly data: P;
1183
1208
  } | {
1184
1209
  readonly type: ServerMsgCode.UPDATE_PRESENCE;
1185
1210
  /**
@@ -1194,25 +1219,25 @@ declare type UpdatePresenceServerMsg<TPresence extends JsonObject> = {
1194
1219
  * A partial Presence patch to apply to the User. It will only contain the
1195
1220
  * fields that have changed since the last broadcast.
1196
1221
  */
1197
- readonly data: Partial<TPresence>;
1222
+ readonly data: Partial<P>;
1198
1223
  };
1199
1224
  /**
1200
1225
  * Sent by the WebSocket server and broadcasted to all clients to announce that
1201
1226
  * a new User has joined the Room.
1202
1227
  */
1203
- declare type UserJoinServerMsg<TUserMeta extends BaseUserMeta> = {
1228
+ declare type UserJoinServerMsg<U extends BaseUserMeta> = {
1204
1229
  readonly type: ServerMsgCode.USER_JOINED;
1205
1230
  readonly actor: number;
1206
1231
  /**
1207
1232
  * The id of the User that has been set in the authentication endpoint.
1208
1233
  * Useful to get additional information about the connected user.
1209
1234
  */
1210
- readonly id: TUserMeta["id"];
1235
+ readonly id: U["id"];
1211
1236
  /**
1212
1237
  * Additional user information that has been set in the authentication
1213
1238
  * endpoint.
1214
1239
  */
1215
- readonly info: TUserMeta["info"];
1240
+ readonly info: U["info"];
1216
1241
  /**
1217
1242
  * Informs the client what (public) permissions this (other) User has.
1218
1243
  */
@@ -1241,7 +1266,7 @@ declare type YDocUpdateServerMsg = {
1241
1266
  * Sent by the WebSocket server and broadcasted to all clients to announce that
1242
1267
  * a User broadcasted an Event to everyone in the Room.
1243
1268
  */
1244
- declare type BroadcastedEventServerMsg<TRoomEvent extends Json> = {
1269
+ declare type BroadcastedEventServerMsg<E extends Json> = {
1245
1270
  readonly type: ServerMsgCode.BROADCASTED_EVENT;
1246
1271
  /**
1247
1272
  * The User who broadcast the Event. Absent when this event is broadcast from
@@ -1252,14 +1277,14 @@ declare type BroadcastedEventServerMsg<TRoomEvent extends Json> = {
1252
1277
  * The arbitrary payload of the Event. This can be any JSON value. Clients
1253
1278
  * will have to manually verify/decode this event.
1254
1279
  */
1255
- readonly event: TRoomEvent;
1280
+ readonly event: E;
1256
1281
  };
1257
1282
  /**
1258
1283
  * Sent by the WebSocket server to a single client in response to the client
1259
1284
  * joining the Room, to provide the initial state of the Room. The payload
1260
1285
  * includes a list of all other Users that already are in the Room.
1261
1286
  */
1262
- declare type RoomStateServerMsg<TUserMeta extends BaseUserMeta> = {
1287
+ declare type RoomStateServerMsg<U extends BaseUserMeta> = {
1263
1288
  readonly type: ServerMsgCode.ROOM_STATE;
1264
1289
  /**
1265
1290
  * Informs the client what their actor ID is going to be.
@@ -1277,7 +1302,7 @@ declare type RoomStateServerMsg<TUserMeta extends BaseUserMeta> = {
1277
1302
  */
1278
1303
  readonly scopes: string[];
1279
1304
  readonly users: {
1280
- readonly [otherActor: number]: TUserMeta & {
1305
+ readonly [otherActor: number]: U & {
1281
1306
  scopes: string[];
1282
1307
  };
1283
1308
  };
@@ -1313,10 +1338,54 @@ declare type RejectedStorageOpServerMsg = {
1313
1338
  readonly reason: string;
1314
1339
  };
1315
1340
 
1341
+ declare type JsonTreeNode = {
1342
+ readonly type: "Json";
1343
+ readonly id: string;
1344
+ readonly key: string;
1345
+ readonly payload: Json;
1346
+ };
1347
+ declare type LiveTreeNode<TName extends `Live${string}` = `Live${string}`> = {
1348
+ readonly type: TName;
1349
+ readonly id: string;
1350
+ readonly key: string;
1351
+ readonly payload: LsonTreeNode[];
1352
+ };
1353
+ declare type LsonTreeNode = LiveTreeNode | JsonTreeNode;
1354
+ declare type UserTreeNode = {
1355
+ readonly type: "User";
1356
+ readonly id: string;
1357
+ readonly key: string;
1358
+ readonly payload: {
1359
+ readonly connectionId: number;
1360
+ readonly id?: string;
1361
+ readonly info?: Json;
1362
+ readonly presence: JsonObject;
1363
+ readonly isReadOnly: boolean;
1364
+ };
1365
+ };
1366
+ declare type CustomEventTreeNode = {
1367
+ readonly type: "CustomEvent";
1368
+ readonly id: string;
1369
+ readonly key: string;
1370
+ readonly connectionId: number;
1371
+ readonly payload: Json;
1372
+ };
1373
+ declare type TreeNode = LsonTreeNode | UserTreeNode | CustomEventTreeNode;
1374
+
1375
+ type DevToolsTreeNode_CustomEventTreeNode = CustomEventTreeNode;
1376
+ type DevToolsTreeNode_JsonTreeNode = JsonTreeNode;
1377
+ type DevToolsTreeNode_LiveTreeNode<TName extends `Live${string}` = `Live${string}`> = LiveTreeNode<TName>;
1378
+ type DevToolsTreeNode_LsonTreeNode = LsonTreeNode;
1379
+ type DevToolsTreeNode_TreeNode = TreeNode;
1380
+ type DevToolsTreeNode_UserTreeNode = UserTreeNode;
1381
+ declare namespace DevToolsTreeNode {
1382
+ export type { DevToolsTreeNode_CustomEventTreeNode as CustomEventTreeNode, DevToolsTreeNode_JsonTreeNode as JsonTreeNode, DevToolsTreeNode_LiveTreeNode as LiveTreeNode, DevToolsTreeNode_LsonTreeNode as LsonTreeNode, DevToolsTreeNode_TreeNode as TreeNode, DevToolsTreeNode_UserTreeNode as UserTreeNode };
1383
+ }
1384
+
1316
1385
  /**
1317
1386
  * Represents a user connected in a room. Treated as immutable.
1318
1387
  */
1319
- declare type User<TPresence extends JsonObject, TUserMeta extends BaseUserMeta> = {
1388
+ declare type User<P extends JsonObject = DP, U extends BaseUserMeta = DU> = {
1320
1389
  /**
1321
1390
  * The connection ID of the User. It is unique and increment at every new connection.
1322
1391
  */
@@ -1325,21 +1394,15 @@ declare type User<TPresence extends JsonObject, TUserMeta extends BaseUserMeta>
1325
1394
  * The ID of the User that has been set in the authentication endpoint.
1326
1395
  * Useful to get additional information about the connected user.
1327
1396
  */
1328
- readonly id: TUserMeta["id"];
1397
+ readonly id: U["id"];
1329
1398
  /**
1330
1399
  * Additional user information that has been set in the authentication endpoint.
1331
1400
  */
1332
- readonly info: TUserMeta["info"];
1401
+ readonly info: U["info"];
1333
1402
  /**
1334
1403
  * The user’s presence data.
1335
1404
  */
1336
- readonly presence: TPresence;
1337
- /**
1338
- * @deprecated Use `!user.canWrite` instead.
1339
- * False if the user can mutate the Room’s Storage and/or YDoc, true if they
1340
- * can only read but not mutate it.
1341
- */
1342
- readonly isReadOnly: boolean;
1405
+ readonly presence: P;
1343
1406
  /**
1344
1407
  * True if the user can mutate the Room’s Storage and/or YDoc, false if they
1345
1408
  * can only read but not mutate it.
@@ -1351,42 +1414,52 @@ declare type User<TPresence extends JsonObject, TUserMeta extends BaseUserMeta>
1351
1414
  readonly canComment: boolean;
1352
1415
  };
1353
1416
 
1354
- /**
1355
- * @deprecated Use `readonly User<TPresence, TUserMeta>[]` instead of `Others<TPresence, TUserMeta>`.
1356
- */
1357
- declare type Others<TPresence extends JsonObject, TUserMeta extends BaseUserMeta> = readonly User<TPresence, TUserMeta>[];
1358
- declare type InternalOthersEvent<TPresence extends JsonObject, TUserMeta extends BaseUserMeta> = {
1417
+ declare type InternalOthersEvent<P extends JsonObject, U extends BaseUserMeta> = {
1359
1418
  type: "leave";
1360
- user: User<TPresence, TUserMeta>;
1419
+ user: User<P, U>;
1361
1420
  } | {
1362
1421
  type: "enter";
1363
- user: User<TPresence, TUserMeta>;
1422
+ user: User<P, U>;
1364
1423
  } | {
1365
1424
  type: "update";
1366
- user: User<TPresence, TUserMeta>;
1367
- updates: Partial<TPresence>;
1425
+ user: User<P, U>;
1426
+ updates: Partial<P>;
1368
1427
  } | {
1369
1428
  type: "reset";
1429
+ user?: never;
1370
1430
  };
1371
- declare type OthersEvent<TPresence extends JsonObject, TUserMeta extends BaseUserMeta> = Resolve<InternalOthersEvent<TPresence, TUserMeta> & {
1372
- others: readonly User<TPresence, TUserMeta>[];
1431
+ declare type OthersEvent<P extends JsonObject = DP, U extends BaseUserMeta = DU> = Resolve<InternalOthersEvent<P, U> & {
1432
+ others: readonly User<P, U>[];
1373
1433
  }>;
1374
1434
 
1375
- declare type LegacyOthersEvent<TPresence extends JsonObject, TUserMeta extends BaseUserMeta> = {
1435
+ declare type OptionalKeys<T> = {
1436
+ [K in keyof T]-?: undefined extends T[K] ? K : never;
1437
+ }[keyof T];
1438
+ declare type MakeOptionalFieldsNullable<T> = {
1439
+ [K in keyof T]: K extends OptionalKeys<T> ? T[K] | null : T[K];
1440
+ };
1441
+ declare type Patchable<T> = Partial<MakeOptionalFieldsNullable<T>>;
1442
+
1443
+ declare type RoomThreadsNotificationSettings = "all" | "replies_and_mentions" | "none";
1444
+ declare type RoomNotificationSettings = {
1445
+ threads: RoomThreadsNotificationSettings;
1446
+ };
1447
+
1448
+ declare type LegacyOthersEvent<P extends JsonObject, U extends BaseUserMeta> = {
1376
1449
  type: "leave";
1377
- user: User<TPresence, TUserMeta>;
1450
+ user: User<P, U>;
1378
1451
  } | {
1379
1452
  type: "enter";
1380
- user: User<TPresence, TUserMeta>;
1453
+ user: User<P, U>;
1381
1454
  } | {
1382
1455
  type: "update";
1383
- user: User<TPresence, TUserMeta>;
1384
- updates: Partial<TPresence>;
1456
+ user: User<P, U>;
1457
+ updates: Partial<P>;
1385
1458
  } | {
1386
1459
  type: "reset";
1387
1460
  };
1388
- declare type LegacyOthersEventCallback<TPresence extends JsonObject, TUserMeta extends BaseUserMeta> = (others: readonly User<TPresence, TUserMeta>[], event: LegacyOthersEvent<TPresence, TUserMeta>) => void;
1389
- declare type RoomEventMessage<TPresence extends JsonObject, TUserMeta extends BaseUserMeta, TRoomEvent extends Json> = {
1461
+ declare type LegacyOthersEventCallback<P extends JsonObject, U extends BaseUserMeta> = (others: readonly User<P, U>[], event: LegacyOthersEvent<P, U>) => void;
1462
+ declare type RoomEventMessage<P extends JsonObject, U extends BaseUserMeta, E extends Json> = {
1390
1463
  /**
1391
1464
  * The connection ID of the client that sent the event.
1392
1465
  * If this message was broadcast from the server (via the REST API), then
@@ -1398,8 +1471,8 @@ declare type RoomEventMessage<TPresence extends JsonObject, TUserMeta extends Ba
1398
1471
  * If this message was broadcast from the server (via the REST API), then
1399
1472
  * this value will be null.
1400
1473
  */
1401
- user: User<TPresence, TUserMeta> | null;
1402
- event: TRoomEvent;
1474
+ user: User<P, U> | null;
1475
+ event: E;
1403
1476
  };
1404
1477
  declare type StorageStatus = "not-loaded" | "loading" | "synchronizing" | "synchronized";
1405
1478
  interface History {
@@ -1491,7 +1564,7 @@ declare type BroadcastOptions = {
1491
1564
  */
1492
1565
  shouldQueueEventIfNotReady: boolean;
1493
1566
  };
1494
- declare type SubscribeFn<TPresence extends JsonObject, _TStorage extends LsonObject, TUserMeta extends BaseUserMeta, TRoomEvent extends Json> = {
1567
+ declare type SubscribeFn<P extends JsonObject, _TStorage extends LsonObject, U extends BaseUserMeta, E extends Json> = {
1495
1568
  /**
1496
1569
  * Subscribe to the current user presence updates.
1497
1570
  *
@@ -1504,7 +1577,7 @@ declare type SubscribeFn<TPresence extends JsonObject, _TStorage extends LsonObj
1504
1577
  * // Do something
1505
1578
  * });
1506
1579
  */
1507
- (type: "my-presence", listener: Callback<TPresence>): () => void;
1580
+ (type: "my-presence", listener: Callback<P>): () => void;
1508
1581
  /**
1509
1582
  * Subscribe to the other users updates.
1510
1583
  *
@@ -1518,7 +1591,7 @@ declare type SubscribeFn<TPresence extends JsonObject, _TStorage extends LsonObj
1518
1591
  * });
1519
1592
  *
1520
1593
  */
1521
- (type: "others", listener: LegacyOthersEventCallback<TPresence, TUserMeta>): () => void;
1594
+ (type: "others", listener: LegacyOthersEventCallback<P, U>): () => void;
1522
1595
  /**
1523
1596
  * Subscribe to events broadcasted by {@link Room.broadcastEvent}
1524
1597
  *
@@ -1531,39 +1604,15 @@ declare type SubscribeFn<TPresence extends JsonObject, _TStorage extends LsonObj
1531
1604
  * // Do something
1532
1605
  * });
1533
1606
  *
1534
- */
1535
- (type: "event", listener: Callback<RoomEventMessage<TPresence, TUserMeta, TRoomEvent>>): () => void;
1536
- /**
1537
- * Subscribe to errors thrown in the room.
1538
- *
1539
- * @returns Unsubscribe function.
1540
- *
1541
- */
1542
- (type: "error", listener: ErrorCallback): () => void;
1543
- /**
1544
- * @deprecated This API will be removed in a future version of Liveblocks.
1545
- * Prefer using the newer `.subscribe('status')` API.
1546
- *
1547
- * We recommend making the following changes if you use these APIs:
1548
- *
1549
- * OLD APIs NEW APIs
1550
- * .getConnectionState() --> .getStatus()
1551
- * .subscribe('connection') --> .subscribe('status')
1552
- *
1553
- * OLD STATUSES NEW STATUSES
1554
- * closed --> initial
1555
- * authenticating --> connecting
1556
- * connecting --> connecting
1557
- * open --> connected
1558
- * unavailable --> reconnecting
1559
- * failed --> disconnected
1560
- *
1561
- * Subscribe to legacy connection status updates.
1607
+ */
1608
+ (type: "event", listener: Callback<RoomEventMessage<P, U, E>>): () => void;
1609
+ /**
1610
+ * Subscribe to errors thrown in the room.
1562
1611
  *
1563
1612
  * @returns Unsubscribe function.
1564
1613
  *
1565
1614
  */
1566
- (type: "connection", listener: Callback<LegacyConnectionStatus>): () => void;
1615
+ (type: "error", listener: Callback<LiveblocksError>): () => void;
1567
1616
  /**
1568
1617
  * Subscribe to connection status updates. The callback will be called any
1569
1618
  * time the status changes.
@@ -1648,36 +1697,88 @@ declare type SubscribeFn<TPresence extends JsonObject, _TStorage extends LsonObj
1648
1697
  */
1649
1698
  (type: "storage-status", listener: Callback<StorageStatus>): () => void;
1650
1699
  };
1651
- declare type Room<TPresence extends JsonObject, TStorage extends LsonObject, TUserMeta extends BaseUserMeta, TRoomEvent extends Json> = CommentsApi<any> & {
1700
+ declare type GetThreadsOptions<M extends BaseMetadata> = {
1701
+ query?: {
1702
+ metadata?: Partial<QueryMetadata<M>>;
1703
+ };
1704
+ since?: Date;
1705
+ };
1706
+ declare type CommentsApi<M extends BaseMetadata> = {
1707
+ getThreads(options?: GetThreadsOptions<M>): Promise<{
1708
+ threads: ThreadData<M>[];
1709
+ inboxNotifications: InboxNotificationData[];
1710
+ deletedThreads: ThreadDeleteInfo[];
1711
+ deletedInboxNotifications: InboxNotificationDeleteInfo[];
1712
+ meta: {
1713
+ requestedAt: Date;
1714
+ };
1715
+ }>;
1716
+ getThread(options: {
1717
+ threadId: string;
1718
+ }): Promise<{
1719
+ thread: ThreadData<M>;
1720
+ inboxNotification?: InboxNotificationData;
1721
+ } | undefined>;
1722
+ createThread(options: {
1723
+ threadId: string;
1724
+ commentId: string;
1725
+ metadata: M | undefined;
1726
+ body: CommentBody;
1727
+ }): Promise<ThreadData<M>>;
1728
+ editThreadMetadata(options: {
1729
+ metadata: Patchable<M>;
1730
+ threadId: string;
1731
+ }): Promise<M>;
1732
+ createComment(options: {
1733
+ threadId: string;
1734
+ commentId: string;
1735
+ body: CommentBody;
1736
+ }): Promise<CommentData>;
1737
+ editComment(options: {
1738
+ threadId: string;
1739
+ commentId: string;
1740
+ body: CommentBody;
1741
+ }): Promise<CommentData>;
1742
+ deleteComment(options: {
1743
+ threadId: string;
1744
+ commentId: string;
1745
+ }): Promise<void>;
1746
+ addReaction(options: {
1747
+ threadId: string;
1748
+ commentId: string;
1749
+ emoji: string;
1750
+ }): Promise<CommentUserReaction>;
1751
+ removeReaction(options: {
1752
+ threadId: string;
1753
+ commentId: string;
1754
+ emoji: string;
1755
+ }): Promise<void>;
1756
+ };
1757
+ /**
1758
+ * @private Widest-possible Room type, matching _any_ Room instance. Note that
1759
+ * this type is different from `Room`-without-type-arguments. That represents
1760
+ * a Room instance using globally augmented types only, which is narrower.
1761
+ */
1762
+ declare type OpaqueRoom = Room<JsonObject, LsonObject, BaseUserMeta, Json, BaseMetadata>;
1763
+ declare type Room<P extends JsonObject = DP, S extends LsonObject = DS, U extends BaseUserMeta = DU, E extends Json = DE, M extends BaseMetadata = DM> = {
1652
1764
  /**
1653
- * The id of the room.
1765
+ * @private
1766
+ *
1767
+ * Private methods and variables used in the core internals, but as a user
1768
+ * of Liveblocks, NEVER USE ANY OF THESE DIRECTLY, because bad things
1769
+ * will probably happen if you do.
1654
1770
  */
1655
- readonly id: string;
1771
+ readonly [kInternal]: PrivateRoomApi<M>;
1656
1772
  /**
1657
- * @deprecated This API will be removed in a future version of Liveblocks.
1658
- * Prefer using `.getStatus()` instead.
1659
- *
1660
- * We recommend making the following changes if you use these APIs:
1661
- *
1662
- * OLD APIs NEW APIs
1663
- * .getConnectionState() --> .getStatus()
1664
- * .subscribe('connection') --> .subscribe('status')
1665
- *
1666
- * OLD STATUSES NEW STATUSES
1667
- * closed --> initial
1668
- * authenticating --> connecting
1669
- * connecting --> connecting
1670
- * open --> connected
1671
- * unavailable --> reconnecting
1672
- * failed --> disconnected
1773
+ * The id of the room.
1673
1774
  */
1674
- getConnectionState(): LegacyConnectionStatus;
1775
+ readonly id: string;
1675
1776
  /**
1676
1777
  * Return the current connection status for this room. Can be used to display
1677
1778
  * a status badge for your Liveblocks connection.
1678
1779
  */
1679
1780
  getStatus(): Status;
1680
- readonly subscribe: SubscribeFn<TPresence, TStorage, TUserMeta, TRoomEvent>;
1781
+ readonly subscribe: SubscribeFn<P, S, U, E>;
1681
1782
  /**
1682
1783
  * Room's history contains functions that let you undo and redo operation made on by the current client on the presence and storage.
1683
1784
  */
@@ -1689,21 +1790,21 @@ declare type Room<TPresence extends JsonObject, TStorage extends LsonObject, TUs
1689
1790
  * @example
1690
1791
  * const user = room.getSelf();
1691
1792
  */
1692
- getSelf(): User<TPresence, TUserMeta> | null;
1793
+ getSelf(): User<P, U> | null;
1693
1794
  /**
1694
1795
  * Gets the presence of the current user.
1695
1796
  *
1696
1797
  * @example
1697
1798
  * const presence = room.getPresence();
1698
1799
  */
1699
- getPresence(): TPresence;
1800
+ getPresence(): P;
1700
1801
  /**
1701
1802
  * Gets all the other users in the room.
1702
1803
  *
1703
1804
  * @example
1704
1805
  * const others = room.getOthers();
1705
1806
  */
1706
- getOthers(): readonly User<TPresence, TUserMeta>[];
1807
+ getOthers(): readonly User<P, U>[];
1707
1808
  /**
1708
1809
  * Updates the presence of the current user. Only pass the properties you want to update. No need to send the full presence.
1709
1810
  * @param patch A partial object that contains the properties you want to update.
@@ -1716,15 +1817,14 @@ declare type Room<TPresence extends JsonObject, TStorage extends LsonObject, TUs
1716
1817
  * const presence = room.getPresence();
1717
1818
  * // presence is equivalent to { x: 0, y: 0 }
1718
1819
  */
1719
- updatePresence(patch: Partial<TPresence>, options?: {
1820
+ updatePresence(patch: Partial<P>, options?: {
1720
1821
  /**
1721
1822
  * Whether or not the presence should have an impact on the undo/redo history.
1722
1823
  */
1723
1824
  addToHistory: boolean;
1724
1825
  }): void;
1725
1826
  /**
1726
- *
1727
- * Sends Yjs document updates to liveblocks server
1827
+ * Sends Yjs document updates to Liveblocks server.
1728
1828
  *
1729
1829
  * @param {string} data the doc update to send to the server, base64 encoded uint8array
1730
1830
  */
@@ -1748,7 +1848,7 @@ declare type Room<TPresence extends JsonObject, TStorage extends LsonObject, TUs
1748
1848
  * }
1749
1849
  * });
1750
1850
  */
1751
- broadcastEvent(event: TRoomEvent, options?: BroadcastOptions): void;
1851
+ broadcastEvent(event: E, options?: BroadcastOptions): void;
1752
1852
  /**
1753
1853
  * Get the room's storage asynchronously.
1754
1854
  * The storage's root is a {@link LiveObject}.
@@ -1757,7 +1857,7 @@ declare type Room<TPresence extends JsonObject, TStorage extends LsonObject, TUs
1757
1857
  * const { root } = await room.getStorage();
1758
1858
  */
1759
1859
  getStorage(): Promise<{
1760
- root: LiveObject<TStorage>;
1860
+ root: LiveObject<S>;
1761
1861
  }>;
1762
1862
  /**
1763
1863
  * Get the room's storage synchronously.
@@ -1766,15 +1866,15 @@ declare type Room<TPresence extends JsonObject, TStorage extends LsonObject, TUs
1766
1866
  * @example
1767
1867
  * const root = room.getStorageSnapshot();
1768
1868
  */
1769
- getStorageSnapshot(): LiveObject<TStorage> | null;
1869
+ getStorageSnapshot(): LiveObject<S> | null;
1770
1870
  readonly events: {
1771
1871
  readonly status: Observable<Status>;
1772
1872
  readonly lostConnection: Observable<LostConnectionEvent>;
1773
- readonly customEvent: Observable<RoomEventMessage<TPresence, TUserMeta, TRoomEvent>>;
1774
- readonly self: Observable<User<TPresence, TUserMeta>>;
1775
- readonly myPresence: Observable<TPresence>;
1776
- readonly others: Observable<OthersEvent<TPresence, TUserMeta>>;
1777
- readonly error: Observable<Error>;
1873
+ readonly customEvent: Observable<RoomEventMessage<P, U, E>>;
1874
+ readonly self: Observable<User<P, U>>;
1875
+ readonly myPresence: Observable<P>;
1876
+ readonly others: Observable<OthersEvent<P, U>>;
1877
+ readonly error: Observable<LiveblocksError>;
1778
1878
  readonly storage: Observable<StorageUpdate[]>;
1779
1879
  readonly history: Observable<HistoryEvent>;
1780
1880
  /**
@@ -1834,21 +1934,53 @@ declare type Room<TPresence extends JsonObject, TStorage extends LsonObject, TUs
1834
1934
  */
1835
1935
  reconnect(): void;
1836
1936
  };
1937
+ /**
1938
+ * @private
1939
+ *
1940
+ * Private methods to directly control the underlying state machine for this
1941
+ * room. Used in the core internals and for unit testing, but as a user of
1942
+ * Liveblocks, NEVER USE ANY OF THESE METHODS DIRECTLY, because bad things
1943
+ * will probably happen if you do.
1944
+ */
1945
+ declare type PrivateRoomApi<M extends BaseMetadata> = {
1946
+ presenceBuffer: Json | undefined;
1947
+ undoStack: readonly (readonly Readonly<HistoryOp<JsonObject>>[])[];
1948
+ nodeCount: number;
1949
+ getSelf_forDevTools(): UserTreeNode | null;
1950
+ getOthers_forDevTools(): readonly UserTreeNode[];
1951
+ reportTextEditor(editor: "lexical", rootKey: string): void;
1952
+ createTextMention(userId: string, mentionId: string): Promise<Response>;
1953
+ deleteTextMention(mentionId: string): Promise<Response>;
1954
+ simulate: {
1955
+ explicitClose(event: IWebSocketCloseEvent): void;
1956
+ rawSend(data: string): void;
1957
+ };
1958
+ comments: CommentsApi<M>;
1959
+ notifications: {
1960
+ getRoomNotificationSettings(): Promise<RoomNotificationSettings>;
1961
+ updateRoomNotificationSettings(settings: Partial<RoomNotificationSettings>): Promise<RoomNotificationSettings>;
1962
+ markInboxNotificationAsRead(notificationId: string): Promise<void>;
1963
+ };
1964
+ };
1965
+ declare type HistoryOp<P extends JsonObject> = Op | {
1966
+ readonly type: "presence";
1967
+ readonly data: P;
1968
+ };
1837
1969
  declare type Polyfills = {
1838
1970
  atob?: (data: string) => string;
1839
1971
  fetch?: typeof fetch;
1840
1972
  WebSocket?: IWebSocket;
1841
1973
  };
1842
- declare type RoomInitializers<TPresence extends JsonObject, TStorage extends LsonObject> = Resolve<{
1974
+ declare type RoomInitializers<P extends JsonObject, S extends LsonObject> = Resolve<{
1843
1975
  /**
1844
1976
  * The initial Presence to use and announce when you enter the Room. The
1845
1977
  * Presence is available on all users in the Room (me & others).
1846
1978
  */
1847
- initialPresence: TPresence | ((roomId: string) => TPresence);
1979
+ initialPresence: P | ((roomId: string) => P);
1848
1980
  /**
1849
1981
  * The initial Storage to use when entering a new Room.
1850
1982
  */
1851
- initialStorage?: TStorage | ((roomId: string) => TStorage);
1983
+ initialStorage?: S | ((roomId: string) => S);
1852
1984
  /**
1853
1985
  * Whether or not the room automatically connects to Liveblock servers.
1854
1986
  * Default is true.
@@ -1857,11 +1989,187 @@ declare type RoomInitializers<TPresence extends JsonObject, TStorage extends Lso
1857
1989
  * the authentication endpoint or connect via WebSocket.
1858
1990
  */
1859
1991
  autoConnect?: boolean;
1860
- /** @deprecated Renamed to `autoConnect` */
1861
- shouldInitiallyConnect?: boolean;
1862
1992
  }>;
1993
+ declare class CommentsApiError extends Error {
1994
+ message: string;
1995
+ status: number;
1996
+ details?: JsonObject | undefined;
1997
+ constructor(message: string, status: number, details?: JsonObject | undefined);
1998
+ }
1999
+
2000
+ declare type BatchStoreStateLoading = {
2001
+ isLoading: true;
2002
+ data?: never;
2003
+ error?: never;
2004
+ };
2005
+ declare type BatchStoreStateError = {
2006
+ isLoading: false;
2007
+ data?: never;
2008
+ error: Error;
2009
+ };
2010
+ declare type BatchStoreStateSuccess<T> = {
2011
+ isLoading: false;
2012
+ data: T;
2013
+ error?: never;
2014
+ };
2015
+ declare type BatchStoreState<T> = BatchStoreStateLoading | BatchStoreStateError | BatchStoreStateSuccess<T>;
2016
+ declare type BatchStore<T, A extends unknown[]> = EventSource<BatchStoreState<T> | undefined> & {
2017
+ get: (...args: A) => Promise<void>;
2018
+ getState: (...args: A) => BatchStoreState<T> | undefined;
2019
+ };
2020
+
2021
+ declare type Store<T> = {
2022
+ get: () => T;
2023
+ set: (callback: (currentState: T) => T) => void;
2024
+ subscribe: (callback: (state: T) => void) => () => void;
2025
+ };
2026
+
2027
+ /**
2028
+ * Back-port of TypeScript 5.4's built-in NoInfer utility type.
2029
+ * See https://stackoverflow.com/a/56688073/148872
2030
+ */
2031
+ declare type NoInfr<A> = [A][A extends any ? 0 : never];
2032
+
2033
+ declare type GetInboxNotificationsOptions = {
2034
+ limit?: number;
2035
+ since?: Date;
2036
+ };
2037
+
2038
+ declare type OptimisticUpdate<M extends BaseMetadata> = CreateThreadOptimisticUpdate<M> | EditThreadMetadataOptimisticUpdate<M> | CreateCommentOptimisticUpdate | EditCommentOptimisticUpdate | DeleteCommentOptimisticUpdate | AddReactionOptimisticUpdate | RemoveReactionOptimisticUpdate | MarkInboxNotificationAsReadOptimisticUpdate | MarkAllInboxNotificationsAsReadOptimisticUpdate | UpdateNotificationSettingsOptimisticUpdate;
2039
+ declare type CreateThreadOptimisticUpdate<M extends BaseMetadata> = {
2040
+ type: "create-thread";
2041
+ id: string;
2042
+ roomId: string;
2043
+ thread: ThreadData<M>;
2044
+ };
2045
+ declare type EditThreadMetadataOptimisticUpdate<M extends BaseMetadata> = {
2046
+ type: "edit-thread-metadata";
2047
+ id: string;
2048
+ threadId: string;
2049
+ metadata: Resolve<Patchable<M>>;
2050
+ updatedAt: Date;
2051
+ };
2052
+ declare type CreateCommentOptimisticUpdate = {
2053
+ type: "create-comment";
2054
+ id: string;
2055
+ comment: CommentData;
2056
+ };
2057
+ declare type EditCommentOptimisticUpdate = {
2058
+ type: "edit-comment";
2059
+ id: string;
2060
+ comment: CommentData;
2061
+ };
2062
+ declare type DeleteCommentOptimisticUpdate = {
2063
+ type: "delete-comment";
2064
+ id: string;
2065
+ roomId: string;
2066
+ threadId: string;
2067
+ deletedAt: Date;
2068
+ commentId: string;
2069
+ };
2070
+ declare type AddReactionOptimisticUpdate = {
2071
+ type: "add-reaction";
2072
+ id: string;
2073
+ threadId: string;
2074
+ commentId: string;
2075
+ reaction: CommentUserReaction;
2076
+ };
2077
+ declare type RemoveReactionOptimisticUpdate = {
2078
+ type: "remove-reaction";
2079
+ id: string;
2080
+ threadId: string;
2081
+ commentId: string;
2082
+ emoji: string;
2083
+ userId: string;
2084
+ removedAt: Date;
2085
+ };
2086
+ declare type MarkInboxNotificationAsReadOptimisticUpdate = {
2087
+ type: "mark-inbox-notification-as-read";
2088
+ id: string;
2089
+ inboxNotificationId: string;
2090
+ readAt: Date;
2091
+ };
2092
+ declare type MarkAllInboxNotificationsAsReadOptimisticUpdate = {
2093
+ type: "mark-inbox-notifications-as-read";
2094
+ id: string;
2095
+ readAt: Date;
2096
+ };
2097
+ declare type UpdateNotificationSettingsOptimisticUpdate = {
2098
+ type: "update-notification-settings";
2099
+ id: string;
2100
+ roomId: string;
2101
+ settings: Partial<RoomNotificationSettings>;
2102
+ };
2103
+ declare type QueryState = {
2104
+ isLoading: true;
2105
+ error?: never;
2106
+ } | {
2107
+ isLoading: false;
2108
+ error?: Error;
2109
+ };
2110
+ declare type CacheState<M extends BaseMetadata> = {
2111
+ /**
2112
+ * Threads by ID.
2113
+ */
2114
+ threads: Record<string, ThreadDataWithDeleteInfo<M>>;
2115
+ /**
2116
+ * Keep track of loading and error status of all the queries made by the client.
2117
+ */
2118
+ queries: Record<string, QueryState>;
2119
+ /**
2120
+ * Optimistic updates that have not been acknowledged by the server yet.
2121
+ * They are applied on top of the threads in selectors.
2122
+ */
2123
+ optimisticUpdates: OptimisticUpdate<M>[];
2124
+ /**
2125
+ * Inbox notifications by ID.
2126
+ */
2127
+ inboxNotifications: Record<string, InboxNotificationData>;
2128
+ /**
2129
+ * Notification settings per room id
2130
+ */
2131
+ notificationSettings: Record<string, RoomNotificationSettings>;
2132
+ };
2133
+ interface CacheStore<M extends BaseMetadata> extends Store<CacheState<M>> {
2134
+ deleteThread(threadId: string): void;
2135
+ updateThreadAndNotification(thread: ThreadData<M>, inboxNotification?: InboxNotificationData): void;
2136
+ updateThreadsAndNotifications(threads: ThreadData<M>[], inboxNotifications: InboxNotificationData[], deletedThreads: ThreadDeleteInfo[], deletedInboxNotifications: InboxNotificationDeleteInfo[], queryKey?: string): void;
2137
+ updateRoomInboxNotificationSettings(roomId: string, settings: RoomNotificationSettings, queryKey: string): void;
2138
+ pushOptimisticUpdate(optimisticUpdate: OptimisticUpdate<M>): void;
2139
+ setQueryState(queryKey: string, queryState: QueryState): void;
2140
+ optimisticUpdatesEventSource: ReturnType<typeof makeEventSource<OptimisticUpdate<M>>>;
2141
+ }
2142
+ declare function applyOptimisticUpdates<M extends BaseMetadata>(state: CacheState<M>): Pick<CacheState<M>, "threads" | "inboxNotifications" | "notificationSettings">;
2143
+ declare function upsertComment<M extends BaseMetadata>(thread: ThreadDataWithDeleteInfo<M>, comment: CommentData): ThreadDataWithDeleteInfo<M>;
2144
+ declare function deleteComment<M extends BaseMetadata>(thread: ThreadDataWithDeleteInfo<M>, commentId: string, deletedAt: Date): ThreadDataWithDeleteInfo<M>;
2145
+ declare function addReaction<M extends BaseMetadata>(thread: ThreadDataWithDeleteInfo<M>, commentId: string, reaction: CommentUserReaction): ThreadDataWithDeleteInfo<M>;
2146
+ declare function removeReaction<M extends BaseMetadata>(thread: ThreadDataWithDeleteInfo<M>, commentId: string, emoji: string, userId: string, removedAt: Date): ThreadDataWithDeleteInfo<M>;
1863
2147
 
1864
- declare type EnterOptions<TPresence extends JsonObject, TStorage extends LsonObject> = Resolve<RoomInitializers<TPresence, TStorage> & {
2148
+ declare type OptionalPromise<T> = T | Promise<T>;
2149
+
2150
+ declare type ResolveMentionSuggestionsArgs = {
2151
+ /**
2152
+ * The ID of the current room.
2153
+ */
2154
+ roomId: string;
2155
+ /**
2156
+ * The text to search for.
2157
+ */
2158
+ text: string;
2159
+ };
2160
+ declare type ResolveUsersArgs = {
2161
+ /**
2162
+ * The IDs of the users to resolve.
2163
+ */
2164
+ userIds: string[];
2165
+ };
2166
+ declare type ResolveRoomsInfoArgs = {
2167
+ /**
2168
+ * The IDs of the rooms to resolve.
2169
+ */
2170
+ roomIds: string[];
2171
+ };
2172
+ declare type EnterOptions<P extends JsonObject = DP, S extends LsonObject = DS> = Resolve<RoomInitializers<P, S> & {
1865
2173
  /**
1866
2174
  * Only necessary when you’re using Liveblocks with React v17 or lower.
1867
2175
  *
@@ -1872,44 +2180,60 @@ declare type EnterOptions<TPresence extends JsonObject, TStorage extends LsonObj
1872
2180
  */
1873
2181
  unstable_batchedUpdates?: (cb: () => void) => void;
1874
2182
  }>;
1875
- declare type Client = {
2183
+ /**
2184
+ * @private
2185
+ *
2186
+ * Private methods and variables used in the core internals, but as a user
2187
+ * of Liveblocks, NEVER USE ANY OF THESE DIRECTLY, because bad things
2188
+ * will probably happen if you do.
2189
+ */
2190
+ declare type PrivateClientApi<U extends BaseUserMeta, M extends BaseMetadata> = {
2191
+ readonly notifications: NotificationsApi<M>;
2192
+ readonly currentUserIdStore: Store<string | null>;
2193
+ readonly resolveMentionSuggestions: ClientOptions<U>["resolveMentionSuggestions"];
2194
+ readonly cacheStore: CacheStore<BaseMetadata>;
2195
+ readonly usersStore: BatchStore<U["info"] | undefined, [string]>;
2196
+ readonly roomsInfoStore: BatchStore<DRI | undefined, [string]>;
2197
+ readonly getRoomIds: () => string[];
2198
+ };
2199
+ declare type NotificationsApi<M extends BaseMetadata> = {
2200
+ getInboxNotifications(options?: GetInboxNotificationsOptions): Promise<{
2201
+ inboxNotifications: InboxNotificationData[];
2202
+ threads: ThreadData<M>[];
2203
+ deletedThreads: ThreadDeleteInfo[];
2204
+ deletedInboxNotifications: InboxNotificationDeleteInfo[];
2205
+ meta: {
2206
+ requestedAt: Date;
2207
+ };
2208
+ }>;
2209
+ getUnreadInboxNotificationsCount(): Promise<number>;
2210
+ markAllInboxNotificationsAsRead(): Promise<void>;
2211
+ markInboxNotificationAsRead(inboxNotificationId: string): Promise<void>;
2212
+ };
2213
+ /**
2214
+ * @private Widest-possible Client type, matching _any_ Client instance. Note
2215
+ * that this type is different from `Client`-without-type-arguments. That
2216
+ * represents a Client instance using globally augmented types only, which is
2217
+ * narrower.
2218
+ */
2219
+ declare type OpaqueClient = Client<BaseUserMeta>;
2220
+ declare type Client<U extends BaseUserMeta = DU> = {
1876
2221
  /**
1877
2222
  * Gets a room. Returns null if {@link Client.enter} has not been called previously.
1878
2223
  *
1879
2224
  * @param roomId The id of the room
1880
2225
  */
1881
- getRoom<TPresence extends JsonObject, TStorage extends LsonObject = LsonObject, TUserMeta extends BaseUserMeta = BaseUserMeta, TRoomEvent extends Json = never>(roomId: string): Room<TPresence, TStorage, TUserMeta, TRoomEvent> | null;
2226
+ getRoom<P extends JsonObject = DP, S extends LsonObject = DS, E extends Json = DE, M extends BaseMetadata = DM>(roomId: string): Room<P, S, U, E, M> | null;
1882
2227
  /**
1883
2228
  * Enter a room.
1884
2229
  * @param roomId The id of the room
1885
2230
  * @param options Optional. You can provide initializers for the Presence or Storage when entering the Room.
1886
2231
  * @returns The room and a leave function. Call the returned leave() function when you no longer need the room.
1887
2232
  */
1888
- enterRoom<TPresence extends JsonObject, TStorage extends LsonObject = LsonObject, TUserMeta extends BaseUserMeta = BaseUserMeta, TRoomEvent extends Json = never>(roomId: string, options: EnterOptions<TPresence, TStorage>): {
1889
- room: Room<TPresence, TStorage, TUserMeta, TRoomEvent>;
2233
+ enterRoom<P extends JsonObject = DP, S extends LsonObject = DS, E extends Json = DE, M extends BaseMetadata = DM>(roomId: string, options: EnterOptions<NoInfr<P>, NoInfr<S>>): {
2234
+ room: Room<P, S, U, E, M>;
1890
2235
  leave: () => void;
1891
2236
  };
1892
- /**
1893
- * @deprecated - Prefer using {@link Client.enterRoom} instead.
1894
- *
1895
- * Enters a room and returns it.
1896
- * @param roomId The id of the room
1897
- * @param options Optional. You can provide initializers for the Presence or Storage when entering the Room.
1898
- */
1899
- enter<TPresence extends JsonObject, TStorage extends LsonObject = LsonObject, TUserMeta extends BaseUserMeta = BaseUserMeta, TRoomEvent extends Json = never>(roomId: string, options: EnterOptions<TPresence, TStorage>): Room<TPresence, TStorage, TUserMeta, TRoomEvent>;
1900
- /**
1901
- * @deprecated - Prefer using {@link Client.enterRoom} and calling the returned leave function instead, which is safer.
1902
- *
1903
- * Forcefully leaves a room.
1904
- *
1905
- * Only call this if you know for sure there are no other "instances" of this
1906
- * room used elsewhere in your application. Force-leaving can trigger
1907
- * unexpected conditions in other parts of your application that may not
1908
- * expect this.
1909
- *
1910
- * @param roomId The id of the room
1911
- */
1912
- leave(roomId: string): void;
1913
2237
  /**
1914
2238
  * Purges all cached auth tokens and reconnects all rooms that are still
1915
2239
  * connected, if any.
@@ -1917,61 +2241,190 @@ declare type Client = {
1917
2241
  * Call this whenever you log out a user in your application.
1918
2242
  */
1919
2243
  logout(): void;
2244
+ /**
2245
+ * @private
2246
+ *
2247
+ * Private methods and variables used in the core internals, but as a user
2248
+ * of Liveblocks, NEVER USE ANY OF THESE DIRECTLY, because bad things
2249
+ * will probably happen if you do.
2250
+ */
2251
+ readonly [kInternal]: PrivateClientApi<U, BaseMetadata>;
1920
2252
  };
1921
- declare type AuthEndpoint = string | ((room: string) => Promise<CustomAuthenticationResult>);
2253
+ declare type AuthEndpoint = string | ((room?: string) => Promise<CustomAuthenticationResult>);
1922
2254
  /**
1923
2255
  * The authentication endpoint that is called to ensure that the current user has access to a room.
1924
2256
  * Can be an url or a callback if you need to add additional headers.
1925
2257
  */
1926
- declare type ClientOptions = {
2258
+ declare type ClientOptions<U extends BaseUserMeta = DU> = {
1927
2259
  throttle?: number;
1928
2260
  lostConnectionTimeout?: number;
1929
2261
  backgroundKeepAliveTimeout?: number;
1930
2262
  polyfills?: Polyfills;
1931
2263
  unstable_fallbackToHTTP?: boolean;
2264
+ unstable_streamData?: boolean;
2265
+ /**
2266
+ * A function that returns a list of user IDs matching a string.
2267
+ */
2268
+ resolveMentionSuggestions?: (args: ResolveMentionSuggestionsArgs) => OptionalPromise<string[]>;
2269
+ /**
2270
+ * A function that returns user info from user IDs.
2271
+ */
2272
+ resolveUsers?: (args: ResolveUsersArgs) => OptionalPromise<(U["info"] | undefined)[] | undefined>;
2273
+ /**
2274
+ * A function that returns room info from room IDs.
2275
+ */
2276
+ resolveRoomsInfo?: (args: ResolveRoomsInfoArgs) => OptionalPromise<(DRI | undefined)[] | undefined>;
2277
+ } & ({
2278
+ publicApiKey: string;
2279
+ authEndpoint?: never;
2280
+ } | {
2281
+ publicApiKey?: never;
2282
+ authEndpoint: AuthEndpoint;
2283
+ });
2284
+ /**
2285
+ * Create a client that will be responsible to communicate with liveblocks servers.
2286
+ *
2287
+ * @example
2288
+ * const client = createClient({
2289
+ * authEndpoint: "/api/auth"
2290
+ * });
2291
+ *
2292
+ * // It's also possible to use a function to call your authentication endpoint.
2293
+ * // Useful to add additional headers or use an API wrapper (like Firebase functions)
2294
+ * const client = createClient({
2295
+ * authEndpoint: async (room?) => {
2296
+ * const response = await fetch("/api/auth", {
2297
+ * method: "POST",
2298
+ * headers: {
2299
+ * Authentication: "token",
2300
+ * "Content-Type": "application/json"
2301
+ * },
2302
+ * body: JSON.stringify({ room })
2303
+ * });
2304
+ *
2305
+ * return await response.json(); // should be: { token: "..." }
2306
+ * }
2307
+ * });
2308
+ */
2309
+ declare function createClient<U extends BaseUserMeta = DU>(options: ClientOptions<U>): Client<U>;
2310
+ declare class NotificationsApiError extends Error {
2311
+ message: string;
2312
+ status: number;
2313
+ details?: JsonObject | undefined;
2314
+ constructor(message: string, status: number, details?: JsonObject | undefined);
2315
+ }
2316
+
2317
+ declare type CommentBodyParagraphElementArgs = {
2318
+ /**
2319
+ * The paragraph element.
2320
+ */
2321
+ element: CommentBodyParagraph;
2322
+ /**
2323
+ * The text content of the paragraph.
2324
+ */
2325
+ children: string;
2326
+ };
2327
+ declare type CommentBodyTextElementArgs = {
2328
+ /**
2329
+ * The text element.
2330
+ */
2331
+ element: CommentBodyText;
2332
+ };
2333
+ declare type CommentBodyLinkElementArgs = {
2334
+ /**
2335
+ * The link element.
2336
+ */
2337
+ element: CommentBodyLink;
2338
+ /**
2339
+ * The absolute URL of the link.
2340
+ */
2341
+ href: string;
2342
+ };
2343
+ declare type CommentBodyMentionElementArgs<U extends BaseUserMeta = DU> = {
2344
+ /**
2345
+ * The mention element.
2346
+ */
2347
+ element: CommentBodyMention;
2348
+ /**
2349
+ * The mention's user info, if the `resolvedUsers` option was provided.
2350
+ */
2351
+ user?: U["info"];
2352
+ };
2353
+ declare type StringifyCommentBodyElements<U extends BaseUserMeta = DU> = {
2354
+ /**
2355
+ * The element used to display paragraphs.
2356
+ */
2357
+ paragraph: (args: CommentBodyParagraphElementArgs, index: number) => string;
2358
+ /**
2359
+ * The element used to display text elements.
2360
+ */
2361
+ text: (args: CommentBodyTextElementArgs, index: number) => string;
2362
+ /**
2363
+ * The element used to display links.
2364
+ */
2365
+ link: (args: CommentBodyLinkElementArgs, index: number) => string;
2366
+ /**
2367
+ * The element used to display mentions.
2368
+ */
2369
+ mention: (args: CommentBodyMentionElementArgs<U>, index: number) => string;
2370
+ };
2371
+ declare type StringifyCommentBodyOptions<U extends BaseUserMeta = DU> = {
1932
2372
  /**
1933
- * @deprecated Use `polyfills: { fetch: ... }` instead.
1934
- * This option will be removed in a future release.
2373
+ * Which format to convert the comment to.
1935
2374
  */
1936
- fetchPolyfill?: Polyfills["fetch"];
2375
+ format?: "plain" | "html" | "markdown";
1937
2376
  /**
1938
- * @deprecated Use `polyfills: { WebSocket: ... }` instead.
1939
- * This option will be removed in a future release.
2377
+ * The elements used to customize the resulting string. Each element has
2378
+ * priority over the defaults inherited from the `format` option.
1940
2379
  */
1941
- WebSocketPolyfill?: Polyfills["WebSocket"];
1942
- } & ({
1943
- publicApiKey: string;
1944
- authEndpoint?: never;
1945
- } | {
1946
- publicApiKey?: never;
1947
- authEndpoint: AuthEndpoint;
1948
- });
2380
+ elements?: Partial<StringifyCommentBodyElements<U>>;
2381
+ /**
2382
+ * The separator used between paragraphs.
2383
+ */
2384
+ separator?: string;
2385
+ /**
2386
+ * A function that returns user info from user IDs.
2387
+ */
2388
+ resolveUsers?: (args: ResolveUsersArgs) => OptionalPromise<(U["info"] | undefined)[] | undefined>;
2389
+ };
1949
2390
  /**
1950
- * Create a client that will be responsible to communicate with liveblocks servers.
1951
- *
1952
- * @example
1953
- * const client = createClient({
1954
- * authEndpoint: "/api/auth"
1955
- * });
1956
- *
1957
- * // It's also possible to use a function to call your authentication endpoint.
1958
- * // Useful to add additional headers or use an API wrapper (like Firebase functions)
1959
- * const client = createClient({
1960
- * authEndpoint: async (room) => {
1961
- * const response = await fetch("/api/auth", {
1962
- * method: "POST",
1963
- * headers: {
1964
- * Authentication: "token",
1965
- * "Content-Type": "application/json"
1966
- * },
1967
- * body: JSON.stringify({ room })
1968
- * });
1969
- *
1970
- * return await response.json(); // should be: { token: "..." }
1971
- * }
1972
- * });
2391
+ * Get an array of each user's ID that has been mentioned in a `CommentBody`.
2392
+ */
2393
+ declare function getMentionedIdsFromCommentBody(body: CommentBody): string[];
2394
+ /**
2395
+ * Convert a `CommentBody` into either a plain string,
2396
+ * Markdown, HTML, or a custom format.
2397
+ */
2398
+ declare function stringifyCommentBody(body: CommentBody, options?: StringifyCommentBodyOptions<BaseUserMeta>): Promise<string>;
2399
+
2400
+ /**
2401
+ * Converts a plain comment data object (usually returned by the API) to a comment data object that can be used by the client.
2402
+ * This is necessary because the plain data object stores dates as ISO strings, but the client expects them as Date objects.
2403
+ * @param data The plain comment data object (usually returned by the API)
2404
+ * @returns The rich comment data object that can be used by the client.
2405
+ */
2406
+ declare function convertToCommentData(data: CommentDataPlain): CommentData;
2407
+ /**
2408
+ * Converts a plain thread data object (usually returned by the API) to a thread data object that can be used by the client.
2409
+ * This is necessary because the plain data object stores dates as ISO strings, but the client expects them as Date objects.
2410
+ * @param data The plain thread data object (usually returned by the API)
2411
+ * @returns The rich thread data object that can be used by the client.
2412
+ */
2413
+ declare function convertToThreadData<M extends BaseMetadata>(data: ThreadDataPlain<M>): ThreadData<M>;
2414
+ /**
2415
+ * Converts a plain comment reaction object (usually returned by the API) to a comment reaction object that can be used by the client.
2416
+ * This is necessary because the plain data object stores dates as ISO strings, but the client expects them as Date objects.
2417
+ * @param data The plain comment reaction object (usually returned by the API)
2418
+ * @returns The rich comment reaction object that can be used by the client.
2419
+ */
2420
+ declare function convertToCommentUserReaction(data: CommentUserReactionPlain): CommentUserReaction;
2421
+ /**
2422
+ * Converts a plain inbox notification data object (usually returned by the API) to an inbox notification data object that can be used by the client.
2423
+ * This is necessary because the plain data object stores dates as ISO strings, but the client expects them as Date objects.
2424
+ * @param data The plain inbox notification data object (usually returned by the API)
2425
+ * @returns The rich inbox notification data object that can be used by the client.
1973
2426
  */
1974
- declare function createClient(options: ClientOptions): Client;
2427
+ declare function convertToInboxNotificationData(data: InboxNotificationDataPlain): InboxNotificationData;
1975
2428
 
1976
2429
  /**
1977
2430
  * Lookup table for nodes (= SerializedCrdt values) by their IDs.
@@ -1990,7 +2443,7 @@ declare function cloneLson<L extends Lson | undefined>(value: L): L;
1990
2443
 
1991
2444
  declare function lsonToJson(value: Lson): Json;
1992
2445
  declare function patchLiveObjectKey<O extends LsonObject, K extends keyof O, V extends Json>(liveObject: LiveObject<O>, key: K, prev?: V, next?: V): void;
1993
- declare function legacy_patchImmutableObject<S extends JsonObject>(state: S, updates: StorageUpdate[]): S;
2446
+ declare function legacy_patchImmutableObject<TState extends JsonObject>(state: TState, updates: StorageUpdate[]): TState;
1994
2447
 
1995
2448
  /**
1996
2449
  * Helper function that can be used to implement exhaustive switch statements
@@ -2035,93 +2488,6 @@ declare function assert(condition: boolean, errmsg: string): asserts condition;
2035
2488
  */
2036
2489
  declare function nn<T>(value: T, errmsg?: string): NonNullable<T>;
2037
2490
 
2038
- declare type PromiseOrNot$1<T> = T | Promise<T>;
2039
- declare type AsyncCacheFunction<T, A extends any[] = any[]> = (...args: A) => PromiseOrNot$1<T>;
2040
- declare type AsyncCacheOptions<T, E> = {
2041
- isStateEqual?: (a: AsyncState<T, E>, b: AsyncState<T, E>) => boolean;
2042
- };
2043
- declare type AsyncStateInitial = {
2044
- readonly isLoading: false;
2045
- readonly data?: never;
2046
- readonly error?: never;
2047
- };
2048
- declare type AsyncStateLoading<T> = {
2049
- readonly isLoading: true;
2050
- readonly data?: T;
2051
- readonly error?: never;
2052
- };
2053
- declare type AsyncStateSuccess<T> = {
2054
- readonly isLoading: false;
2055
- readonly data: T;
2056
- readonly error?: never;
2057
- };
2058
- declare type AsyncStateError<T, E> = {
2059
- readonly isLoading: false;
2060
- readonly data?: T;
2061
- readonly error: E;
2062
- };
2063
- declare type AsyncState<T, E> = AsyncStateInitial | AsyncStateLoading<T> | AsyncStateSuccess<T> | AsyncStateError<T, E>;
2064
- declare type AsyncStateResolved<T, E> = AsyncStateSuccess<T> | AsyncStateError<T, E>;
2065
- declare type AsyncCacheItem<T, E> = Observable<AsyncState<T, E>> & {
2066
- get(): Promise<AsyncStateResolved<T, E>>;
2067
- getState(): AsyncState<T, E>;
2068
- revalidate(): Promise<AsyncStateResolved<T, E>>;
2069
- };
2070
- declare type AsyncCache<T, E> = {
2071
- /**
2072
- * @private
2073
- *
2074
- * Creates a key in the cache.
2075
- *
2076
- * @param key The key to create.
2077
- * @param asyncFunction Override the cache's function for this key.
2078
- */
2079
- create(key: string, asyncFunction?: AsyncCacheFunction<T, [string]>): AsyncCacheItem<T, E>;
2080
- /**
2081
- * Returns a promise which resolves with the state of the key.
2082
- *
2083
- * @param key The key to get.
2084
- */
2085
- get(key: string): Promise<AsyncStateResolved<T, E>>;
2086
- /**
2087
- * Returns the current state of the key synchronously.
2088
- *
2089
- * @param key The key to get the state of.
2090
- */
2091
- getState(key: string): AsyncState<T, E> | undefined;
2092
- /**
2093
- * Revalidates the key.
2094
- *
2095
- * @param key The key to revalidate.
2096
- */
2097
- revalidate(key: string): Promise<AsyncStateResolved<T, E>>;
2098
- /**
2099
- * Subscribes to the key's changes.
2100
- *
2101
- * @param key The key to subscribe to.
2102
- * @param callback The function invoked on every change.
2103
- */
2104
- subscribe(key: string, callback: Callback<AsyncState<T, E>>): UnsubscribeCallback;
2105
- /**
2106
- * Subscribes to the key's changes once.
2107
- *
2108
- * @param key The key to subscribe to.
2109
- * @param callback The function invoked on every change.
2110
- */
2111
- subscribeOnce(key: string, callback: Callback<AsyncState<T, E>>): UnsubscribeCallback;
2112
- /**
2113
- * Returns whether a key already exists in the cache.
2114
- *
2115
- * @param key The key to look for.
2116
- */
2117
- has(key: string): boolean;
2118
- /**
2119
- * Clears all keys.
2120
- */
2121
- clear(): void;
2122
- };
2123
- declare function createAsyncCache<T, E>(asyncFunction: AsyncCacheFunction<T, [string]>, options?: AsyncCacheOptions<T, E>): AsyncCache<T, E>;
2124
-
2125
2491
  /**
2126
2492
  * Displays a deprecation warning in the dev console. Only in dev mode, and
2127
2493
  * only once per message/key. In production, this is a no-op.
@@ -2167,6 +2533,39 @@ declare namespace fancyConsole {
2167
2533
  */
2168
2534
  declare const freeze: typeof Object.freeze;
2169
2535
 
2536
+ /**
2537
+ * Converts an object to a query string
2538
+ * Example:
2539
+ * ```ts
2540
+ * const query = objectToQuery({
2541
+ resolved: true,
2542
+ metadata: {
2543
+ status: "open",
2544
+ priority: 3,
2545
+ org: {
2546
+ startsWith: "liveblocks:",
2547
+ },
2548
+ },
2549
+ });
2550
+
2551
+ console.log(query);
2552
+ // resolved:true AND metadata["status"]:open AND metadata["priority"]:3 AND metadata["org"]^"liveblocks:"
2553
+
2554
+ * ```
2555
+ *
2556
+ *
2557
+ */
2558
+ declare type SimpleFilterValue = string | number | boolean;
2559
+ declare type OperatorFilterValue = {
2560
+ startsWith: string;
2561
+ };
2562
+ declare type FilterValue = SimpleFilterValue | OperatorFilterValue;
2563
+ declare function objectToQuery(obj: {
2564
+ [key: string]: FilterValue | {
2565
+ [key: string]: FilterValue | undefined;
2566
+ } | undefined;
2567
+ }): string;
2568
+
2170
2569
  declare type Poller = {
2171
2570
  start(interval: number): void;
2172
2571
  restart(interval: number): void;
@@ -2282,50 +2681,6 @@ declare function shallow(a: unknown, b: unknown): boolean;
2282
2681
  declare type OmitFirstTupleElement<T extends any[]> = T extends [any, ...infer R] ? R : never;
2283
2682
  declare function stringify(object: Parameters<typeof JSON.stringify>[0], ...args: OmitFirstTupleElement<Parameters<typeof JSON.stringify>>): string;
2284
2683
 
2285
- declare type JsonTreeNode = {
2286
- readonly type: "Json";
2287
- readonly id: string;
2288
- readonly key: string;
2289
- readonly payload: Json;
2290
- };
2291
- declare type LiveTreeNode<TName extends `Live${string}` = `Live${string}`> = {
2292
- readonly type: TName;
2293
- readonly id: string;
2294
- readonly key: string;
2295
- readonly payload: LsonTreeNode[];
2296
- };
2297
- declare type LsonTreeNode = LiveTreeNode | JsonTreeNode;
2298
- declare type UserTreeNode = {
2299
- readonly type: "User";
2300
- readonly id: string;
2301
- readonly key: string;
2302
- readonly payload: {
2303
- readonly connectionId: number;
2304
- readonly id?: string;
2305
- readonly info?: Json;
2306
- readonly presence: JsonObject;
2307
- readonly isReadOnly: boolean;
2308
- };
2309
- };
2310
- declare type CustomEventTreeNode = {
2311
- readonly type: "CustomEvent";
2312
- readonly id: string;
2313
- readonly key: string;
2314
- readonly connectionId: number;
2315
- readonly payload: Json;
2316
- };
2317
- declare type TreeNode = LsonTreeNode | UserTreeNode | CustomEventTreeNode;
2318
-
2319
- type DevToolsTreeNode_CustomEventTreeNode = CustomEventTreeNode;
2320
- type DevToolsTreeNode_JsonTreeNode = JsonTreeNode;
2321
- type DevToolsTreeNode_LiveTreeNode<TName extends `Live${string}` = `Live${string}`> = LiveTreeNode<TName>;
2322
- type DevToolsTreeNode_LsonTreeNode = LsonTreeNode;
2323
- type DevToolsTreeNode_TreeNode = TreeNode;
2324
- type DevToolsTreeNode_UserTreeNode = UserTreeNode;
2325
- declare namespace DevToolsTreeNode {
2326
- export type { DevToolsTreeNode_CustomEventTreeNode as CustomEventTreeNode, DevToolsTreeNode_JsonTreeNode as JsonTreeNode, DevToolsTreeNode_LiveTreeNode as LiveTreeNode, DevToolsTreeNode_LsonTreeNode as LsonTreeNode, DevToolsTreeNode_TreeNode as TreeNode, DevToolsTreeNode_UserTreeNode as UserTreeNode };
2327
- }
2328
-
2329
2684
  /**
2330
2685
  * Definition of all messages the Panel can send to the Client.
2331
2686
  */
@@ -2446,127 +2801,16 @@ declare namespace protocol {
2446
2801
  export type { protocol_ClientToPanelMessage as ClientToPanelMessage, protocol_FullClientToPanelMessage as FullClientToPanelMessage, protocol_FullPanelToClientMessage as FullPanelToClientMessage, protocol_PanelToClientMessage as PanelToClientMessage };
2447
2802
  }
2448
2803
 
2449
- declare type PromiseOrNot<T> = T | Promise<T>;
2450
- declare type CommentBodyResolveUsersArgs = {
2451
- /**
2452
- * The ID of the users to resolve.
2453
- */
2454
- userIds: string[];
2455
- };
2456
- declare type CommentBodyParagraphElementArgs = {
2457
- /**
2458
- * The paragraph element.
2459
- */
2460
- element: CommentBodyParagraph;
2461
- /**
2462
- * The text content of the paragraph.
2463
- */
2464
- children: string;
2465
- };
2466
- declare type CommentBodyTextElementArgs = {
2467
- /**
2468
- * The text element.
2469
- */
2470
- element: CommentBodyText;
2471
- };
2472
- declare type CommentBodyLinkElementArgs = {
2473
- /**
2474
- * The link element.
2475
- */
2476
- element: CommentBodyLink;
2477
- /**
2478
- * The absolute URL of the link.
2479
- */
2480
- href: string;
2481
- };
2482
- declare type CommentBodyMentionElementArgs<TUserMeta extends BaseUserMeta = BaseUserMeta> = {
2483
- /**
2484
- * The mention element.
2485
- */
2486
- element: CommentBodyMention;
2487
- /**
2488
- * The mention's user info, if the `resolvedUsers` option was provided.
2489
- */
2490
- user?: TUserMeta["info"];
2491
- };
2492
- declare type StringifyCommentBodyElements<TUserMeta extends BaseUserMeta = BaseUserMeta> = {
2493
- /**
2494
- * The element used to display paragraphs.
2495
- */
2496
- paragraph: (args: CommentBodyParagraphElementArgs, index: number) => string;
2497
- /**
2498
- * The element used to display text elements.
2499
- */
2500
- text: (args: CommentBodyTextElementArgs, index: number) => string;
2501
- /**
2502
- * The element used to display links.
2503
- */
2504
- link: (args: CommentBodyLinkElementArgs, index: number) => string;
2505
- /**
2506
- * The element used to display mentions.
2507
- */
2508
- mention: (args: CommentBodyMentionElementArgs<TUserMeta>, index: number) => string;
2509
- };
2510
- declare type StringifyCommentBodyOptions<TUserMeta extends BaseUserMeta = BaseUserMeta> = {
2511
- /**
2512
- * Which format to convert the comment to.
2513
- */
2514
- format?: "plain" | "html" | "markdown";
2515
- /**
2516
- * The elements used to customize the resulting string. Each element has
2517
- * priority over the defaults inherited from the `format` option.
2518
- */
2519
- elements?: Partial<StringifyCommentBodyElements<TUserMeta>>;
2520
- /**
2521
- * The separator used between paragraphs.
2522
- */
2523
- separator?: string;
2524
- /**
2525
- * A function that returns user info from user IDs.
2526
- */
2527
- resolveUsers?: (args: CommentBodyResolveUsersArgs) => PromiseOrNot<(TUserMeta["info"] | undefined)[] | undefined>;
2528
- };
2529
- /**
2530
- * Get an array of each user's ID that has been mentioned in a `CommentBody`.
2531
- */
2532
- declare function getMentionedIdsFromCommentBody(body: CommentBody): string[];
2533
- /**
2534
- * Convert a `CommentBody` into either a plain string,
2535
- * Markdown, HTML, or a custom format.
2536
- */
2537
- declare function stringifyCommentBody<TUserMeta extends BaseUserMeta = BaseUserMeta>(body: CommentBody, options?: StringifyCommentBodyOptions<TUserMeta>): Promise<string>;
2538
- /**
2539
- * Converts a plain comment data object (usually returned by the API) to a comment data object that can be used by the client.
2540
- * This is necessary because the plain data object stores dates as ISO strings, but the client expects them as Date objects.
2541
- * @param data The plain comment data object (usually returned by the API)
2542
- * @returns The rich comment data object that can be used by the client.
2543
- */
2544
- declare function convertToCommentData(data: CommentDataPlain): CommentData;
2545
- /**
2546
- * Converts a plain thread data object (usually returned by the API) to a thread data object that can be used by the client.
2547
- * This is necessary because the plain data object stores dates as ISO strings, but the client expects them as Date objects.
2548
- * @param data The plain thread data object (usually returned by the API)
2549
- * @returns The rich hread data object that can be used by the client.
2550
- */
2551
- declare function convertToThreadData<TThreadMetadata extends BaseMetadata = never>(data: ThreadDataPlain<TThreadMetadata>): ThreadData<TThreadMetadata>;
2552
- /**
2553
- * Converts a plain comment reaction object (usually returned by the API) to a comment reaction object that can be used by the client.
2554
- * This is necessary because the plain data object stores dates as ISO strings, but the client expects them as Date objects.
2555
- * @param data The plain comment reaction object (usually returned by the API)
2556
- * @returns The rich comment reaction object that can be used by the client.
2557
- */
2558
- declare function convertToCommentUserReaction(data: CommentUserReactionPlain): CommentUserReaction;
2559
-
2560
2804
  /**
2561
2805
  * Helper type to help users adopt to Lson types from interface definitions.
2562
2806
  * You should only use this to wrap interfaces you don't control. For more
2563
2807
  * information, see
2564
2808
  * https://liveblocks.io/docs/guides/limits#lson-constraint-and-interfaces
2565
2809
  */
2566
- declare type EnsureJson<T> = [
2810
+ declare type EnsureJson<T> = T extends Json ? T : T extends Array<infer I> ? (EnsureJson<I>)[] : [
2567
2811
  unknown
2568
- ] extends [T] ? T : T extends (...args: unknown[]) => unknown ? T : {
2569
- [K in keyof T]: EnsureJson<T[K]>;
2812
+ ] extends [T] ? Json | undefined : T extends Date ? string : T extends (...args: any[]) => any ? never : {
2813
+ [K in keyof T as EnsureJson<T[K]> extends never ? never : K]: EnsureJson<T[K]>;
2570
2814
  };
2571
2815
 
2572
- export { type AckOp, type AsyncCache, type AsyncState, type AsyncStateError, type AsyncStateInitial, type AsyncStateLoading, type AsyncStateResolved, type AsyncStateSuccess, type BaseAuthResult, type BaseMetadata, type BaseUserMeta, type Brand, type BroadcastEventClientMsg, type BroadcastOptions, type BroadcastedEventServerMsg, type Client, type ClientMsg, ClientMsgCode, type CommentBody, type CommentBodyBlockElement, type CommentBodyElement, type CommentBodyInlineElement, type CommentBodyLink, type CommentBodyLinkElementArgs, type CommentBodyMention, type CommentBodyMentionElementArgs, type CommentBodyParagraph, type CommentBodyParagraphElementArgs, type CommentBodyResolveUsersArgs, type CommentBodyText, type CommentBodyTextElementArgs, type CommentData, type CommentDataPlain, type CommentReaction, type CommentUserReaction, type CommentUserReactionPlain, type CommentsApi, CommentsApiError, CrdtType, type CreateListOp, type CreateMapOp, type CreateObjectOp, type CreateOp, type CreateRegisterOp, type CustomAuthenticationResult, type Delegates, type DeleteCrdtOp, type DeleteObjectKeyOp, DevToolsTreeNode as DevTools, protocol as DevToolsMsg, type EnsureJson, type EnterOptions, type EventSource, type FetchStorageClientMsg, type FetchYDocClientMsg, type History, type IUserInfo, type IWebSocket, type IWebSocketCloseEvent, type IWebSocketEvent, type IWebSocketInstance, type IWebSocketMessageEvent, type IdTuple, type Immutable, type InitialDocumentStateServerMsg, type Json, type JsonArray, type JsonObject, type JsonScalar, type LegacyConnectionStatus, LiveList, type LiveListUpdate, LiveMap, type LiveMapUpdate, type LiveNode, LiveObject, type LiveObjectUpdate, type LiveStructure, type LostConnectionEvent, type Lson, type LsonObject, type NodeMap, type Op, OpCode, type Others, type OthersEvent, type ParentToChildNodeMap, type PlainLson, type PlainLsonFields, type PlainLsonList, type PlainLsonMap, type PlainLsonObject, type RejectedStorageOpServerMsg, type Resolve, type Room, type RoomEventMessage, type RoomInitializers, type RoomStateServerMsg, type SerializedChild, type SerializedCrdt, type SerializedList, type SerializedMap, type SerializedObject, type SerializedRegister, type SerializedRootObject, type ServerMsg, ServerMsgCode, type SetParentKeyOp, type Status, type StorageStatus, type StorageUpdate, type StringifyCommentBodyElements, type StringifyCommentBodyOptions, type ThreadData, type ThreadDataPlain, type ThreadsFilterOptions, type ToImmutable, type ToJson, type UnsubscribeCallback, type UpdateObjectOp, type UpdatePresenceClientMsg, type UpdatePresenceServerMsg, type UpdateStorageClientMsg, type UpdateStorageServerMsg, type UpdateYDocClientMsg, type User, type UserJoinServerMsg, type UserLeftServerMsg, WebsocketCloseCodes, type YDocUpdateServerMsg, asPos, assert, assertNever, b64decode, cloneLson, fancyConsole as console, convertToCommentData, convertToCommentUserReaction, convertToThreadData, createAsyncCache, createClient, createCommentsApi, deprecate, deprecateIf, detectDupes, errorIf, freeze, getMentionedIdsFromCommentBody, isChildCrdt, isJsonArray, isJsonObject, isJsonScalar, isLiveNode, isPlainObject, isRootCrdt, legacy_patchImmutableObject, lsonToJson, makeEventSource, makePoller, makePosition, nn, patchLiveObjectKey, raise, shallow, stringify, stringifyCommentBody, throwUsageError, toPlainLson, tryParseJson, withTimeout };
2816
+ export { type AckOp, type ActivityData, type BaseActivitiesData, type BaseAuthResult, type BaseMetadata, type BaseRoomInfo, type BaseUserMeta, type Brand, type BroadcastEventClientMsg, type BroadcastOptions, type BroadcastedEventServerMsg, type CacheState, type CacheStore, type Client, type ClientMsg, ClientMsgCode, type ClientOptions, type CommentBody, type CommentBodyBlockElement, type CommentBodyElement, type CommentBodyInlineElement, type CommentBodyLink, type CommentBodyLinkElementArgs, type CommentBodyMention, type CommentBodyMentionElementArgs, type CommentBodyParagraph, type CommentBodyParagraphElementArgs, type CommentBodyText, type CommentBodyTextElementArgs, type CommentData, type CommentDataPlain, type CommentReaction, type CommentUserReaction, type CommentUserReactionPlain, CommentsApiError, type CommentsEventServerMsg, CrdtType, type CreateListOp, type CreateMapOp, type CreateObjectOp, type CreateOp, type CreateRegisterOp, type CustomAuthenticationResult, type DAD, type DE, type DM, type DP, type DRI, type DS, type DU, type Delegates, type DeleteCrdtOp, type DeleteObjectKeyOp, DevToolsTreeNode as DevTools, protocol as DevToolsMsg, type EnsureJson, type EnterOptions, type EventSource, type FetchStorageClientMsg, type FetchYDocClientMsg, type GetThreadsOptions, type History, type IUserInfo, type IWebSocket, type IWebSocketCloseEvent, type IWebSocketEvent, type IWebSocketInstance, type IWebSocketMessageEvent, type IdTuple, type Immutable, type InboxNotificationCustomData, type InboxNotificationCustomDataPlain, type InboxNotificationData, type InboxNotificationDataPlain, type InboxNotificationDeleteInfo, type InboxNotificationTextMentionData, type InboxNotificationTextMentionDataPlain, type InboxNotificationThreadData, type InboxNotificationThreadDataPlain, type InitialDocumentStateServerMsg, type Json, type JsonArray, type JsonObject, type JsonScalar, LiveList, type LiveListUpdate, LiveMap, type LiveMapUpdate, type LiveNode, LiveObject, type LiveObjectUpdate, type LiveStructure, LiveblocksError, type LostConnectionEvent, type Lson, type LsonObject, type NodeMap, NotificationsApiError, type Op, OpCode, type OpaqueClient, type OpaqueRoom, type OptionalPromise, type OthersEvent, type ParentToChildNodeMap, type Patchable, type PlainLson, type PlainLsonFields, type PlainLsonList, type PlainLsonMap, type PlainLsonObject, type PrivateClientApi, type PrivateRoomApi, type QueryMetadata, type RejectedStorageOpServerMsg, type Resolve, type ResolveMentionSuggestionsArgs, type ResolveRoomsInfoArgs, type ResolveUsersArgs, type Room, type RoomEventMessage, type RoomInitializers, type RoomNotificationSettings, type RoomStateServerMsg, type SerializedChild, type SerializedCrdt, type SerializedList, type SerializedMap, type SerializedObject, type SerializedRegister, type SerializedRootObject, type ServerMsg, ServerMsgCode, type SetParentKeyOp, type Status, type StorageStatus, type StorageUpdate, type Store, type StringifyCommentBodyElements, type StringifyCommentBodyOptions, type ThreadData, type ThreadDataPlain, type ThreadDeleteInfo, type ToImmutable, type ToJson, type UnsubscribeCallback, type UpdateObjectOp, type UpdatePresenceClientMsg, type UpdatePresenceServerMsg, type UpdateStorageClientMsg, type UpdateStorageServerMsg, type UpdateYDocClientMsg, type User, type UserJoinServerMsg, type UserLeftServerMsg, WebsocketCloseCodes, type YDocUpdateServerMsg, ackOp, addReaction, applyOptimisticUpdates, asPos, assert, assertNever, b64decode, cloneLson, fancyConsole as console, convertToCommentData, convertToCommentUserReaction, convertToInboxNotificationData, convertToThreadData, createClient, deleteComment, deprecate, deprecateIf, detectDupes, errorIf, freeze, getMentionedIdsFromCommentBody, isChildCrdt, isJsonArray, isJsonObject, isJsonScalar, isLiveNode, isPlainObject, isRootCrdt, kInternal, legacy_patchImmutableObject, lsonToJson, makeEventSource, makePoller, makePosition, nn, objectToQuery, patchLiveObjectKey, raise, removeReaction, shallow, stringify, stringifyCommentBody, throwUsageError, toPlainLson, tryParseJson, upsertComment, withTimeout };