stream-chat 8.59.0 → 8.61.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/client.ts CHANGED
@@ -32,6 +32,7 @@ import {
32
32
  import {
33
33
  APIErrorResponse,
34
34
  APIResponse,
35
+ AppIdentifier,
35
36
  AppSettings,
36
37
  AppSettingsAPIResponse,
37
38
  BannedUsersFilters,
@@ -283,6 +284,8 @@ export class StreamChat<StreamChatGenerics extends ExtendableGenerics = DefaultG
283
284
  defaultWSTimeout: number;
284
285
  sdkIdentifier?: SdkIdentifier;
285
286
  deviceIdentifier?: DeviceIdentifier;
287
+ appIdentifier?: AppIdentifier;
288
+ private cachedUserAgent?: string;
286
289
  private nextRequestAbortController: AbortController | null = null;
287
290
 
288
291
  /**
@@ -2828,6 +2831,8 @@ export class StreamChat<StreamChatGenerics extends ExtendableGenerics = DefaultG
2828
2831
  * @param {boolean} options.watch Subscribes the user to the channels of the threads.
2829
2832
  * @param {number} options.participant_limit Limits the number of participants returned per threads.
2830
2833
  * @param {number} options.reply_limit Limits the number of replies returned per threads.
2834
+ * @param {ThreadFilters} options.filter MongoDB style filters for threads
2835
+ * @param {ThreadSort} options.sort MongoDB style sort for threads
2831
2836
  *
2832
2837
  * @returns {{ threads: Thread<StreamChatGenerics>[], next: string }} Returns the list of threads and the next cursor.
2833
2838
  */
@@ -2840,9 +2845,26 @@ export class StreamChat<StreamChatGenerics extends ExtendableGenerics = DefaultG
2840
2845
  ...options,
2841
2846
  };
2842
2847
 
2848
+ const requestBody: Record<string, unknown> = {
2849
+ ...optionsWithDefaults,
2850
+ };
2851
+
2852
+ if (optionsWithDefaults.filter && Object.keys(optionsWithDefaults.filter).length > 0) {
2853
+ requestBody.filter = optionsWithDefaults.filter;
2854
+ }
2855
+
2856
+ if (
2857
+ optionsWithDefaults.sort &&
2858
+ (Array.isArray(optionsWithDefaults.sort)
2859
+ ? optionsWithDefaults.sort.length > 0
2860
+ : Object.keys(optionsWithDefaults.sort).length > 0)
2861
+ ) {
2862
+ requestBody.sort = normalizeQuerySort(optionsWithDefaults.sort);
2863
+ }
2864
+
2843
2865
  const response = await this.post<QueryThreadsAPIResponse<StreamChatGenerics>>(
2844
2866
  `${this.baseURL}/threads`,
2845
- optionsWithDefaults,
2867
+ requestBody,
2846
2868
  );
2847
2869
 
2848
2870
  return {
@@ -2926,36 +2948,42 @@ export class StreamChat<StreamChatGenerics extends ExtendableGenerics = DefaultG
2926
2948
  );
2927
2949
  }
2928
2950
 
2929
- getUserAgent() {
2951
+ getUserAgent = (): string => {
2952
+ // An explicit override (deprecated `setUserAgent`) always wins and is never cached.
2930
2953
  if (this.userAgent) {
2931
2954
  return this.userAgent;
2932
2955
  }
2933
2956
 
2934
- const version = process.env.PKG_VERSION;
2935
- const clientBundle = process.env.CLIENT_BUNDLE;
2957
+ // Computed once, then memoized for the client's lifetime - inputs read on
2958
+ // the first call (sdk/app/device identifiers, build-time env) are not re-read.
2959
+ if (!this.cachedUserAgent) {
2960
+ const version = process.env.PKG_VERSION;
2961
+ const { name: sdkName, version: sdkVersion } = this.sdkIdentifier ?? {};
2962
+ const { name: appName, version: appVersion } = this.appIdentifier ?? {};
2963
+ const { os, model: deviceModel } = this.deviceIdentifier ?? {};
2964
+
2965
+ const head = sdkName
2966
+ ? `stream-chat-${sdkName}-v${sdkVersion}-llc-v${version}`
2967
+ : `stream-chat-js-v${version}-${this.node ? 'node' : 'browser'}`;
2968
+
2969
+ this.cachedUserAgent = [
2970
+ head,
2971
+ // reports the host app, the device OS, the device model, and the picked
2972
+ // exports bundle, each only when a value is present
2973
+ ...Object.entries({
2974
+ app: appName,
2975
+ app_version: appVersion,
2976
+ os,
2977
+ device_model: deviceModel,
2978
+ client_bundle: process.env.CLIENT_BUNDLE,
2979
+ })
2980
+ .filter(([, value]) => value && value.length > 0)
2981
+ .map(([key, value]) => `${key}=${value}`),
2982
+ ].join('|');
2983
+ }
2936
2984
 
2937
- let userAgentString = '';
2938
- if (this.sdkIdentifier) {
2939
- userAgentString = `stream-chat-${this.sdkIdentifier.name}-v${this.sdkIdentifier.version}-llc-v${version}`;
2940
- } else {
2941
- userAgentString = `stream-chat-js-v${version}-${this.node ? 'node' : 'browser'}`;
2942
- }
2943
-
2944
- const { os, model } = this.deviceIdentifier ?? {};
2945
-
2946
- return ([
2947
- // reports the device OS, if provided
2948
- ['os', os],
2949
- // reports the device model, if provided
2950
- ['device_model', model],
2951
- // reports which bundle is being picked from the exports
2952
- ['client_bundle', clientBundle],
2953
- ] as const).reduce(
2954
- (withArguments, [key, value]) =>
2955
- value && value.length > 0 ? withArguments.concat(`|${key}=${value}`) : withArguments,
2956
- userAgentString,
2957
- );
2958
- }
2985
+ return this.cachedUserAgent;
2986
+ };
2959
2987
 
2960
2988
  /**
2961
2989
  * @deprecated use sdkIdentifier instead
package/src/types.ts CHANGED
@@ -353,7 +353,7 @@ export type ChannelMemberUpdates<
353
353
  export type ChannelMemberResponse<
354
354
  StreamChatGenerics extends ExtendableGenerics = DefaultGenerics
355
355
  > = StreamChatGenerics['memberType'] & {
356
- archived_at?: string;
356
+ archived_at?: string | null;
357
357
  ban_expires?: string;
358
358
  banned?: boolean;
359
359
  channel_role?: Role;
@@ -363,7 +363,7 @@ export type ChannelMemberResponse<
363
363
  invited?: boolean;
364
364
  is_moderator?: boolean;
365
365
  notifications_muted?: boolean;
366
- pinned_at?: string;
366
+ pinned_at?: string | null;
367
367
  role?: string;
368
368
  shadow_banned?: boolean;
369
369
  status?: InviteStatus;
@@ -571,11 +571,13 @@ export type PartialThreadUpdate = {
571
571
  };
572
572
 
573
573
  export type QueryThreadsOptions = {
574
+ filter?: ThreadFilters;
574
575
  limit?: number;
575
576
  member_limit?: number;
576
577
  next?: string;
577
578
  participant_limit?: number;
578
579
  reply_limit?: number;
580
+ sort?: ThreadSort;
579
581
  watch?: boolean;
580
582
  };
581
583
 
@@ -3859,6 +3861,13 @@ export type SdkIdentifier = { name: 'react' | 'react-native' | 'expo' | 'angular
3859
3861
  */
3860
3862
  export type DeviceIdentifier = { os: string; model?: string };
3861
3863
 
3864
+ /**
3865
+ * An identifier containing information about the downstream application integrating
3866
+ * stream-chat, if available. `name` is reported as `app` and `version` as `app_version`
3867
+ * in the user agent. Distinct from the SDK and device identifiers.
3868
+ */
3869
+ export type AppIdentifier = { name: string; version?: string };
3870
+
3862
3871
  export type DraftResponse<StreamChatGenerics extends ExtendableGenerics = DefaultGenerics> = {
3863
3872
  channel_cid: string;
3864
3873
  created_at: string;
@@ -3900,3 +3909,41 @@ export type DraftMessage<StreamChatGenerics extends ExtendableGenerics = Default
3900
3909
  silent?: boolean;
3901
3910
  type?: MessageLabel;
3902
3911
  };
3912
+
3913
+ export type ThreadSort = ThreadSortBase | Array<ThreadSortBase>;
3914
+
3915
+ export type ThreadSortBase = {
3916
+ active_participant_count?: AscDesc;
3917
+ created_at?: AscDesc;
3918
+ last_message_at?: AscDesc;
3919
+ parent_message_id?: AscDesc;
3920
+ participant_count?: AscDesc;
3921
+ reply_count?: AscDesc;
3922
+ updated_at?: AscDesc;
3923
+ };
3924
+
3925
+ export type ThreadFilters = QueryFilters<
3926
+ {
3927
+ channel_cid?: RequireOnlyOne<Pick<QueryFilter<string>, '$eq' | '$in'>> | PrimitiveFilter<string>;
3928
+ } & {
3929
+ parent_message_id?:
3930
+ | RequireOnlyOne<Pick<QueryFilter<ThreadResponse['parent_message_id']>, '$eq' | '$in'>>
3931
+ | PrimitiveFilter<ThreadResponse['parent_message_id']>;
3932
+ } & {
3933
+ created_by_user_id?:
3934
+ | RequireOnlyOne<Pick<QueryFilter<ThreadResponse['created_by_user_id']>, '$eq' | '$in'>>
3935
+ | PrimitiveFilter<ThreadResponse['created_by_user_id']>;
3936
+ } & {
3937
+ created_at?:
3938
+ | RequireOnlyOne<Pick<QueryFilter<ThreadResponse['created_at']>, '$eq' | '$gt' | '$lt' | '$gte' | '$lte'>>
3939
+ | PrimitiveFilter<ThreadResponse['created_at']>;
3940
+ } & {
3941
+ updated_at?:
3942
+ | RequireOnlyOne<Pick<QueryFilter<ThreadResponse['updated_at']>, '$eq' | '$gt' | '$lt' | '$gte' | '$lte'>>
3943
+ | PrimitiveFilter<ThreadResponse['updated_at']>;
3944
+ } & {
3945
+ last_message_at?:
3946
+ | RequireOnlyOne<Pick<QueryFilter<ThreadResponse['last_message_at']>, '$eq' | '$gt' | '$lt' | '$gte' | '$lte'>>
3947
+ | PrimitiveFilter<ThreadResponse['last_message_at']>;
3948
+ }
3949
+ >;