@xmtp/browser-sdk 1.1.3 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,20 +11,28 @@ import type {
11
11
  SafeMessage,
12
12
  } from "@/utils/conversions";
13
13
  import { nsToDate } from "@/utils/date";
14
+ import { MissingContentTypeError } from "@/utils/errors";
14
15
 
16
+ /**
17
+ * Represents a conversation
18
+ *
19
+ * This class is not intended to be initialized directly.
20
+ */
15
21
  export class Conversation {
22
+ #addedByInboxId?: SafeConversation["addedByInboxId"];
16
23
  #client: Client;
17
-
24
+ #createdAtNs?: SafeConversation["createdAtNs"];
18
25
  #id: string;
19
-
20
26
  #isActive?: SafeConversation["isActive"];
21
-
22
- #addedByInboxId?: SafeConversation["addedByInboxId"];
23
-
24
27
  #metadata?: SafeConversation["metadata"];
25
28
 
26
- #createdAtNs?: SafeConversation["createdAtNs"];
27
-
29
+ /**
30
+ * Creates a new conversation instance
31
+ *
32
+ * @param client - The client instance managing the conversation
33
+ * @param id - The unique identifier for this conversation
34
+ * @param data - Optional conversation data to initialize with
35
+ */
28
36
  constructor(client: Client, id: string, data?: SafeConversation) {
29
37
  this.#client = client;
30
38
  this.#id = id;
@@ -62,12 +70,22 @@ export class Conversation {
62
70
  return this.#metadata;
63
71
  }
64
72
 
73
+ /**
74
+ * Gets the conversation members
75
+ *
76
+ * @returns Promise that resolves with the conversation members
77
+ */
65
78
  async members() {
66
79
  return this.#client.sendMessage("getGroupMembers", {
67
80
  id: this.#id,
68
81
  });
69
82
  }
70
83
 
84
+ /**
85
+ * Synchronizes conversation data from the network
86
+ *
87
+ * @returns Promise that resolves with the updated conversation data
88
+ */
71
89
  async sync() {
72
90
  const data = await this.#client.sendMessage("syncGroup", {
73
91
  id: this.#id,
@@ -76,17 +94,28 @@ export class Conversation {
76
94
  return data;
77
95
  }
78
96
 
97
+ /**
98
+ * Publishes pending messages that were sent optimistically
99
+ *
100
+ * @returns Promise that resolves when publishing is complete
101
+ */
79
102
  async publishMessages() {
80
103
  return this.#client.sendMessage("publishGroupMessages", {
81
104
  id: this.#id,
82
105
  });
83
106
  }
84
107
 
108
+ /**
109
+ * Sends a message optimistically
110
+ *
111
+ * @param content - The content to send
112
+ * @param contentType - Optional content type of the message content
113
+ * @returns Promise that resolves with the message ID
114
+ * @throws {MissingContentTypeError} When content type is required but not provided
115
+ */
85
116
  async sendOptimistic(content: any, contentType?: ContentTypeId) {
86
117
  if (typeof content !== "string" && !contentType) {
87
- throw new Error(
88
- "Content type is required when sending content other than text",
89
- );
118
+ throw new MissingContentTypeError();
90
119
  }
91
120
 
92
121
  const safeEncodedContent =
@@ -101,11 +130,17 @@ export class Conversation {
101
130
  });
102
131
  }
103
132
 
133
+ /**
134
+ * Sends a message
135
+ *
136
+ * @param content - The content to send
137
+ * @param contentType - Optional content type of the message content
138
+ * @returns Promise that resolves with the message ID after it has been sent
139
+ * @throws {MissingContentTypeError} When content type is required but not provided
140
+ */
104
141
  async send(content: any, contentType?: ContentTypeId) {
105
142
  if (typeof content !== "string" && !contentType) {
106
- throw new Error(
107
- "Content type is required when sending content other than text",
108
- );
143
+ throw new MissingContentTypeError();
109
144
  }
110
145
 
111
146
  const safeEncodedContent =
@@ -120,6 +155,12 @@ export class Conversation {
120
155
  });
121
156
  }
122
157
 
158
+ /**
159
+ * Lists messages in this conversation
160
+ *
161
+ * @param options - Optional filtering and pagination options
162
+ * @returns Promise that resolves with an array of decoded messages
163
+ */
123
164
  async messages(options?: SafeListMessagesOptions) {
124
165
  const messages = await this.#client.sendMessage("getGroupMessages", {
125
166
  id: this.#id,
@@ -129,12 +170,23 @@ export class Conversation {
129
170
  return messages.map((message) => new DecodedMessage(this.#client, message));
130
171
  }
131
172
 
173
+ /**
174
+ * Gets the consent state for this conversation
175
+ *
176
+ * @returns Promise that resolves with the current consent state
177
+ */
132
178
  async consentState() {
133
179
  return this.#client.sendMessage("getGroupConsentState", {
134
180
  id: this.#id,
135
181
  });
136
182
  }
137
183
 
184
+ /**
185
+ * Updates the consent state for this conversation
186
+ *
187
+ * @param state - The new consent state to set
188
+ * @returns Promise that resolves when the update is complete
189
+ */
138
190
  async updateConsentState(state: ConsentState) {
139
191
  return this.#client.sendMessage("updateGroupConsentState", {
140
192
  id: this.#id,
@@ -142,12 +194,24 @@ export class Conversation {
142
194
  });
143
195
  }
144
196
 
197
+ /**
198
+ * Gets the message disappearing settings for this conversation
199
+ *
200
+ * @returns Promise that resolves with the current message disappearing settings
201
+ */
145
202
  async messageDisappearingSettings() {
146
203
  return this.#client.sendMessage("getGroupMessageDisappearingSettings", {
147
204
  id: this.#id,
148
205
  });
149
206
  }
150
207
 
208
+ /**
209
+ * Updates message disappearing settings for this conversation
210
+ *
211
+ * @param fromNs - The timestamp from which messages should start disappearing
212
+ * @param inNs - The duration after which messages should disappear
213
+ * @returns Promise that resolves when the update is complete
214
+ */
151
215
  async updateMessageDisappearingSettings(fromNs: bigint, inNs: bigint) {
152
216
  return this.#client.sendMessage("updateGroupMessageDisappearingSettings", {
153
217
  id: this.#id,
@@ -156,18 +220,34 @@ export class Conversation {
156
220
  });
157
221
  }
158
222
 
223
+ /**
224
+ * Removes message disappearing settings from this conversation
225
+ *
226
+ * @returns Promise that resolves when the settings are removed
227
+ */
159
228
  async removeMessageDisappearingSettings() {
160
229
  return this.#client.sendMessage("removeGroupMessageDisappearingSettings", {
161
230
  id: this.#id,
162
231
  });
163
232
  }
164
233
 
234
+ /**
235
+ * Checks if message disappearing is enabled for this conversation
236
+ *
237
+ * @returns Promise that resolves with whether message disappearing is enabled
238
+ */
165
239
  async isMessageDisappearingEnabled() {
166
240
  return this.#client.sendMessage("isGroupMessageDisappearingEnabled", {
167
241
  id: this.#id,
168
242
  });
169
243
  }
170
244
 
245
+ /**
246
+ * Creates a stream for new messages in this conversation
247
+ *
248
+ * @param callback - Optional callback function for handling new stream values
249
+ * @returns AsyncStream instance for new messages
250
+ */
171
251
  async stream(callback?: StreamCallback<DecodedMessage>) {
172
252
  const streamId = v4();
173
253
  const asyncStream = new AsyncStream<DecodedMessage>();
@@ -205,4 +285,15 @@ export class Conversation {
205
285
  id: this.#id,
206
286
  });
207
287
  }
288
+
289
+ /**
290
+ * Retrieves HMAC keys for this conversation
291
+ *
292
+ * @returns Promise that resolves with the HMAC keys
293
+ */
294
+ async getHmacKeys() {
295
+ return this.#client.sendMessage("getGroupHmacKeys", {
296
+ id: this.#id,
297
+ });
298
+ }
208
299
  }
@@ -17,23 +17,52 @@ import type {
17
17
  SafeMessage,
18
18
  } from "@/utils/conversions";
19
19
 
20
+ /**
21
+ * Manages conversations
22
+ *
23
+ * This class is not intended to be initialized directly.
24
+ */
20
25
  export class Conversations {
21
26
  #client: Client;
22
27
 
28
+ /**
29
+ * Creates a new conversations instance
30
+ *
31
+ * @param client - The client instance managing the conversations
32
+ */
23
33
  constructor(client: Client) {
24
34
  this.#client = client;
25
35
  }
26
36
 
37
+ /**
38
+ * Synchronizes conversations for the current client from the network
39
+ *
40
+ * @returns Promise that resolves when sync is complete
41
+ */
27
42
  async sync() {
28
43
  return this.#client.sendMessage("syncConversations", undefined);
29
44
  }
30
45
 
46
+ /**
47
+ * Synchronizes all conversations and messages from the network with optional
48
+ * consent state filtering, then uploads conversation and message history to
49
+ * the history sync server
50
+ *
51
+ * @param consentStates - Optional array of consent states to filter by
52
+ * @returns Promise that resolves when sync is complete
53
+ */
31
54
  async syncAll(consentStates?: ConsentState[]) {
32
55
  return this.#client.sendMessage("syncAllConversations", {
33
56
  consentStates,
34
57
  });
35
58
  }
36
59
 
60
+ /**
61
+ * Retrieves a conversation by its ID
62
+ *
63
+ * @param id - The conversation ID to look up
64
+ * @returns Promise that resolves with the conversation, if found
65
+ */
37
66
  async getConversationById(id: string) {
38
67
  const data = await this.#client.sendMessage("getConversationById", {
39
68
  id,
@@ -46,6 +75,12 @@ export class Conversations {
46
75
  return undefined;
47
76
  }
48
77
 
78
+ /**
79
+ * Retrieves a message by its ID
80
+ *
81
+ * @param id - The message ID to look up
82
+ * @returns Promise that resolves with the decoded message, if found
83
+ */
49
84
  async getMessageById(id: string) {
50
85
  const data = await this.#client.sendMessage("getMessageById", {
51
86
  id,
@@ -53,6 +88,12 @@ export class Conversations {
53
88
  return data ? new DecodedMessage(this.#client, data) : undefined;
54
89
  }
55
90
 
91
+ /**
92
+ * Retrieves a DM by inbox ID
93
+ *
94
+ * @param inboxId - The inbox ID to look up
95
+ * @returns Promise that resolves with the DM, if found
96
+ */
56
97
  async getDmByInboxId(inboxId: string) {
57
98
  const data = await this.#client.sendMessage("getDmByInboxId", {
58
99
  inboxId,
@@ -60,6 +101,12 @@ export class Conversations {
60
101
  return data ? new Dm(this.#client, data.id, data) : undefined;
61
102
  }
62
103
 
104
+ /**
105
+ * Lists all conversations with optional filtering
106
+ *
107
+ * @param options - Optional filtering and pagination options
108
+ * @returns Promise that resolves with an array of conversations
109
+ */
63
110
  async list(options?: SafeListConversationsOptions) {
64
111
  const conversations = await this.#client.sendMessage("getConversations", {
65
112
  options,
@@ -72,6 +119,12 @@ export class Conversations {
72
119
  );
73
120
  }
74
121
 
122
+ /**
123
+ * Lists all group conversations with optional filtering
124
+ *
125
+ * @param options - Optional filtering and pagination options
126
+ * @returns Promise that resolves with an array of groups
127
+ */
75
128
  async listGroups(
76
129
  options?: Omit<SafeListConversationsOptions, "conversation_type">,
77
130
  ) {
@@ -84,6 +137,12 @@ export class Conversations {
84
137
  );
85
138
  }
86
139
 
140
+ /**
141
+ * Lists all DM conversations with optional filtering
142
+ *
143
+ * @param options - Optional filtering and pagination options
144
+ * @returns Promise that resolves with an array of DMs
145
+ */
87
146
  async listDms(
88
147
  options?: Omit<SafeListConversationsOptions, "conversation_type">,
89
148
  ) {
@@ -96,6 +155,13 @@ export class Conversations {
96
155
  );
97
156
  }
98
157
 
158
+ /**
159
+ * Creates a new group conversation with the specified identifiers
160
+ *
161
+ * @param identifiers - Array of identifiers for group members
162
+ * @param options - Optional group creation options
163
+ * @returns Promise that resolves with the new group
164
+ */
99
165
  async newGroupWithIdentifiers(
100
166
  identifiers: Identifier[],
101
167
  options?: SafeCreateGroupOptions,
@@ -111,6 +177,13 @@ export class Conversations {
111
177
  return new Group(this.#client, conversation.id, conversation);
112
178
  }
113
179
 
180
+ /**
181
+ * Creates a new group conversation with the specified inbox IDs
182
+ *
183
+ * @param inboxIds - Array of inbox IDs for group members
184
+ * @param options - Optional group creation options
185
+ * @returns Promise that resolves with the new group
186
+ */
114
187
  async newGroup(inboxIds: string[], options?: SafeCreateGroupOptions) {
115
188
  const conversation = await this.#client.sendMessage(
116
189
  "newGroupWithInboxIds",
@@ -123,6 +196,13 @@ export class Conversations {
123
196
  return new Group(this.#client, conversation.id, conversation);
124
197
  }
125
198
 
199
+ /**
200
+ * Creates a new DM conversation with the specified identifier
201
+ *
202
+ * @param identifier - Identifier for the DM recipient
203
+ * @param options - Optional DM creation options
204
+ * @returns Promise that resolves with the new DM
205
+ */
126
206
  async newDmWithIdentifier(
127
207
  identifier: Identifier,
128
208
  options?: SafeCreateDmOptions,
@@ -135,6 +215,13 @@ export class Conversations {
135
215
  return new Dm(this.#client, conversation.id, conversation);
136
216
  }
137
217
 
218
+ /**
219
+ * Creates a new DM conversation with the specified inbox ID
220
+ *
221
+ * @param inboxId - Inbox ID for the DM recipient
222
+ * @param options - Optional DM creation options
223
+ * @returns Promise that resolves with the new DM
224
+ */
138
225
  async newDm(inboxId: string, options?: SafeCreateDmOptions) {
139
226
  const conversation = await this.#client.sendMessage("newDmWithInboxId", {
140
227
  inboxId,
@@ -144,10 +231,22 @@ export class Conversations {
144
231
  return new Dm(this.#client, conversation.id, conversation);
145
232
  }
146
233
 
234
+ /**
235
+ * Retrieves HMAC keys for all conversations
236
+ *
237
+ * @returns Promise that resolves with the HMAC keys for all conversations
238
+ */
147
239
  async getHmacKeys() {
148
240
  return this.#client.sendMessage("getHmacKeys", undefined);
149
241
  }
150
242
 
243
+ /**
244
+ * Creates a stream for new conversations
245
+ *
246
+ * @param callback - Optional callback function for handling new stream value
247
+ * @param conversationType - Optional type to filter conversations
248
+ * @returns AsyncStream instance for new conversations
249
+ */
151
250
  async stream<T extends Group | Dm = Group | Dm>(
152
251
  callback?: StreamCallback<T>,
153
252
  conversationType?: ConversationType,
@@ -189,14 +288,33 @@ export class Conversations {
189
288
  return asyncStream;
190
289
  }
191
290
 
291
+ /**
292
+ * Creates a stream for new group conversations
293
+ *
294
+ * @param callback - Optional callback function for handling new stream value
295
+ * @returns AsyncStream instance for new group conversations
296
+ */
192
297
  async streamGroups(callback?: StreamCallback<Group>) {
193
298
  return this.stream<Group>(callback, ConversationType.Group);
194
299
  }
195
300
 
301
+ /**
302
+ * Creates a stream for new DM conversations
303
+ *
304
+ * @param callback - Optional callback function for handling new stream value
305
+ * @returns AsyncStream instance for new DM conversations
306
+ */
196
307
  async streamDms(callback?: StreamCallback<Dm>) {
197
308
  return this.stream<Dm>(callback, ConversationType.Dm);
198
309
  }
199
310
 
311
+ /**
312
+ * Creates a stream for all new messages
313
+ *
314
+ * @param callback - Optional callback function for handling new stream value
315
+ * @param conversationType - Optional conversation type to filter messages
316
+ * @returns AsyncStream instance for new messages
317
+ */
200
318
  async streamAllMessages(
201
319
  callback?: StreamCallback<DecodedMessage>,
202
320
  conversationType?: ConversationType,
@@ -232,10 +350,22 @@ export class Conversations {
232
350
  return asyncStream;
233
351
  }
234
352
 
353
+ /**
354
+ * Creates a stream for all new group messages
355
+ *
356
+ * @param callback - Optional callback function for handling new stream value
357
+ * @returns AsyncStream instance for new group messages
358
+ */
235
359
  async streamAllGroupMessages(callback?: StreamCallback<DecodedMessage>) {
236
360
  return this.streamAllMessages(callback, ConversationType.Group);
237
361
  }
238
362
 
363
+ /**
364
+ * Creates a stream for all new DM messages
365
+ *
366
+ * @param callback - Optional callback function for handling new stream value
367
+ * @returns AsyncStream instance for new DM messages
368
+ */
239
369
  async streamAllDmMessages(callback?: StreamCallback<DecodedMessage>) {
240
370
  return this.streamAllMessages(callback, ConversationType.Dm);
241
371
  }
@@ -6,31 +6,39 @@ import { fromSafeContentTypeId, type SafeMessage } from "@/utils/conversions";
6
6
  export type MessageKind = "application" | "membership_change";
7
7
  export type MessageDeliveryStatus = "unpublished" | "published" | "failed";
8
8
 
9
+ /**
10
+ * Represents a decoded XMTP message
11
+ *
12
+ * This class transforms network messages into a structured format with
13
+ * content decoding.
14
+ *
15
+ * @class
16
+ * @property {any} content - The decoded content of the message
17
+ * @property {ContentTypeId} contentType - The content type of the message content
18
+ * @property {string} conversationId - Unique identifier for the conversation
19
+ * @property {MessageDeliveryStatus} deliveryStatus - Current delivery status of the message ("unpublished" | "published" | "failed")
20
+ * @property {string} [fallback] - Optional fallback text for the message
21
+ * @property {number} [compression] - Optional compression level applied to the message
22
+ * @property {string} id - Unique identifier for the message
23
+ * @property {MessageKind} kind - Type of message ("application" | "membership_change")
24
+ * @property {Map<string, string>} parameters - Additional parameters associated with the message
25
+ * @property {SafeMessage["content"]} encodedContent - Raw encoded content of the message
26
+ * @property {string} senderInboxId - Identifier for the sender's inbox
27
+ * @property {bigint} sentAtNs - Timestamp when the message was sent (in nanoseconds)
28
+ */
9
29
  export class DecodedMessage {
10
30
  #client: Client;
11
-
12
31
  content: any;
13
-
14
32
  contentType: ContentTypeId;
15
-
16
33
  conversationId: string;
17
-
18
34
  deliveryStatus: MessageDeliveryStatus;
19
-
20
35
  fallback?: string;
21
-
22
36
  compression?: number;
23
-
24
37
  id: string;
25
-
26
38
  kind: MessageKind;
27
-
28
39
  parameters: Map<string, string>;
29
-
30
40
  encodedContent: SafeMessage["content"];
31
-
32
41
  senderInboxId: string;
33
-
34
42
  sentAtNs: bigint;
35
43
 
36
44
  constructor(client: Client, message: SafeMessage) {
package/src/Dm.ts CHANGED
@@ -2,17 +2,33 @@ import type { Client } from "@/Client";
2
2
  import { Conversation } from "@/Conversation";
3
3
  import type { SafeConversation } from "@/utils/conversions";
4
4
 
5
+ /**
6
+ * Represents a direct message conversation between two inboxes
7
+ *
8
+ * This class is not intended to be initialized directly.
9
+ */
5
10
  export class Dm extends Conversation {
6
11
  #client: Client;
7
-
8
12
  #id: string;
9
13
 
14
+ /**
15
+ * Creates a new direct message conversation instance
16
+ *
17
+ * @param client - The client instance managing this direct message conversation
18
+ * @param id - Identifier for the direct message conversation
19
+ * @param data - Optional conversation data to initialize with
20
+ */
10
21
  constructor(client: Client, id: string, data?: SafeConversation) {
11
22
  super(client, id, data);
12
23
  this.#client = client;
13
24
  this.#id = id;
14
25
  }
15
26
 
27
+ /**
28
+ * Retrieves the inbox ID of the other participant in the DM
29
+ *
30
+ * @returns Promise that resolves with the peer's inbox ID
31
+ */
16
32
  async peerInboxId() {
17
33
  return this.#client.sendMessage("getDmPeerInboxId", {
18
34
  id: this.#id,