stream-chat 9.44.2 → 9.45.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.
Files changed (50) hide show
  1. package/dist/cjs/index.browser.js +3460 -2659
  2. package/dist/cjs/index.browser.js.map +4 -4
  3. package/dist/cjs/index.node.js +3469 -2659
  4. package/dist/cjs/index.node.js.map +4 -4
  5. package/dist/esm/index.mjs +3460 -2659
  6. package/dist/esm/index.mjs.map +4 -4
  7. package/dist/types/channel_state.d.ts +1 -1
  8. package/dist/types/client.d.ts +81 -3
  9. package/dist/types/constants.d.ts +1 -0
  10. package/dist/types/messageComposer/LocationComposer.d.ts +1 -1
  11. package/dist/types/messageComposer/configuration/commands.configuration.d.ts +6 -0
  12. package/dist/types/messageComposer/configuration/configuration.d.ts +1 -2
  13. package/dist/types/messageComposer/configuration/index.d.ts +4 -0
  14. package/dist/types/messageComposer/configuration/types.d.ts +21 -0
  15. package/dist/types/messageComposer/fileUtils.d.ts +1 -1
  16. package/dist/types/messageComposer/messageComposer.d.ts +6 -4
  17. package/dist/types/messageComposer/middleware/messageComposer/compositionValidation.d.ts +2 -1
  18. package/dist/types/messageComposer/middleware/messageComposer/textComposer.d.ts +1 -1
  19. package/dist/types/messageComposer/middleware/textComposer/commandUtils.d.ts +10 -1
  20. package/dist/types/messageComposer/middleware/textComposer/mentionUtils.d.ts +8 -0
  21. package/dist/types/messageComposer/middleware/textComposer/mentions.d.ts +77 -15
  22. package/dist/types/messageComposer/middleware/textComposer/types.d.ts +51 -2
  23. package/dist/types/messageComposer/pollComposer.d.ts +2 -2
  24. package/dist/types/messageComposer/textComposer.d.ts +17 -3
  25. package/dist/types/pagination/UserGroupPaginator.d.ts +21 -0
  26. package/dist/types/pagination/index.d.ts +1 -0
  27. package/dist/types/types.d.ts +123 -2
  28. package/dist/types/utils.d.ts +2 -0
  29. package/package.json +38 -31
  30. package/src/client.ts +143 -2
  31. package/src/constants.ts +1 -0
  32. package/src/messageComposer/MessageComposerEffectHandlers.ts +1 -0
  33. package/src/messageComposer/configuration/commands.configuration.ts +55 -0
  34. package/src/messageComposer/configuration/configuration.ts +3 -1
  35. package/src/messageComposer/configuration/index.ts +4 -0
  36. package/src/messageComposer/configuration/types.ts +27 -0
  37. package/src/messageComposer/messageComposer.ts +73 -22
  38. package/src/messageComposer/middleware/messageComposer/compositionValidation.ts +23 -15
  39. package/src/messageComposer/middleware/messageComposer/textComposer.ts +151 -31
  40. package/src/messageComposer/middleware/textComposer/commandUtils.ts +68 -1
  41. package/src/messageComposer/middleware/textComposer/commands.ts +6 -2
  42. package/src/messageComposer/middleware/textComposer/mentionUtils.ts +33 -0
  43. package/src/messageComposer/middleware/textComposer/mentions.ts +596 -66
  44. package/src/messageComposer/middleware/textComposer/types.ts +70 -2
  45. package/src/messageComposer/textComposer.ts +154 -10
  46. package/src/pagination/UserGroupPaginator.ts +93 -0
  47. package/src/pagination/index.ts +1 -0
  48. package/src/permissions.ts +1 -0
  49. package/src/types.ts +152 -2
  50. package/src/utils.ts +1 -0
@@ -16,9 +16,73 @@ export type BaseSuggestion = {
16
16
  export type CommandSuggestionDisabledReason = 'editing' | 'quoted_message';
17
17
 
18
18
  export type CommandSuggestion = BaseSuggestion & CommandResponse;
19
- export type UserSuggestion = BaseSuggestion & UserResponse & TokenizationPayload;
19
+ export type UserSuggestion = BaseSuggestion &
20
+ UserResponse &
21
+ TokenizationPayload & {
22
+ mentionType: 'user';
23
+ };
24
+ export type ChannelMentionSuggestion = BaseSuggestion &
25
+ TokenizationPayload & {
26
+ mentionType: 'channel';
27
+ name: 'channel';
28
+ };
29
+ export type HereMentionSuggestion = BaseSuggestion &
30
+ TokenizationPayload & {
31
+ mentionType: 'here';
32
+ name: 'here';
33
+ };
34
+ export type RoleMentionSuggestion = BaseSuggestion &
35
+ TokenizationPayload & {
36
+ mentionType: 'role';
37
+ name: string;
38
+ };
39
+ export type UserGroupMentionSuggestion = BaseSuggestion &
40
+ TokenizationPayload & {
41
+ description?: string;
42
+ memberCount?: number;
43
+ mentionType: 'user_group';
44
+ name: string;
45
+ };
46
+ export type MentionSuggestion =
47
+ | UserSuggestion
48
+ | ChannelMentionSuggestion
49
+ | HereMentionSuggestion
50
+ | RoleMentionSuggestion
51
+ | UserGroupMentionSuggestion;
52
+
20
53
  export type CustomValidSuggestion = BaseSuggestion & CustomTextComposerSuggestion;
21
- export type Suggestion = CommandSuggestion | UserSuggestion | CustomValidSuggestion;
54
+ export type Suggestion = CommandSuggestion | MentionSuggestion | CustomValidSuggestion;
55
+
56
+ export type UserMentionEntity = UserResponse & {
57
+ mentionType: 'user';
58
+ };
59
+ export type ChannelMentionEntity = {
60
+ id: 'channel';
61
+ mentionType: 'channel';
62
+ name: 'channel';
63
+ };
64
+ export type HereMentionEntity = {
65
+ id: 'here';
66
+ mentionType: 'here';
67
+ name: 'here';
68
+ };
69
+ export type RoleMentionEntity = {
70
+ id: string;
71
+ mentionType: 'role';
72
+ name?: string;
73
+ };
74
+ export type UserGroupMentionEntity = {
75
+ id: string;
76
+ mentionType: 'user_group';
77
+ name?: string;
78
+ };
79
+
80
+ export type MentionEntity =
81
+ | UserMentionEntity
82
+ | ChannelMentionEntity
83
+ | HereMentionEntity
84
+ | RoleMentionEntity
85
+ | UserGroupMentionEntity;
22
86
 
23
87
  export type TextComposerStateSnapshot = TextComposerState;
24
88
 
@@ -55,7 +119,11 @@ export type Suggestions<T extends Suggestion = Suggestion> = {
55
119
  export type TextSelection = { end: number; start: number };
56
120
 
57
121
  export type TextComposerState<T extends Suggestion = Suggestion> = {
122
+ /**
123
+ * @deprecated Use `mentions` instead.
124
+ */
58
125
  mentionedUsers: UserResponse[];
126
+ mentions?: MentionEntity[];
59
127
  selection: TextSelection;
60
128
  text: string;
61
129
  command?: CommandResponse | null;
@@ -5,11 +5,18 @@ import type { TextComposerMiddlewareExecutorState } from './middleware';
5
5
  import type { TextComposerSuggestion } from './middleware/textComposer/types';
6
6
  import type { TextSelection } from './middleware/textComposer/types';
7
7
  import type {
8
+ MentionEntity,
8
9
  TextComposerCommandActivationEffect,
9
10
  TextComposerState,
10
11
  TextComposerStateSnapshot,
12
+ UserMentionEntity,
11
13
  } from './middleware/textComposer/types';
12
14
  import type { Suggestions } from './middleware/textComposer/types';
15
+ import {
16
+ isUserMentionEntity,
17
+ mentionEntityToUserResponse,
18
+ userResponseToMentionEntity,
19
+ } from './middleware/textComposer/mentionUtils';
13
20
  import type { MessageComposer } from './messageComposer';
14
21
  import type { CommandResponse, DraftMessage, LocalMessage, UserResponse } from '../types';
15
22
 
@@ -34,6 +41,71 @@ export const textIsEmpty = (text: string) => {
34
41
  );
35
42
  };
36
43
 
44
+ const getInitialMentions = (message?: DraftMessage | LocalMessage): MentionEntity[] => {
45
+ if (!message) return [];
46
+
47
+ const mentions: MentionEntity[] = (message.mentioned_users ?? []).map(
48
+ (item: string | UserResponse) =>
49
+ typeof item === 'string'
50
+ ? ({ id: item, mentionType: 'user' } as UserMentionEntity)
51
+ : { ...item, mentionType: 'user' },
52
+ );
53
+
54
+ if (message.mentioned_channel) {
55
+ mentions.push({
56
+ id: 'channel',
57
+ mentionType: 'channel',
58
+ name: 'channel',
59
+ });
60
+ }
61
+
62
+ if (message.mentioned_here) {
63
+ mentions.push({
64
+ id: 'here',
65
+ mentionType: 'here',
66
+ name: 'here',
67
+ });
68
+ }
69
+
70
+ if (message.mentioned_roles?.length) {
71
+ mentions.push(
72
+ ...message.mentioned_roles.map((role) => ({
73
+ id: role,
74
+ mentionType: 'role' as const,
75
+ name: role,
76
+ })),
77
+ );
78
+ }
79
+
80
+ if (message.mentioned_groups?.length) {
81
+ mentions.push(
82
+ ...message.mentioned_groups.map((group) => ({
83
+ id: group.id,
84
+ mentionType: 'user_group' as const,
85
+ name: group.name,
86
+ })),
87
+ );
88
+ } else if (message.mentioned_group_ids?.length) {
89
+ // Composer rehydration can still receive draft/local request-shaped data, where
90
+ // group mentions are represented only by ids even though response/render paths use
91
+ // `mentioned_groups` for presentation metadata.
92
+ mentions.push(
93
+ ...message.mentioned_group_ids.map((groupId) => ({
94
+ id: groupId,
95
+ mentionType: 'user_group' as const,
96
+ })),
97
+ );
98
+ }
99
+
100
+ return mentions;
101
+ };
102
+
103
+ const isSameMentionEntity = (first: MentionEntity, second: MentionEntity) =>
104
+ first.id === second.id && first.mentionType === second.mentionType;
105
+
106
+ const getMentionsFromState = (state: TextComposerState) =>
107
+ state.mentions ?? state.mentionedUsers.map(userResponseToMentionEntity);
108
+
37
109
  const initState = ({
38
110
  composer,
39
111
  message,
@@ -46,15 +118,20 @@ const initState = ({
46
118
  return {
47
119
  command: null,
48
120
  mentionedUsers: [],
121
+ mentions: [],
49
122
  text,
50
123
  selection: { start: text.length, end: text.length },
51
124
  };
52
125
  }
53
126
  const text = message.text ?? '';
54
- return {
55
- mentionedUsers: (message.mentioned_users ?? []).map((item: string | UserResponse) =>
127
+ const mentions = getInitialMentions(message);
128
+ const mentionedUsers = (message.mentioned_users ?? []).map(
129
+ (item: string | UserResponse) =>
56
130
  typeof item === 'string' ? ({ id: item } as UserResponse) : item,
57
- ),
131
+ );
132
+ return {
133
+ mentionedUsers,
134
+ mentions,
58
135
  text,
59
136
  selection: { start: text.length, end: text.length },
60
137
  };
@@ -134,6 +211,10 @@ export class TextComposer {
134
211
  return this.state.getLatestValue().mentionedUsers;
135
212
  }
136
213
 
214
+ get mentions() {
215
+ return getMentionsFromState(this.state.getLatestValue());
216
+ }
217
+
137
218
  get selection() {
138
219
  return this.state.getLatestValue().selection;
139
220
  }
@@ -161,7 +242,22 @@ export class TextComposer {
161
242
  };
162
243
 
163
244
  setMentionedUsers(users: UserResponse[]) {
164
- this.state.partialNext({ mentionedUsers: users });
245
+ const nonUserMentions = this.mentions.filter(
246
+ (entity) => !isUserMentionEntity(entity),
247
+ );
248
+ this.state.partialNext({
249
+ mentionedUsers: users,
250
+ mentions: [...nonUserMentions, ...users.map(userResponseToMentionEntity)],
251
+ });
252
+ }
253
+
254
+ setMentions(entities: MentionEntity[]) {
255
+ this.state.partialNext({
256
+ mentionedUsers: entities
257
+ .filter(isUserMentionEntity)
258
+ .map(mentionEntityToUserResponse),
259
+ mentions: entities,
260
+ });
165
261
  }
166
262
 
167
263
  clearCommand() {
@@ -174,27 +270,75 @@ export class TextComposer {
174
270
  });
175
271
  }
176
272
 
273
+ /**
274
+ * @deprecated Use `upsertMentionEntity({ ...user, mentionType: 'user' })` instead.
275
+ */
177
276
  upsertMentionedUser = (user: UserResponse) => {
178
277
  const mentionedUsers = [...this.mentionedUsers];
179
- const existingUserIndex = mentionedUsers.findIndex((u) => u.id === user.id);
278
+ const existingUserIndex = mentionedUsers.findIndex((entity) => entity.id === user.id);
180
279
  if (existingUserIndex >= 0) {
181
280
  mentionedUsers.splice(existingUserIndex, 1, user);
182
- this.state.partialNext({ mentionedUsers });
281
+ this.setMentionedUsers(mentionedUsers);
183
282
  } else {
184
283
  mentionedUsers.push(user);
185
- this.state.partialNext({ mentionedUsers });
284
+ this.setMentionedUsers(mentionedUsers);
186
285
  }
187
286
  };
188
287
 
288
+ /**
289
+ * @deprecated Use `getMentionEntity('user', userId)` instead.
290
+ */
189
291
  getMentionedUser = (userId: string) =>
190
- this.state.getLatestValue().mentionedUsers.find((u: UserResponse) => u.id === userId);
292
+ this.mentionedUsers.find((user) => user.id === userId);
191
293
 
294
+ /**
295
+ * @deprecated Use `removeMentionEntity('user', userId)` instead.
296
+ */
192
297
  removeMentionedUser = (userId: string) => {
193
- const existingUserIndex = this.mentionedUsers.findIndex((u) => u.id === userId);
298
+ const existingUserIndex = this.mentionedUsers.findIndex(
299
+ (entity) => entity.id === userId,
300
+ );
194
301
  if (existingUserIndex === -1) return;
195
302
  const mentionedUsers = [...this.mentionedUsers];
196
303
  mentionedUsers.splice(existingUserIndex, 1);
197
- this.state.partialNext({ mentionedUsers });
304
+ this.setMentionedUsers(mentionedUsers);
305
+ };
306
+
307
+ upsertMentionEntity = (entity: MentionEntity) => {
308
+ const mentions = [...this.mentions];
309
+ const existingEntityIndex = mentions.findIndex((currentEntity) =>
310
+ isSameMentionEntity(currentEntity, entity),
311
+ );
312
+
313
+ if (existingEntityIndex >= 0) {
314
+ mentions.splice(existingEntityIndex, 1, entity);
315
+ } else {
316
+ mentions.push(entity);
317
+ }
318
+
319
+ this.setMentions(mentions);
320
+ };
321
+
322
+ getMentionEntity = (
323
+ mentionType: MentionEntity['mentionType'],
324
+ id: MentionEntity['id'],
325
+ ) =>
326
+ this.mentions.find(
327
+ (entity) => entity.mentionType === mentionType && entity.id === id,
328
+ );
329
+
330
+ removeMentionEntity = (
331
+ mentionType: MentionEntity['mentionType'],
332
+ id: MentionEntity['id'],
333
+ ) => {
334
+ const existingEntityIndex = this.mentions.findIndex(
335
+ (entity) => entity.mentionType === mentionType && entity.id === id,
336
+ );
337
+ if (existingEntityIndex === -1) return;
338
+
339
+ const mentions = [...this.mentions];
340
+ mentions.splice(existingEntityIndex, 1);
341
+ this.setMentions(mentions);
198
342
  };
199
343
 
200
344
  setCommand = (command: CommandResponse | null) => {
@@ -0,0 +1,93 @@
1
+ import { BasePaginator } from './BasePaginator';
2
+ import type {
3
+ PaginationQueryParams,
4
+ PaginationQueryReturnValue,
5
+ PaginatorOptions,
6
+ PaginatorState,
7
+ } from './BasePaginator';
8
+ import type { QueryUserGroupsOptions, UserGroupResponse } from '../types';
9
+ import type { StreamChat } from '../client';
10
+
11
+ type UserGroupListCursor = {
12
+ created_at_gt: string;
13
+ id_gt: string;
14
+ };
15
+
16
+ const isRecord = (value: unknown): value is Record<string, unknown> =>
17
+ typeof value === 'object' && value !== null;
18
+
19
+ const decodeCursor = <TCursor extends object>(cursor: string | null | undefined) => {
20
+ if (!cursor) return undefined;
21
+
22
+ try {
23
+ const parsed = JSON.parse(cursor);
24
+ return isRecord(parsed) ? (parsed as TCursor) : undefined;
25
+ } catch {
26
+ return undefined;
27
+ }
28
+ };
29
+
30
+ /**
31
+ * Paginates user-group listing through `/usergroups`.
32
+ *
33
+ * This entity only supports forward cursor pagination via `created_at_gt` and `id_gt`.
34
+ * Previous-page pagination is not available because the API does not expose a backward cursor.
35
+ */
36
+ export class UserGroupPaginator extends BasePaginator<UserGroupResponse> {
37
+ private client: StreamChat;
38
+ protected _teamId: string | undefined;
39
+
40
+ constructor(client: StreamChat, options?: PaginatorOptions) {
41
+ super(options);
42
+ this.client = client;
43
+ }
44
+
45
+ get initialState(): PaginatorState<UserGroupResponse> {
46
+ return {
47
+ ...super.initialState,
48
+ hasPrev: false,
49
+ };
50
+ }
51
+
52
+ get teamId() {
53
+ return this._teamId;
54
+ }
55
+
56
+ set teamId(teamId: string | undefined) {
57
+ if (teamId === this._teamId) return;
58
+ this._teamId = teamId;
59
+ this.resetState();
60
+ }
61
+
62
+ private buildNextCursor = (items: UserGroupResponse[]) => {
63
+ if (items.length < this.pageSize) return undefined;
64
+ const lastItem = items[items.length - 1];
65
+ if (!lastItem) return undefined;
66
+
67
+ return JSON.stringify({
68
+ created_at_gt: lastItem.created_at,
69
+ id_gt: lastItem.id,
70
+ } satisfies UserGroupListCursor);
71
+ };
72
+
73
+ query = async ({
74
+ direction,
75
+ }: PaginationQueryParams): Promise<PaginationQueryReturnValue<UserGroupResponse>> => {
76
+ if (direction === 'prev') {
77
+ return { items: [] };
78
+ }
79
+
80
+ const cursor = decodeCursor<UserGroupListCursor>(this.cursor?.next);
81
+ const options: QueryUserGroupsOptions = {
82
+ limit: this.pageSize,
83
+ ...(this.teamId ? { team_id: this.teamId } : {}),
84
+ ...(cursor?.id_gt ? { id_gt: cursor.id_gt } : {}),
85
+ ...(cursor?.created_at_gt ? { created_at_gt: cursor.created_at_gt } : {}),
86
+ };
87
+
88
+ const { user_groups: items } = await this.client.queryUserGroups(options);
89
+ return { items, next: this.buildNextCursor(items) };
90
+ };
91
+
92
+ filterQueryResults = (items: UserGroupResponse[]) => items;
93
+ }
@@ -1,3 +1,4 @@
1
1
  export * from './BasePaginator';
2
2
  export * from './FilterBuilder';
3
3
  export * from './ReminderPaginator';
4
+ export * from './UserGroupPaginator';
@@ -56,6 +56,7 @@ export const DenyAll = new Permission(
56
56
  Deny,
57
57
  );
58
58
 
59
+ // Fixme: rename to RoleName with next major release
59
60
  export type Role =
60
61
  | 'admin'
61
62
  | 'user'
package/src/types.ts CHANGED
@@ -133,6 +133,7 @@ export type AppSettingsAPIResponse = APIResponse & {
133
133
  async_url_enrich_enabled?: boolean;
134
134
  auto_translation_enabled?: boolean;
135
135
  before_message_send_hook_url?: string;
136
+ before_message_send_hook_attempt_timeout_ms?: number;
136
137
  campaign_enabled?: boolean;
137
138
  cdn_expiration_seconds?: number;
138
139
  custom_action_handler_url?: string;
@@ -754,6 +755,8 @@ export type MessageResponseBase = MessageBase & {
754
755
  mentioned_users?: UserResponse[];
755
756
  mentioned_channel?: boolean;
756
757
  mentioned_here?: boolean;
758
+ mentioned_group_ids?: string[];
759
+ mentioned_groups?: UserGroupResponse[];
757
760
  mentioned_roles?: string[];
758
761
  message_text_updated_at?: string;
759
762
  moderation?: ModerationResponse; // present only with Moderation v2
@@ -905,6 +908,35 @@ export type SearchAPIResponse = APIResponse & {
905
908
  results_warning?: SearchWarning | null;
906
909
  };
907
910
 
911
+ export type RoleResponse = {
912
+ name: Role;
913
+ custom: boolean;
914
+ scopes: string[];
915
+ created_at: string;
916
+ updated_at: string;
917
+ };
918
+
919
+ export type CreateRoleAPIResponse = APIResponse & {
920
+ role: RoleResponse;
921
+ };
922
+
923
+ export type ListRolesAPIResponse = APIResponse & {
924
+ roles: RoleResponse[];
925
+ };
926
+
927
+ export type SearchRolesAPIResponse = APIResponse & {
928
+ roles: RoleResponse[];
929
+ };
930
+
931
+ export type SearchRolesOptions = {
932
+ query: string;
933
+ include_global_roles?: boolean;
934
+ limit?: number;
935
+ name_gt?: string;
936
+ // If not provided, the default is search performed both in user-assignable + channel-assignable roles
937
+ role_type?: 'user' | 'channel';
938
+ };
939
+
908
940
  export type SearchWarning = {
909
941
  channel_search_cids: string[];
910
942
  channel_search_count: number;
@@ -2403,6 +2435,7 @@ export type AppSettings = {
2403
2435
  async_url_enrich_enabled?: boolean;
2404
2436
  auto_translation_enabled?: boolean;
2405
2437
  before_message_send_hook_url?: string;
2438
+ before_message_send_hook_attempt_timeout_ms?: number;
2406
2439
  cdn_expiration_seconds?: number;
2407
2440
  custom_action_handler_url?: string;
2408
2441
  disable_auth_checks?: boolean;
@@ -2901,6 +2934,9 @@ export type Message = Partial<
2901
2934
  mentioned_users: string[];
2902
2935
  shared_location?: StaticLocationPayload | LiveLocationPayload;
2903
2936
  mentioned_channel?: boolean;
2937
+ mentioned_here?: boolean;
2938
+ mentioned_group_ids?: string[];
2939
+ mentioned_roles?: string[];
2904
2940
  }
2905
2941
  >;
2906
2942
 
@@ -3171,8 +3207,15 @@ export type TypingStartEvent = Event;
3171
3207
 
3172
3208
  export type ReservedUpdatedMessageFields = keyof typeof RESERVED_UPDATED_MESSAGE_FIELDS;
3173
3209
 
3174
- export type UpdatedMessage = Omit<MessageResponse, ReservedUpdatedMessageFields> & {
3210
+ export type UpdatedMessage = Omit<
3211
+ MessageResponse,
3212
+ ReservedUpdatedMessageFields | 'mentioned_groups'
3213
+ > & {
3175
3214
  mentioned_users?: string[];
3215
+ mentioned_channel?: boolean;
3216
+ mentioned_here?: boolean;
3217
+ mentioned_group_ids?: string[];
3218
+ mentioned_roles?: string[];
3176
3219
  type?: MessageLabel;
3177
3220
  };
3178
3221
 
@@ -4468,7 +4511,10 @@ export type QueryDraftsResponse = APIResponse & {
4468
4511
  drafts: DraftResponse[];
4469
4512
  } & Omit<Pager, 'limit'>;
4470
4513
 
4471
- export type DraftMessagePayload = PartializeKeys<DraftMessage, 'id'> & {
4514
+ export type DraftMessagePayload = PartializeKeys<
4515
+ Omit<DraftMessage, 'mentioned_groups'>,
4516
+ 'id'
4517
+ > & {
4472
4518
  user_id?: string;
4473
4519
  };
4474
4520
 
@@ -4479,6 +4525,11 @@ export type DraftMessage = {
4479
4525
  custom?: {};
4480
4526
  html?: string;
4481
4527
  mentioned_users?: string[];
4528
+ mentioned_channel?: boolean;
4529
+ mentioned_here?: boolean;
4530
+ mentioned_group_ids?: string[];
4531
+ mentioned_groups?: UserGroupResponse[];
4532
+ mentioned_roles?: string[];
4482
4533
  mml?: string;
4483
4534
  parent_id?: string;
4484
4535
  poll_id?: string;
@@ -4696,6 +4747,105 @@ export type QueryRemindersResponse = {
4696
4747
  next?: string;
4697
4748
  };
4698
4749
 
4750
+ export type UserGroupMemberResponse = {
4751
+ group_id: string;
4752
+ user_id: string;
4753
+ is_admin: boolean;
4754
+ created_at: string;
4755
+ };
4756
+
4757
+ export type UserGroupResponse = {
4758
+ id: string;
4759
+ name: string;
4760
+ created_at: string;
4761
+ updated_at: string;
4762
+ description?: string;
4763
+ team_id?: string;
4764
+ members?: UserGroupMemberResponse[];
4765
+ created_by?: string;
4766
+ };
4767
+
4768
+ export type CreateUserGroupOptions = {
4769
+ /** Human-readable user group name */
4770
+ name: string;
4771
+ /** Optional user group description shown to members */
4772
+ description?: string;
4773
+ /** Optional custom user group ID. If omitted, the backend generates one */
4774
+ id?: string;
4775
+ /** Optional list of user IDs to add as members when the group is created */
4776
+ member_ids?: string[];
4777
+ /** Optional team ID that scopes the user group to a specific team */
4778
+ team_id?: string;
4779
+ };
4780
+
4781
+ export type CreateUserGroupResponse = APIResponse & {
4782
+ user_group: UserGroupResponse;
4783
+ };
4784
+
4785
+ export type GetUserGroupOptions = {
4786
+ team_id?: string;
4787
+ };
4788
+
4789
+ export type GetUserGroupResponse = APIResponse & {
4790
+ user_group: UserGroupResponse;
4791
+ };
4792
+
4793
+ export type QueryUserGroupsOptions = {
4794
+ limit?: number;
4795
+ id_gt?: string;
4796
+ created_at_gt?: string;
4797
+ team_id?: string;
4798
+ };
4799
+
4800
+ export type QueryUserGroupsResponse = APIResponse & {
4801
+ user_groups: UserGroupResponse[];
4802
+ };
4803
+
4804
+ export type SearchUserGroupsOptions = {
4805
+ query: string;
4806
+ limit?: number;
4807
+ id_gt?: string;
4808
+ name_gt?: string;
4809
+ team_id?: string;
4810
+ };
4811
+
4812
+ export type SearchUserGroupsResponse = APIResponse & {
4813
+ user_groups: UserGroupResponse[];
4814
+ };
4815
+
4816
+ export type UpdateUserGroupOptions = {
4817
+ description?: string;
4818
+ name?: string;
4819
+ team_id?: string;
4820
+ };
4821
+
4822
+ export type UpdateUserGroupResponse = APIResponse & {
4823
+ user_group: UserGroupResponse;
4824
+ };
4825
+
4826
+ export type DeleteUserGroupOptions = {
4827
+ team_id?: string;
4828
+ };
4829
+
4830
+ export type AddUserGroupMembersOptions = {
4831
+ member_ids: string[];
4832
+ as_admin?: boolean;
4833
+ team_id?: string;
4834
+ };
4835
+
4836
+ export type AddUserGroupMembersResponse = APIResponse & {
4837
+ user_group: UserGroupResponse;
4838
+ };
4839
+
4840
+ export type RemoveUserGroupMembersOptions = {
4841
+ member_ids: string[];
4842
+ team_id?: string;
4843
+ };
4844
+
4845
+ export type RemoveUserGroupMembersResponse = APIResponse & {
4846
+ user_group: UserGroupResponse;
4847
+ };
4848
+
4699
4849
  export type HookType = 'webhook' | 'sqs' | 'sns' | 'pending_message';
4700
4850
 
4701
4851
  export type EventHook = {
package/src/utils.ts CHANGED
@@ -381,6 +381,7 @@ export const localMessageToNewMessagePayload = (localMessage: LocalMessage): Mes
381
381
  command,
382
382
  html,
383
383
  i18n,
384
+ mentioned_groups,
384
385
  quoted_message,
385
386
  mentioned_users,
386
387
  // Message content related fields