@xmtp/browser-sdk 5.3.0 → 6.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/index.d.ts +541 -671
  2. package/dist/index.js +1 -1
  3. package/dist/index.js.map +1 -1
  4. package/dist/workers/client.js +1 -1
  5. package/dist/workers/client.js.map +1 -1
  6. package/dist/workers/opfs.js +2 -0
  7. package/dist/workers/opfs.js.map +1 -0
  8. package/package.json +12 -16
  9. package/src/Client.ts +92 -219
  10. package/src/CodecRegistry.ts +27 -0
  11. package/src/Conversation.ts +275 -104
  12. package/src/Conversations.ts +188 -99
  13. package/src/DebugInformation.ts +10 -27
  14. package/src/DecodedMessage.ts +155 -58
  15. package/src/Dm.ts +25 -9
  16. package/src/Group.ts +30 -29
  17. package/src/Opfs.ts +63 -0
  18. package/src/Preferences.ts +68 -52
  19. package/src/WorkerClient.ts +5 -5
  20. package/src/WorkerConversation.ts +98 -45
  21. package/src/WorkerConversations.ts +35 -74
  22. package/src/WorkerDebugInformation.ts +1 -12
  23. package/src/WorkerPreferences.ts +6 -14
  24. package/src/index.ts +54 -24
  25. package/src/types/actions/client.ts +6 -17
  26. package/src/types/actions/conversation.ts +160 -31
  27. package/src/types/actions/conversations.ts +21 -24
  28. package/src/types/actions/debugInformation.ts +3 -11
  29. package/src/types/actions/dm.ts +1 -1
  30. package/src/types/actions/opfs.ts +66 -0
  31. package/src/types/actions/preferences.ts +6 -13
  32. package/src/types/actions/streams.ts +8 -8
  33. package/src/types/actions.ts +11 -9
  34. package/src/types/options.ts +46 -6
  35. package/src/{ClientWorkerClass.ts → utils/WorkerBridge.ts} +35 -45
  36. package/src/utils/contentTypes.ts +77 -0
  37. package/src/utils/conversions.ts +17 -590
  38. package/src/utils/createClient.ts +16 -11
  39. package/src/utils/errors.ts +13 -19
  40. package/src/utils/inboxId.ts +46 -0
  41. package/src/utils/inboxState.ts +23 -0
  42. package/src/utils/installations.ts +95 -0
  43. package/src/utils/metadata.ts +15 -0
  44. package/src/utils/signer.ts +4 -4
  45. package/src/utils/uuid.ts +8 -0
  46. package/src/workers/client.ts +176 -135
  47. package/src/workers/opfs.ts +127 -0
  48. package/dist/workers/utils.js +0 -2
  49. package/dist/workers/utils.js.map +0 -1
  50. package/src/Utils.ts +0 -143
  51. package/src/UtilsWorkerClass.ts +0 -121
  52. package/src/types/actions/utils.ts +0 -69
  53. package/src/workers/utils.ts +0 -155
@@ -1,89 +1,186 @@
1
- import type { ContentTypeId } from "@xmtp/content-type-primitives";
2
- import { DeliveryStatus, GroupMessageKind } from "@xmtp/wasm-bindings";
3
- import type { Client } from "@/Client";
4
- import { fromSafeContentTypeId, type SafeMessage } from "@/utils/conversions";
1
+ import {
2
+ contentTypeToString,
3
+ type EncodedContent,
4
+ } from "@xmtp/content-type-primitives";
5
+ import type {
6
+ ContentTypeId,
7
+ DecodedMessageContent,
8
+ DeliveryStatus,
9
+ GroupMessageKind,
10
+ Reaction,
11
+ DecodedMessage as XmtpDecodedMessage,
12
+ } from "@xmtp/wasm-bindings";
13
+ import type { CodecRegistry } from "@/CodecRegistry";
14
+ import { nsToDate } from "@/utils/date";
5
15
 
6
- export type MessageKind = "application" | "membership_change";
7
- export type MessageDeliveryStatus = "unpublished" | "published" | "failed";
16
+ const getContentFromDecodedMessageContent = <T = unknown>(
17
+ content: DecodedMessageContent,
18
+ ): T => {
19
+ switch (content.type) {
20
+ case "text": {
21
+ return content.content as T;
22
+ }
23
+ case "markdown": {
24
+ return content.content as T;
25
+ }
26
+ case "reply": {
27
+ return content.content as T;
28
+ }
29
+ case "reaction": {
30
+ return content.content as T;
31
+ }
32
+ case "attachment": {
33
+ return content.content as T;
34
+ }
35
+ case "remoteAttachment": {
36
+ return content.content as T;
37
+ }
38
+ case "multiRemoteAttachment": {
39
+ return content.content as T;
40
+ }
41
+ case "transactionReference": {
42
+ return content.content as T;
43
+ }
44
+ case "groupUpdated": {
45
+ return content.content as T;
46
+ }
47
+ case "readReceipt": {
48
+ return content.content as T;
49
+ }
50
+ case "leaveRequest": {
51
+ return content.content as T;
52
+ }
53
+ case "walletSendCalls": {
54
+ return content.content as T;
55
+ }
56
+ case "intent": {
57
+ return content.content as T;
58
+ }
59
+ case "actions": {
60
+ return content.content as T;
61
+ }
62
+ case "custom": {
63
+ return content.content as T;
64
+ }
65
+ default:
66
+ content satisfies never;
67
+ return null as T;
68
+ }
69
+ };
8
70
 
9
71
  /**
10
72
  * Represents a decoded XMTP message
11
73
  *
12
- * This class transforms network messages into a structured format with
13
- * content decoding.
14
- *
15
74
  * @class
16
- * @property {any} content - The decoded content of the message
75
+ * @property {unknown} content - The decoded content of the message
17
76
  * @property {ContentTypeId} contentType - The content type of the message content
18
77
  * @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
78
+ * @property {DeliveryStatus} deliveryStatus - Current delivery status of the message ("unpublished" | "published" | "failed")
79
+ * @property {bigint} expiresAtNs - Timestamp when the message will expire (in nanoseconds)
80
+ * @property {Date} expiresAt - Timestamp when the message will expire
81
+ * @property {string} fallback - Optional fallback text for the message
22
82
  * @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
83
+ * @property {GroupMessageKind} kind - Type of message ("application" | "membership_change")
84
+ * @property {bigint} numReplies - Number of replies to the message
85
+ * @property {DecodedMessage<Reaction>[]} reactions - Reactions to the message
26
86
  * @property {string} senderInboxId - Identifier for the sender's inbox
87
+ * @property {Date} sentAt - Timestamp when the message was sent
27
88
  * @property {bigint} sentAtNs - Timestamp when the message was sent (in nanoseconds)
28
89
  */
29
90
  export class DecodedMessage<ContentTypes = unknown> {
30
- #client: Client<ContentTypes>;
31
91
  content: ContentTypes | undefined;
32
92
  contentType: ContentTypeId;
33
93
  conversationId: string;
34
- deliveryStatus: MessageDeliveryStatus;
94
+ deliveryStatus: DeliveryStatus;
95
+ expiresAtNs?: bigint;
96
+ expiresAt?: Date;
35
97
  fallback?: string;
36
- compression?: number;
37
98
  id: string;
38
- kind: MessageKind;
39
- parameters: Map<string, string>;
40
- encodedContent: SafeMessage["content"];
99
+ kind: GroupMessageKind;
100
+ numReplies: bigint;
101
+ reactions: DecodedMessage<Reaction>[];
41
102
  senderInboxId: string;
103
+ sentAt: Date;
42
104
  sentAtNs: bigint;
43
105
 
44
- constructor(client: Client<ContentTypes>, message: SafeMessage) {
45
- this.#client = client;
106
+ constructor(codecRegistry: CodecRegistry, message: XmtpDecodedMessage) {
46
107
  this.id = message.id;
108
+ this.expiresAtNs = message.expiresAtNs;
109
+ this.expiresAt = message.expiresAtNs
110
+ ? nsToDate(message.expiresAtNs)
111
+ : undefined;
47
112
  this.sentAtNs = message.sentAtNs;
48
- this.conversationId = message.convoId;
113
+ this.sentAt = nsToDate(message.sentAtNs);
114
+ this.conversationId = message.conversationId;
49
115
  this.senderInboxId = message.senderInboxId;
50
- this.encodedContent = message.content;
116
+ this.contentType = message.contentType;
117
+ this.fallback = message.fallback ?? undefined;
51
118
 
52
- switch (message.kind) {
53
- case GroupMessageKind.Application:
54
- this.kind = "application";
55
- break;
56
- case GroupMessageKind.MembershipChange:
57
- this.kind = "membership_change";
58
- break;
59
- // no default
60
- }
119
+ this.kind = message.kind;
120
+ this.deliveryStatus = message.deliveryStatus;
61
121
 
62
- switch (message.deliveryStatus) {
63
- case DeliveryStatus.Unpublished:
64
- this.deliveryStatus = "unpublished";
65
- break;
66
- case DeliveryStatus.Published:
67
- this.deliveryStatus = "published";
68
- break;
69
- case DeliveryStatus.Failed:
70
- this.deliveryStatus = "failed";
71
- break;
72
- // no default
73
- }
122
+ this.numReplies = message.numReplies;
123
+ this.reactions = message.reactions.map(
124
+ (reaction) => new DecodedMessage<Reaction>(codecRegistry, reaction),
125
+ );
74
126
 
75
- this.contentType = fromSafeContentTypeId(message.content.type);
76
- this.parameters = new Map(Object.entries(message.content.parameters));
77
- this.fallback = message.content.fallback;
78
- this.compression = message.content.compression;
127
+ this.content =
128
+ getContentFromDecodedMessageContent<ContentTypes>(message.content) ??
129
+ undefined;
79
130
 
80
- try {
81
- this.content = this.#client.decodeContent<ContentTypes>(
82
- message,
83
- this.contentType,
84
- );
85
- } catch {
86
- this.content = undefined;
131
+ switch (message.content.type) {
132
+ case "reply": {
133
+ const reply = message.content.content;
134
+ let replyContent = getContentFromDecodedMessageContent<ContentTypes>(
135
+ reply.content,
136
+ );
137
+ if (reply.content.type === "custom") {
138
+ const codec = codecRegistry.getCodec<ContentTypes>(
139
+ reply.content.content.type as ContentTypeId,
140
+ );
141
+ if (codec) {
142
+ try {
143
+ replyContent = codec.decode(replyContent as EncodedContent);
144
+ } catch (error) {
145
+ if (error instanceof Error) {
146
+ console.warn(`Error decoding custom content: ${error.message}`);
147
+ } else {
148
+ console.warn(`Error decoding custom content`);
149
+ }
150
+ }
151
+ }
152
+ }
153
+ this.content = {
154
+ referenceId: reply.referenceId,
155
+ content: replyContent,
156
+ inReplyTo: reply.inReplyTo
157
+ ? new DecodedMessage<ContentTypes>(codecRegistry, reply.inReplyTo)
158
+ : null,
159
+ } as ContentTypes;
160
+ break;
161
+ }
162
+ case "custom": {
163
+ const encodedContent = message.content.content;
164
+ const codec = codecRegistry.getCodec<ContentTypes>(this.contentType);
165
+ if (codec) {
166
+ try {
167
+ this.content = codec.decode(encodedContent);
168
+ } catch (error) {
169
+ if (error instanceof Error) {
170
+ console.warn(`Error decoding custom content: ${error.message}`);
171
+ } else {
172
+ console.warn(`Error decoding custom content`);
173
+ }
174
+ this.content = undefined;
175
+ }
176
+ } else {
177
+ console.warn(
178
+ `No codec found for content type "${contentTypeToString(this.contentType)}"`,
179
+ );
180
+ this.content = undefined;
181
+ }
182
+ break;
183
+ }
87
184
  }
88
185
  }
89
186
  }
package/src/Dm.ts CHANGED
@@ -1,6 +1,8 @@
1
- import type { Client } from "@/Client";
1
+ import type { CodecRegistry } from "@/CodecRegistry";
2
2
  import { Conversation } from "@/Conversation";
3
+ import type { ClientWorkerAction } from "@/types/actions";
3
4
  import type { SafeConversation } from "@/utils/conversions";
5
+ import type { WorkerBridge } from "@/utils/WorkerBridge";
4
6
 
5
7
  /**
6
8
  * Represents a direct message conversation between two inboxes
@@ -8,23 +10,27 @@ import type { SafeConversation } from "@/utils/conversions";
8
10
  * This class is not intended to be initialized directly.
9
11
  */
10
12
  export class Dm<ContentTypes = unknown> extends Conversation<ContentTypes> {
11
- #client: Client<ContentTypes>;
13
+ #codecRegistry: CodecRegistry;
14
+ #worker: WorkerBridge<ClientWorkerAction>;
12
15
  #id: string;
13
16
 
14
17
  /**
15
18
  * Creates a new direct message conversation instance
16
19
  *
17
- * @param client - The client instance managing this direct message conversation
20
+ * @param worker - The worker bridge instance for client communication
21
+ * @param codecRegistry - The codec registry instance
18
22
  * @param id - Identifier for the direct message conversation
19
23
  * @param data - Optional conversation data to initialize with
20
24
  */
21
25
  constructor(
22
- client: Client<ContentTypes>,
26
+ worker: WorkerBridge<ClientWorkerAction>,
27
+ codecRegistry: CodecRegistry,
23
28
  id: string,
24
29
  data?: SafeConversation,
25
30
  ) {
26
- super(client, id, data);
27
- this.#client = client;
31
+ super(worker, codecRegistry, id, data);
32
+ this.#worker = worker;
33
+ this.#codecRegistry = codecRegistry;
28
34
  this.#id = id;
29
35
  }
30
36
 
@@ -34,14 +40,24 @@ export class Dm<ContentTypes = unknown> extends Conversation<ContentTypes> {
34
40
  * @returns Promise that resolves with the peer's inbox ID
35
41
  */
36
42
  async peerInboxId() {
37
- return this.#client.sendMessage("dm.peerInboxId", {
43
+ return this.#worker.action("dm.peerInboxId", {
38
44
  id: this.#id,
39
45
  });
40
46
  }
41
47
 
42
- async getDuplicateDms() {
43
- return this.#client.sendMessage("dm.getDuplicateDms", {
48
+ async duplicateDms() {
49
+ const conversations = await this.#worker.action("dm.duplicateDms", {
44
50
  id: this.#id,
45
51
  });
52
+
53
+ return conversations.map(
54
+ (conversation) =>
55
+ new Dm<ContentTypes>(
56
+ this.#worker,
57
+ this.#codecRegistry,
58
+ conversation.id,
59
+ conversation,
60
+ ),
61
+ );
46
62
  }
47
63
  }
package/src/Group.ts CHANGED
@@ -4,9 +4,11 @@ import type {
4
4
  PermissionPolicy,
5
5
  PermissionUpdateType,
6
6
  } from "@xmtp/wasm-bindings";
7
- import type { Client } from "@/Client";
7
+ import type { CodecRegistry } from "@/CodecRegistry";
8
8
  import { Conversation } from "@/Conversation";
9
+ import type { ClientWorkerAction } from "@/types/actions";
9
10
  import type { SafeConversation } from "@/utils/conversions";
11
+ import type { WorkerBridge } from "@/utils/WorkerBridge";
10
12
 
11
13
  /**
12
14
  * Represents a group conversation between multiple inboxes
@@ -16,7 +18,7 @@ import type { SafeConversation } from "@/utils/conversions";
16
18
  export class Group<ContentTypes = unknown> extends Conversation<ContentTypes> {
17
19
  #admins: SafeConversation["admins"] = [];
18
20
  #appData?: SafeConversation["appData"];
19
- #client: Client<ContentTypes>;
21
+ #worker: WorkerBridge<ClientWorkerAction>;
20
22
  #description?: SafeConversation["description"];
21
23
  #id: string;
22
24
  #imageUrl?: SafeConversation["imageUrl"];
@@ -35,17 +37,19 @@ export class Group<ContentTypes = unknown> extends Conversation<ContentTypes> {
35
37
  /**
36
38
  * Creates a new group conversation instance
37
39
  *
38
- * @param client - The client instance managing this group conversation
40
+ * @param worker - The worker bridge instance for client communication
41
+ * @param codecRegistry - The codec registry instance
39
42
  * @param id - Identifier for the group conversation
40
43
  * @param data - Optional conversation data to initialize with
41
44
  */
42
45
  constructor(
43
- client: Client<ContentTypes>,
46
+ worker: WorkerBridge<ClientWorkerAction>,
47
+ codecRegistry: CodecRegistry,
44
48
  id: string,
45
49
  data?: SafeConversation,
46
50
  ) {
47
- super(client, id, data);
48
- this.#client = client;
51
+ super(worker, codecRegistry, id, data);
52
+ this.#worker = worker;
49
53
  this.#id = id;
50
54
  this.#syncData(data);
51
55
  }
@@ -74,7 +78,7 @@ export class Group<ContentTypes = unknown> extends Conversation<ContentTypes> {
74
78
  * @param name The new name for the group
75
79
  */
76
80
  async updateName(name: string) {
77
- await this.#client.sendMessage("group.updateName", {
81
+ await this.#worker.action("group.updateName", {
78
82
  id: this.#id,
79
83
  name,
80
84
  });
@@ -94,7 +98,7 @@ export class Group<ContentTypes = unknown> extends Conversation<ContentTypes> {
94
98
  * @param imageUrl The new image URL for the group
95
99
  */
96
100
  async updateImageUrl(imageUrl: string) {
97
- await this.#client.sendMessage("group.updateImageUrl", {
101
+ await this.#worker.action("group.updateImageUrl", {
98
102
  id: this.#id,
99
103
  imageUrl,
100
104
  });
@@ -114,7 +118,7 @@ export class Group<ContentTypes = unknown> extends Conversation<ContentTypes> {
114
118
  * @param description The new description for the group
115
119
  */
116
120
  async updateDescription(description: string) {
117
- await this.#client.sendMessage("group.updateDescription", {
121
+ await this.#worker.action("group.updateDescription", {
118
122
  id: this.#id,
119
123
  description,
120
124
  });
@@ -134,7 +138,7 @@ export class Group<ContentTypes = unknown> extends Conversation<ContentTypes> {
134
138
  * @param appData The new app data for the group
135
139
  */
136
140
  async updateAppData(appData: string) {
137
- await this.#client.sendMessage("group.updateAppData", {
141
+ await this.#worker.action("group.updateAppData", {
138
142
  id: this.#id,
139
143
  appData,
140
144
  });
@@ -161,7 +165,7 @@ export class Group<ContentTypes = unknown> extends Conversation<ContentTypes> {
161
165
  * @returns Array of admin inbox IDs
162
166
  */
163
167
  async listAdmins() {
164
- const admins = await this.#client.sendMessage("group.listAdmins", {
168
+ const admins = await this.#worker.action("group.listAdmins", {
165
169
  id: this.#id,
166
170
  });
167
171
  this.#admins = admins;
@@ -174,12 +178,9 @@ export class Group<ContentTypes = unknown> extends Conversation<ContentTypes> {
174
178
  * @returns Array of super admin inbox IDs
175
179
  */
176
180
  async listSuperAdmins() {
177
- const superAdmins = await this.#client.sendMessage(
178
- "group.listSuperAdmins",
179
- {
180
- id: this.#id,
181
- },
182
- );
181
+ const superAdmins = await this.#worker.action("group.listSuperAdmins", {
182
+ id: this.#id,
183
+ });
183
184
  this.#superAdmins = superAdmins;
184
185
  return superAdmins;
185
186
  }
@@ -190,7 +191,7 @@ export class Group<ContentTypes = unknown> extends Conversation<ContentTypes> {
190
191
  * @returns The group's permissions
191
192
  */
192
193
  async permissions() {
193
- return this.#client.sendMessage("group.permissions", {
194
+ return this.#worker.action("group.permissions", {
194
195
  id: this.#id,
195
196
  });
196
197
  }
@@ -207,7 +208,7 @@ export class Group<ContentTypes = unknown> extends Conversation<ContentTypes> {
207
208
  policy: PermissionPolicy,
208
209
  metadataField?: MetadataField,
209
210
  ) {
210
- return this.#client.sendMessage("group.updatePermission", {
211
+ return this.#worker.action("group.updatePermission", {
211
212
  id: this.#id,
212
213
  permissionType,
213
214
  policy,
@@ -243,7 +244,7 @@ export class Group<ContentTypes = unknown> extends Conversation<ContentTypes> {
243
244
  * @param identifiers Array of member identifiers to add
244
245
  */
245
246
  async addMembersByIdentifiers(identifiers: Identifier[]) {
246
- return this.#client.sendMessage("group.addMembersByIdentifiers", {
247
+ return this.#worker.action("group.addMembersByIdentifiers", {
247
248
  id: this.#id,
248
249
  identifiers,
249
250
  });
@@ -255,7 +256,7 @@ export class Group<ContentTypes = unknown> extends Conversation<ContentTypes> {
255
256
  * @param inboxIds Array of inbox IDs to add
256
257
  */
257
258
  async addMembers(inboxIds: string[]) {
258
- return this.#client.sendMessage("group.addMembers", {
259
+ return this.#worker.action("group.addMembers", {
259
260
  id: this.#id,
260
261
  inboxIds,
261
262
  });
@@ -267,7 +268,7 @@ export class Group<ContentTypes = unknown> extends Conversation<ContentTypes> {
267
268
  * @param identifiers Array of member identifiers to remove
268
269
  */
269
270
  async removeMembersByIdentifiers(identifiers: Identifier[]) {
270
- return this.#client.sendMessage("group.removeMembersByIdentifiers", {
271
+ return this.#worker.action("group.removeMembersByIdentifiers", {
271
272
  id: this.#id,
272
273
  identifiers,
273
274
  });
@@ -279,7 +280,7 @@ export class Group<ContentTypes = unknown> extends Conversation<ContentTypes> {
279
280
  * @param inboxIds Array of inbox IDs to remove
280
281
  */
281
282
  async removeMembers(inboxIds: string[]) {
282
- return this.#client.sendMessage("group.removeMembers", {
283
+ return this.#worker.action("group.removeMembers", {
283
284
  id: this.#id,
284
285
  inboxIds,
285
286
  });
@@ -291,7 +292,7 @@ export class Group<ContentTypes = unknown> extends Conversation<ContentTypes> {
291
292
  * @param inboxId The inbox ID of the member to promote
292
293
  */
293
294
  async addAdmin(inboxId: string) {
294
- return this.#client.sendMessage("group.addAdmin", {
295
+ return this.#worker.action("group.addAdmin", {
295
296
  id: this.#id,
296
297
  inboxId,
297
298
  });
@@ -303,7 +304,7 @@ export class Group<ContentTypes = unknown> extends Conversation<ContentTypes> {
303
304
  * @param inboxId The inbox ID of the admin to demote
304
305
  */
305
306
  async removeAdmin(inboxId: string) {
306
- return this.#client.sendMessage("group.removeAdmin", {
307
+ return this.#worker.action("group.removeAdmin", {
307
308
  id: this.#id,
308
309
  inboxId,
309
310
  });
@@ -315,7 +316,7 @@ export class Group<ContentTypes = unknown> extends Conversation<ContentTypes> {
315
316
  * @param inboxId The inbox ID of the member to promote
316
317
  */
317
318
  async addSuperAdmin(inboxId: string) {
318
- return this.#client.sendMessage("group.addSuperAdmin", {
319
+ return this.#worker.action("group.addSuperAdmin", {
319
320
  id: this.#id,
320
321
  inboxId,
321
322
  });
@@ -327,7 +328,7 @@ export class Group<ContentTypes = unknown> extends Conversation<ContentTypes> {
327
328
  * @param inboxId The inbox ID of the super admin to demote
328
329
  */
329
330
  async removeSuperAdmin(inboxId: string) {
330
- return this.#client.sendMessage("group.removeSuperAdmin", {
331
+ return this.#worker.action("group.removeSuperAdmin", {
331
332
  id: this.#id,
332
333
  inboxId,
333
334
  });
@@ -337,7 +338,7 @@ export class Group<ContentTypes = unknown> extends Conversation<ContentTypes> {
337
338
  * Request to leave the group
338
339
  */
339
340
  async requestRemoval() {
340
- return this.#client.sendMessage("group.requestRemoval", {
341
+ return this.#worker.action("group.requestRemoval", {
341
342
  id: this.#id,
342
343
  });
343
344
  }
@@ -348,7 +349,7 @@ export class Group<ContentTypes = unknown> extends Conversation<ContentTypes> {
348
349
  * @returns Boolean
349
350
  */
350
351
  async isPendingRemoval() {
351
- return this.#client.sendMessage("group.isPendingRemoval", {
352
+ return this.#worker.action("group.isPendingRemoval", {
352
353
  id: this.#id,
353
354
  });
354
355
  }
package/src/Opfs.ts ADDED
@@ -0,0 +1,63 @@
1
+ import type { OpfsAction } from "@/types/actions/opfs";
2
+ import { WorkerBridge } from "@/utils/WorkerBridge";
3
+
4
+ export class Opfs {
5
+ #worker: WorkerBridge<OpfsAction>;
6
+ #enableLogging: boolean;
7
+
8
+ constructor(enableLogging?: boolean) {
9
+ const worker = new Worker(new URL("./workers/opfs", import.meta.url), {
10
+ type: "module",
11
+ });
12
+ this.#worker = new WorkerBridge<OpfsAction>(worker, enableLogging);
13
+ this.#enableLogging = enableLogging ?? false;
14
+ }
15
+
16
+ async init() {
17
+ await this.#worker.action("opfs.init", {
18
+ enableLogging: this.#enableLogging,
19
+ });
20
+ }
21
+
22
+ close() {
23
+ this.#worker.close();
24
+ }
25
+
26
+ static async create(enableLogging?: boolean) {
27
+ const opfs = new Opfs(enableLogging);
28
+ await opfs.init();
29
+ return opfs;
30
+ }
31
+
32
+ async listFiles() {
33
+ return this.#worker.action("opfs.listFiles");
34
+ }
35
+
36
+ async fileCount() {
37
+ return this.#worker.action("opfs.fileCount");
38
+ }
39
+
40
+ async poolCapacity() {
41
+ return this.#worker.action("opfs.poolCapacity");
42
+ }
43
+
44
+ async fileExists(path: string) {
45
+ return this.#worker.action("opfs.fileExists", { path });
46
+ }
47
+
48
+ async deleteFile(path: string) {
49
+ return this.#worker.action("opfs.deleteFile", { path });
50
+ }
51
+
52
+ async exportDb(path: string) {
53
+ return this.#worker.action("opfs.exportDb", { path });
54
+ }
55
+
56
+ async importDb(path: string, data: Uint8Array) {
57
+ return this.#worker.action("opfs.importDb", { path, data });
58
+ }
59
+
60
+ async clearAll() {
61
+ return this.#worker.action("opfs.clearAll");
62
+ }
63
+ }