stream-chat 9.50.3 → 9.51.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 (33) hide show
  1. package/dist/cjs/index.browser.js +221 -90
  2. package/dist/cjs/index.browser.js.map +3 -3
  3. package/dist/cjs/index.node.js +221 -90
  4. package/dist/cjs/index.node.js.map +3 -3
  5. package/dist/esm/index.mjs +221 -90
  6. package/dist/esm/index.mjs.map +3 -3
  7. package/dist/types/channel.d.ts +3 -2
  8. package/dist/types/client.d.ts +13 -9
  9. package/dist/types/messageComposer/middleware/textComposer/mentions.d.ts +15 -9
  10. package/dist/types/offline-support/offline_support_api.d.ts +7 -1
  11. package/dist/types/offline-support/offline_sync_manager.d.ts +12 -1
  12. package/dist/types/search/BaseSearchSource.d.ts +42 -24
  13. package/dist/types/search/ChannelMemberSearchSource.d.ts +9 -4
  14. package/dist/types/search/ChannelSearchSource.d.ts +9 -3
  15. package/dist/types/search/MessageSearchSource.d.ts +14 -3
  16. package/dist/types/search/UserSearchSource.d.ts +9 -3
  17. package/dist/types/search/types.d.ts +14 -1
  18. package/dist/types/types.d.ts +12 -1
  19. package/dist/types/utils.d.ts +1 -1
  20. package/package.json +7 -7
  21. package/src/channel.ts +4 -0
  22. package/src/client.ts +54 -12
  23. package/src/messageComposer/middleware/textComposer/mentions.ts +75 -23
  24. package/src/offline-support/offline_support_api.ts +17 -2
  25. package/src/offline-support/offline_sync_manager.ts +36 -8
  26. package/src/search/BaseSearchSource.ts +123 -39
  27. package/src/search/ChannelMemberSearchSource.ts +22 -11
  28. package/src/search/ChannelSearchSource.ts +16 -5
  29. package/src/search/MessageSearchSource.ts +36 -4
  30. package/src/search/UserSearchSource.ts +16 -5
  31. package/src/search/types.ts +14 -1
  32. package/src/types.ts +13 -1
  33. package/src/utils.ts +6 -3
@@ -998,7 +998,8 @@ var debounce = (fn, timeout = 0, { leading = false, trailing = true } = {}) => {
998
998
  }
999
999
  runningTimeout = null;
1000
1000
  };
1001
- runningTimeout = setTimeout(timeoutHandler, timeout);
1001
+ const delay = typeof timeout === "function" ? timeout(...args) : timeout;
1002
+ runningTimeout = setTimeout(timeoutHandler, delay);
1002
1003
  return lastResult;
1003
1004
  };
1004
1005
  debouncedFn.cancel = () => {
@@ -4436,13 +4437,41 @@ function isErrorResponse(res) {
4436
4437
 
4437
4438
  // src/search/BaseSearchSource.ts
4438
4439
  var DEFAULT_SEARCH_SOURCE_OPTIONS = {
4439
- debounceMs: 300,
4440
4440
  pageSize: 10,
4441
4441
  allowEmptySearchString: false,
4442
4442
  resetOnNewSearchQuery: true
4443
4443
  };
4444
+ var resolveDebounceOptions = ({
4445
+ debounceMs,
4446
+ shortQueryDebounceMs,
4447
+ longQueryDebounceMs,
4448
+ shortQueryMaxLength
4449
+ }) => ({
4450
+ shortQueryDebounceMs: shortQueryDebounceMs ?? debounceMs ?? 500,
4451
+ longQueryDebounceMs: longQueryDebounceMs ?? debounceMs ?? 300,
4452
+ shortQueryMaxLength: shortQueryMaxLength ?? 2
4453
+ });
4444
4454
  var BaseSearchSourceBase = class {
4445
4455
  constructor(options) {
4456
+ this.setDebounceOptions = (options = {}) => {
4457
+ const resolved = resolveDebounceOptions(options);
4458
+ this.shortQueryDebounceMs = resolved.shortQueryDebounceMs;
4459
+ this.longQueryDebounceMs = resolved.longQueryDebounceMs;
4460
+ this.shortQueryMaxLength = resolved.shortQueryMaxLength;
4461
+ this.searchDebounced = debounce(
4462
+ this.executeQuery.bind(this),
4463
+ (searchString) => this.getDebounceMs(searchString)
4464
+ );
4465
+ };
4466
+ /**
4467
+ * Short queries match too much and are slow server-side, so they get a longer debounce.
4468
+ * Resolved per call, which is what lets the interval switch as the user keeps typing.
4469
+ */
4470
+ this.getDebounceMs = (searchString) => {
4471
+ const { length } = searchString ?? this.searchQuery;
4472
+ return length <= this.shortQueryMaxLength ? this.shortQueryDebounceMs : this.longQueryDebounceMs;
4473
+ };
4474
+ this.search = (searchQuery) => this.searchDebounced(searchQuery);
4446
4475
  this.activate = () => {
4447
4476
  if (this.isActive) return;
4448
4477
  this.state.partialNext({ isActive: true });
@@ -4454,7 +4483,7 @@ var BaseSearchSourceBase = class {
4454
4483
  this.canExecuteQuery = (newSearchString) => {
4455
4484
  const hasNewSearchQuery = typeof newSearchString !== "undefined";
4456
4485
  const searchString = newSearchString ?? this.searchQuery;
4457
- return !!(this.isActive && !this.isLoading && (this.hasNext || hasNewSearchQuery) && (this.allowEmptySearchString || searchString));
4486
+ return !!(this.isActive && this.canDispatchQuery(hasNewSearchQuery) && (this.allowEmptySearchString || searchString));
4458
4487
  };
4459
4488
  const { pageSize, allowEmptySearchString, resetOnNewSearchQuery } = {
4460
4489
  ...DEFAULT_SEARCH_SOURCE_OPTIONS,
@@ -4464,6 +4493,14 @@ var BaseSearchSourceBase = class {
4464
4493
  this.allowEmptySearchString = allowEmptySearchString;
4465
4494
  this.resetOnNewSearchQuery = resetOnNewSearchQuery;
4466
4495
  this.state = new StateStore(this.initialState);
4496
+ this.setDebounceOptions(options ?? {});
4497
+ }
4498
+ /**
4499
+ * A new search query preempts an in-flight one; pagination waits for it to finish
4500
+ * and needs a next page to fetch.
4501
+ */
4502
+ canDispatchQuery(hasNewSearchQuery) {
4503
+ return hasNewSearchQuery || !this.isLoading && this.hasNext;
4467
4504
  }
4468
4505
  get lastQueryError() {
4469
4506
  return this.state.getLatestValue().lastQueryError;
@@ -4558,21 +4595,30 @@ var BaseSearchSourceBase = class {
4558
4595
  }
4559
4596
  };
4560
4597
  var BaseSearchSource = class extends BaseSearchSourceBase {
4561
- constructor(options) {
4562
- const { debounceMs } = { ...DEFAULT_SEARCH_SOURCE_OPTIONS, ...options };
4563
- super(options);
4564
- this.setDebounceOptions = ({ debounceMs }) => {
4565
- this.searchDebounced = debounce(this.executeQuery.bind(this), debounceMs);
4566
- };
4567
- this.search = (searchQuery) => this.searchDebounced(searchQuery);
4568
- this.setDebounceOptions({ debounceMs });
4598
+ constructor() {
4599
+ super(...arguments);
4600
+ /** Aborts the in-flight request, if any, once a newer query is dispatched. */
4601
+ this.queryAbortController = null;
4602
+ }
4603
+ /** Aborts the in-flight request, if any. Returns true when one was aborted. */
4604
+ abortInFlightQuery() {
4605
+ if (!this.queryAbortController) return false;
4606
+ this.queryAbortController.abort();
4607
+ this.queryAbortController = null;
4608
+ return true;
4609
+ }
4610
+ resetState() {
4611
+ this.abortInFlightQuery();
4612
+ super.resetState();
4569
4613
  }
4570
4614
  async executeQuery(newSearchString) {
4571
4615
  if (!this.canExecuteQuery(newSearchString)) return;
4616
+ this.abortInFlightQuery();
4617
+ const { signal } = this.queryAbortController = new AbortController();
4572
4618
  const { hasNewSearchQuery, searchString } = this.prepareStateForQuery(newSearchString);
4573
4619
  let stateUpdate = {};
4574
4620
  try {
4575
- const results = await this.query(searchString);
4621
+ const results = await this.query(searchString, { signal });
4576
4622
  if (!results) return;
4577
4623
  const { items } = results;
4578
4624
  stateUpdate = this.updatePaginationStateFromQuery(results);
@@ -4583,23 +4629,19 @@ var BaseSearchSource = class extends BaseSearchSourceBase {
4583
4629
  stateUpdate.hasNext = false;
4584
4630
  }
4585
4631
  } finally {
4586
- this.state.next(this.getStateAfterQuery(stateUpdate, hasNewSearchQuery));
4632
+ if (!signal.aborted) {
4633
+ this.state.next(this.getStateAfterQuery(stateUpdate, hasNewSearchQuery));
4634
+ }
4587
4635
  }
4588
4636
  }
4589
4637
  cancelScheduledQuery() {
4590
4638
  this.searchDebounced.cancel();
4639
+ if (this.abortInFlightQuery() && this.isLoading) {
4640
+ this.state.partialNext({ isLoading: false });
4641
+ }
4591
4642
  }
4592
4643
  };
4593
4644
  var BaseSearchSourceSync = class extends BaseSearchSourceBase {
4594
- constructor(options) {
4595
- const { debounceMs } = { ...DEFAULT_SEARCH_SOURCE_OPTIONS, ...options };
4596
- super(options);
4597
- this.setDebounceOptions = ({ debounceMs }) => {
4598
- this.searchDebounced = debounce(this.executeQuery.bind(this), debounceMs);
4599
- };
4600
- this.search = (searchQuery) => this.searchDebounced(searchQuery);
4601
- this.setDebounceOptions({ debounceMs });
4602
- }
4603
4645
  executeQuery(newSearchString) {
4604
4646
  if (!this.canExecuteQuery(newSearchString)) return;
4605
4647
  const { hasNewSearchQuery, searchString } = this.prepareStateForQuery(newSearchString);
@@ -4895,13 +4937,13 @@ var UserGroupPaginator = class extends BasePaginator {
4895
4937
  // src/search/ChannelMemberSearchSource.ts
4896
4938
  var ChannelMemberSearchSource = class extends BaseSearchSource {
4897
4939
  constructor(channel, options, filterBuilderOptions = {}) {
4898
- super(options);
4940
+ const { filters, sort, searchOptions, ...restOptions } = options || {};
4941
+ super({ ...restOptions, allowEmptySearchString: true });
4899
4942
  this.type = "members";
4900
- this.canExecuteQuery = (newSearchString) => {
4901
- const hasNewSearchQuery = typeof newSearchString !== "undefined";
4902
- return this.isActive && !this.isLoading && (this.hasNext || hasNewSearchQuery);
4903
- };
4904
4943
  this.channel = channel;
4944
+ this.filters = filters;
4945
+ this.sort = sort;
4946
+ this.searchOptions = searchOptions;
4905
4947
  this.filterBuilder = new FilterBuilder({
4906
4948
  initialFilterConfig: {
4907
4949
  default: {
@@ -4917,7 +4959,7 @@ var ChannelMemberSearchSource = class extends BaseSearchSource {
4917
4959
  ...filterBuilderOptions
4918
4960
  });
4919
4961
  }
4920
- async query(searchQuery) {
4962
+ async query(searchQuery, queryOptions = {}) {
4921
4963
  const filters = this.filterBuilder.buildFilters({
4922
4964
  baseFilters: this.filters,
4923
4965
  context: {
@@ -4926,7 +4968,12 @@ var ChannelMemberSearchSource = class extends BaseSearchSource {
4926
4968
  });
4927
4969
  const sort = this.sort ?? [];
4928
4970
  const options = { ...this.searchOptions, limit: this.pageSize, offset: this.offset };
4929
- const { members } = await this.channel.queryMembers(filters ?? {}, sort, options);
4971
+ const { members } = await this.channel.queryMembers(
4972
+ filters ?? {},
4973
+ sort,
4974
+ options,
4975
+ queryOptions
4976
+ );
4930
4977
  return { items: members };
4931
4978
  }
4932
4979
  filterQueryResults(items) {
@@ -5041,9 +5088,13 @@ var SearchController = class {
5041
5088
  // src/search/UserSearchSource.ts
5042
5089
  var UserSearchSource = class extends BaseSearchSource {
5043
5090
  constructor(client, options, filterBuilderOptions = {}) {
5044
- super(options);
5091
+ const { filters, sort, searchOptions, ...restOptions } = options || {};
5092
+ super(restOptions);
5045
5093
  this.type = "users";
5046
5094
  this.client = client;
5095
+ this.filters = filters;
5096
+ this.sort = sort;
5097
+ this.searchOptions = searchOptions;
5047
5098
  this.filterBuilder = new FilterBuilder({
5048
5099
  initialFilterConfig: {
5049
5100
  $or: {
@@ -5059,7 +5110,7 @@ var UserSearchSource = class extends BaseSearchSource {
5059
5110
  ...filterBuilderOptions
5060
5111
  });
5061
5112
  }
5062
- async query(searchQuery) {
5113
+ async query(searchQuery, queryOptions = {}) {
5063
5114
  const filters = this.filterBuilder.buildFilters({
5064
5115
  baseFilters: this.filters,
5065
5116
  context: { searchQuery }
@@ -5072,7 +5123,7 @@ var UserSearchSource = class extends BaseSearchSource {
5072
5123
  sort = { id: 1, ...this.sort };
5073
5124
  }
5074
5125
  const options = { ...this.searchOptions, limit: this.pageSize, offset: this.offset };
5075
- const { users } = await this.client.queryUsers(filters, sort, options);
5126
+ const { users } = await this.client.queryUsers(filters, sort, options, queryOptions);
5076
5127
  return { items: users };
5077
5128
  }
5078
5129
  filterQueryResults(items) {
@@ -5083,9 +5134,13 @@ var UserSearchSource = class extends BaseSearchSource {
5083
5134
  // src/search/ChannelSearchSource.ts
5084
5135
  var ChannelSearchSource = class extends BaseSearchSource {
5085
5136
  constructor(client, options, filterBuilderOptions = {}) {
5086
- super(options);
5137
+ const { filters, sort, searchOptions, ...restOptions } = options || {};
5138
+ super(restOptions);
5087
5139
  this.type = "channels";
5088
5140
  this.client = client;
5141
+ this.filters = filters;
5142
+ this.sort = sort;
5143
+ this.searchOptions = searchOptions;
5089
5144
  this.filterBuilder = new FilterBuilder({
5090
5145
  ...filterBuilderOptions,
5091
5146
  initialFilterConfig: {
@@ -5097,7 +5152,7 @@ var ChannelSearchSource = class extends BaseSearchSource {
5097
5152
  }
5098
5153
  });
5099
5154
  }
5100
- async query(searchQuery) {
5155
+ async query(searchQuery, queryOptions = {}) {
5101
5156
  const filters = this.filterBuilder.buildFilters({
5102
5157
  baseFilters: {
5103
5158
  ...this.client.userID ? { members: { $in: [this.client.userID] } } : {},
@@ -5107,7 +5162,7 @@ var ChannelSearchSource = class extends BaseSearchSource {
5107
5162
  });
5108
5163
  const sort = this.sort ?? {};
5109
5164
  const options = { ...this.searchOptions, limit: this.pageSize, offset: this.offset };
5110
- const items = await this.client.queryChannels(filters, sort, options);
5165
+ const items = await this.client.queryChannels(filters, sort, options, queryOptions);
5111
5166
  return { items };
5112
5167
  }
5113
5168
  filterQueryResults(items) {
@@ -5118,9 +5173,24 @@ var ChannelSearchSource = class extends BaseSearchSource {
5118
5173
  // src/search/MessageSearchSource.ts
5119
5174
  var MessageSearchSource = class extends BaseSearchSource {
5120
5175
  constructor(client, options, filterBuilderOptions) {
5121
- super(options);
5176
+ const {
5177
+ messageSearchChannelFilters,
5178
+ messageSearchFilters,
5179
+ messageSearchSort,
5180
+ channelQueryFilters,
5181
+ channelQuerySort,
5182
+ channelQueryOptions,
5183
+ ...restOptions
5184
+ } = options || {};
5185
+ super(restOptions);
5122
5186
  this.type = "messages";
5123
5187
  this.client = client;
5188
+ this.messageSearchChannelFilters = messageSearchChannelFilters;
5189
+ this.messageSearchFilters = messageSearchFilters;
5190
+ this.messageSearchSort = messageSearchSort;
5191
+ this.channelQueryFilters = channelQueryFilters;
5192
+ this.channelQuerySort = channelQuerySort;
5193
+ this.channelQueryOptions = channelQueryOptions;
5124
5194
  this.messageSearchChannelFilterBuilder = new FilterBuilder(filterBuilderOptions?.messageSearchChannel);
5125
5195
  this.messageSearchFilterBuilder = new FilterBuilder({
5126
5196
  ...filterBuilderOptions?.messageSearch,
@@ -5143,7 +5213,7 @@ var MessageSearchSource = class extends BaseSearchSource {
5143
5213
  }
5144
5214
  });
5145
5215
  }
5146
- async query(searchQuery) {
5216
+ async query(searchQuery, queryOptions = {}) {
5147
5217
  if (!this.client.userID || this.next === null) return { items: [] };
5148
5218
  const channelFilters = this.messageSearchChannelFilterBuilder.buildFilters({
5149
5219
  baseFilters: {
@@ -5171,9 +5241,11 @@ var MessageSearchSource = class extends BaseSearchSource {
5171
5241
  const { next, results } = await this.client.search(
5172
5242
  channelFilters,
5173
5243
  messageFilters,
5174
- options
5244
+ options,
5245
+ queryOptions
5175
5246
  );
5176
5247
  const items = results.map(({ message }) => message);
5248
+ if (queryOptions.signal?.aborted) return { items, next };
5177
5249
  const cids = Array.from(
5178
5250
  items.reduce((acc, message) => {
5179
5251
  if (message.cid && !this.client.activeChannels[message.cid]) acc.add(message.cid);
@@ -5191,7 +5263,8 @@ var MessageSearchSource = class extends BaseSearchSource {
5191
5263
  last_message_at: -1,
5192
5264
  ...this.channelQuerySort
5193
5265
  },
5194
- this.channelQueryOptions
5266
+ this.channelQueryOptions,
5267
+ queryOptions
5195
5268
  );
5196
5269
  }
5197
5270
  return { items, next };
@@ -6485,13 +6558,18 @@ var MentionsSearchSource = class extends BaseSearchSource {
6485
6558
  constructor(channel, options) {
6486
6559
  const {
6487
6560
  mentionAllAppUsers,
6561
+ memberFilters,
6562
+ memberSort,
6563
+ searchOptions,
6488
6564
  suggestionFactoryMappers,
6489
6565
  textComposerText,
6490
6566
  transliterate,
6491
6567
  trigger,
6568
+ userFilters,
6569
+ userSort,
6492
6570
  ...restOptions
6493
6571
  } = options || {};
6494
- super(restOptions);
6572
+ super({ ...restOptions, allowEmptySearchString: true });
6495
6573
  this.type = "mentions";
6496
6574
  this.normalizeSearchValue = (value) => this.transliterate(removeDiacritics(value)).toLowerCase();
6497
6575
  this.matchesSearchQuery = (value, searchQuery) => {
@@ -6529,10 +6607,6 @@ var MentionsSearchSource = class extends BaseSearchSource {
6529
6607
  this.toHereMentionSuggestion = (searchToken = this.searchQuery) => this.mapMentionSuggestion("here", "here", searchToken);
6530
6608
  this.toRoleMentionSuggestion = (role, searchToken = this.searchQuery) => this.mapMentionSuggestion("role", role, searchToken);
6531
6609
  this.toUserGroupMentionSuggestion = (userGroup, searchToken = this.searchQuery) => this.mapMentionSuggestion("user_group", userGroup, searchToken);
6532
- this.canExecuteQuery = (newSearchString) => {
6533
- const hasNewSearchQuery = typeof newSearchString !== "undefined";
6534
- return this.isActive && !this.isLoading && (hasNewSearchQuery || this.hasNext);
6535
- };
6536
6610
  this.transliterate = (text) => text;
6537
6611
  this.getMembersAndWatchers = () => {
6538
6612
  const memberUsers = Object.values(this.channel.state.members ?? {}).map(
@@ -6552,10 +6626,10 @@ var MentionsSearchSource = class extends BaseSearchSource {
6552
6626
  ...this.isMentionTypeAllowed("channel") ? [this.toChannelMentionSuggestion(searchQuery)] : [],
6553
6627
  ...this.isMentionTypeAllowed("here") ? [this.toHereMentionSuggestion(searchQuery)] : []
6554
6628
  ].filter(({ name }) => this.matchesPrefixSearchQuery(name, searchQuery));
6555
- this.getRoleMentionSuggestions = async (query) => {
6629
+ this.getRoleMentionSuggestions = async (query, queryOptions = {}) => {
6556
6630
  if (!this.isMentionTypeAllowed("role")) return [];
6557
6631
  if (!query) return [];
6558
- const { roles } = await this.client.searchRoles({ query });
6632
+ const { roles } = await this.client.searchRoles({ query }, queryOptions);
6559
6633
  return [...roles?.map((role) => role.name) ?? []].sort((left, right) => left.localeCompare(right)).map((role) => this.toRoleMentionSuggestion(role, query));
6560
6634
  };
6561
6635
  this.searchMembersLocally = (searchQuery) => {
@@ -6617,20 +6691,25 @@ var MentionsSearchSource = class extends BaseSearchSource {
6617
6691
  options: { ...this.searchOptions, limit: this.pageSize, offset }
6618
6692
  };
6619
6693
  };
6620
- this.queryUsers = async (searchQuery, offset = 0) => {
6694
+ this.queryUsers = async (searchQuery, offset = 0, queryOptions = {}) => {
6621
6695
  const { filters, sort, options } = this.prepareQueryUsersParams(searchQuery, offset);
6622
- const { users } = await this.client.queryUsers(filters, sort, options);
6696
+ const { users } = await this.client.queryUsers(filters, sort, options, queryOptions);
6623
6697
  return users;
6624
6698
  };
6625
- this.queryMembers = async (searchQuery, offset = 0) => {
6699
+ this.queryMembers = async (searchQuery, offset = 0, queryOptions = {}) => {
6626
6700
  const { filters, sort, options } = this.prepareQueryMembersParams(
6627
6701
  searchQuery,
6628
6702
  offset
6629
6703
  );
6630
- const response = await this.channel.queryMembers(filters, sort, options);
6704
+ const response = await this.channel.queryMembers(
6705
+ filters,
6706
+ sort,
6707
+ options,
6708
+ queryOptions
6709
+ );
6631
6710
  return response.members.map((member) => member.user);
6632
6711
  };
6633
- this.getUserSuggestionsPage = async (searchQuery, userOffset = 0) => {
6712
+ this.getUserSuggestionsPage = async (searchQuery, userOffset = 0, queryOptions = {}) => {
6634
6713
  if (!this.isMentionTypeAllowed("user")) {
6635
6714
  return {
6636
6715
  items: [],
@@ -6640,7 +6719,7 @@ var MentionsSearchSource = class extends BaseSearchSource {
6640
6719
  let users;
6641
6720
  const shouldSearchLocally = this.allMembersLoadedWithInitialChannelQuery || !searchQuery;
6642
6721
  if (this.config.mentionAllAppUsers) {
6643
- users = await this.queryUsers(searchQuery, userOffset);
6722
+ users = await this.queryUsers(searchQuery, userOffset, queryOptions);
6644
6723
  } else if (shouldSearchLocally) {
6645
6724
  const localUsers = this.searchMembersLocally(searchQuery);
6646
6725
  const items2 = localUsers.slice(userOffset, userOffset + this.pageSize).map((user) => this.toUserSuggestion(user, searchQuery));
@@ -6649,7 +6728,7 @@ var MentionsSearchSource = class extends BaseSearchSource {
6649
6728
  nextOffset: localUsers.length > userOffset + this.pageSize ? userOffset + items2.length : void 0
6650
6729
  };
6651
6730
  } else {
6652
- users = await this.queryMembers(searchQuery, userOffset);
6731
+ users = await this.queryMembers(searchQuery, userOffset, queryOptions);
6653
6732
  }
6654
6733
  const items = users.map((user) => this.toUserSuggestion(user, searchQuery));
6655
6734
  return {
@@ -6666,7 +6745,7 @@ var MentionsSearchSource = class extends BaseSearchSource {
6666
6745
  name_gt: lastItem.name
6667
6746
  });
6668
6747
  };
6669
- this.getUserGroupSuggestionsPage = async (searchQuery, cursor) => {
6748
+ this.getUserGroupSuggestionsPage = async (searchQuery, cursor, queryOptions = {}) => {
6670
6749
  if (!this.isMentionTypeAllowed("user_group")) {
6671
6750
  return {
6672
6751
  items: [],
@@ -6688,7 +6767,7 @@ var MentionsSearchSource = class extends BaseSearchSource {
6688
6767
  ...userGroupCursor?.id_gt ? { id_gt: userGroupCursor.id_gt } : {},
6689
6768
  ...userGroupCursor?.name_gt ? { name_gt: userGroupCursor.name_gt } : {}
6690
6769
  };
6691
- const { user_groups } = await this.client.searchUserGroups(options);
6770
+ const { user_groups } = await this.client.searchUserGroups(options, queryOptions);
6692
6771
  return {
6693
6772
  items: user_groups.map(
6694
6773
  (userGroup) => this.toUserGroupMentionSuggestion(userGroup, searchQuery)
@@ -6698,6 +6777,11 @@ var MentionsSearchSource = class extends BaseSearchSource {
6698
6777
  };
6699
6778
  this.client = channel.getClient();
6700
6779
  this.channel = channel;
6780
+ this.userFilters = userFilters;
6781
+ this.userSort = userSort;
6782
+ this.memberFilters = memberFilters;
6783
+ this.memberSort = memberSort;
6784
+ this.searchOptions = searchOptions;
6701
6785
  this.config = {
6702
6786
  mentionAllAppUsers,
6703
6787
  suggestionFactoryMappers,
@@ -6730,16 +6814,21 @@ var MentionsSearchSource = class extends BaseSearchSource {
6730
6814
  offset: (this.offset ?? 0) + userPaginationState.itemCount
6731
6815
  };
6732
6816
  }
6733
- async query(searchQuery) {
6817
+ async query(searchQuery, queryOptions = {}) {
6734
6818
  const userOffset = this.offset ?? 0;
6735
6819
  const isFirstPage = userOffset === 0 && typeof this.userGroupCursor === "undefined";
6736
6820
  const previousUserPaginationState = this.latestUserPaginationState;
6737
6821
  const previousUserGroupCursor = this.userGroupCursor;
6738
6822
  const [userResultsState, userGroupResultsState, roleSuggestionsState] = await Promise.allSettled([
6739
- this.getUserSuggestionsPage(searchQuery, userOffset),
6740
- this.getUserGroupSuggestionsPage(searchQuery, previousUserGroupCursor),
6741
- isFirstPage ? this.getRoleMentionSuggestions(searchQuery) : Promise.resolve([])
6823
+ this.getUserSuggestionsPage(searchQuery, userOffset, queryOptions),
6824
+ this.getUserGroupSuggestionsPage(
6825
+ searchQuery,
6826
+ previousUserGroupCursor,
6827
+ queryOptions
6828
+ ),
6829
+ isFirstPage ? this.getRoleMentionSuggestions(searchQuery, queryOptions) : Promise.resolve([])
6742
6830
  ]);
6831
+ if (queryOptions.signal?.aborted) return { items: [] };
6743
6832
  const userResults = userResultsState.status === "fulfilled" ? userResultsState.value : {
6744
6833
  items: [],
6745
6834
  nextOffset: isFirstPage ? void 0 : previousUserPaginationState?.nextOffset
@@ -9415,10 +9504,11 @@ var Channel = class {
9415
9504
  * @param {MemberSort} [sort] Sort options, for instance [{created_at: -1}].
9416
9505
  * When using multiple fields, make sure you use array of objects to guarantee field order, for instance [{name: -1}, {created_at: 1}]
9417
9506
  * @param {{ limit?: number; offset?: number }} [options] Option object, {limit: 10, offset:10}
9507
+ * @param {RequestOptions} [requestOptions] Carries an abort signal. Not sent in the request.
9418
9508
  *
9419
9509
  * @return {Promise<ChannelMemberAPIResponse>} Query Members response
9420
9510
  */
9421
- async queryMembers(filterConditions, sort = [], options = {}) {
9511
+ async queryMembers(filterConditions, sort = [], options = {}, requestOptions = {}) {
9422
9512
  let id;
9423
9513
  const type = this.type;
9424
9514
  let members;
@@ -9438,7 +9528,8 @@ var Channel = class {
9438
9528
  filter_conditions: filterConditions,
9439
9529
  ...options
9440
9530
  }
9441
- }
9531
+ },
9532
+ requestOptions
9442
9533
  );
9443
9534
  }
9444
9535
  /**
@@ -14570,6 +14661,7 @@ var StreamChat = class _StreamChat {
14570
14661
  return this.handleResponse(response);
14571
14662
  } catch (e) {
14572
14663
  e.client_request_id = requestConfig.headers?.["x-client-request-id"];
14664
+ if (import_axios3.default.isCancel(e)) throw e;
14573
14665
  this._logApiError(type, url, e);
14574
14666
  this.consecutiveFailures += 1;
14575
14667
  if (e.response) {
@@ -14881,7 +14973,7 @@ var StreamChat = class _StreamChat {
14881
14973
  return this.userAgent;
14882
14974
  }
14883
14975
  if (!this.cachedUserAgent) {
14884
- const version = "9.50.3";
14976
+ const version = "9.51.0";
14885
14977
  const { name: sdkName, version: sdkVersion } = this.sdkIdentifier ?? {};
14886
14978
  const { name: appName, version: appVersion } = this.appIdentifier ?? {};
14887
14979
  const { os, model: deviceModel } = this.deviceIdentifier ?? {};
@@ -15257,14 +15349,14 @@ var StreamChat = class _StreamChat {
15257
15349
  error
15258
15350
  });
15259
15351
  }
15260
- get(url, params) {
15261
- return this.doAxiosRequest("get", url, null, { params });
15352
+ get(url, params, config) {
15353
+ return this.doAxiosRequest("get", url, null, { params, config });
15262
15354
  }
15263
15355
  put(url, data) {
15264
15356
  return this.doAxiosRequest("put", url, data);
15265
15357
  }
15266
- post(url, data) {
15267
- return this.doAxiosRequest("post", url, data);
15358
+ post(url, data, config) {
15359
+ return this.doAxiosRequest("post", url, data, { config });
15268
15360
  }
15269
15361
  patch(url, data) {
15270
15362
  return this.doAxiosRequest("patch", url, data);
@@ -15459,10 +15551,11 @@ var StreamChat = class _StreamChat {
15459
15551
  * @param {UserSort} sort Sort options, for instance [{last_active: -1}].
15460
15552
  * When using multiple fields, make sure you use array of objects to guarantee field order, for instance [{last_active: -1}, {created_at: 1}]
15461
15553
  * @param {UserOptions} options Option object, {presence: true}
15554
+ * @param {RequestOptions} [requestOptions] Carries an abort signal. Not sent in the request.
15462
15555
  *
15463
15556
  * @return {Promise<{ users: Array<UserResponse> }>} User Query Response
15464
15557
  */
15465
- async queryUsers(filterConditions, sort = [], options = {}) {
15558
+ async queryUsers(filterConditions, sort = [], options = {}, requestOptions = {}) {
15466
15559
  const defaultOptions = {
15467
15560
  presence: false
15468
15561
  };
@@ -15479,7 +15572,8 @@ var StreamChat = class _StreamChat {
15479
15572
  ...defaultOptions,
15480
15573
  ...options
15481
15574
  }
15482
- }
15575
+ },
15576
+ requestOptions
15483
15577
  );
15484
15578
  this.state.updateUsers(data.users);
15485
15579
  return data;
@@ -15525,13 +15619,14 @@ var StreamChat = class _StreamChat {
15525
15619
  * searchUserGroups - Search user groups by prefix for autocomplete
15526
15620
  *
15527
15621
  * @param {SearchUserGroupsOptions} options The search options
15528
- *
15622
+ * @param {RequestOptions} [requestOptions] Carries an abort signal. Not sent in the request.
15529
15623
  * @return {Promise<SearchUserGroupsResponse>} User Group Search Response
15530
15624
  */
15531
- async searchUserGroups(options) {
15625
+ async searchUserGroups(options, requestOptions = {}) {
15532
15626
  return await this.get(
15533
15627
  this.baseURL + "/usergroups/search",
15534
- options
15628
+ options,
15629
+ requestOptions
15535
15630
  );
15536
15631
  }
15537
15632
  /**
@@ -15651,10 +15746,11 @@ var StreamChat = class _StreamChat {
15651
15746
  * @param {ChannelSort} [sort] Sort options, for instance {created_at: -1}.
15652
15747
  * When using multiple fields, make sure you use array of objects to guarantee field order, for instance [{last_updated: -1}, {created_at: 1}]
15653
15748
  * @param {ChannelOptions} [options] Options object. Can include predefined_filter, filter_values, and sort_values for using predefined filters.
15749
+ * @param {RequestOptions} [requestOptions] Carries an abort signal. Not sent in the request.
15654
15750
  *
15655
15751
  * @return {Promise<QueryChannelsAPIResponse>} full search channels response
15656
15752
  */
15657
- async queryChannelsRequestWithResponse(filterConditions, sort = [], options = {}) {
15753
+ async queryChannelsRequestWithResponse(filterConditions, sort = [], options = {}, requestOptions = {}) {
15658
15754
  const defaultOptions = {
15659
15755
  state: true,
15660
15756
  watch: true,
@@ -15679,7 +15775,11 @@ var StreamChat = class _StreamChat {
15679
15775
  ...defaultOptions,
15680
15776
  ...restOptions
15681
15777
  };
15682
- return await this.post(this.baseURL + "/channels", payload);
15778
+ return await this.post(
15779
+ this.baseURL + "/channels",
15780
+ payload,
15781
+ requestOptions
15782
+ );
15683
15783
  }
15684
15784
  /**
15685
15785
  * queryChannelsRequest - Queries channels and returns the raw channel response list.
@@ -15708,7 +15808,9 @@ var StreamChat = class _StreamChat {
15708
15808
  const queryChannelsResponse = await this.queryChannelsRequestWithResponse(
15709
15809
  filterConditions,
15710
15810
  sort,
15711
- options
15811
+ options,
15812
+ // stateOptions is never serialized, so it carries the abort signal
15813
+ { signal: stateOptions.signal }
15712
15814
  );
15713
15815
  const channels = queryChannelsResponse.channels;
15714
15816
  this.dispatchEvent({
@@ -15825,10 +15927,11 @@ var StreamChat = class _StreamChat {
15825
15927
  * @param {ChannelFilters} filterConditions MongoDB style filter conditions
15826
15928
  * @param {MessageFilters | string} query search query or object MongoDB style filters
15827
15929
  * @param {SearchOptions} [options] Option object, {user_id: 'tommaso'}
15930
+ * @param {RequestOptions} [requestOptions] Carries an abort signal. Not sent in the request.
15828
15931
  *
15829
15932
  * @return {Promise<SearchAPIResponse>} search messages response
15830
15933
  */
15831
- async search(filterConditions, query, options = {}) {
15934
+ async search(filterConditions, query, options = {}, requestOptions = {}) {
15832
15935
  if (options.offset && options.next) {
15833
15936
  throw Error(`Cannot specify offset with next`);
15834
15937
  }
@@ -15845,7 +15948,11 @@ var StreamChat = class _StreamChat {
15845
15948
  throw Error(`Invalid type ${typeof query} for query parameter`);
15846
15949
  }
15847
15950
  await this.wsPromise;
15848
- return await this.get(this.baseURL + "/search", { payload });
15951
+ return await this.get(
15952
+ this.baseURL + "/search",
15953
+ { payload },
15954
+ requestOptions
15955
+ );
15849
15956
  }
15850
15957
  /**
15851
15958
  * setLocalDevice - Set the device info for the current client(device) that will be sent via WS connection automatically
@@ -16882,6 +16989,7 @@ var StreamChat = class _StreamChat {
16882
16989
  headers: axiosRequestConfigHeaders,
16883
16990
  ...axiosRequestConfigRest
16884
16991
  } = this.options.axiosRequestConfig || {};
16992
+ const resolvedSignal = options.config?.signal ?? axiosRequestConfigRest.signal ?? signal;
16885
16993
  return {
16886
16994
  params: {
16887
16995
  user_id: this.userID,
@@ -16897,9 +17005,9 @@ var StreamChat = class _StreamChat {
16897
17005
  ...options.headers,
16898
17006
  ...axiosRequestConfigHeaders || {}
16899
17007
  },
16900
- ...signal ? { signal } : {},
16901
17008
  ...options.config,
16902
- ...axiosRequestConfigRest || {}
17009
+ ...axiosRequestConfigRest,
17010
+ ...resolvedSignal ? { signal: resolvedSignal } : {}
16903
17011
  };
16904
17012
  }
16905
17013
  _getToken() {
@@ -17039,8 +17147,12 @@ var StreamChat = class _StreamChat {
17039
17147
  *
17040
17148
  * @returns {Promise<APIResponse>}
17041
17149
  */
17042
- searchRoles(options) {
17043
- return this.get(`${this.baseURL}/roles/search`, options);
17150
+ searchRoles(options, requestOptions = {}) {
17151
+ return this.get(
17152
+ `${this.baseURL}/roles/search`,
17153
+ options,
17154
+ requestOptions
17155
+ );
17044
17156
  }
17045
17157
  /** deleteRole - deletes a custom role
17046
17158
  *
@@ -18397,7 +18509,8 @@ var import_axios4 = require("axios");
18397
18509
  var OfflineDBSyncManager = class {
18398
18510
  constructor({
18399
18511
  client,
18400
- offlineDb
18512
+ offlineDb,
18513
+ syncMaxEventCount
18401
18514
  }) {
18402
18515
  this.syncStatus = false;
18403
18516
  this.connectionChangedListener = null;
@@ -18514,13 +18627,23 @@ var OfflineDBSyncManager = class {
18514
18627
  await this.offlineDb.resetDB();
18515
18628
  } else {
18516
18629
  const result = await this.client.sync(cids, lastSyncedAtDate.toISOString());
18517
- const queryPromises = result.events.map(
18518
- (event) => this.offlineDb.handleEvent({ event, execute: false })
18519
- );
18520
- const queriesArray = await Promise.all(queryPromises);
18521
- const queries = queriesArray.flat();
18522
- if (queries.length) {
18523
- await this.offlineDb.executeSqlBatch(queries);
18630
+ const { syncMaxEventCount } = this;
18631
+ const exceedsLimit = typeof syncMaxEventCount === "number" && syncMaxEventCount > 0 && result.events.length > syncMaxEventCount;
18632
+ if (exceedsLimit) {
18633
+ this.client.logger(
18634
+ "warn",
18635
+ `Skipping sync event replay: received ${result.events.length} events, which exceeds the configured limit of ${syncMaxEventCount}. Visible channels are refreshed on reconnect instead.`,
18636
+ { tags: ["sync", "offline"] }
18637
+ );
18638
+ } else {
18639
+ const queryPromises = result.events.map(
18640
+ (event) => this.offlineDb.handleEvent({ event, execute: false })
18641
+ );
18642
+ const queriesArray = await Promise.all(queryPromises);
18643
+ const queries = queriesArray.flat();
18644
+ if (queries.length) {
18645
+ await this.offlineDb.executeSqlBatch(queries);
18646
+ }
18524
18647
  }
18525
18648
  }
18526
18649
  }
@@ -18564,12 +18687,16 @@ var OfflineDBSyncManager = class {
18564
18687
  };
18565
18688
  this.client = client;
18566
18689
  this.offlineDb = offlineDb;
18690
+ this.syncMaxEventCount = syncMaxEventCount;
18567
18691
  }
18568
18692
  };
18569
18693
 
18570
18694
  // src/offline-support/offline_support_api.ts
18571
18695
  var AbstractOfflineDB = class {
18572
- constructor({ client }) {
18696
+ constructor({
18697
+ client,
18698
+ syncMaxEventCount
18699
+ }) {
18573
18700
  /**
18574
18701
  * Initializes the DB as well as its syncManager for a given userId.
18575
18702
  * It will update the DBs reactive state with initialization values.
@@ -19259,7 +19386,11 @@ var AbstractOfflineDB = class {
19259
19386
  }
19260
19387
  };
19261
19388
  this.client = client;
19262
- this.syncManager = new OfflineDBSyncManager({ client, offlineDb: this });
19389
+ this.syncManager = new OfflineDBSyncManager({
19390
+ client,
19391
+ offlineDb: this,
19392
+ syncMaxEventCount
19393
+ });
19263
19394
  this.state = new StateStore({
19264
19395
  initialized: false,
19265
19396
  userId: this.client.userID