stream-chat 8.14.5 → 8.16.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.
package/src/channel.ts CHANGED
@@ -170,18 +170,10 @@ export class Channel<StreamChatGenerics extends ExtendableGenerics = DefaultGene
170
170
  * @return {Promise<SendMessageAPIResponse<StreamChatGenerics>>} The Server Response
171
171
  */
172
172
  async sendMessage(message: Message<StreamChatGenerics>, options?: SendMessageOptions) {
173
- const sendMessageResponse = await this.getClient().post<SendMessageAPIResponse<StreamChatGenerics>>(
174
- this._channelURL() + '/message',
175
- {
176
- message,
177
- ...options,
178
- },
179
- );
180
-
181
- // Reset unreadCount to 0.
182
- this.state.unreadCount = 0;
183
-
184
- return sendMessageResponse;
173
+ return await this.getClient().post<SendMessageAPIResponse<StreamChatGenerics>>(this._channelURL() + '/message', {
174
+ message,
175
+ ...options,
176
+ });
185
177
  }
186
178
 
187
179
  sendFile(
@@ -649,7 +641,7 @@ export class Channel<StreamChatGenerics extends ExtendableGenerics = DefaultGene
649
641
  * @see {@link https://getstream.io/chat/docs/typing_indicators/?language=js|Docs}
650
642
  * @param {string} [parent_id] set this field to `message.id` to indicate that typing event is happening in a thread
651
643
  */
652
- async keystroke(parent_id?: string) {
644
+ async keystroke(parent_id?: string, options?: { user_id: string }) {
653
645
  if (!this.getConfig()?.typing_events) {
654
646
  return;
655
647
  }
@@ -663,6 +655,7 @@ export class Channel<StreamChatGenerics extends ExtendableGenerics = DefaultGene
663
655
  await this.sendEvent({
664
656
  type: 'typing.start',
665
657
  parent_id,
658
+ ...(options || {}),
666
659
  } as Event<StreamChatGenerics>);
667
660
  }
668
661
  }
@@ -672,7 +665,7 @@ export class Channel<StreamChatGenerics extends ExtendableGenerics = DefaultGene
672
665
  * @see {@link https://getstream.io/chat/docs/typing_indicators/?language=js|Docs}
673
666
  * @param {string} [parent_id] set this field to `message.id` to indicate that typing event is happening in a thread
674
667
  */
675
- async stopTyping(parent_id?: string) {
668
+ async stopTyping(parent_id?: string, options?: { user_id: string }) {
676
669
  if (!this.getConfig()?.typing_events) {
677
670
  return;
678
671
  }
@@ -681,6 +674,7 @@ export class Channel<StreamChatGenerics extends ExtendableGenerics = DefaultGene
681
674
  await this.sendEvent({
682
675
  type: 'typing.stop',
683
676
  parent_id,
677
+ ...(options || {}),
684
678
  } as Event<StreamChatGenerics>);
685
679
  }
686
680
 
@@ -1241,7 +1235,6 @@ export class Channel<StreamChatGenerics extends ExtendableGenerics = DefaultGene
1241
1235
  case 'message.read':
1242
1236
  if (event.user?.id && event.created_at) {
1243
1237
  channelState.read[event.user.id] = {
1244
- // because in client.ts the handleEvent call that flows to this sets this `event.received_at = new Date();`
1245
1238
  last_read: new Date(event.created_at),
1246
1239
  last_read_message_id: event.last_read_message_id,
1247
1240
  user: event.user,
@@ -1290,6 +1283,12 @@ export class Channel<StreamChatGenerics extends ExtendableGenerics = DefaultGene
1290
1283
  channelState.addPinnedMessage(event.message);
1291
1284
  }
1292
1285
 
1286
+ // do not increase the unread count - the back-end does not increase the count neither in the following cases:
1287
+ // 1. the message is mine
1288
+ // 2. the message is a thread reply from any user
1289
+ const preventUnreadCountUpdate = ownMessage || isThreadMessage;
1290
+ if (preventUnreadCountUpdate) break;
1291
+
1293
1292
  if (event.user?.id) {
1294
1293
  for (const userId in channelState.read) {
1295
1294
  if (userId === event.user.id) {
@@ -1304,9 +1303,7 @@ export class Channel<StreamChatGenerics extends ExtendableGenerics = DefaultGene
1304
1303
  }
1305
1304
  }
1306
1305
 
1307
- if (ownMessage) {
1308
- channelState.unreadCount = 0;
1309
- } else if (this._countMessageAsUnread(event.message)) {
1306
+ if (this._countMessageAsUnread(event.message)) {
1310
1307
  channelState.unreadCount = channelState.unreadCount + 1;
1311
1308
  }
1312
1309
  }
@@ -1360,6 +1357,23 @@ export class Channel<StreamChatGenerics extends ExtendableGenerics = DefaultGene
1360
1357
  delete channelState.members[event.user.id];
1361
1358
  }
1362
1359
  break;
1360
+ case 'notification.mark_unread': {
1361
+ const ownMessage = event.user?.id === this.getClient().user?.id;
1362
+ if (!(ownMessage && event.user)) break;
1363
+
1364
+ const unreadCount = event.unread_messages ?? 0;
1365
+
1366
+ channelState.read[event.user.id] = {
1367
+ first_unread_message_id: event.first_unread_message_id,
1368
+ last_read: new Date(event.last_read_at as string),
1369
+ last_read_message_id: event.last_read_message_id,
1370
+ user: event.user,
1371
+ unread_messages: unreadCount,
1372
+ };
1373
+
1374
+ channelState.unreadCount = unreadCount;
1375
+ break;
1376
+ }
1363
1377
  case 'channel.updated':
1364
1378
  if (event.channel) {
1365
1379
  const isFrozenChanged = event.channel?.frozen !== undefined && event.channel.frozen !== channel.data?.frozen;
@@ -12,10 +12,17 @@ import {
12
12
  UserResponse,
13
13
  PendingMessageResponse,
14
14
  } from './types';
15
+ import { addToMessageList } from './utils';
15
16
 
16
17
  type ChannelReadStatus<StreamChatGenerics extends ExtendableGenerics = DefaultGenerics> = Record<
17
18
  string,
18
- { last_read: Date; unread_messages: number; user: UserResponse<StreamChatGenerics>; last_read_message_id?: string }
19
+ {
20
+ last_read: Date;
21
+ unread_messages: number;
22
+ user: UserResponse<StreamChatGenerics>;
23
+ first_unread_message_id?: string;
24
+ last_read_message_id?: string;
25
+ }
19
26
  >;
20
27
 
21
28
  /**
@@ -435,64 +442,7 @@ export class ChannelState<StreamChatGenerics extends ExtendableGenerics = Defaul
435
442
  sortBy: 'pinned_at' | 'created_at' = 'created_at',
436
443
  addIfDoesNotExist = true,
437
444
  ) {
438
- const addMessageToList = addIfDoesNotExist || timestampChanged;
439
- let messageArr = messages;
440
-
441
- // if created_at has changed, message should be filtered and re-inserted in correct order
442
- // slow op but usually this only happens for a message inserted to state before actual response with correct timestamp
443
- if (timestampChanged) {
444
- messageArr = messageArr.filter((msg) => !(msg.id && message.id === msg.id));
445
- }
446
-
447
- // Get array length after filtering
448
- const messageArrayLength = messageArr.length;
449
-
450
- // for empty list just concat and return unless it's an update or deletion
451
- if (messageArrayLength === 0 && addMessageToList) {
452
- return messageArr.concat(message);
453
- } else if (messageArrayLength === 0) {
454
- return [...messageArr];
455
- }
456
-
457
- const messageTime = (message[sortBy] as Date).getTime();
458
- const messageIsNewest = (messageArr[messageArrayLength - 1][sortBy] as Date).getTime() < messageTime;
459
-
460
- // if message is newer than last item in the list concat and return unless it's an update or deletion
461
- if (messageIsNewest && addMessageToList) {
462
- return messageArr.concat(message);
463
- } else if (messageIsNewest) {
464
- return [...messageArr];
465
- }
466
-
467
- // find the closest index to push the new message
468
- let left = 0;
469
- let middle = 0;
470
- let right = messageArrayLength - 1;
471
- while (left <= right) {
472
- middle = Math.floor((right + left) / 2);
473
- if ((messageArr[middle][sortBy] as Date).getTime() <= messageTime) left = middle + 1;
474
- else right = middle - 1;
475
- }
476
-
477
- // message already exists and not filtered due to timestampChanged, update and return
478
- if (!timestampChanged && message.id) {
479
- if (messageArr[left] && message.id === messageArr[left].id) {
480
- messageArr[left] = message;
481
- return [...messageArr];
482
- }
483
-
484
- if (messageArr[left - 1] && message.id === messageArr[left - 1].id) {
485
- messageArr[left - 1] = message;
486
- return [...messageArr];
487
- }
488
- }
489
-
490
- // Do not add updated or deleted messages to the list if they do not already exist
491
- // or have a timestamp change.
492
- if (addMessageToList) {
493
- messageArr.splice(left, 0, message);
494
- }
495
- return [...messageArr];
445
+ return addToMessageList(messages, message, timestampChanged, sortBy, addIfDoesNotExist);
496
446
  }
497
447
 
498
448
  /**
package/src/client.ts CHANGED
@@ -95,7 +95,9 @@ import {
95
95
  GetImportResponse,
96
96
  GetMessageAPIResponse,
97
97
  GetRateLimitsResponse,
98
+ QueryThreadsAPIResponse,
98
99
  GetUnreadCountAPIResponse,
100
+ GetUnreadCountBatchAPIResponse,
99
101
  ListChannelResponse,
100
102
  ListCommandsResponse,
101
103
  ListImportsPaginationOptions,
@@ -123,12 +125,10 @@ import {
123
125
  PushProviderListResponse,
124
126
  PushProviderUpsertResponse,
125
127
  QueryChannelsAPIResponse,
128
+ QuerySegmentsOptions,
126
129
  ReactionResponse,
127
130
  ReactivateUserOptions,
128
131
  ReactivateUsersOptions,
129
- Recipient,
130
- RecipientFilters,
131
- RecipientQueryOptions,
132
132
  ReservedMessageFields,
133
133
  ReviewFlagReportOptions,
134
134
  ReviewFlagReportResponse,
@@ -138,8 +138,7 @@ import {
138
138
  SearchPayload,
139
139
  Segment,
140
140
  SegmentData,
141
- SegmentFilters,
142
- SegmentQueryOptions,
141
+ SegmentType,
143
142
  SendFileAPIResponse,
144
143
  StreamChatOptions,
145
144
  SyncOptions,
@@ -159,13 +158,19 @@ import {
159
158
  UpdatedMessage,
160
159
  UpdateMessageAPIResponse,
161
160
  UpdateMessageOptions,
161
+ UpdateSegmentData,
162
162
  UserCustomEvent,
163
163
  UserFilters,
164
164
  UserOptions,
165
165
  UserResponse,
166
166
  UserSort,
167
+ GetThreadAPIResponse,
168
+ PartialThreadUpdate,
169
+ QueryThreadsOptions,
170
+ GetThreadOptions,
167
171
  } from './types';
168
172
  import { InsightMetrics, postInsights } from './insights';
173
+ import { Thread } from './thread';
169
174
 
170
175
  function isString(x: unknown): x is string {
171
176
  return typeof x === 'string' || x instanceof String;
@@ -1688,10 +1693,28 @@ export class StreamChat<StreamChatGenerics extends ExtendableGenerics = DefaultG
1688
1693
  );
1689
1694
  }
1690
1695
 
1696
+ /**
1697
+ * getUnreadCount - Returns unread counts for a single user
1698
+ *
1699
+ * @param {string} [userID] User ID.
1700
+ *
1701
+ * @return {<GetUnreadCountAPIResponse>}
1702
+ */
1691
1703
  async getUnreadCount(userID?: string) {
1692
1704
  return await this.get<GetUnreadCountAPIResponse>(this.baseURL + '/unread', userID ? { user_id: userID } : {});
1693
1705
  }
1694
1706
 
1707
+ /**
1708
+ * getUnreadCountBatch - Returns unread counts for multiple users at once. Only works server side.
1709
+ *
1710
+ * @param {string[]} [userIDs] List of user IDs to fetch unread counts for.
1711
+ *
1712
+ * @return {<GetUnreadCountBatchAPIResponse>}
1713
+ */
1714
+ async getUnreadCountBatch(userIDs: string[]) {
1715
+ return await this.post<GetUnreadCountBatchAPIResponse>(this.baseURL + '/unread_batch', { user_ids: userIDs });
1716
+ }
1717
+
1695
1718
  /**
1696
1719
  * removeDevice - Removes the device with the given id. Clientside users can only delete their own devices
1697
1720
  *
@@ -2578,6 +2601,103 @@ export class StreamChat<StreamChatGenerics extends ExtendableGenerics = DefaultG
2578
2601
  );
2579
2602
  }
2580
2603
 
2604
+ /**
2605
+ * queryThreads - returns the list of threads of current user.
2606
+ *
2607
+ * @param {QueryThreadsOptions} options Options object for pagination and limiting the participants and replies.
2608
+ * @param {number} options.limit Limits the number of threads to be returned.
2609
+ * @param {boolean} options.watch Subscribes the user to the channels of the threads.
2610
+ * @param {number} options.participant_limit Limits the number of participants returned per threads.
2611
+ * @param {number} options.reply_limit Limits the number of replies returned per threads.
2612
+ *
2613
+ * @returns {{ threads: Thread<StreamChatGenerics>[], next: string }} Returns the list of threads and the next cursor.
2614
+ */
2615
+ async queryThreads(options?: QueryThreadsOptions) {
2616
+ const opts = {
2617
+ limit: 10,
2618
+ participant_limit: 10,
2619
+ reply_limit: 3,
2620
+ watch: true,
2621
+ ...options,
2622
+ };
2623
+
2624
+ const res = await this.post<QueryThreadsAPIResponse<StreamChatGenerics>>(this.baseURL + `/threads`, opts);
2625
+
2626
+ return {
2627
+ threads: res.threads.map((thread) => new Thread(this, thread)),
2628
+ next: res.next,
2629
+ };
2630
+ }
2631
+
2632
+ /**
2633
+ * getThread - returns the thread of a message by its id.
2634
+ *
2635
+ * @param {string} messageId The message id
2636
+ * @param {GetThreadOptions} options Options object for pagination and limiting the participants and replies.
2637
+ * @param {boolean} options.watch Subscribes the user to the channel of the thread.
2638
+ * @param {number} options.participant_limit Limits the number of participants returned per threads.
2639
+ * @param {number} options.reply_limit Limits the number of replies returned per threads.
2640
+ *
2641
+ * @returns {Thread<StreamChatGenerics>} Returns the thread.
2642
+ */
2643
+ async getThread(messageId: string, options: GetThreadOptions = {}) {
2644
+ if (!messageId) {
2645
+ throw Error('Please specify the message id when calling partialUpdateThread');
2646
+ }
2647
+
2648
+ const opts = {
2649
+ participant_limit: 100,
2650
+ reply_limit: 3,
2651
+ watch: true,
2652
+ ...options,
2653
+ };
2654
+
2655
+ const res = await this.get<GetThreadAPIResponse<StreamChatGenerics>>(this.baseURL + `/threads/${messageId}`, opts);
2656
+
2657
+ return new Thread<StreamChatGenerics>(this, res.thread);
2658
+ }
2659
+
2660
+ /**
2661
+ * partialUpdateThread - updates the given thread
2662
+ *
2663
+ * @param {string} messageId The id of the thread message which needs to be updated.
2664
+ * @param {PartialThreadUpdate} partialThreadObject should contain "set" or "unset" params for any of the thread's non-reserved fields.
2665
+ *
2666
+ * @returns {GetThreadAPIResponse<StreamChatGenerics>} Returns the updated thread.
2667
+ */
2668
+ async partialUpdateThread(messageId: string, partialThreadObject: PartialThreadUpdate) {
2669
+ if (!messageId) {
2670
+ throw Error('Please specify the message id when calling partialUpdateThread');
2671
+ }
2672
+
2673
+ // check for reserved fields from ThreadResponse type within partialThreadObject's set and unset.
2674
+ // Throw error if any of the reserved field is found.
2675
+ const reservedThreadFields = [
2676
+ 'created_at',
2677
+ 'id',
2678
+ 'last_message_at',
2679
+ 'type',
2680
+ 'updated_at',
2681
+ 'user',
2682
+ 'reply_count',
2683
+ 'participants',
2684
+ 'channel',
2685
+ ];
2686
+
2687
+ for (const key in { ...partialThreadObject.set, ...partialThreadObject.unset }) {
2688
+ if (reservedThreadFields.includes(key)) {
2689
+ throw Error(
2690
+ `You cannot set ${key} field on Thread object. ${key} is reserved for server-side use. Please omit ${key} from your set object.`,
2691
+ );
2692
+ }
2693
+ }
2694
+
2695
+ return await this.patch<GetThreadAPIResponse<StreamChatGenerics>>(
2696
+ this.baseURL + `/threads/${messageId}`,
2697
+ partialThreadObject,
2698
+ );
2699
+ }
2700
+
2581
2701
  getUserAgent() {
2582
2702
  return (
2583
2703
  this.userAgent || `stream-chat-javascript-client-${this.node ? 'node' : 'browser'}-${process.env.PKG_VERSION}`
@@ -2824,56 +2944,132 @@ export class StreamChat<StreamChatGenerics extends ExtendableGenerics = DefaultG
2824
2944
  }
2825
2945
 
2826
2946
  /**
2827
- * createSegment - Creates a Campaign Segment
2947
+ * createSegment - Creates a segment
2828
2948
  *
2949
+ * @private
2950
+ * @param {SegmentType} type Segment type
2951
+ * @param {string} id Segment ID (valid UUID)
2952
+ * @param {string} name Segment name (valid UUID)
2829
2953
  * @param {SegmentData} params Segment data
2830
2954
  *
2831
- * @return {Segment} The Created Segment
2955
+ * @return {Segment} The created Segment
2832
2956
  */
2833
- async createSegment(params: SegmentData) {
2834
- const { segment } = await this.post<{ segment: Segment }>(this.baseURL + `/segments`, { segment: params });
2957
+ private async createSegment(type: SegmentType, id: string, name: string, data?: SegmentData): Promise<Segment> {
2958
+ const body = {
2959
+ id,
2960
+ type,
2961
+ name,
2962
+ data,
2963
+ };
2964
+ const { segment } = await this.post<{ segment: Segment }>(this.baseURL + `/segments`, body);
2835
2965
  return segment;
2836
2966
  }
2837
2967
 
2838
2968
  /**
2839
- * querySegments - Query Campaign Segments
2969
+ * createUserSegment - Creates a user segment
2840
2970
  *
2971
+ * @param {string} id Segment ID (valid UUID)
2972
+ * @param {string} name Segment name
2973
+ * @param {SegmentData} data Segment data
2974
+ *
2975
+ * @return {Segment} The created Segment
2976
+ */
2977
+ async createUserSegment(id: string, name: string, data?: SegmentData): Promise<Segment> {
2978
+ return await this.createSegment('user', id, name, data);
2979
+ }
2980
+
2981
+ /**
2982
+ * createChannelSegment - Creates a channel segment
2983
+ *
2984
+ * @param {string} id Segment ID (valid UUID)
2985
+ * @param {string} name Segment name
2986
+ * @param {SegmentData} data Segment data
2987
+ *
2988
+ * @return {Segment} The created Segment
2989
+ */
2990
+ async createChannelSegment(id: string, name: string, data?: SegmentData): Promise<Segment> {
2991
+ return await this.createSegment('channel', id, name, data);
2992
+ }
2993
+
2994
+ /**
2995
+ * updateSegment - Update a segment
2996
+ *
2997
+ * @param {string} id Segment ID
2998
+ * @param {Partial<UpdateSegmentData>} data Data to update
2999
+ *
3000
+ * @return {Segment} Updated Segment
3001
+ */
3002
+ async updateSegment(id: string, data: Partial<UpdateSegmentData>) {
3003
+ const { segment } = await this.put<{ segment: Segment }>(this.baseURL + `/segments/${id}`, data);
3004
+ return segment;
3005
+ }
3006
+
3007
+ /**
3008
+ * addSegmentTargets - Add targets to a segment
3009
+ *
3010
+ * @param {string} id Segment ID
3011
+ * @param {string[]} targets Targets to add to the segment
3012
+ *
3013
+ * @return {APIResponse} API response
3014
+ */
3015
+ async addSegmentTargets(id: string, targets: string[]) {
3016
+ const body = { targets };
3017
+ return await this.post<APIResponse>(this.baseURL + `/segments/${id}/addtargets`, body);
3018
+ }
3019
+
3020
+ /**
3021
+ * deleteSegmentTargets - Delete targets from a segment
3022
+ *
3023
+ * @param {string} id Segment ID
3024
+ * @param {string[]} targets Targets to add to the segment
3025
+ *
3026
+ * @return {APIResponse} API response
3027
+ */
3028
+ async deleteSegmentTargets(id: string, targets: string[]) {
3029
+ const body = { targets };
3030
+ return await this.post<APIResponse>(this.baseURL + `/segments/${id}/deletetargets`, body);
3031
+ }
3032
+
3033
+ /**
3034
+ * querySegments - Query Segments
3035
+ *
3036
+ * @param {filter} filter MongoDB style filter conditions
3037
+ * @param {QuerySegmentsOptions} options Options for sorting/paginating the results
2841
3038
  *
2842
3039
  * @return {Segment[]} Segments
2843
3040
  */
2844
- async querySegments(filters: SegmentFilters, options: SegmentQueryOptions = {}) {
3041
+ async querySegments(filter: {}, options: QuerySegmentsOptions = {}) {
2845
3042
  return await this.get<{
2846
3043
  segments: Segment[];
2847
3044
  }>(this.baseURL + `/segments`, {
2848
3045
  payload: {
2849
- filter_conditions: filters,
3046
+ filter,
2850
3047
  ...options,
2851
3048
  },
2852
3049
  });
2853
3050
  }
2854
3051
 
2855
3052
  /**
2856
- * updateSegment - Update a Campaign Segment
3053
+ * deleteSegment - Delete a Campaign Segment
2857
3054
  *
2858
3055
  * @param {string} id Segment ID
2859
- * @param {Partial<SegmentData>} params Segment data
2860
3056
  *
2861
- * @return {Segment} Updated Segment
3057
+ * @return {Promise<APIResponse>} The Server Response
2862
3058
  */
2863
- async updateSegment(id: string, params: Partial<SegmentData>) {
2864
- const { segment } = await this.put<{ segment: Segment }>(this.baseURL + `/segments/${id}`, { segment: params });
2865
- return segment;
3059
+ async deleteSegment(id: string) {
3060
+ return await this.delete<APIResponse>(this.baseURL + `/segments/${id}`);
2866
3061
  }
2867
3062
 
2868
3063
  /**
2869
- * deleteSegment - Delete a Campaign Segment
3064
+ * segmentTargetExists - Check if a target exists in a segment
2870
3065
  *
2871
- * @param {string} id Segment ID
3066
+ * @param {string} segmentId Segment ID
3067
+ * @param {string} targetId Target ID
2872
3068
  *
2873
3069
  * @return {Promise<APIResponse>} The Server Response
2874
3070
  */
2875
- async deleteSegment(id: string) {
2876
- return this.delete<APIResponse>(this.baseURL + `/segments/${id}`);
3071
+ async segmentTargetExists(segmentId: string, targetId: string) {
3072
+ return await this.get<APIResponse>(this.baseURL + `/segments/${segmentId}/target/${targetId}`);
2877
3073
  }
2878
3074
 
2879
3075
  /**
@@ -2987,27 +3183,6 @@ export class StreamChat<StreamChatGenerics extends ExtendableGenerics = DefaultG
2987
3183
  return await this.post<APIResponse & TestCampaignResponse>(this.baseURL + `/campaigns/${id}/test`, { users });
2988
3184
  }
2989
3185
 
2990
- /**
2991
- * queryRecipients - Query Campaign Recipient Results
2992
- *
2993
- *
2994
- * @return {Recipient[]} Recipients
2995
- */
2996
- async queryRecipients(filters: RecipientFilters, options: RecipientQueryOptions = {}) {
2997
- return await this.get<{
2998
- campaigns: Record<string, Campaign>;
2999
- recipients: Recipient[];
3000
- segments: Record<string, Segment>;
3001
- channels?: Record<string, ChannelResponse<StreamChatGenerics>>;
3002
- users?: Record<string, UserResponse<StreamChatGenerics>>;
3003
- }>(this.baseURL + `/recipients`, {
3004
- payload: {
3005
- filter_conditions: filters,
3006
- ...options,
3007
- },
3008
- });
3009
- }
3010
-
3011
3186
  /**
3012
3187
  * enrichURL - Get OpenGraph data of the given link
3013
3188
  *
package/src/events.ts CHANGED
@@ -24,9 +24,11 @@ export const EVENT_MAP = {
24
24
  'notification.invite_rejected': true,
25
25
  'notification.invited': true,
26
26
  'notification.mark_read': true,
27
+ 'notification.mark_unread': true,
27
28
  'notification.message_new': true,
28
29
  'notification.mutes_updated': true,
29
30
  'notification.removed_from_channel': true,
31
+ 'notification.thread_message_new': true,
30
32
  'reaction.deleted': true,
31
33
  'reaction.new': true,
32
34
  'reaction.updated': true,
package/src/index.ts CHANGED
@@ -3,6 +3,7 @@ export * from './client';
3
3
  export * from './client_state';
4
4
  export * from './channel';
5
5
  export * from './channel_state';
6
+ export * from './thread';
6
7
  export * from './connection';
7
8
  export * from './events';
8
9
  export * from './permissions';
@@ -10,4 +11,4 @@ export * from './signing';
10
11
  export * from './token_manager';
11
12
  export * from './insights';
12
13
  export * from './types';
13
- export { isOwnUser, chatCodes, logChatPromiseExecution } from './utils';
14
+ export { isOwnUser, chatCodes, logChatPromiseExecution, formatMessage } from './utils';