stream-chat 9.44.1 → 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.
- package/dist/cjs/index.browser.js +3546 -2681
- package/dist/cjs/index.browser.js.map +4 -4
- package/dist/cjs/index.node.js +3555 -2681
- package/dist/cjs/index.node.js.map +4 -4
- package/dist/esm/index.mjs +3546 -2681
- package/dist/esm/index.mjs.map +4 -4
- package/dist/types/channel_manager.d.ts +5 -2
- package/dist/types/channel_state.d.ts +1 -1
- package/dist/types/client.d.ts +112 -5
- package/dist/types/constants.d.ts +1 -0
- package/dist/types/messageComposer/LocationComposer.d.ts +1 -1
- package/dist/types/messageComposer/configuration/commands.configuration.d.ts +6 -0
- package/dist/types/messageComposer/configuration/configuration.d.ts +1 -2
- package/dist/types/messageComposer/configuration/index.d.ts +4 -0
- package/dist/types/messageComposer/configuration/types.d.ts +21 -0
- package/dist/types/messageComposer/fileUtils.d.ts +1 -1
- package/dist/types/messageComposer/messageComposer.d.ts +6 -4
- package/dist/types/messageComposer/middleware/messageComposer/compositionValidation.d.ts +2 -1
- package/dist/types/messageComposer/middleware/messageComposer/textComposer.d.ts +1 -1
- package/dist/types/messageComposer/middleware/textComposer/commandUtils.d.ts +10 -1
- package/dist/types/messageComposer/middleware/textComposer/mentionUtils.d.ts +8 -0
- package/dist/types/messageComposer/middleware/textComposer/mentions.d.ts +77 -15
- package/dist/types/messageComposer/middleware/textComposer/types.d.ts +51 -2
- package/dist/types/messageComposer/pollComposer.d.ts +2 -2
- package/dist/types/messageComposer/textComposer.d.ts +17 -3
- package/dist/types/pagination/UserGroupPaginator.d.ts +21 -0
- package/dist/types/pagination/index.d.ts +1 -0
- package/dist/types/types.d.ts +132 -2
- package/dist/types/utils.d.ts +2 -0
- package/package.json +38 -31
- package/src/channel_manager.ts +88 -13
- package/src/client.ts +217 -12
- package/src/constants.ts +1 -0
- package/src/messageComposer/MessageComposerEffectHandlers.ts +1 -0
- package/src/messageComposer/configuration/commands.configuration.ts +55 -0
- package/src/messageComposer/configuration/configuration.ts +3 -1
- package/src/messageComposer/configuration/index.ts +4 -0
- package/src/messageComposer/configuration/types.ts +27 -0
- package/src/messageComposer/messageComposer.ts +73 -22
- package/src/messageComposer/middleware/messageComposer/compositionValidation.ts +23 -15
- package/src/messageComposer/middleware/messageComposer/textComposer.ts +151 -31
- package/src/messageComposer/middleware/textComposer/commandUtils.ts +68 -1
- package/src/messageComposer/middleware/textComposer/commands.ts +6 -2
- package/src/messageComposer/middleware/textComposer/mentionUtils.ts +33 -0
- package/src/messageComposer/middleware/textComposer/mentions.ts +596 -66
- package/src/messageComposer/middleware/textComposer/types.ts +70 -2
- package/src/messageComposer/textComposer.ts +154 -10
- package/src/pagination/UserGroupPaginator.ts +93 -0
- package/src/pagination/index.ts +1 -0
- package/src/permissions.ts +1 -0
- package/src/types.ts +161 -2
- package/src/utils.ts +1 -0
|
@@ -2,7 +2,7 @@ import { TextComposerMiddlewareExecutor } from './middleware';
|
|
|
2
2
|
import { StateStore } from '../store';
|
|
3
3
|
import type { TextComposerSuggestion } from './middleware/textComposer/types';
|
|
4
4
|
import type { TextSelection } from './middleware/textComposer/types';
|
|
5
|
-
import type { TextComposerState, TextComposerStateSnapshot } from './middleware/textComposer/types';
|
|
5
|
+
import type { MentionEntity, TextComposerState, TextComposerStateSnapshot } from './middleware/textComposer/types';
|
|
6
6
|
import type { Suggestions } from './middleware/textComposer/types';
|
|
7
7
|
import type { MessageComposer } from './messageComposer';
|
|
8
8
|
import type { CommandResponse, DraftMessage, LocalMessage, UserResponse } from '../types';
|
|
@@ -18,7 +18,7 @@ export declare class TextComposer {
|
|
|
18
18
|
middlewareExecutor: TextComposerMiddlewareExecutor;
|
|
19
19
|
constructor({ composer, message }: TextComposerOptions);
|
|
20
20
|
get channel(): import("..").Channel;
|
|
21
|
-
get config(): import("
|
|
21
|
+
get config(): import("..").TextComposerConfig;
|
|
22
22
|
get enabled(): boolean;
|
|
23
23
|
set enabled(enabled: boolean);
|
|
24
24
|
get defaultValue(): string | undefined;
|
|
@@ -31,8 +31,9 @@ export declare class TextComposer {
|
|
|
31
31
|
set publishTypingEvents(publishTypingEvents: boolean);
|
|
32
32
|
get command(): CommandResponse | null | undefined;
|
|
33
33
|
get mentionedUsers(): UserResponse[];
|
|
34
|
+
get mentions(): MentionEntity[];
|
|
34
35
|
get selection(): TextSelection;
|
|
35
|
-
get suggestions(): Suggestions<import("
|
|
36
|
+
get suggestions(): Suggestions<import("..").Suggestion> | undefined;
|
|
36
37
|
get text(): string;
|
|
37
38
|
get textIsEmpty(): boolean;
|
|
38
39
|
initState: ({ message }?: {
|
|
@@ -41,10 +42,23 @@ export declare class TextComposer {
|
|
|
41
42
|
getSnapshot: (state?: TextComposerState) => TextComposerSnapshot;
|
|
42
43
|
restoreSnapshot: (snapshot: TextComposerSnapshot) => void;
|
|
43
44
|
setMentionedUsers(users: UserResponse[]): void;
|
|
45
|
+
setMentions(entities: MentionEntity[]): void;
|
|
44
46
|
clearCommand(): void;
|
|
47
|
+
/**
|
|
48
|
+
* @deprecated Use `upsertMentionEntity({ ...user, mentionType: 'user' })` instead.
|
|
49
|
+
*/
|
|
45
50
|
upsertMentionedUser: (user: UserResponse) => void;
|
|
51
|
+
/**
|
|
52
|
+
* @deprecated Use `getMentionEntity('user', userId)` instead.
|
|
53
|
+
*/
|
|
46
54
|
getMentionedUser: (userId: string) => UserResponse | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* @deprecated Use `removeMentionEntity('user', userId)` instead.
|
|
57
|
+
*/
|
|
47
58
|
removeMentionedUser: (userId: string) => void;
|
|
59
|
+
upsertMentionEntity: (entity: MentionEntity) => void;
|
|
60
|
+
getMentionEntity: (mentionType: MentionEntity["mentionType"], id: MentionEntity["id"]) => MentionEntity | undefined;
|
|
61
|
+
removeMentionEntity: (mentionType: MentionEntity["mentionType"], id: MentionEntity["id"]) => void;
|
|
48
62
|
setCommand: (command: CommandResponse | null) => void;
|
|
49
63
|
setText: (text: string) => void;
|
|
50
64
|
setSelection: (selection: TextSelection) => void;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { BasePaginator } from './BasePaginator';
|
|
2
|
+
import type { PaginationQueryParams, PaginationQueryReturnValue, PaginatorOptions, PaginatorState } from './BasePaginator';
|
|
3
|
+
import type { UserGroupResponse } from '../types';
|
|
4
|
+
import type { StreamChat } from '../client';
|
|
5
|
+
/**
|
|
6
|
+
* Paginates user-group listing through `/usergroups`.
|
|
7
|
+
*
|
|
8
|
+
* This entity only supports forward cursor pagination via `created_at_gt` and `id_gt`.
|
|
9
|
+
* Previous-page pagination is not available because the API does not expose a backward cursor.
|
|
10
|
+
*/
|
|
11
|
+
export declare class UserGroupPaginator extends BasePaginator<UserGroupResponse> {
|
|
12
|
+
private client;
|
|
13
|
+
protected _teamId: string | undefined;
|
|
14
|
+
constructor(client: StreamChat, options?: PaginatorOptions);
|
|
15
|
+
get initialState(): PaginatorState<UserGroupResponse>;
|
|
16
|
+
get teamId(): string | undefined;
|
|
17
|
+
set teamId(teamId: string | undefined);
|
|
18
|
+
private buildNextCursor;
|
|
19
|
+
query: ({ direction, }: PaginationQueryParams) => Promise<PaginationQueryReturnValue<UserGroupResponse>>;
|
|
20
|
+
filterQueryResults: (items: UserGroupResponse[]) => UserGroupResponse[];
|
|
21
|
+
}
|
package/dist/types/types.d.ts
CHANGED
|
@@ -88,6 +88,7 @@ export type AppSettingsAPIResponse = APIResponse & {
|
|
|
88
88
|
async_url_enrich_enabled?: boolean;
|
|
89
89
|
auto_translation_enabled?: boolean;
|
|
90
90
|
before_message_send_hook_url?: string;
|
|
91
|
+
before_message_send_hook_attempt_timeout_ms?: number;
|
|
91
92
|
campaign_enabled?: boolean;
|
|
92
93
|
cdn_expiration_seconds?: number;
|
|
93
94
|
custom_action_handler_url?: string;
|
|
@@ -631,6 +632,8 @@ export type MessageResponseBase = MessageBase & {
|
|
|
631
632
|
mentioned_users?: UserResponse[];
|
|
632
633
|
mentioned_channel?: boolean;
|
|
633
634
|
mentioned_here?: boolean;
|
|
635
|
+
mentioned_group_ids?: string[];
|
|
636
|
+
mentioned_groups?: UserGroupResponse[];
|
|
634
637
|
mentioned_roles?: string[];
|
|
635
638
|
message_text_updated_at?: string;
|
|
636
639
|
moderation?: ModerationResponse;
|
|
@@ -766,6 +769,29 @@ export type SearchAPIResponse = APIResponse & {
|
|
|
766
769
|
previous?: string;
|
|
767
770
|
results_warning?: SearchWarning | null;
|
|
768
771
|
};
|
|
772
|
+
export type RoleResponse = {
|
|
773
|
+
name: Role;
|
|
774
|
+
custom: boolean;
|
|
775
|
+
scopes: string[];
|
|
776
|
+
created_at: string;
|
|
777
|
+
updated_at: string;
|
|
778
|
+
};
|
|
779
|
+
export type CreateRoleAPIResponse = APIResponse & {
|
|
780
|
+
role: RoleResponse;
|
|
781
|
+
};
|
|
782
|
+
export type ListRolesAPIResponse = APIResponse & {
|
|
783
|
+
roles: RoleResponse[];
|
|
784
|
+
};
|
|
785
|
+
export type SearchRolesAPIResponse = APIResponse & {
|
|
786
|
+
roles: RoleResponse[];
|
|
787
|
+
};
|
|
788
|
+
export type SearchRolesOptions = {
|
|
789
|
+
query: string;
|
|
790
|
+
include_global_roles?: boolean;
|
|
791
|
+
limit?: number;
|
|
792
|
+
name_gt?: string;
|
|
793
|
+
role_type?: 'user' | 'channel';
|
|
794
|
+
};
|
|
769
795
|
export type SearchWarning = {
|
|
770
796
|
channel_search_cids: string[];
|
|
771
797
|
channel_search_count: number;
|
|
@@ -949,6 +975,15 @@ export type ChannelStateOptions = {
|
|
|
949
975
|
offlineMode?: boolean;
|
|
950
976
|
skipInitialization?: string[];
|
|
951
977
|
skipHydration?: boolean;
|
|
978
|
+
/**
|
|
979
|
+
* Returns the full query response with hydrated channels from `queryChannels()`.
|
|
980
|
+
*
|
|
981
|
+
* This is a compatibility bridge for internal callers that need response level
|
|
982
|
+
* metadata such as `predefined_filter`. The default `queryChannels()` return value
|
|
983
|
+
* remains `Channel[]` to avoid a breaking change. This should be folded into a
|
|
984
|
+
* single full response API in the next major release.
|
|
985
|
+
*/
|
|
986
|
+
withResponse?: boolean;
|
|
952
987
|
};
|
|
953
988
|
export type CreateChannelOptions = {
|
|
954
989
|
automod?: ChannelConfigAutomod;
|
|
@@ -1861,6 +1896,7 @@ export type AppSettings = {
|
|
|
1861
1896
|
async_url_enrich_enabled?: boolean;
|
|
1862
1897
|
auto_translation_enabled?: boolean;
|
|
1863
1898
|
before_message_send_hook_url?: string;
|
|
1899
|
+
before_message_send_hook_attempt_timeout_ms?: number;
|
|
1864
1900
|
cdn_expiration_seconds?: number;
|
|
1865
1901
|
custom_action_handler_url?: string;
|
|
1866
1902
|
disable_auth_checks?: boolean;
|
|
@@ -2165,6 +2201,9 @@ export type Message = Partial<MessageBase & {
|
|
|
2165
2201
|
mentioned_users: string[];
|
|
2166
2202
|
shared_location?: StaticLocationPayload | LiveLocationPayload;
|
|
2167
2203
|
mentioned_channel?: boolean;
|
|
2204
|
+
mentioned_here?: boolean;
|
|
2205
|
+
mentioned_group_ids?: string[];
|
|
2206
|
+
mentioned_roles?: string[];
|
|
2168
2207
|
}>;
|
|
2169
2208
|
export type MessageBase = CustomMessageData & {
|
|
2170
2209
|
id: string;
|
|
@@ -2318,8 +2357,12 @@ export type TokenProvider = () => Promise<string>;
|
|
|
2318
2357
|
export type TranslationLanguages = 'af' | 'am' | 'ar' | 'az' | 'bg' | 'bn' | 'bs' | 'cs' | 'da' | 'de' | 'el' | 'en' | 'es' | 'es-MX' | 'et' | 'fa' | 'fa-AF' | 'fi' | 'fr' | 'fr-CA' | 'ha' | 'he' | 'hi' | 'hr' | 'hu' | 'id' | 'it' | 'ja' | 'ka' | 'ko' | 'lt' | 'lv' | 'ms' | 'nl' | 'no' | 'pl' | 'ps' | 'pt' | 'ro' | 'ru' | 'sk' | 'sl' | 'so' | 'sq' | 'sr' | 'sv' | 'sw' | 'ta' | 'th' | 'tl' | 'tr' | 'uk' | 'ur' | 'vi' | 'zh' | 'zh-TW' | (string & {});
|
|
2319
2358
|
export type TypingStartEvent = Event;
|
|
2320
2359
|
export type ReservedUpdatedMessageFields = keyof typeof RESERVED_UPDATED_MESSAGE_FIELDS;
|
|
2321
|
-
export type UpdatedMessage = Omit<MessageResponse, ReservedUpdatedMessageFields> & {
|
|
2360
|
+
export type UpdatedMessage = Omit<MessageResponse, ReservedUpdatedMessageFields | 'mentioned_groups'> & {
|
|
2322
2361
|
mentioned_users?: string[];
|
|
2362
|
+
mentioned_channel?: boolean;
|
|
2363
|
+
mentioned_here?: boolean;
|
|
2364
|
+
mentioned_group_ids?: string[];
|
|
2365
|
+
mentioned_roles?: string[];
|
|
2323
2366
|
type?: MessageLabel;
|
|
2324
2367
|
};
|
|
2325
2368
|
/**
|
|
@@ -3329,7 +3372,7 @@ export type GetDraftResponse = APIResponse & {
|
|
|
3329
3372
|
export type QueryDraftsResponse = APIResponse & {
|
|
3330
3373
|
drafts: DraftResponse[];
|
|
3331
3374
|
} & Omit<Pager, 'limit'>;
|
|
3332
|
-
export type DraftMessagePayload = PartializeKeys<DraftMessage, 'id'> & {
|
|
3375
|
+
export type DraftMessagePayload = PartializeKeys<Omit<DraftMessage, 'mentioned_groups'>, 'id'> & {
|
|
3333
3376
|
user_id?: string;
|
|
3334
3377
|
};
|
|
3335
3378
|
export type DraftMessage = {
|
|
@@ -3339,6 +3382,11 @@ export type DraftMessage = {
|
|
|
3339
3382
|
custom?: {};
|
|
3340
3383
|
html?: string;
|
|
3341
3384
|
mentioned_users?: string[];
|
|
3385
|
+
mentioned_channel?: boolean;
|
|
3386
|
+
mentioned_here?: boolean;
|
|
3387
|
+
mentioned_group_ids?: string[];
|
|
3388
|
+
mentioned_groups?: UserGroupResponse[];
|
|
3389
|
+
mentioned_roles?: string[];
|
|
3342
3390
|
mml?: string;
|
|
3343
3391
|
parent_id?: string;
|
|
3344
3392
|
poll_id?: string;
|
|
@@ -3469,6 +3517,88 @@ export type QueryRemindersResponse = {
|
|
|
3469
3517
|
prev?: string;
|
|
3470
3518
|
next?: string;
|
|
3471
3519
|
};
|
|
3520
|
+
export type UserGroupMemberResponse = {
|
|
3521
|
+
group_id: string;
|
|
3522
|
+
user_id: string;
|
|
3523
|
+
is_admin: boolean;
|
|
3524
|
+
created_at: string;
|
|
3525
|
+
};
|
|
3526
|
+
export type UserGroupResponse = {
|
|
3527
|
+
id: string;
|
|
3528
|
+
name: string;
|
|
3529
|
+
created_at: string;
|
|
3530
|
+
updated_at: string;
|
|
3531
|
+
description?: string;
|
|
3532
|
+
team_id?: string;
|
|
3533
|
+
members?: UserGroupMemberResponse[];
|
|
3534
|
+
created_by?: string;
|
|
3535
|
+
};
|
|
3536
|
+
export type CreateUserGroupOptions = {
|
|
3537
|
+
/** Human-readable user group name */
|
|
3538
|
+
name: string;
|
|
3539
|
+
/** Optional user group description shown to members */
|
|
3540
|
+
description?: string;
|
|
3541
|
+
/** Optional custom user group ID. If omitted, the backend generates one */
|
|
3542
|
+
id?: string;
|
|
3543
|
+
/** Optional list of user IDs to add as members when the group is created */
|
|
3544
|
+
member_ids?: string[];
|
|
3545
|
+
/** Optional team ID that scopes the user group to a specific team */
|
|
3546
|
+
team_id?: string;
|
|
3547
|
+
};
|
|
3548
|
+
export type CreateUserGroupResponse = APIResponse & {
|
|
3549
|
+
user_group: UserGroupResponse;
|
|
3550
|
+
};
|
|
3551
|
+
export type GetUserGroupOptions = {
|
|
3552
|
+
team_id?: string;
|
|
3553
|
+
};
|
|
3554
|
+
export type GetUserGroupResponse = APIResponse & {
|
|
3555
|
+
user_group: UserGroupResponse;
|
|
3556
|
+
};
|
|
3557
|
+
export type QueryUserGroupsOptions = {
|
|
3558
|
+
limit?: number;
|
|
3559
|
+
id_gt?: string;
|
|
3560
|
+
created_at_gt?: string;
|
|
3561
|
+
team_id?: string;
|
|
3562
|
+
};
|
|
3563
|
+
export type QueryUserGroupsResponse = APIResponse & {
|
|
3564
|
+
user_groups: UserGroupResponse[];
|
|
3565
|
+
};
|
|
3566
|
+
export type SearchUserGroupsOptions = {
|
|
3567
|
+
query: string;
|
|
3568
|
+
limit?: number;
|
|
3569
|
+
id_gt?: string;
|
|
3570
|
+
name_gt?: string;
|
|
3571
|
+
team_id?: string;
|
|
3572
|
+
};
|
|
3573
|
+
export type SearchUserGroupsResponse = APIResponse & {
|
|
3574
|
+
user_groups: UserGroupResponse[];
|
|
3575
|
+
};
|
|
3576
|
+
export type UpdateUserGroupOptions = {
|
|
3577
|
+
description?: string;
|
|
3578
|
+
name?: string;
|
|
3579
|
+
team_id?: string;
|
|
3580
|
+
};
|
|
3581
|
+
export type UpdateUserGroupResponse = APIResponse & {
|
|
3582
|
+
user_group: UserGroupResponse;
|
|
3583
|
+
};
|
|
3584
|
+
export type DeleteUserGroupOptions = {
|
|
3585
|
+
team_id?: string;
|
|
3586
|
+
};
|
|
3587
|
+
export type AddUserGroupMembersOptions = {
|
|
3588
|
+
member_ids: string[];
|
|
3589
|
+
as_admin?: boolean;
|
|
3590
|
+
team_id?: string;
|
|
3591
|
+
};
|
|
3592
|
+
export type AddUserGroupMembersResponse = APIResponse & {
|
|
3593
|
+
user_group: UserGroupResponse;
|
|
3594
|
+
};
|
|
3595
|
+
export type RemoveUserGroupMembersOptions = {
|
|
3596
|
+
member_ids: string[];
|
|
3597
|
+
team_id?: string;
|
|
3598
|
+
};
|
|
3599
|
+
export type RemoveUserGroupMembersResponse = APIResponse & {
|
|
3600
|
+
user_group: UserGroupResponse;
|
|
3601
|
+
};
|
|
3472
3602
|
export type HookType = 'webhook' | 'sqs' | 'sns' | 'pending_message';
|
|
3473
3603
|
export type EventHook = {
|
|
3474
3604
|
id?: string;
|
package/dist/types/utils.d.ts
CHANGED
|
@@ -90,6 +90,7 @@ export declare const toDeletedMessage: ({ message, deletedAt, hardDelete, }: {
|
|
|
90
90
|
text?: string | undefined;
|
|
91
91
|
user_id?: string | undefined;
|
|
92
92
|
command?: string | undefined;
|
|
93
|
+
mentioned_groups?: import("./types").UserGroupResponse[] | undefined;
|
|
93
94
|
mentioned_users?: UserResponse[] | undefined;
|
|
94
95
|
latest_reactions?: import("./types").ReactionResponse[] | undefined;
|
|
95
96
|
own_reactions?: import("./types").ReactionResponse[] | null | undefined;
|
|
@@ -123,6 +124,7 @@ export declare const toDeletedMessage: ({ message, deletedAt, hardDelete, }: {
|
|
|
123
124
|
member?: import("./types").ChannelMemberResponse | undefined;
|
|
124
125
|
mentioned_channel?: boolean | undefined;
|
|
125
126
|
mentioned_here?: boolean | undefined;
|
|
127
|
+
mentioned_group_ids?: string[] | undefined;
|
|
126
128
|
mentioned_roles?: string[] | undefined;
|
|
127
129
|
message_text_updated_at?: string | undefined;
|
|
128
130
|
moderation?: import("./types").ModerationResponse | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stream-chat",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.45.0",
|
|
4
4
|
"description": "JS SDK for the Stream Chat API",
|
|
5
5
|
"homepage": "https://getstream.io/chat/",
|
|
6
6
|
"author": {
|
|
@@ -29,11 +29,11 @@
|
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
31
|
"browser": {
|
|
32
|
-
"https": false,
|
|
33
32
|
"crypto": false,
|
|
34
|
-
"
|
|
33
|
+
"https": false,
|
|
35
34
|
"jsonwebtoken": false,
|
|
36
|
-
"ws": false
|
|
35
|
+
"ws": false,
|
|
36
|
+
"zlib": false
|
|
37
37
|
},
|
|
38
38
|
"license": "SEE LICENSE IN LICENSE",
|
|
39
39
|
"keywords": [
|
|
@@ -51,40 +51,39 @@
|
|
|
51
51
|
],
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@types/jsonwebtoken": "^9.0.8",
|
|
54
|
-
"@types/ws": "^8.
|
|
55
|
-
"axios": "^1.
|
|
54
|
+
"@types/ws": "^8.18.1",
|
|
55
|
+
"axios": "^1.16.1",
|
|
56
56
|
"base64-js": "^1.5.1",
|
|
57
|
-
"form-data": "^4.0.
|
|
57
|
+
"form-data": "^4.0.5",
|
|
58
58
|
"isomorphic-ws": "^5.0.0",
|
|
59
59
|
"jsonwebtoken": "^9.0.3",
|
|
60
|
-
"linkifyjs": "^4.3.
|
|
61
|
-
"ws": "^8.
|
|
60
|
+
"linkifyjs": "^4.3.3",
|
|
61
|
+
"ws": "^8.20.1"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
|
-
"@commitlint/cli": "^
|
|
65
|
-
"@commitlint/config-conventional": "^
|
|
66
|
-
"@eslint/js": "^9.
|
|
64
|
+
"@commitlint/cli": "^21.0.1",
|
|
65
|
+
"@commitlint/config-conventional": "^21.0.1",
|
|
66
|
+
"@eslint/js": "^9.39.4",
|
|
67
67
|
"@semantic-release/changelog": "^6.0.3",
|
|
68
68
|
"@semantic-release/git": "^10.0.1",
|
|
69
|
-
"@types/
|
|
70
|
-
"@types/node": "^22.15.21",
|
|
69
|
+
"@types/node": "^22.19.19",
|
|
71
70
|
"@types/sinon": "^10.0.6",
|
|
72
|
-
"@vitest/coverage-v8": "
|
|
73
|
-
"concurrently": "^9.1
|
|
74
|
-
"conventional-changelog-conventionalcommits": "^
|
|
75
|
-
"dotenv": "^
|
|
76
|
-
"esbuild": "^0.
|
|
77
|
-
"eslint": "^9.
|
|
78
|
-
"eslint-plugin-import": "^2.
|
|
79
|
-
"globals": "^
|
|
71
|
+
"@vitest/coverage-v8": "^4.1.7",
|
|
72
|
+
"concurrently": "^9.2.1",
|
|
73
|
+
"conventional-changelog-conventionalcommits": "^9.3.1",
|
|
74
|
+
"dotenv": "^17.4.2",
|
|
75
|
+
"esbuild": "^0.28.0",
|
|
76
|
+
"eslint": "^9.39.4",
|
|
77
|
+
"eslint-plugin-import": "^2.32.0",
|
|
78
|
+
"globals": "^17.6.0",
|
|
80
79
|
"husky": "^9.1.7",
|
|
81
|
-
"lint-staged": "^
|
|
82
|
-
"prettier": "^3.
|
|
83
|
-
"semantic-release": "^25.0.
|
|
80
|
+
"lint-staged": "^17.0.5",
|
|
81
|
+
"prettier": "^3.8.3",
|
|
82
|
+
"semantic-release": "^25.0.3",
|
|
84
83
|
"sinon": "^12.0.1",
|
|
85
|
-
"typescript": "^
|
|
86
|
-
"typescript-eslint": "^8.
|
|
87
|
-
"vitest": "^
|
|
84
|
+
"typescript": "^6.0.3",
|
|
85
|
+
"typescript-eslint": "^8.59.4",
|
|
86
|
+
"vitest": "^4.1.7"
|
|
88
87
|
},
|
|
89
88
|
"scripts": {
|
|
90
89
|
"build": "rm -rf dist && concurrently 'tsc' './scripts/bundle.mjs'",
|
|
@@ -97,7 +96,6 @@
|
|
|
97
96
|
"eslint": "eslint --max-warnings 0",
|
|
98
97
|
"eslint-fix": "yarn run eslint --fix",
|
|
99
98
|
"test": "yarn test-unit",
|
|
100
|
-
"testwatch": "NODE_ENV=test nodemon ./node_modules/.bin/mocha --timeout 20000 --require test-entry.js test/test.js",
|
|
101
99
|
"test-types": "yarn run-test-types && yarn run-types-gen",
|
|
102
100
|
"run-test-types": "node test/typescript/index.js",
|
|
103
101
|
"run-types-gen": "tsc --esModuleInterop true --noEmit true --strictNullChecks true --noImplicitAny true --strict true test/typescript/*.ts",
|
|
@@ -105,10 +103,19 @@
|
|
|
105
103
|
"test-coverage": "vitest run --coverage",
|
|
106
104
|
"fix-staged": "lint-staged --config .lintstagedrc.fix.json --concurrent 1",
|
|
107
105
|
"semantic-release": "semantic-release",
|
|
108
|
-
"
|
|
106
|
+
"postinstall": "husky",
|
|
107
|
+
"prepare": "yarn run build"
|
|
109
108
|
},
|
|
110
109
|
"engines": {
|
|
111
110
|
"node": ">=18"
|
|
112
111
|
},
|
|
113
|
-
"packageManager": "yarn@
|
|
112
|
+
"packageManager": "yarn@4.15.0",
|
|
113
|
+
"dependenciesMeta": {
|
|
114
|
+
"esbuild": {
|
|
115
|
+
"built": true
|
|
116
|
+
},
|
|
117
|
+
"husky": {
|
|
118
|
+
"built": true
|
|
119
|
+
}
|
|
120
|
+
}
|
|
114
121
|
}
|
package/src/channel_manager.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import type { StreamChat } from './client';
|
|
1
|
+
import type { QueryChannelsResponseWithChannels, StreamChat } from './client';
|
|
2
2
|
import type {
|
|
3
3
|
ChannelFilters,
|
|
4
4
|
ChannelOptions,
|
|
5
5
|
ChannelSort,
|
|
6
6
|
ChannelStateOptions,
|
|
7
7
|
Event,
|
|
8
|
+
QueryChannelsAPIResponse,
|
|
8
9
|
} from './types';
|
|
9
10
|
import type { ValueOrPatch } from './store';
|
|
10
11
|
import { isPatch, StateStore } from './store';
|
|
@@ -34,6 +35,8 @@ export type ChannelManagerPagination = {
|
|
|
34
35
|
isLoading: boolean;
|
|
35
36
|
isLoadingNext: boolean;
|
|
36
37
|
options: ChannelOptions;
|
|
38
|
+
responseFilters?: ChannelFilters;
|
|
39
|
+
responseSort?: ChannelSort;
|
|
37
40
|
sort: ChannelSort;
|
|
38
41
|
};
|
|
39
42
|
|
|
@@ -133,9 +136,14 @@ export type ChannelManagerOptions = {
|
|
|
133
136
|
lockChannelOrder?: boolean;
|
|
134
137
|
};
|
|
135
138
|
|
|
139
|
+
export type QueryChannelsRequestOutput = Channel[] | QueryChannelsResponseWithChannels;
|
|
140
|
+
|
|
136
141
|
export type QueryChannelsRequestType = (
|
|
137
|
-
|
|
138
|
-
|
|
142
|
+
filters: ChannelFilters,
|
|
143
|
+
sort?: ChannelSort,
|
|
144
|
+
options?: ChannelOptions,
|
|
145
|
+
stateOptions?: ChannelStateOptions,
|
|
146
|
+
) => Promise<QueryChannelsRequestOutput>;
|
|
139
147
|
|
|
140
148
|
export const DEFAULT_CHANNEL_MANAGER_OPTIONS = {
|
|
141
149
|
abortInFlightQuery: false,
|
|
@@ -152,6 +160,54 @@ export const DEFAULT_CHANNEL_MANAGER_PAGINATION_OPTIONS = {
|
|
|
152
160
|
offset: 0,
|
|
153
161
|
};
|
|
154
162
|
|
|
163
|
+
const mapPredefinedFilterSortToChannelSort = (
|
|
164
|
+
sort: NonNullable<QueryChannelsAPIResponse['predefined_filter']>['sort'],
|
|
165
|
+
): ChannelSort =>
|
|
166
|
+
(sort ?? []).map(({ direction = 1, field }) => ({
|
|
167
|
+
[field]: direction,
|
|
168
|
+
})) as ChannelSort;
|
|
169
|
+
|
|
170
|
+
const getResponsePaginationParams = ({
|
|
171
|
+
queryChannelsResponse,
|
|
172
|
+
sort,
|
|
173
|
+
}: {
|
|
174
|
+
queryChannelsResponse?: Pick<QueryChannelsAPIResponse, 'predefined_filter'>;
|
|
175
|
+
sort: ChannelSort;
|
|
176
|
+
}): Pick<ChannelManagerPagination, 'responseFilters' | 'responseSort'> => {
|
|
177
|
+
const predefinedFilter = queryChannelsResponse?.predefined_filter;
|
|
178
|
+
|
|
179
|
+
if (!predefinedFilter) {
|
|
180
|
+
return {};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
responseFilters: predefinedFilter.filter as ChannelFilters,
|
|
185
|
+
responseSort:
|
|
186
|
+
predefinedFilter.sort !== undefined
|
|
187
|
+
? mapPredefinedFilterSortToChannelSort(predefinedFilter.sort)
|
|
188
|
+
: sort,
|
|
189
|
+
};
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
const getResponseFiltersAndSort = (
|
|
193
|
+
pagination: ChannelManagerPagination,
|
|
194
|
+
): Pick<ChannelManagerPagination, 'filters' | 'sort'> => ({
|
|
195
|
+
filters: pagination.responseFilters ?? pagination.filters,
|
|
196
|
+
sort: pagination.responseSort ?? pagination.sort,
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
const omitResponsePaginationParams = (pagination: ChannelManagerPagination) => {
|
|
200
|
+
const paginationWithoutResponseParams = { ...pagination };
|
|
201
|
+
delete paginationWithoutResponseParams.responseFilters;
|
|
202
|
+
delete paginationWithoutResponseParams.responseSort;
|
|
203
|
+
|
|
204
|
+
return paginationWithoutResponseParams;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
const isQueryChannelsResponseWithChannels = (
|
|
208
|
+
response: QueryChannelsRequestOutput,
|
|
209
|
+
): response is QueryChannelsResponseWithChannels => !Array.isArray(response);
|
|
210
|
+
|
|
155
211
|
/**
|
|
156
212
|
* A class that manages a list of channels and changes it based on configuration and WS events. The
|
|
157
213
|
* list of channels is reactive as well as the pagination and it can be subscribed to for state updates.
|
|
@@ -279,23 +335,39 @@ export class ChannelManager extends WithSubscriptions {
|
|
|
279
335
|
...options,
|
|
280
336
|
};
|
|
281
337
|
try {
|
|
282
|
-
const
|
|
338
|
+
const queryChannelsResponse = await this.queryChannelsRequest(
|
|
283
339
|
filters,
|
|
284
340
|
sort,
|
|
285
341
|
options,
|
|
286
|
-
stateOptions,
|
|
342
|
+
{ ...stateOptions, withResponse: true },
|
|
287
343
|
);
|
|
344
|
+
const channels = isQueryChannelsResponseWithChannels(queryChannelsResponse)
|
|
345
|
+
? queryChannelsResponse.channels
|
|
346
|
+
: queryChannelsResponse;
|
|
288
347
|
const newOffset = offset + (channels?.length ?? 0);
|
|
289
348
|
const newOptions = { ...options, offset: newOffset };
|
|
290
349
|
const { pagination } = this.state.getLatestValue();
|
|
350
|
+
const responsePaginationParams = getResponsePaginationParams({
|
|
351
|
+
queryChannelsResponse: isQueryChannelsResponseWithChannels(queryChannelsResponse)
|
|
352
|
+
? queryChannelsResponse
|
|
353
|
+
: undefined,
|
|
354
|
+
sort,
|
|
355
|
+
});
|
|
356
|
+
const paginationWithoutResponseParams = omitResponsePaginationParams(pagination);
|
|
291
357
|
|
|
292
358
|
this.state.partialNext({
|
|
293
359
|
channels,
|
|
294
360
|
pagination: {
|
|
295
|
-
|
|
361
|
+
// Drop response derived filter/sort from the previous query before applying
|
|
362
|
+
// the current response. Non predefined queries do not return this metadata,
|
|
363
|
+
// so keeping the old values would make later WS mutations use stale
|
|
364
|
+
// predefined filter semantics. Also the predefined_filter might change, producing
|
|
365
|
+
// a different combination as well so we always need to first clean up.
|
|
366
|
+
...paginationWithoutResponseParams,
|
|
296
367
|
hasNext: (channels?.length ?? 0) >= (limit ?? 1),
|
|
297
368
|
isLoading: false,
|
|
298
369
|
options: newOptions,
|
|
370
|
+
...responsePaginationParams,
|
|
299
371
|
},
|
|
300
372
|
initialized: true,
|
|
301
373
|
error: undefined,
|
|
@@ -368,7 +440,7 @@ export class ChannelManager extends WithSubscriptions {
|
|
|
368
440
|
this.state.next((currentState) => ({
|
|
369
441
|
...currentState,
|
|
370
442
|
pagination: {
|
|
371
|
-
...currentState.pagination,
|
|
443
|
+
...omitResponsePaginationParams(currentState.pagination),
|
|
372
444
|
isLoading: true,
|
|
373
445
|
isLoadingNext: false,
|
|
374
446
|
filters,
|
|
@@ -434,12 +506,15 @@ export class ChannelManager extends WithSubscriptions {
|
|
|
434
506
|
this.state.partialNext({
|
|
435
507
|
pagination: { ...pagination, isLoading: false, isLoadingNext: true },
|
|
436
508
|
});
|
|
437
|
-
const
|
|
509
|
+
const queryChannelsResponse = await this.queryChannelsRequest(
|
|
438
510
|
filters,
|
|
439
511
|
sort,
|
|
440
512
|
options,
|
|
441
513
|
this.stateOptions,
|
|
442
514
|
);
|
|
515
|
+
const nextChannels = isQueryChannelsResponseWithChannels(queryChannelsResponse)
|
|
516
|
+
? queryChannelsResponse.channels
|
|
517
|
+
: queryChannelsResponse;
|
|
443
518
|
const { channels } = this.state.getLatestValue();
|
|
444
519
|
const newOffset = offset + (nextChannels?.length ?? 0);
|
|
445
520
|
const newOptions = { ...options, offset: newOffset };
|
|
@@ -498,7 +573,7 @@ export class ChannelManager extends WithSubscriptions {
|
|
|
498
573
|
return;
|
|
499
574
|
}
|
|
500
575
|
|
|
501
|
-
const { sort } = pagination
|
|
576
|
+
const { sort } = getResponseFiltersAndSort(pagination);
|
|
502
577
|
|
|
503
578
|
this.setChannels(
|
|
504
579
|
promoteChannel({
|
|
@@ -535,7 +610,7 @@ export class ChannelManager extends WithSubscriptions {
|
|
|
535
610
|
if (!channels) {
|
|
536
611
|
return;
|
|
537
612
|
}
|
|
538
|
-
const { filters, sort } = pagination
|
|
613
|
+
const { filters, sort } = getResponseFiltersAndSort(pagination);
|
|
539
614
|
|
|
540
615
|
const channelType = event.channel_type;
|
|
541
616
|
const channelId = event.channel_id;
|
|
@@ -594,7 +669,7 @@ export class ChannelManager extends WithSubscriptions {
|
|
|
594
669
|
});
|
|
595
670
|
|
|
596
671
|
const { channels, pagination } = this.state.getLatestValue();
|
|
597
|
-
const { filters, sort } = pagination
|
|
672
|
+
const { filters, sort } = getResponseFiltersAndSort(pagination);
|
|
598
673
|
|
|
599
674
|
const considerArchivedChannels = shouldConsiderArchivedChannels(filters);
|
|
600
675
|
const isTargetChannelArchived = isChannelArchived(channel);
|
|
@@ -631,7 +706,7 @@ export class ChannelManager extends WithSubscriptions {
|
|
|
631
706
|
});
|
|
632
707
|
|
|
633
708
|
const { channels, pagination } = this.state.getLatestValue();
|
|
634
|
-
const {
|
|
709
|
+
const { filters, sort } = getResponseFiltersAndSort(pagination);
|
|
635
710
|
|
|
636
711
|
const considerArchivedChannels = shouldConsiderArchivedChannels(filters);
|
|
637
712
|
const isTargetChannelArchived = isChannelArchived(channel);
|
|
@@ -658,7 +733,7 @@ export class ChannelManager extends WithSubscriptions {
|
|
|
658
733
|
|
|
659
734
|
private memberUpdatedHandler = (event: Event) => {
|
|
660
735
|
const { pagination, channels } = this.state.getLatestValue();
|
|
661
|
-
const { filters, sort } = pagination;
|
|
736
|
+
const { filters, sort } = getResponseFiltersAndSort(pagination);
|
|
662
737
|
if (
|
|
663
738
|
!event.member?.user ||
|
|
664
739
|
event.member.user.id !== this.client.userID ||
|