stream-chat 4.4.3 → 5.1.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 (52) hide show
  1. package/README.md +4 -13
  2. package/dist/browser.es.js +1954 -1288
  3. package/dist/browser.es.js.map +1 -1
  4. package/dist/browser.full-bundle.min.js +1 -1
  5. package/dist/browser.full-bundle.min.js.map +1 -1
  6. package/dist/browser.js +1954 -1288
  7. package/dist/browser.js.map +1 -1
  8. package/dist/index.es.js +1954 -1288
  9. package/dist/index.es.js.map +1 -1
  10. package/dist/index.js +1954 -1288
  11. package/dist/index.js.map +1 -1
  12. package/dist/types/base64.d.ts.map +1 -1
  13. package/dist/types/channel.d.ts +31 -15
  14. package/dist/types/channel.d.ts.map +1 -1
  15. package/dist/types/channel_state.d.ts +2 -2
  16. package/dist/types/channel_state.d.ts.map +1 -1
  17. package/dist/types/client.d.ts +52 -43
  18. package/dist/types/client.d.ts.map +1 -1
  19. package/dist/types/client_state.d.ts +2 -2
  20. package/dist/types/client_state.d.ts.map +1 -1
  21. package/dist/types/connection.d.ts +14 -49
  22. package/dist/types/connection.d.ts.map +1 -1
  23. package/dist/types/connection_fallback.d.ts +41 -0
  24. package/dist/types/connection_fallback.d.ts.map +1 -0
  25. package/dist/types/errors.d.ts +14 -0
  26. package/dist/types/errors.d.ts.map +1 -0
  27. package/dist/types/insights.d.ts +6 -6
  28. package/dist/types/insights.d.ts.map +1 -1
  29. package/dist/types/permissions.d.ts.map +1 -1
  30. package/dist/types/signing.d.ts +3 -3
  31. package/dist/types/signing.d.ts.map +1 -1
  32. package/dist/types/token_manager.d.ts +2 -2
  33. package/dist/types/token_manager.d.ts.map +1 -1
  34. package/dist/types/types.d.ts +174 -90
  35. package/dist/types/types.d.ts.map +1 -1
  36. package/dist/types/utils.d.ts +12 -2
  37. package/dist/types/utils.d.ts.map +1 -1
  38. package/package.json +25 -31
  39. package/src/base64.ts +1 -4
  40. package/src/channel.ts +157 -461
  41. package/src/channel_state.ts +31 -158
  42. package/src/client.ts +332 -683
  43. package/src/client_state.ts +2 -2
  44. package/src/connection.ts +143 -394
  45. package/src/connection_fallback.ts +209 -0
  46. package/src/errors.ts +58 -0
  47. package/src/insights.ts +15 -23
  48. package/src/permissions.ts +3 -24
  49. package/src/signing.ts +6 -17
  50. package/src/token_manager.ts +6 -18
  51. package/src/types.ts +391 -513
  52. package/src/utils.ts +48 -19
package/src/client.ts CHANGED
@@ -11,6 +11,8 @@ import { StableWSConnection } from './connection';
11
11
  import { isValidEventType } from './events';
12
12
  import { JWTUserToken, DevToken, CheckSignature } from './signing';
13
13
  import { TokenManager } from './token_manager';
14
+ import { WSConnectionFallback } from './connection_fallback';
15
+ import { isWSFailure } from './errors';
14
16
  import {
15
17
  isFunction,
16
18
  isOwnUserBaseProperty,
@@ -20,6 +22,7 @@ import {
20
22
  randomId,
21
23
  sleep,
22
24
  retryInterval,
25
+ isOnline,
23
26
  } from './utils';
24
27
 
25
28
  import {
@@ -45,7 +48,6 @@ import {
45
48
  CheckSQSResponse,
46
49
  Configs,
47
50
  ConnectAPIResponse,
48
- ConnectionChangeEvent,
49
51
  CreateChannelOptions,
50
52
  CreateChannelResponse,
51
53
  CreateCommandOptions,
@@ -95,7 +97,7 @@ import {
95
97
  TestSQSDataInput,
96
98
  TokenOrProvider,
97
99
  UnBanUserOptions,
98
- UnknownType,
100
+ UR,
99
101
  UpdateChannelOptions,
100
102
  UpdateChannelResponse,
101
103
  UpdateCommandOptions,
@@ -117,6 +119,12 @@ import {
117
119
  DeleteUserOptions,
118
120
  DeleteChannelsResponse,
119
121
  TaskResponse,
122
+ ReservedMessageFields,
123
+ ReviewFlagReportResponse,
124
+ FlagReportsFilters,
125
+ FlagReportsResponse,
126
+ ReviewFlagReportOptions,
127
+ FlagReportsPaginationOptions,
120
128
  } from './types';
121
129
  import { InsightMetrics, postInsights } from './insights';
122
130
 
@@ -125,27 +133,19 @@ function isString(x: unknown): x is string {
125
133
  }
126
134
 
127
135
  export class StreamChat<
128
- AttachmentType extends UnknownType = UnknownType,
129
- ChannelType extends UnknownType = UnknownType,
136
+ AttachmentType extends UR = UR,
137
+ ChannelType extends UR = UR,
130
138
  CommandType extends string = LiteralStringForUnion,
131
- EventType extends UnknownType = UnknownType,
132
- MessageType extends UnknownType = UnknownType,
133
- ReactionType extends UnknownType = UnknownType,
134
- UserType extends UnknownType = UnknownType
139
+ EventType extends UR = UR,
140
+ MessageType extends UR = UR,
141
+ ReactionType extends UR = UR,
142
+ UserType extends UR = UR
135
143
  > {
136
144
  private static _instance?: unknown | StreamChat; // type is undefined|StreamChat, unknown is due to TS limitations with statics
137
145
 
138
146
  _user?: OwnUserResponse<ChannelType, CommandType, UserType> | UserResponse<UserType>;
139
147
  activeChannels: {
140
- [key: string]: Channel<
141
- AttachmentType,
142
- ChannelType,
143
- CommandType,
144
- EventType,
145
- MessageType,
146
- ReactionType,
147
- UserType
148
- >;
148
+ [key: string]: Channel<AttachmentType, ChannelType, CommandType, EventType, MessageType, ReactionType, UserType>;
149
149
  };
150
150
  anonymous: boolean;
151
151
  axiosInstance: AxiosInstance;
@@ -154,22 +154,10 @@ export class StreamChat<
154
154
  cleaningIntervalRef?: NodeJS.Timeout;
155
155
  clientID?: string;
156
156
  configs: Configs<CommandType>;
157
- connectionID?: string;
158
- failures?: number;
159
157
  key: string;
160
158
  listeners: {
161
159
  [key: string]: Array<
162
- (
163
- event: Event<
164
- AttachmentType,
165
- ChannelType,
166
- CommandType,
167
- EventType,
168
- MessageType,
169
- ReactionType,
170
- UserType
171
- >,
172
- ) => void
160
+ (event: Event<AttachmentType, ChannelType, CommandType, EventType, MessageType, ReactionType, UserType>) => void
173
161
  >;
174
162
  };
175
163
  logger: Logger;
@@ -195,10 +183,29 @@ export class StreamChat<
195
183
  userAgent?: string;
196
184
  userID?: string;
197
185
  wsBaseURL?: string;
198
- wsConnection: StableWSConnection<ChannelType, CommandType, UserType> | null;
186
+ wsConnection: StableWSConnection<
187
+ ChannelType,
188
+ CommandType,
189
+ UserType,
190
+ AttachmentType,
191
+ EventType,
192
+ MessageType,
193
+ ReactionType
194
+ > | null;
195
+ wsFallback?: WSConnectionFallback<
196
+ AttachmentType,
197
+ ChannelType,
198
+ CommandType,
199
+ EventType,
200
+ MessageType,
201
+ ReactionType,
202
+ UserType
203
+ >;
199
204
  wsPromise: ConnectAPIResponse<ChannelType, CommandType, UserType> | null;
200
205
  consecutiveFailures: number;
201
206
  insightMetrics: InsightMetrics;
207
+ defaultWSTimeoutWithFallback: number;
208
+ defaultWSTimeout: number;
202
209
 
203
210
  /**
204
211
  * Initialize a client
@@ -221,11 +228,7 @@ export class StreamChat<
221
228
  */
222
229
  constructor(key: string, options?: StreamChatOptions);
223
230
  constructor(key: string, secret?: string, options?: StreamChatOptions);
224
- constructor(
225
- key: string,
226
- secretOrOptions?: StreamChatOptions | string,
227
- options?: StreamChatOptions,
228
- ) {
231
+ constructor(key: string, secretOrOptions?: StreamChatOptions | string, options?: StreamChatOptions) {
229
232
  // set the key
230
233
  this.key = key;
231
234
  this.listeners = {};
@@ -240,16 +243,9 @@ export class StreamChat<
240
243
  }
241
244
 
242
245
  // set the options... and figure out defaults...
243
- const inputOptions = options
244
- ? options
245
- : secretOrOptions && !isString(secretOrOptions)
246
- ? secretOrOptions
247
- : {};
248
-
249
- this.browser =
250
- typeof inputOptions.browser !== 'undefined'
251
- ? inputOptions.browser
252
- : typeof window !== 'undefined';
246
+ const inputOptions = options ? options : secretOrOptions && !isString(secretOrOptions) ? secretOrOptions : {};
247
+
248
+ this.browser = typeof inputOptions.browser !== 'undefined' ? inputOptions.browser : typeof window !== 'undefined';
253
249
  this.node = !this.browser;
254
250
 
255
251
  this.options = {
@@ -295,6 +291,9 @@ export class StreamChat<
295
291
  this.consecutiveFailures = 0;
296
292
  this.insightMetrics = new InsightMetrics();
297
293
 
294
+ this.defaultWSTimeoutWithFallback = 6000;
295
+ this.defaultWSTimeout = 15000;
296
+
298
297
  /**
299
298
  * logger function should accept 3 parameters:
300
299
  * @param logLevel string
@@ -370,67 +369,43 @@ export class StreamChat<
370
369
  * StreamChat.getInstance('api_key', "secret", { httpsAgent: customAgent })
371
370
  */
372
371
  public static getInstance<
373
- AttachmentType extends UnknownType = UnknownType,
374
- ChannelType extends UnknownType = UnknownType,
372
+ AttachmentType extends UR = UR,
373
+ ChannelType extends UR = UR,
375
374
  CommandType extends string = LiteralStringForUnion,
376
- EventType extends UnknownType = UnknownType,
377
- MessageType extends UnknownType = UnknownType,
378
- ReactionType extends UnknownType = UnknownType,
379
- UserType extends UnknownType = UnknownType
375
+ EventType extends UR = UR,
376
+ MessageType extends UR = UR,
377
+ ReactionType extends UR = UR,
378
+ UserType extends UR = UR
380
379
  >(
381
380
  key: string,
382
381
  options?: StreamChatOptions,
383
- ): StreamChat<
384
- AttachmentType,
385
- ChannelType,
386
- CommandType,
387
- EventType,
388
- MessageType,
389
- ReactionType,
390
- UserType
391
- >;
382
+ ): StreamChat<AttachmentType, ChannelType, CommandType, EventType, MessageType, ReactionType, UserType>;
392
383
  public static getInstance<
393
- AttachmentType extends UnknownType = UnknownType,
394
- ChannelType extends UnknownType = UnknownType,
384
+ AttachmentType extends UR = UR,
385
+ ChannelType extends UR = UR,
395
386
  CommandType extends string = LiteralStringForUnion,
396
- EventType extends UnknownType = UnknownType,
397
- MessageType extends UnknownType = UnknownType,
398
- ReactionType extends UnknownType = UnknownType,
399
- UserType extends UnknownType = UnknownType
387
+ EventType extends UR = UR,
388
+ MessageType extends UR = UR,
389
+ ReactionType extends UR = UR,
390
+ UserType extends UR = UR
400
391
  >(
401
392
  key: string,
402
393
  secret?: string,
403
394
  options?: StreamChatOptions,
404
- ): StreamChat<
405
- AttachmentType,
406
- ChannelType,
407
- CommandType,
408
- EventType,
409
- MessageType,
410
- ReactionType,
411
- UserType
412
- >;
395
+ ): StreamChat<AttachmentType, ChannelType, CommandType, EventType, MessageType, ReactionType, UserType>;
413
396
  public static getInstance<
414
- AttachmentType extends UnknownType = UnknownType,
415
- ChannelType extends UnknownType = UnknownType,
397
+ AttachmentType extends UR = UR,
398
+ ChannelType extends UR = UR,
416
399
  CommandType extends string = LiteralStringForUnion,
417
- EventType extends UnknownType = UnknownType,
418
- MessageType extends UnknownType = UnknownType,
419
- ReactionType extends UnknownType = UnknownType,
420
- UserType extends UnknownType = UnknownType
400
+ EventType extends UR = UR,
401
+ MessageType extends UR = UR,
402
+ ReactionType extends UR = UR,
403
+ UserType extends UR = UR
421
404
  >(
422
405
  key: string,
423
406
  secretOrOptions?: StreamChatOptions | string,
424
407
  options?: StreamChatOptions,
425
- ): StreamChat<
426
- AttachmentType,
427
- ChannelType,
428
- CommandType,
429
- EventType,
430
- MessageType,
431
- ReactionType,
432
- UserType
433
- > {
408
+ ): StreamChat<AttachmentType, ChannelType, CommandType, EventType, MessageType, ReactionType, UserType> {
434
409
  if (!StreamChat._instance) {
435
410
  if (typeof secretOrOptions === 'string') {
436
411
  StreamChat._instance = new StreamChat<
@@ -479,7 +454,9 @@ export class StreamChat<
479
454
  this.wsBaseURL = this.baseURL.replace('http', 'ws').replace(':3030', ':8800');
480
455
  }
481
456
 
482
- _hasConnectionID = () => Boolean(this.wsConnection?.connectionID);
457
+ _getConnectionID = () => this.wsConnection?.connectionID || this.wsFallback?.connectionID;
458
+
459
+ _hasConnectionID = () => Boolean(this._getConnectionID());
483
460
 
484
461
  /**
485
462
  * connectUser - Set the current user and open a WebSocket connection
@@ -514,10 +491,7 @@ export class StreamChat<
514
491
  );
515
492
  }
516
493
 
517
- if (
518
- (this._isUsingServerAuth() || this.node) &&
519
- !this.options.allowServerSideConnect
520
- ) {
494
+ if ((this._isUsingServerAuth() || this.node) && !this.options.allowServerSideConnect) {
521
495
  console.warn(
522
496
  'Please do not use connectUser server side. connectUser impacts MAU and concurrent connection usage and thus your bill. If you have a valid use-case, add "allowServerSideConnect: true" to the client options to disable this warning.',
523
497
  );
@@ -560,9 +534,7 @@ export class StreamChat<
560
534
  _setToken = (user: UserResponse<UserType>, userTokenOrProvider: TokenOrProvider) =>
561
535
  this.tokenManager.setTokenOrProvider(userTokenOrProvider, user);
562
536
 
563
- _setUser(
564
- user: OwnUserResponse<ChannelType, CommandType, UserType> | UserResponse<UserType>,
565
- ) {
537
+ _setUser(user: OwnUserResponse<ChannelType, CommandType, UserType> | UserResponse<UserType>) {
566
538
  /**
567
539
  * This one is used by the frontend. This is a copy of the current user object stored on backend.
568
540
  * It contains reserved properties and own user properties which are not present in `this._user`.
@@ -585,17 +557,14 @@ export class StreamChat<
585
557
  * @param timeout Max number of ms, to wait for close event of websocket, before forcefully assuming succesful disconnection.
586
558
  * https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
587
559
  */
588
- closeConnection = (timeout?: number) => {
560
+ closeConnection = async (timeout?: number) => {
589
561
  if (this.cleaningIntervalRef != null) {
590
562
  clearInterval(this.cleaningIntervalRef);
591
563
  this.cleaningIntervalRef = undefined;
592
564
  }
593
565
 
594
- if (!this.wsConnection) {
595
- return Promise.resolve();
596
- }
597
-
598
- return this.wsConnection.disconnect(timeout);
566
+ await Promise.all([this.wsConnection?.disconnect(timeout), this.wsFallback?.disconnect(timeout)]);
567
+ return Promise.resolve();
599
568
  };
600
569
 
601
570
  /**
@@ -603,19 +572,13 @@ export class StreamChat<
603
572
  */
604
573
  openConnection = async () => {
605
574
  if (!this.userID) {
606
- throw Error(
607
- 'User is not set on client, use client.connectUser or client.connectAnonymousUser instead',
608
- );
575
+ throw Error('User is not set on client, use client.connectUser or client.connectAnonymousUser instead');
609
576
  }
610
577
 
611
- if (this.wsConnection?.isHealthy && this._hasConnectionID()) {
612
- this.logger(
613
- 'info',
614
- 'client:openConnection() - openConnection called twice, healthy connection already exists',
615
- {
616
- tags: ['connection', 'client'],
617
- },
618
- );
578
+ if ((this.wsConnection?.isHealthy || this.wsFallback?.isHealthy()) && this._hasConnectionID()) {
579
+ this.logger('info', 'client:openConnection() - openConnection called twice, healthy connection already exists', {
580
+ tags: ['connection', 'client'],
581
+ });
619
582
 
620
583
  return Promise.resolve();
621
584
  }
@@ -661,9 +624,7 @@ export class StreamChat<
661
624
  */
662
625
  async updateAppSettings(options: AppSettings) {
663
626
  if (options.apn_config?.p12_cert) {
664
- options.apn_config.p12_cert = Buffer.from(options.apn_config.p12_cert).toString(
665
- 'base64',
666
- );
627
+ options.apn_config.p12_cert = Buffer.from(options.apn_config.p12_cert).toString('base64');
667
628
  }
668
629
  return await this.patch<APIResponse>(this.baseURL + '/app', options);
669
630
  }
@@ -674,9 +635,7 @@ export class StreamChat<
674
635
  }
675
636
 
676
637
  if (before === '') {
677
- throw new Error(
678
- "Don't pass blank string for since, use null instead if resetting the token revoke",
679
- );
638
+ throw new Error("Don't pass blank string for since, use null instead if resetting the token revoke");
680
639
  }
681
640
 
682
641
  return before;
@@ -748,12 +707,8 @@ export class StreamChat<
748
707
  ...(data.messageID ? { message_id: data.messageID } : {}),
749
708
  ...(data.apnTemplate ? { apn_template: data.apnTemplate } : {}),
750
709
  ...(data.firebaseTemplate ? { firebase_template: data.firebaseTemplate } : {}),
751
- ...(data.firebaseDataTemplate
752
- ? { firebase_data_template: data.firebaseDataTemplate }
753
- : {}),
754
- ...(data.huaweiDataTemplate
755
- ? { huawei_data_template: data.huaweiDataTemplate }
756
- : {}),
710
+ ...(data.firebaseDataTemplate ? { firebase_data_template: data.firebaseDataTemplate } : {}),
711
+ ...(data.huaweiDataTemplate ? { huawei_data_template: data.huaweiDataTemplate } : {}),
757
712
  ...(data.skipDevices ? { skip_devices: true } : {}),
758
713
  });
759
714
  }
@@ -801,7 +756,7 @@ export class StreamChat<
801
756
  // reset client state
802
757
  this.state = new ClientState();
803
758
  // reset token manager
804
- this.tokenManager.reset();
759
+ setTimeout(this.tokenManager.reset); // delay reseting to use token for disconnect calls
805
760
 
806
761
  // close the WS connection
807
762
  return closePromise;
@@ -819,10 +774,7 @@ export class StreamChat<
819
774
  * connectAnonymousUser - Set an anonymous user and open a WebSocket connection
820
775
  */
821
776
  connectAnonymousUser = () => {
822
- if (
823
- (this._isUsingServerAuth() || this.node) &&
824
- !this.options.allowServerSideConnect
825
- ) {
777
+ if ((this._isUsingServerAuth() || this.node) && !this.options.allowServerSideConnect) {
826
778
  console.warn(
827
779
  'Please do not use connectUser server side. connectUser impacts MAU and concurrent connection usage and thus your bill. If you have a valid use-case, add "allowServerSideConnect: true" to the client options to disable this warning.',
828
780
  );
@@ -857,9 +809,10 @@ export class StreamChat<
857
809
  let response: { access_token: string; user: UserResponse<UserType> } | undefined;
858
810
  this.anonymous = true;
859
811
  try {
860
- response = await this.post<
861
- APIResponse & { access_token: string; user: UserResponse<UserType> }
862
- >(this.baseURL + '/guest', { user });
812
+ response = await this.post<APIResponse & { access_token: string; user: UserResponse<UserType> }>(
813
+ this.baseURL + '/guest',
814
+ { user },
815
+ );
863
816
  } catch (e) {
864
817
  this.anonymous = false;
865
818
  throw e;
@@ -867,10 +820,7 @@ export class StreamChat<
867
820
  this.anonymous = false;
868
821
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
869
822
  const { created_at, updated_at, last_active, online, ...guestUser } = response.user;
870
- return await this.connectUser(
871
- guestUser as UserResponse<UserType>,
872
- response.access_token,
873
- );
823
+ return await this.connectUser(guestUser as UserResponse<UserType>, response.access_token);
874
824
  }
875
825
 
876
826
  /**
@@ -912,39 +862,15 @@ export class StreamChat<
912
862
  * @return {{ unsubscribe: () => void }} Description
913
863
  */
914
864
  on(
915
- callback: EventHandler<
916
- AttachmentType,
917
- ChannelType,
918
- CommandType,
919
- EventType,
920
- MessageType,
921
- ReactionType,
922
- UserType
923
- >,
865
+ callback: EventHandler<AttachmentType, ChannelType, CommandType, EventType, MessageType, ReactionType, UserType>,
924
866
  ): { unsubscribe: () => void };
925
867
  on(
926
868
  eventType: string,
927
- callback: EventHandler<
928
- AttachmentType,
929
- ChannelType,
930
- CommandType,
931
- EventType,
932
- MessageType,
933
- ReactionType,
934
- UserType
935
- >,
869
+ callback: EventHandler<AttachmentType, ChannelType, CommandType, EventType, MessageType, ReactionType, UserType>,
936
870
  ): { unsubscribe: () => void };
937
871
  on(
938
872
  callbackOrString:
939
- | EventHandler<
940
- AttachmentType,
941
- ChannelType,
942
- CommandType,
943
- EventType,
944
- MessageType,
945
- ReactionType,
946
- UserType
947
- >
873
+ | EventHandler<AttachmentType, ChannelType, CommandType, EventType, MessageType, ReactionType, UserType>
948
874
  | string,
949
875
  callbackOrNothing?: EventHandler<
950
876
  AttachmentType,
@@ -995,39 +921,15 @@ export class StreamChat<
995
921
  *
996
922
  */
997
923
  off(
998
- callback: EventHandler<
999
- AttachmentType,
1000
- ChannelType,
1001
- CommandType,
1002
- EventType,
1003
- MessageType,
1004
- ReactionType,
1005
- UserType
1006
- >,
924
+ callback: EventHandler<AttachmentType, ChannelType, CommandType, EventType, MessageType, ReactionType, UserType>,
1007
925
  ): void;
1008
926
  off(
1009
927
  eventType: string,
1010
- callback: EventHandler<
1011
- AttachmentType,
1012
- ChannelType,
1013
- CommandType,
1014
- EventType,
1015
- MessageType,
1016
- ReactionType,
1017
- UserType
1018
- >,
928
+ callback: EventHandler<AttachmentType, ChannelType, CommandType, EventType, MessageType, ReactionType, UserType>,
1019
929
  ): void;
1020
930
  off(
1021
931
  callbackOrString:
1022
- | EventHandler<
1023
- AttachmentType,
1024
- ChannelType,
1025
- CommandType,
1026
- EventType,
1027
- MessageType,
1028
- ReactionType,
1029
- UserType
1030
- >
932
+ | EventHandler<AttachmentType, ChannelType, CommandType, EventType, MessageType, ReactionType, UserType>
1031
933
  | string,
1032
934
  callbackOrNothing?: EventHandler<
1033
935
  AttachmentType,
@@ -1082,15 +984,11 @@ export class StreamChat<
1082
984
  }
1083
985
 
1084
986
  _logApiResponse<T>(type: string, url: string, response: AxiosResponse<T>) {
1085
- this.logger(
1086
- 'info',
1087
- `client:${type} - Response - url: ${url} > status ${response.status}`,
1088
- {
1089
- tags: ['api', 'api_response', 'client'],
1090
- url,
1091
- response,
1092
- },
1093
- );
987
+ this.logger('info', `client:${type} - Response - url: ${url} > status ${response.status}`, {
988
+ tags: ['api', 'api_response', 'client'],
989
+ url,
990
+ response,
991
+ });
1094
992
  }
1095
993
 
1096
994
  _logApiError(type: string, url: string, error: unknown) {
@@ -1139,15 +1037,14 @@ export class StreamChat<
1139
1037
  this._logApiResponse<T>(type, url, response);
1140
1038
  this.consecutiveFailures = 0;
1141
1039
  return this.handleResponse(response);
1142
- } catch (e) {
1040
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1041
+ } catch (e: any /**TODO: generalize error types */) {
1143
1042
  e.client_request_id = requestConfig.headers?.['x-client-request-id'];
1144
1043
  this._logApiError(type, url, e);
1145
1044
  this.consecutiveFailures += 1;
1146
1045
  if (e.response) {
1147
- if (
1148
- e.response.data.code === chatCodes.TOKEN_EXPIRED &&
1149
- !this.tokenManager.isStatic()
1150
- ) {
1046
+ /** connection_fallback depends on this token expiration logic */
1047
+ if (e.response.data.code === chatCodes.TOKEN_EXPIRED && !this.tokenManager.isStatic()) {
1151
1048
  if (this.consecutiveFailures > 1) {
1152
1049
  await sleep(retryInterval(this.consecutiveFailures));
1153
1050
  }
@@ -1205,9 +1102,7 @@ export class StreamChat<
1205
1102
  let err: Error & { code?: number; response?: AxiosResponse<T>; status?: number };
1206
1103
  err = new Error(`StreamChat error HTTP code: ${response.status}`);
1207
1104
  if (response.data && response.data.code) {
1208
- err = new Error(
1209
- `StreamChat error code ${response.data.code}: ${response.data.message}`,
1210
- );
1105
+ err = new Error(`StreamChat error code ${response.data.code}: ${response.data.message}`);
1211
1106
  err.code = response.data.code;
1212
1107
  }
1213
1108
  err.response = response;
@@ -1224,16 +1119,10 @@ export class StreamChat<
1224
1119
  }
1225
1120
 
1226
1121
  dispatchEvent = (
1227
- event: Event<
1228
- AttachmentType,
1229
- ChannelType,
1230
- CommandType,
1231
- EventType,
1232
- MessageType,
1233
- ReactionType,
1234
- UserType
1235
- >,
1122
+ event: Event<AttachmentType, ChannelType, CommandType, EventType, MessageType, ReactionType, UserType>,
1236
1123
  ) => {
1124
+ if (!event.received_at) event.received_at = new Date();
1125
+
1237
1126
  // client event handlers
1238
1127
  const postListenerCallbacks = this._handleClientEvent(event);
1239
1128
 
@@ -1265,7 +1154,6 @@ export class StreamChat<
1265
1154
  ReactionType,
1266
1155
  UserType
1267
1156
  >;
1268
- event.received_at = new Date();
1269
1157
  this.dispatchEvent(event);
1270
1158
  };
1271
1159
 
@@ -1350,15 +1238,7 @@ export class StreamChat<
1350
1238
  * @param {Event} event
1351
1239
  */
1352
1240
  _handleUserEvent = (
1353
- event: Event<
1354
- AttachmentType,
1355
- ChannelType,
1356
- CommandType,
1357
- EventType,
1358
- MessageType,
1359
- ReactionType,
1360
- UserType
1361
- >,
1241
+ event: Event<AttachmentType, ChannelType, CommandType, EventType, MessageType, ReactionType, UserType>,
1362
1242
  ) => {
1363
1243
  if (!event.user) {
1364
1244
  return;
@@ -1400,42 +1280,22 @@ export class StreamChat<
1400
1280
  this._updateUserMessageReferences(event.user);
1401
1281
  }
1402
1282
 
1403
- if (
1404
- event.type === 'user.deleted' &&
1405
- event.user.deleted_at &&
1406
- (event.mark_messages_deleted || event.hard_delete)
1407
- ) {
1283
+ if (event.type === 'user.deleted' && event.user.deleted_at && (event.mark_messages_deleted || event.hard_delete)) {
1408
1284
  this._deleteUserMessageReference(event.user, event.hard_delete);
1409
1285
  }
1410
1286
  };
1411
1287
 
1412
1288
  _handleClientEvent(
1413
- event: Event<
1414
- AttachmentType,
1415
- ChannelType,
1416
- CommandType,
1417
- EventType,
1418
- MessageType,
1419
- ReactionType,
1420
- UserType
1421
- >,
1289
+ event: Event<AttachmentType, ChannelType, CommandType, EventType, MessageType, ReactionType, UserType>,
1422
1290
  ) {
1423
1291
  const client = this;
1424
1292
  const postListenerCallbacks = [];
1425
- this.logger(
1426
- 'info',
1427
- `client:_handleClientEvent - Received event of type { ${event.type} }`,
1428
- {
1429
- tags: ['event', 'client'],
1430
- event,
1431
- },
1432
- );
1293
+ this.logger('info', `client:_handleClientEvent - Received event of type { ${event.type} }`, {
1294
+ tags: ['event', 'client'],
1295
+ event,
1296
+ });
1433
1297
 
1434
- if (
1435
- event.type === 'user.presence.changed' ||
1436
- event.type === 'user.updated' ||
1437
- event.type === 'user.deleted'
1438
- ) {
1298
+ if (event.type === 'user.presence.changed' || event.type === 'user.updated' || event.type === 'user.deleted') {
1439
1299
  this._handleUserEvent(event);
1440
1300
  }
1441
1301
 
@@ -1454,12 +1314,8 @@ export class StreamChat<
1454
1314
  const currentMutedChannelIds: string[] = [];
1455
1315
  const nextMutedChannelIds: string[] = [];
1456
1316
 
1457
- this.mutedChannels.forEach(
1458
- (mute) => mute.channel && currentMutedChannelIds.push(mute.channel.cid),
1459
- );
1460
- event.me.channel_mutes.forEach(
1461
- (mute) => mute.channel && nextMutedChannelIds.push(mute.channel.cid),
1462
- );
1317
+ this.mutedChannels.forEach((mute) => mute.channel && currentMutedChannelIds.push(mute.channel.cid));
1318
+ event.me.channel_mutes.forEach((mute) => mute.channel && nextMutedChannelIds.push(mute.channel.cid));
1463
1319
 
1464
1320
  /** Set the unread count of un-muted channels to 0, which is the behaviour of backend */
1465
1321
  currentMutedChannelIds.forEach((cid) => {
@@ -1475,11 +1331,7 @@ export class StreamChat<
1475
1331
  this.mutedUsers = event.me.mutes;
1476
1332
  }
1477
1333
 
1478
- if (
1479
- (event.type === 'channel.deleted' ||
1480
- event.type === 'notification.channel_deleted') &&
1481
- event.cid
1482
- ) {
1334
+ if ((event.type === 'channel.deleted' || event.type === 'notification.channel_deleted') && event.cid) {
1483
1335
  client.state.deleteAllChannelReference(event.cid);
1484
1336
  this.activeChannels[event.cid]?._disconnect();
1485
1337
 
@@ -1499,9 +1351,7 @@ export class StreamChat<
1499
1351
  const mute = this.mutedChannels[i];
1500
1352
  if (mute.channel?.cid === cid) {
1501
1353
  muteStatus = {
1502
- muted: mute.expires
1503
- ? new Date(mute.expires).getTime() > new Date().getTime()
1504
- : true,
1354
+ muted: mute.expires ? new Date(mute.expires).getTime() > new Date().getTime() : true,
1505
1355
  createdAt: mute.created_at ? new Date(mute.created_at) : new Date(),
1506
1356
  expiresAt: mute.expires ? new Date(mute.expires) : null,
1507
1357
  };
@@ -1521,30 +1371,12 @@ export class StreamChat<
1521
1371
  }
1522
1372
 
1523
1373
  _callClientListeners = (
1524
- event: Event<
1525
- AttachmentType,
1526
- ChannelType,
1527
- CommandType,
1528
- EventType,
1529
- MessageType,
1530
- ReactionType,
1531
- UserType
1532
- >,
1374
+ event: Event<AttachmentType, ChannelType, CommandType, EventType, MessageType, ReactionType, UserType>,
1533
1375
  ) => {
1534
1376
  const client = this;
1535
1377
  // gather and call the listeners
1536
1378
  const listeners: Array<
1537
- (
1538
- event: Event<
1539
- AttachmentType,
1540
- ChannelType,
1541
- CommandType,
1542
- EventType,
1543
- MessageType,
1544
- ReactionType,
1545
- UserType
1546
- >,
1547
- ) => void
1379
+ (event: Event<AttachmentType, ChannelType, CommandType, EventType, MessageType, ReactionType, UserType>) => void
1548
1380
  > = [];
1549
1381
  if (client.listeners.all) {
1550
1382
  listeners.push(...client.listeners.all);
@@ -1560,21 +1392,15 @@ export class StreamChat<
1560
1392
  };
1561
1393
 
1562
1394
  recoverState = async () => {
1563
- this.logger(
1564
- 'info',
1565
- `client:recoverState() - Start of recoverState with connectionID ${this.wsConnection?.connectionID}`,
1566
- {
1567
- tags: ['connection'],
1568
- },
1569
- );
1395
+ this.logger('info', `client:recoverState() - Start of recoverState with connectionID ${this._getConnectionID()}`, {
1396
+ tags: ['connection'],
1397
+ });
1570
1398
 
1571
1399
  const cids = Object.keys(this.activeChannels);
1572
1400
  if (cids.length && this.recoverStateOnReconnect) {
1573
- this.logger(
1574
- 'info',
1575
- `client:recoverState() - Start the querying of ${cids.length} channels`,
1576
- { tags: ['connection', 'client'] },
1577
- );
1401
+ this.logger('info', `client:recoverState() - Start the querying of ${cids.length} channels`, {
1402
+ tags: ['connection', 'client'],
1403
+ });
1578
1404
 
1579
1405
  await this.queryChannels(
1580
1406
  { cid: { $in: cids } } as ChannelFilters<ChannelType, CommandType, UserType>,
@@ -1603,20 +1429,13 @@ export class StreamChat<
1603
1429
  * @private
1604
1430
  */
1605
1431
  async connect() {
1606
- const client = this;
1607
- this.failures = 0;
1608
-
1609
- if (client.userID == null || this._user == null) {
1610
- throw Error(
1611
- 'Call connectUser or connectAnonymousUser before starting the connection',
1612
- );
1432
+ if (!this.userID || !this._user) {
1433
+ throw Error('Call connectUser or connectAnonymousUser before starting the connection');
1613
1434
  }
1614
-
1615
- if (client.wsBaseURL == null) {
1435
+ if (!this.wsBaseURL) {
1616
1436
  throw Error('Websocket base url not set');
1617
1437
  }
1618
-
1619
- if (client.clientID == null) {
1438
+ if (!this.clientID) {
1620
1439
  throw Error('clientID is not set');
1621
1440
  }
1622
1441
 
@@ -1625,25 +1444,50 @@ export class StreamChat<
1625
1444
  }
1626
1445
 
1627
1446
  // The StableWSConnection handles all the reconnection logic.
1628
- this.wsConnection = new StableWSConnection<ChannelType, CommandType, UserType>({
1629
- wsBaseURL: client.wsBaseURL,
1630
- enableInsights: this.options.enableInsights,
1631
- clientID: client.clientID,
1632
- userID: client.userID,
1633
- tokenManager: client.tokenManager,
1634
- user: this._user,
1635
- authType: this.getAuthType(),
1636
- userAgent: this.getUserAgent(),
1637
- apiKey: this.key,
1638
- recoverCallback: this.recoverState,
1639
- messageCallback: this.handleEvent,
1640
- eventCallback: this.dispatchEvent as (event: ConnectionChangeEvent) => void,
1641
- logger: this.logger,
1642
- device: this.options.device,
1643
- insightMetrics: this.insightMetrics,
1644
- });
1447
+ this.wsConnection = new StableWSConnection<
1448
+ ChannelType,
1449
+ CommandType,
1450
+ UserType,
1451
+ AttachmentType,
1452
+ EventType,
1453
+ MessageType,
1454
+ ReactionType
1455
+ >({ client: this });
1456
+
1457
+ try {
1458
+ // if fallback is used before, continue using it instead of waiting for WS to fail
1459
+ if (this.wsFallback) {
1460
+ return await this.wsFallback.connect();
1461
+ }
1645
1462
 
1646
- return await this.wsConnection.connect();
1463
+ // if WSFallback is enabled, ws connect should timeout faster so fallback can try
1464
+ return await this.wsConnection.connect(
1465
+ this.options.enableWSFallback ? this.defaultWSTimeoutWithFallback : this.defaultWSTimeout,
1466
+ );
1467
+ } catch (err) {
1468
+ // run fallback only if it's WS/Network error and not a normal API error
1469
+ // make sure browser is online before even trying the longpoll
1470
+ if (this.options.enableWSFallback && isWSFailure(err) && isOnline()) {
1471
+ this.logger('info', 'client:connect() - WS failed, fallback to longpoll', { tags: ['connection', 'client'] });
1472
+ // @ts-expect-error
1473
+ this.dispatchEvent({ type: 'transport.changed', mode: 'longpoll' });
1474
+
1475
+ this.wsConnection._destroyCurrentWSConnection();
1476
+ this.wsConnection.disconnect().then(); // close WS so no retry
1477
+ this.wsFallback = new WSConnectionFallback<
1478
+ AttachmentType,
1479
+ ChannelType,
1480
+ CommandType,
1481
+ EventType,
1482
+ MessageType,
1483
+ ReactionType,
1484
+ UserType
1485
+ >({ client: this });
1486
+ return await this.wsFallback.connect();
1487
+ }
1488
+
1489
+ throw err;
1490
+ }
1647
1491
  }
1648
1492
 
1649
1493
  /**
@@ -1675,11 +1519,7 @@ export class StreamChat<
1675
1519
  *
1676
1520
  * @return {Promise<APIResponse & { users: Array<UserResponse<UserType>> }>} User Query Response
1677
1521
  */
1678
- async queryUsers(
1679
- filterConditions: UserFilters<UserType>,
1680
- sort: UserSort<UserType> = [],
1681
- options: UserOptions = {},
1682
- ) {
1522
+ async queryUsers(filterConditions: UserFilters<UserType>, sort: UserSort<UserType> = [], options: UserOptions = {}) {
1683
1523
  const defaultOptions = {
1684
1524
  presence: false,
1685
1525
  };
@@ -1745,10 +1585,7 @@ export class StreamChat<
1745
1585
  *
1746
1586
  * @return {Promise<MessageFlagsResponse<ChannelType, CommandType, UserType>>} Message Flags Response
1747
1587
  */
1748
- async queryMessageFlags(
1749
- filterConditions: MessageFlagsFilters = {},
1750
- options: MessageFlagsPaginationOptions = {},
1751
- ) {
1588
+ async queryMessageFlags(filterConditions: MessageFlagsFilters = {}, options: MessageFlagsPaginationOptions = {}) {
1752
1589
  // Return a list of message flags
1753
1590
  return await this.get<MessageFlagsResponse<ChannelType, CommandType, UserType>>(
1754
1591
  this.baseURL + '/moderation/flags/message',
@@ -1802,14 +1639,7 @@ export class StreamChat<
1802
1639
  };
1803
1640
 
1804
1641
  const data = await this.post<{
1805
- channels: ChannelAPIResponse<
1806
- AttachmentType,
1807
- ChannelType,
1808
- CommandType,
1809
- MessageType,
1810
- ReactionType,
1811
- UserType
1812
- >[];
1642
+ channels: ChannelAPIResponse<AttachmentType, ChannelType, CommandType, MessageType, ReactionType, UserType>[];
1813
1643
  }>(this.baseURL + '/channels', payload);
1814
1644
 
1815
1645
  const channels: Channel<
@@ -1855,34 +1685,16 @@ export class StreamChat<
1855
1685
  */
1856
1686
  async search(
1857
1687
  filterConditions: ChannelFilters<ChannelType, CommandType, UserType>,
1858
- query:
1859
- | string
1860
- | MessageFilters<
1861
- AttachmentType,
1862
- ChannelType,
1863
- CommandType,
1864
- MessageType,
1865
- ReactionType,
1866
- UserType
1867
- >,
1688
+ query: string | MessageFilters<AttachmentType, ChannelType, CommandType, MessageType, ReactionType, UserType>,
1868
1689
  options: SearchOptions<MessageType> = {},
1869
1690
  ) {
1870
1691
  if (options.offset && (options.sort || options.next)) {
1871
1692
  throw Error(`Cannot specify offset with sort or next parameters`);
1872
1693
  }
1873
- const payload: SearchPayload<
1874
- AttachmentType,
1875
- ChannelType,
1876
- CommandType,
1877
- MessageType,
1878
- ReactionType,
1879
- UserType
1880
- > = {
1694
+ const payload: SearchPayload<AttachmentType, ChannelType, CommandType, MessageType, ReactionType, UserType> = {
1881
1695
  filter_conditions: filterConditions,
1882
1696
  ...options,
1883
- sort: options.sort
1884
- ? normalizeQuerySort<SearchMessageSortBase<MessageType>>(options.sort)
1885
- : undefined,
1697
+ sort: options.sort ? normalizeQuerySort<SearchMessageSortBase<MessageType>>(options.sort) : undefined,
1886
1698
  };
1887
1699
  if (typeof query === 'string') {
1888
1700
  payload.query = query;
@@ -1896,14 +1708,7 @@ export class StreamChat<
1896
1708
  await this.setUserPromise;
1897
1709
 
1898
1710
  return await this.get<
1899
- SearchAPIResponse<
1900
- AttachmentType,
1901
- ChannelType,
1902
- CommandType,
1903
- MessageType,
1904
- ReactionType,
1905
- UserType
1906
- >
1711
+ SearchAPIResponse<AttachmentType, ChannelType, CommandType, MessageType, ReactionType, UserType>
1907
1712
  >(this.baseURL + '/search', {
1908
1713
  payload,
1909
1714
  });
@@ -1918,7 +1723,7 @@ export class StreamChat<
1918
1723
  *
1919
1724
  */
1920
1725
  setLocalDevice(device: BaseDeviceFields) {
1921
- if (this.wsConnection) {
1726
+ if (this.wsConnection || this.wsFallback) {
1922
1727
  throw new Error('you can only set device before opening a websocket connection');
1923
1728
  }
1924
1729
 
@@ -1994,14 +1799,7 @@ export class StreamChat<
1994
1799
  }
1995
1800
 
1996
1801
  _addChannelConfig(
1997
- channelState: ChannelAPIResponse<
1998
- AttachmentType,
1999
- ChannelType,
2000
- CommandType,
2001
- MessageType,
2002
- ReactionType,
2003
- UserType
2004
- >,
1802
+ channelState: ChannelAPIResponse<AttachmentType, ChannelType, CommandType, MessageType, ReactionType, UserType>,
2005
1803
  ) {
2006
1804
  this.configs[channelState.channel.type] = channelState.channel.config;
2007
1805
  }
@@ -2024,27 +1822,11 @@ export class StreamChat<
2024
1822
  channelType: string,
2025
1823
  channelID?: string | null,
2026
1824
  custom?: ChannelData<ChannelType>,
2027
- ): Channel<
2028
- AttachmentType,
2029
- ChannelType,
2030
- CommandType,
2031
- EventType,
2032
- MessageType,
2033
- ReactionType,
2034
- UserType
2035
- >;
1825
+ ): Channel<AttachmentType, ChannelType, CommandType, EventType, MessageType, ReactionType, UserType>;
2036
1826
  channel(
2037
1827
  channelType: string,
2038
1828
  custom?: ChannelData<ChannelType>,
2039
- ): Channel<
2040
- AttachmentType,
2041
- ChannelType,
2042
- CommandType,
2043
- EventType,
2044
- MessageType,
2045
- ReactionType,
2046
- UserType
2047
- >;
1829
+ ): Channel<AttachmentType, ChannelType, CommandType, EventType, MessageType, ReactionType, UserType>;
2048
1830
  channel(
2049
1831
  channelType: string,
2050
1832
  channelIDOrCustom?: string | ChannelData<ChannelType> | null,
@@ -2062,15 +1844,12 @@ export class StreamChat<
2062
1844
  // support channel("messaging", undefined, {options})
2063
1845
  // support channel("messaging", "", {options})
2064
1846
  if (channelIDOrCustom == null || channelIDOrCustom === '') {
2065
- return new Channel<
2066
- AttachmentType,
2067
- ChannelType,
2068
- CommandType,
2069
- EventType,
2070
- MessageType,
2071
- ReactionType,
2072
- UserType
2073
- >(this, channelType, undefined, custom);
1847
+ return new Channel<AttachmentType, ChannelType, CommandType, EventType, MessageType, ReactionType, UserType>(
1848
+ this,
1849
+ channelType,
1850
+ undefined,
1851
+ custom,
1852
+ );
2074
1853
  }
2075
1854
 
2076
1855
  // support channel("messaging", {options})
@@ -2123,9 +1902,7 @@ export class StreamChat<
2123
1902
  }
2124
1903
 
2125
1904
  if (key.indexOf(`${channelType}:!members-`) === 0) {
2126
- const membersStrInExistingChannel = Object.keys(channel.state.members)
2127
- .sort()
2128
- .join(',');
1905
+ const membersStrInExistingChannel = Object.keys(channel.state.members).sort().join(',');
2129
1906
  if (membersStrInExistingChannel === membersStr) {
2130
1907
  return channel;
2131
1908
  }
@@ -2164,11 +1941,7 @@ export class StreamChat<
2164
1941
  *
2165
1942
  * @return {channel} The channel object, initialize it using channel.watch()
2166
1943
  */
2167
- getChannelById = (
2168
- channelType: string,
2169
- channelID: string,
2170
- custom: ChannelData<ChannelType>,
2171
- ) => {
1944
+ getChannelById = (channelType: string, channelID: string, custom: ChannelData<ChannelType>) => {
2172
1945
  if (typeof channelID === 'string' && ~channelID.indexOf(':')) {
2173
1946
  throw Error(`Invalid channel id ${channelID}, can't contain the : character`);
2174
1947
  }
@@ -2316,10 +2089,7 @@ export class StreamChat<
2316
2089
  });
2317
2090
  }
2318
2091
 
2319
- async deactivateUser(
2320
- userID: string,
2321
- options?: { created_by_id?: string; mark_messages_deleted?: boolean },
2322
- ) {
2092
+ async deactivateUser(userID: string, options?: { created_by_id?: string; mark_messages_deleted?: boolean }) {
2323
2093
  return await this.post<APIResponse & { user: UserResponse<UserType> }>(
2324
2094
  this.baseURL + `/users/${userID}/deactivate`,
2325
2095
  {
@@ -2331,14 +2101,7 @@ export class StreamChat<
2331
2101
  async exportUser(userID: string, options?: Record<string, string>) {
2332
2102
  return await this.get<
2333
2103
  APIResponse & {
2334
- messages: MessageResponse<
2335
- AttachmentType,
2336
- ChannelType,
2337
- CommandType,
2338
- MessageType,
2339
- ReactionType,
2340
- UserType
2341
- >[];
2104
+ messages: MessageResponse<AttachmentType, ChannelType, CommandType, MessageType, ReactionType, UserType>[];
2342
2105
  reactions: ReactionResponse<ReactionType, UserType>[];
2343
2106
  user: UserResponse<UserType>;
2344
2107
  }
@@ -2354,20 +2117,6 @@ export class StreamChat<
2354
2117
  * @returns {Promise<APIResponse>}
2355
2118
  */
2356
2119
  async banUser(targetUserID: string, options?: BanUserOptions<UserType>) {
2357
- if (options?.user_id !== undefined) {
2358
- options.banned_by_id = options.user_id;
2359
- delete options.user_id;
2360
- console.warn(
2361
- "banUser: 'user_id' is deprecated, please consider switching to 'banned_by_id'",
2362
- );
2363
- }
2364
- if (options?.user !== undefined) {
2365
- options.banned_by = options.user;
2366
- delete options.user;
2367
- console.warn(
2368
- "banUser: 'user' is deprecated, please consider switching to 'banned_by'",
2369
- );
2370
- }
2371
2120
  return await this.post<APIResponse>(this.baseURL + '/moderation/ban', {
2372
2121
  target_user_id: targetUserID,
2373
2122
  ...options,
@@ -2420,19 +2169,12 @@ export class StreamChat<
2420
2169
  * @param {MuteUserOptions<UserType>} [options]
2421
2170
  * @returns {Promise<MuteUserResponse<ChannelType, CommandType, UserType>>}
2422
2171
  */
2423
- async muteUser(
2424
- targetID: string,
2425
- userID?: string,
2426
- options: MuteUserOptions<UserType> = {},
2427
- ) {
2428
- return await this.post<MuteUserResponse<ChannelType, CommandType, UserType>>(
2429
- this.baseURL + '/moderation/mute',
2430
- {
2431
- target_id: targetID,
2432
- ...(userID ? { user_id: userID } : {}),
2433
- ...options,
2434
- },
2435
- );
2172
+ async muteUser(targetID: string, userID?: string, options: MuteUserOptions<UserType> = {}) {
2173
+ return await this.post<MuteUserResponse<ChannelType, CommandType, UserType>>(this.baseURL + '/moderation/mute', {
2174
+ target_id: targetID,
2175
+ ...(userID ? { user_id: userID } : {}),
2176
+ ...options,
2177
+ });
2436
2178
  }
2437
2179
 
2438
2180
  /** unmuteUser - unmutes a user
@@ -2471,13 +2213,10 @@ export class StreamChat<
2471
2213
  * @returns {Promise<APIResponse>}
2472
2214
  */
2473
2215
  async flagMessage(targetMessageID: string, options: { user_id?: string } = {}) {
2474
- return await this.post<FlagMessageResponse<UserType>>(
2475
- this.baseURL + '/moderation/flag',
2476
- {
2477
- target_message_id: targetMessageID,
2478
- ...options,
2479
- },
2480
- );
2216
+ return await this.post<FlagMessageResponse<UserType>>(this.baseURL + '/moderation/flag', {
2217
+ target_message_id: targetMessageID,
2218
+ ...options,
2219
+ });
2481
2220
  }
2482
2221
 
2483
2222
  /**
@@ -2487,13 +2226,10 @@ export class StreamChat<
2487
2226
  * @returns {Promise<APIResponse>}
2488
2227
  */
2489
2228
  async flagUser(targetID: string, options: { user_id?: string } = {}) {
2490
- return await this.post<FlagUserResponse<UserType>>(
2491
- this.baseURL + '/moderation/flag',
2492
- {
2493
- target_user_id: targetID,
2494
- ...options,
2495
- },
2496
- );
2229
+ return await this.post<FlagUserResponse<UserType>>(this.baseURL + '/moderation/flag', {
2230
+ target_user_id: targetID,
2231
+ ...options,
2232
+ });
2497
2233
  }
2498
2234
 
2499
2235
  /**
@@ -2503,13 +2239,10 @@ export class StreamChat<
2503
2239
  * @returns {Promise<APIResponse>}
2504
2240
  */
2505
2241
  async unflagMessage(targetMessageID: string, options: { user_id?: string } = {}) {
2506
- return await this.post<FlagMessageResponse<UserType>>(
2507
- this.baseURL + '/moderation/unflag',
2508
- {
2509
- target_message_id: targetMessageID,
2510
- ...options,
2511
- },
2512
- );
2242
+ return await this.post<FlagMessageResponse<UserType>>(this.baseURL + '/moderation/unflag', {
2243
+ target_message_id: targetMessageID,
2244
+ ...options,
2245
+ });
2513
2246
  }
2514
2247
 
2515
2248
  /**
@@ -2519,15 +2252,55 @@ export class StreamChat<
2519
2252
  * @returns {Promise<APIResponse>}
2520
2253
  */
2521
2254
  async unflagUser(targetID: string, options: { user_id?: string } = {}) {
2522
- return await this.post<FlagUserResponse<UserType>>(
2523
- this.baseURL + '/moderation/unflag',
2255
+ return await this.post<FlagUserResponse<UserType>>(this.baseURL + '/moderation/unflag', {
2256
+ target_user_id: targetID,
2257
+ ...options,
2258
+ });
2259
+ }
2260
+
2261
+ /**
2262
+ * _queryFlagReports - Query flag reports.
2263
+ *
2264
+ * Note: Do not use this.
2265
+ * It is present for internal usage only.
2266
+ * This function can, and will, break and/or be removed at any point in time.
2267
+ *
2268
+ * @param {FlagReportsFilters} filterConditions MongoDB style filter conditions
2269
+ * @param {FlagReportsPaginationOptions} options Option object, {limit: 10, offset:0}
2270
+ *
2271
+ * @return {Promise<FlagReportsResponse<ChannelType, CommandType, UserType>>} Flag Reports Response
2272
+ */
2273
+ async _queryFlagReports(filterConditions: FlagReportsFilters = {}, options: FlagReportsPaginationOptions = {}) {
2274
+ // Return a list of message flags
2275
+ return await this.post<FlagReportsResponse<ChannelType, CommandType, UserType>>(
2276
+ this.baseURL + '/moderation/reports',
2524
2277
  {
2525
- target_user_id: targetID,
2278
+ filter_conditions: filterConditions,
2526
2279
  ...options,
2527
2280
  },
2528
2281
  );
2529
2282
  }
2530
2283
 
2284
+ /**
2285
+ * _reviewFlagReport - review flag report
2286
+ *
2287
+ * Note: Do not use this.
2288
+ * It is present for internal usage only.
2289
+ * This function can, and will, break and/or be removed at any point in time.
2290
+ *
2291
+ * @param {string} [id] flag report to review
2292
+ * @param {string} [reviewResult] flag report review result
2293
+ * @param {string} [options.user_id] currentUserID, only used with serverside auth
2294
+ * @param {string} [options.review_details] custom information about review result
2295
+ * @returns {Promise<ReviewFlagReportResponse>>}
2296
+ */
2297
+ async _reviewFlagReport(id: string, reviewResult: string, options: ReviewFlagReportOptions = {}) {
2298
+ return await this.patch<ReviewFlagReportResponse<UserType>>(this.baseURL + `/moderation/reports/${id}`, {
2299
+ review_result: reviewResult,
2300
+ ...options,
2301
+ });
2302
+ }
2303
+
2531
2304
  /**
2532
2305
  * @deprecated use markChannelsRead instead
2533
2306
  *
@@ -2553,10 +2326,7 @@ export class StreamChat<
2553
2326
  }
2554
2327
 
2555
2328
  createCommand(data: CreateCommandOptions<CommandType>) {
2556
- return this.post<CreateCommandResponse<CommandType>>(
2557
- this.baseURL + '/commands',
2558
- data,
2559
- );
2329
+ return this.post<CreateCommandResponse<CommandType>>(this.baseURL + '/commands', data);
2560
2330
  }
2561
2331
 
2562
2332
  getCommand(name: string) {
@@ -2564,16 +2334,11 @@ export class StreamChat<
2564
2334
  }
2565
2335
 
2566
2336
  updateCommand(name: string, data: UpdateCommandOptions<CommandType>) {
2567
- return this.put<UpdateCommandResponse<CommandType>>(
2568
- this.baseURL + `/commands/${name}`,
2569
- data,
2570
- );
2337
+ return this.put<UpdateCommandResponse<CommandType>>(this.baseURL + `/commands/${name}`, data);
2571
2338
  }
2572
2339
 
2573
2340
  deleteCommand(name: string) {
2574
- return this.delete<DeleteCommandResponse<CommandType>>(
2575
- this.baseURL + `/commands/${name}`,
2576
- );
2341
+ return this.delete<DeleteCommandResponse<CommandType>>(this.baseURL + `/commands/${name}`);
2577
2342
  }
2578
2343
 
2579
2344
  listCommands() {
@@ -2582,23 +2347,15 @@ export class StreamChat<
2582
2347
 
2583
2348
  createChannelType(data: CreateChannelOptions<CommandType>) {
2584
2349
  const channelData = Object.assign({}, { commands: ['all'] }, data);
2585
- return this.post<CreateChannelResponse<CommandType>>(
2586
- this.baseURL + '/channeltypes',
2587
- channelData,
2588
- );
2350
+ return this.post<CreateChannelResponse<CommandType>>(this.baseURL + '/channeltypes', channelData);
2589
2351
  }
2590
2352
 
2591
2353
  getChannelType(channelType: string) {
2592
- return this.get<GetChannelTypeResponse<CommandType>>(
2593
- this.baseURL + `/channeltypes/${channelType}`,
2594
- );
2354
+ return this.get<GetChannelTypeResponse<CommandType>>(this.baseURL + `/channeltypes/${channelType}`);
2595
2355
  }
2596
2356
 
2597
2357
  updateChannelType(channelType: string, data: UpdateChannelOptions<CommandType>) {
2598
- return this.put<UpdateChannelResponse<CommandType>>(
2599
- this.baseURL + `/channeltypes/${channelType}`,
2600
- data,
2601
- );
2358
+ return this.put<UpdateChannelResponse<CommandType>>(this.baseURL + `/channeltypes/${channelType}`, data);
2602
2359
  }
2603
2360
 
2604
2361
  deleteChannelType(channelType: string) {
@@ -2619,15 +2376,7 @@ export class StreamChat<
2619
2376
  */
2620
2377
  async translateMessage(messageId: string, language: string) {
2621
2378
  return await this.post<
2622
- APIResponse &
2623
- MessageResponse<
2624
- AttachmentType,
2625
- ChannelType,
2626
- CommandType,
2627
- MessageType,
2628
- ReactionType,
2629
- UserType
2630
- >
2379
+ APIResponse & MessageResponse<AttachmentType, ChannelType, CommandType, MessageType, ReactionType, UserType>
2631
2380
  >(this.baseURL + `/messages/${messageId}/translate`, {
2632
2381
  language,
2633
2382
  });
@@ -2638,7 +2387,7 @@ export class StreamChat<
2638
2387
  * @param {undefined|null|number|string|Date} timeoutOrExpirationDate expiration date or timeout. Use number type to set timeout in seconds, string or Date to set exact expiration date
2639
2388
  */
2640
2389
  _normalizeExpiration(timeoutOrExpirationDate?: null | number | string | Date) {
2641
- let pinExpires: undefined | string;
2390
+ let pinExpires: null | string = null;
2642
2391
  if (typeof timeoutOrExpirationDate === 'number') {
2643
2392
  const now = new Date();
2644
2393
  now.setSeconds(now.getSeconds() + timeoutOrExpirationDate);
@@ -2656,10 +2405,7 @@ export class StreamChat<
2656
2405
  * @param {string | { id: string }} messageOrMessageId message object or message id
2657
2406
  * @param {string} errorText error message to report in case of message id absence
2658
2407
  */
2659
- _validateAndGetMessageId(
2660
- messageOrMessageId: string | { id: string },
2661
- errorText: string,
2662
- ) {
2408
+ _validateAndGetMessageId(messageOrMessageId: string | { id: string }, errorText: string) {
2663
2409
  let messageId: string;
2664
2410
  if (typeof messageOrMessageId === 'string') {
2665
2411
  messageId = messageOrMessageId;
@@ -2676,12 +2422,14 @@ export class StreamChat<
2676
2422
  * pinMessage - pins the message
2677
2423
  * @param {string | { id: string }} messageOrMessageId message object or message id
2678
2424
  * @param {undefined|null|number|string|Date} timeoutOrExpirationDate expiration date or timeout. Use number type to set timeout in seconds, string or Date to set exact expiration date
2679
- * @param {string | { id: string }} [userId]
2425
+ * @param {undefined|string | { id: string }} [pinnedBy] who will appear as a user who pinned a message. Only for server-side use. Provide `undefined` when pinning message client-side
2426
+ * @param {undefined|number|string|Date} pinnedAt date when message should be pinned. It affects the order of pinned messages. Use negative number to set relative time in the past, string or Date to set exact date of pin
2680
2427
  */
2681
2428
  pinMessage(
2682
2429
  messageOrMessageId: string | { id: string },
2683
2430
  timeoutOrExpirationDate?: null | number | string | Date,
2684
- userId?: string | { id: string },
2431
+ pinnedBy?: string | { id: string },
2432
+ pinnedAt?: number | string | Date,
2685
2433
  ) {
2686
2434
  const messageId = this._validateAndGetMessageId(
2687
2435
  messageOrMessageId,
@@ -2693,9 +2441,10 @@ export class StreamChat<
2693
2441
  set: {
2694
2442
  pinned: true,
2695
2443
  pin_expires: this._normalizeExpiration(timeoutOrExpirationDate),
2444
+ pinned_at: this._normalizeExpiration(pinnedAt),
2696
2445
  },
2697
2446
  },
2698
- userId,
2447
+ pinnedBy,
2699
2448
  );
2700
2449
  }
2701
2450
 
@@ -2704,10 +2453,7 @@ export class StreamChat<
2704
2453
  * @param {string | { id: string }} messageOrMessageId message object or message id
2705
2454
  * @param {string | { id: string }} [userId]
2706
2455
  */
2707
- unpinMessage(
2708
- messageOrMessageId: string | { id: string },
2709
- userId?: string | { id: string },
2710
- ) {
2456
+ unpinMessage(messageOrMessageId: string | { id: string }, userId?: string | { id: string }) {
2711
2457
  const messageId = this._validateAndGetMessageId(
2712
2458
  messageOrMessageId,
2713
2459
  'Please specify the message id when calling unpinMessage',
@@ -2733,14 +2479,7 @@ export class StreamChat<
2733
2479
  * @return {APIResponse & { message: MessageResponse<AttachmentType, ChannelType, CommandType, MessageType, ReactionType, UserType> }} Response that includes the message
2734
2480
  */
2735
2481
  async updateMessage(
2736
- message: UpdatedMessage<
2737
- AttachmentType,
2738
- ChannelType,
2739
- CommandType,
2740
- MessageType,
2741
- ReactionType,
2742
- UserType
2743
- >,
2482
+ message: UpdatedMessage<AttachmentType, ChannelType, CommandType, MessageType, ReactionType, UserType>,
2744
2483
  userId?: string | { id: string },
2745
2484
  options?: { skip_enrich_url?: boolean },
2746
2485
  ) {
@@ -2751,24 +2490,13 @@ export class StreamChat<
2751
2490
  const clonedMessage: Message = Object.assign({}, message);
2752
2491
  delete clonedMessage.id;
2753
2492
 
2754
- const reservedMessageFields: Array<
2755
- | 'command'
2756
- | 'created_at'
2757
- | 'html'
2758
- | 'latest_reactions'
2759
- | 'own_reactions'
2760
- | 'reaction_counts'
2761
- | 'reply_count'
2762
- | 'type'
2763
- | 'updated_at'
2764
- | 'user'
2765
- | '__html'
2766
- > = [
2493
+ const reservedMessageFields: Array<ReservedMessageFields> = [
2767
2494
  'command',
2768
2495
  'created_at',
2769
2496
  'html',
2770
2497
  'latest_reactions',
2771
2498
  'own_reactions',
2499
+ 'quoted_message',
2772
2500
  'reaction_counts',
2773
2501
  'reply_count',
2774
2502
  'type',
@@ -2795,24 +2523,12 @@ export class StreamChat<
2795
2523
  * Server always expects mentioned_users to be array of string. We are adding extra check, just in case
2796
2524
  * SDK missed this conversion.
2797
2525
  */
2798
- if (
2799
- Array.isArray(clonedMessage.mentioned_users) &&
2800
- !isString(clonedMessage.mentioned_users[0])
2801
- ) {
2802
- clonedMessage.mentioned_users = clonedMessage.mentioned_users.map(
2803
- (mu) => ((mu as unknown) as UserResponse).id,
2804
- );
2526
+ if (Array.isArray(clonedMessage.mentioned_users) && !isString(clonedMessage.mentioned_users[0])) {
2527
+ clonedMessage.mentioned_users = clonedMessage.mentioned_users.map((mu) => ((mu as unknown) as UserResponse).id);
2805
2528
  }
2806
2529
 
2807
2530
  return await this.post<
2808
- UpdateMessageAPIResponse<
2809
- AttachmentType,
2810
- ChannelType,
2811
- CommandType,
2812
- MessageType,
2813
- ReactionType,
2814
- UserType
2815
- >
2531
+ UpdateMessageAPIResponse<AttachmentType, ChannelType, CommandType, MessageType, ReactionType, UserType>
2816
2532
  >(this.baseURL + `/messages/${message.id}`, {
2817
2533
  message: clonedMessage,
2818
2534
  ...options,
@@ -2846,14 +2562,7 @@ export class StreamChat<
2846
2562
  user = { id: userId };
2847
2563
  }
2848
2564
  return await this.put<
2849
- UpdateMessageAPIResponse<
2850
- AttachmentType,
2851
- ChannelType,
2852
- CommandType,
2853
- MessageType,
2854
- ReactionType,
2855
- UserType
2856
- >
2565
+ UpdateMessageAPIResponse<AttachmentType, ChannelType, CommandType, MessageType, ReactionType, UserType>
2857
2566
  >(this.baseURL + `/messages/${id}`, {
2858
2567
  ...partialMessageObject,
2859
2568
  ...options,
@@ -2868,14 +2577,7 @@ export class StreamChat<
2868
2577
  }
2869
2578
  return await this.delete<
2870
2579
  APIResponse & {
2871
- message: MessageResponse<
2872
- AttachmentType,
2873
- ChannelType,
2874
- CommandType,
2875
- MessageType,
2876
- ReactionType,
2877
- UserType
2878
- >;
2580
+ message: MessageResponse<AttachmentType, ChannelType, CommandType, MessageType, ReactionType, UserType>;
2879
2581
  }
2880
2582
  >(this.baseURL + `/messages/${messageID}`, params);
2881
2583
  }
@@ -2883,24 +2585,14 @@ export class StreamChat<
2883
2585
  async getMessage(messageID: string) {
2884
2586
  return await this.get<
2885
2587
  APIResponse & {
2886
- message: MessageResponse<
2887
- AttachmentType,
2888
- ChannelType,
2889
- CommandType,
2890
- MessageType,
2891
- ReactionType,
2892
- UserType
2893
- >;
2588
+ message: MessageResponse<AttachmentType, ChannelType, CommandType, MessageType, ReactionType, UserType>;
2894
2589
  }
2895
2590
  >(this.baseURL + `/messages/${messageID}`);
2896
2591
  }
2897
2592
 
2898
2593
  getUserAgent() {
2899
2594
  return (
2900
- this.userAgent ||
2901
- `stream-chat-javascript-client-${this.node ? 'node' : 'browser'}-${
2902
- process.env.PKG_VERSION
2903
- }`
2595
+ this.userAgent || `stream-chat-javascript-client-${this.node ? 'node' : 'browser'}-${process.env.PKG_VERSION}`
2904
2596
  );
2905
2597
  }
2906
2598
 
@@ -2919,8 +2611,9 @@ export class StreamChat<
2919
2611
  headers: {},
2920
2612
  config: {},
2921
2613
  },
2922
- ) {
2614
+ ): AxiosRequestConfig {
2923
2615
  const token = this._getToken();
2616
+ const authorization = token ? { Authorization: token } : undefined;
2924
2617
 
2925
2618
  if (!options.headers?.['x-client-request-id']) {
2926
2619
  options.headers = {
@@ -2932,12 +2625,12 @@ export class StreamChat<
2932
2625
  return {
2933
2626
  params: {
2934
2627
  user_id: this.userID,
2935
- ...options.params,
2628
+ connection_id: this._getConnectionID(),
2936
2629
  api_key: this.key,
2937
- connection_id: this.wsConnection?.connectionID,
2630
+ ...options.params,
2938
2631
  },
2939
2632
  headers: {
2940
- Authorization: token,
2633
+ ...authorization,
2941
2634
  'stream-auth-type': this.getAuthType(),
2942
2635
  'X-Stream-Client': this.getUserAgent(),
2943
2636
  ...options.headers,
@@ -2965,6 +2658,20 @@ export class StreamChat<
2965
2658
  }, 500);
2966
2659
  }
2967
2660
 
2661
+ /**
2662
+ * encode ws url payload
2663
+ * @private
2664
+ * @returns json string
2665
+ */
2666
+ _buildWSPayload = (client_request_id?: string) => {
2667
+ return JSON.stringify({
2668
+ user_id: this.userID,
2669
+ user_details: this._user,
2670
+ device: this.options.device,
2671
+ client_request_id,
2672
+ });
2673
+ };
2674
+
2968
2675
  verifyWebhook(requestBody: string, xSignature: string) {
2969
2676
  return !!this.secret && CheckSignature(requestBody, this.secret, xSignature);
2970
2677
  }
@@ -3051,15 +2758,7 @@ export class StreamChat<
3051
2758
  sync(channel_cids: string[], last_sync_at: string) {
3052
2759
  return this.post<
3053
2760
  APIResponse & {
3054
- events: Event<
3055
- AttachmentType,
3056
- ChannelType,
3057
- CommandType,
3058
- EventType,
3059
- MessageType,
3060
- ReactionType,
3061
- UserType
3062
- >[];
2761
+ events: Event<AttachmentType, ChannelType, CommandType, EventType, MessageType, ReactionType, UserType>[];
3063
2762
  }
3064
2763
  >(`${this.baseURL}/sync`, {
3065
2764
  channel_cids,
@@ -3086,15 +2785,11 @@ export class StreamChat<
3086
2785
  }
3087
2786
 
3088
2787
  listBlockLists() {
3089
- return this.get<APIResponse & { blocklists: BlockListResponse[] }>(
3090
- `${this.baseURL}/blocklists`,
3091
- );
2788
+ return this.get<APIResponse & { blocklists: BlockListResponse[] }>(`${this.baseURL}/blocklists`);
3092
2789
  }
3093
2790
 
3094
2791
  getBlockList(name: string) {
3095
- return this.get<APIResponse & { blocklist: BlockListResponse }>(
3096
- `${this.baseURL}/blocklists/${name}`,
3097
- );
2792
+ return this.get<APIResponse & { blocklist: BlockListResponse }>(`${this.baseURL}/blocklists/${name}`);
3098
2793
  }
3099
2794
 
3100
2795
  updateBlockList(name: string, data: { words: string[] }) {
@@ -3105,18 +2800,12 @@ export class StreamChat<
3105
2800
  return this.delete<APIResponse>(`${this.baseURL}/blocklists/${name}`);
3106
2801
  }
3107
2802
 
3108
- exportChannels(
3109
- request: Array<ExportChannelRequest>,
3110
- options: ExportChannelOptions = {},
3111
- ) {
2803
+ exportChannels(request: Array<ExportChannelRequest>, options: ExportChannelOptions = {}) {
3112
2804
  const payload = {
3113
2805
  channels: request,
3114
2806
  ...options,
3115
2807
  };
3116
- return this.post<APIResponse & ExportChannelResponse>(
3117
- `${this.baseURL}/export_channels`,
3118
- payload,
3119
- );
2808
+ return this.post<APIResponse & ExportChannelResponse>(`${this.baseURL}/export_channels`, payload);
3120
2809
  }
3121
2810
 
3122
2811
  exportChannel(request: ExportChannelRequest, options?: ExportChannelOptions) {
@@ -3124,9 +2813,7 @@ export class StreamChat<
3124
2813
  }
3125
2814
 
3126
2815
  getExportChannelStatus(id: string) {
3127
- return this.get<APIResponse & ExportChannelStatusResponse>(
3128
- `${this.baseURL}/export_channels/${id}`,
3129
- );
2816
+ return this.get<APIResponse & ExportChannelStatusResponse>(`${this.baseURL}/export_channels/${id}`);
3130
2817
  }
3131
2818
 
3132
2819
  /**
@@ -3137,10 +2824,7 @@ export class StreamChat<
3137
2824
  * @return {Segment} The Created Segment
3138
2825
  */
3139
2826
  async createSegment(params: SegmentData) {
3140
- const { segment } = await this.post<{ segment: Segment }>(
3141
- this.baseURL + `/segments`,
3142
- { segment: params },
3143
- );
2827
+ const { segment } = await this.post<{ segment: Segment }>(this.baseURL + `/segments`, { segment: params });
3144
2828
  return segment;
3145
2829
  }
3146
2830
 
@@ -3152,9 +2836,7 @@ export class StreamChat<
3152
2836
  * @return {Segment} A Segment
3153
2837
  */
3154
2838
  async getSegment(id: string) {
3155
- const { segment } = await this.get<{ segment: Segment }>(
3156
- this.baseURL + `/segments/${id}`,
3157
- );
2839
+ const { segment } = await this.get<{ segment: Segment }>(this.baseURL + `/segments/${id}`);
3158
2840
  return segment;
3159
2841
  }
3160
2842
 
@@ -3165,10 +2847,7 @@ export class StreamChat<
3165
2847
  * @return {Segment[]} Segments
3166
2848
  */
3167
2849
  async listSegments(options: { limit?: number; offset?: number }) {
3168
- const { segments } = await this.get<{ segments: Segment[] }>(
3169
- this.baseURL + `/segments`,
3170
- options,
3171
- );
2850
+ const { segments } = await this.get<{ segments: Segment[] }>(this.baseURL + `/segments`, options);
3172
2851
  return segments;
3173
2852
  }
3174
2853
 
@@ -3181,10 +2860,7 @@ export class StreamChat<
3181
2860
  * @return {Segment} Updated Segment
3182
2861
  */
3183
2862
  async updateSegment(id: string, params: Partial<SegmentData>) {
3184
- const { segment } = await this.put<{ segment: Segment }>(
3185
- this.baseURL + `/segments/${id}`,
3186
- { segment: params },
3187
- );
2863
+ const { segment } = await this.put<{ segment: Segment }>(this.baseURL + `/segments/${id}`, { segment: params });
3188
2864
  return segment;
3189
2865
  }
3190
2866
 
@@ -3207,10 +2883,7 @@ export class StreamChat<
3207
2883
  * @return {Campaign} The Created Campaign
3208
2884
  */
3209
2885
  async createCampaign(params: CampaignData) {
3210
- const { campaign } = await this.post<{ campaign: Campaign }>(
3211
- this.baseURL + `/campaigns`,
3212
- { campaign: params },
3213
- );
2886
+ const { campaign } = await this.post<{ campaign: Campaign }>(this.baseURL + `/campaigns`, { campaign: params });
3214
2887
  return campaign;
3215
2888
  }
3216
2889
 
@@ -3222,9 +2895,7 @@ export class StreamChat<
3222
2895
  * @return {Campaign} A Campaign
3223
2896
  */
3224
2897
  async getCampaign(id: string) {
3225
- const { campaign } = await this.get<{ campaign: Campaign }>(
3226
- this.baseURL + `/campaigns/${id}`,
3227
- );
2898
+ const { campaign } = await this.get<{ campaign: Campaign }>(this.baseURL + `/campaigns/${id}`);
3228
2899
  return campaign;
3229
2900
  }
3230
2901
 
@@ -3235,10 +2906,7 @@ export class StreamChat<
3235
2906
  * @return {Campaign[]} Campaigns
3236
2907
  */
3237
2908
  async listCampaigns(options: { limit?: number; offset?: number }) {
3238
- const { campaigns } = await this.get<{ campaigns: Campaign[] }>(
3239
- this.baseURL + `/campaigns`,
3240
- options,
3241
- );
2909
+ const { campaigns } = await this.get<{ campaigns: Campaign[] }>(this.baseURL + `/campaigns`, options);
3242
2910
  return campaigns;
3243
2911
  }
3244
2912
 
@@ -3251,10 +2919,9 @@ export class StreamChat<
3251
2919
  * @return {Campaign} Updated Campaign
3252
2920
  */
3253
2921
  async updateCampaign(id: string, params: Partial<CampaignData>) {
3254
- const { campaign } = await this.put<{ campaign: Campaign }>(
3255
- this.baseURL + `/campaigns/${id}`,
3256
- { campaign: params },
3257
- );
2922
+ const { campaign } = await this.put<{ campaign: Campaign }>(this.baseURL + `/campaigns/${id}`, {
2923
+ campaign: params,
2924
+ });
3258
2925
  return campaign;
3259
2926
  }
3260
2927
 
@@ -3279,10 +2946,9 @@ export class StreamChat<
3279
2946
  */
3280
2947
  async scheduleCampaign(id: string, params: { sendAt: number }) {
3281
2948
  const { sendAt } = params;
3282
- const { campaign } = await this.patch<{ campaign: Campaign }>(
3283
- this.baseURL + `/campaigns/${id}/schedule`,
3284
- { send_at: sendAt },
3285
- );
2949
+ const { campaign } = await this.patch<{ campaign: Campaign }>(this.baseURL + `/campaigns/${id}/schedule`, {
2950
+ send_at: sendAt,
2951
+ });
3286
2952
  return campaign;
3287
2953
  }
3288
2954
 
@@ -3294,9 +2960,7 @@ export class StreamChat<
3294
2960
  * @return {Campaign} Stopped Campaign
3295
2961
  */
3296
2962
  async stopCampaign(id: string) {
3297
- const { campaign } = await this.patch<{ campaign: Campaign }>(
3298
- this.baseURL + `/campaigns/${id}/stop`,
3299
- );
2963
+ const { campaign } = await this.patch<{ campaign: Campaign }>(this.baseURL + `/campaigns/${id}/stop`);
3300
2964
  return campaign;
3301
2965
  }
3302
2966
 
@@ -3308,9 +2972,7 @@ export class StreamChat<
3308
2972
  * @return {Campaign} Resumed Campaign
3309
2973
  */
3310
2974
  async resumeCampaign(id: string) {
3311
- const { campaign } = await this.patch<{ campaign: Campaign }>(
3312
- this.baseURL + `/campaigns/${id}/resume`,
3313
- );
2975
+ const { campaign } = await this.patch<{ campaign: Campaign }>(this.baseURL + `/campaigns/${id}/resume`);
3314
2976
  return campaign;
3315
2977
  }
3316
2978
 
@@ -3323,10 +2985,7 @@ export class StreamChat<
3323
2985
  */
3324
2986
  async testCampaign(id: string, params: { users: string[] }) {
3325
2987
  const { users } = params;
3326
- const { campaign } = await this.post<{ campaign: Campaign }>(
3327
- this.baseURL + `/campaigns/${id}/test`,
3328
- { users },
3329
- );
2988
+ const { campaign } = await this.post<{ campaign: Campaign }>(this.baseURL + `/campaigns/${id}/test`, { users });
3330
2989
  return campaign;
3331
2990
  }
3332
2991
 
@@ -3360,10 +3019,10 @@ export class StreamChat<
3360
3019
  * @return {DeleteChannelsResponse} Result of the soft deletion, if server-side, it holds the task ID as well
3361
3020
  */
3362
3021
  async deleteChannels(cids: string[], options: { hard_delete?: boolean } = {}) {
3363
- return await this.post<APIResponse & DeleteChannelsResponse>(
3364
- this.baseURL + `/channels/delete`,
3365
- { cids, ...options },
3366
- );
3022
+ return await this.post<APIResponse & DeleteChannelsResponse>(this.baseURL + `/channels/delete`, {
3023
+ cids,
3024
+ ...options,
3025
+ });
3367
3026
  }
3368
3027
 
3369
3028
  /**
@@ -3378,21 +3037,11 @@ export class StreamChat<
3378
3037
  if (options?.user !== 'soft' && options?.user !== 'hard') {
3379
3038
  throw new Error('Invalid delete user options. user must be one of [soft hard]');
3380
3039
  }
3381
- if (
3382
- options.messages !== undefined &&
3383
- options.messages !== 'soft' &&
3384
- options.messages !== 'hard'
3385
- ) {
3040
+ if (options.messages !== undefined && options.messages !== 'soft' && options.messages !== 'hard') {
3386
3041
  throw new Error('Invalid delete user options. messages must be one of [soft hard]');
3387
3042
  }
3388
- if (
3389
- options.conversations !== undefined &&
3390
- options.conversations !== 'soft' &&
3391
- options.conversations !== 'hard'
3392
- ) {
3393
- throw new Error(
3394
- 'Invalid delete user options. conversations must be one of [soft hard]',
3395
- );
3043
+ if (options.conversations !== undefined && options.conversations !== 'soft' && options.conversations !== 'hard') {
3044
+ throw new Error('Invalid delete user options. conversations must be one of [soft hard]');
3396
3045
  }
3397
3046
  return await this.post<APIResponse & TaskResponse>(this.baseURL + `/users/delete`, {
3398
3047
  user_ids,