stream-chat 9.3.0 → 9.5.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 (53) hide show
  1. package/dist/cjs/index.browser.cjs +843 -146
  2. package/dist/cjs/index.browser.cjs.map +4 -4
  3. package/dist/cjs/index.node.cjs +859 -152
  4. package/dist/cjs/index.node.cjs.map +4 -4
  5. package/dist/esm/index.js +846 -149
  6. package/dist/esm/index.js.map +4 -4
  7. package/dist/types/client.d.ts +52 -19
  8. package/dist/types/events.d.ts +4 -0
  9. package/dist/types/index.d.ts +3 -1
  10. package/dist/types/messageComposer/middleware/textComposer/commands.d.ts +2 -2
  11. package/dist/types/messageComposer/middleware/textComposer/mentions.d.ts +2 -2
  12. package/dist/types/messageComposer/middleware/textComposer/types.d.ts +1 -1
  13. package/dist/types/pagination/BasePaginator.d.ts +69 -0
  14. package/dist/types/pagination/ReminderPaginator.d.ts +12 -0
  15. package/dist/types/pagination/index.d.ts +2 -0
  16. package/dist/types/reminders/Reminder.d.ts +37 -0
  17. package/dist/types/reminders/ReminderManager.d.ts +65 -0
  18. package/dist/types/reminders/ReminderTimer.d.ts +17 -0
  19. package/dist/types/reminders/index.d.ts +3 -0
  20. package/dist/types/search/BaseSearchSource.d.ts +87 -0
  21. package/dist/types/search/ChannelSearchSource.d.ts +17 -0
  22. package/dist/types/search/MessageSearchSource.d.ts +23 -0
  23. package/dist/types/search/SearchController.d.ts +44 -0
  24. package/dist/types/search/UserSearchSource.d.ts +16 -0
  25. package/dist/types/search/index.d.ts +5 -0
  26. package/dist/types/store.d.ts +114 -5
  27. package/dist/types/types.d.ts +48 -3
  28. package/package.json +4 -4
  29. package/src/channel.ts +2 -1
  30. package/src/client.ts +108 -39
  31. package/src/events.ts +6 -0
  32. package/src/index.ts +3 -1
  33. package/src/messageComposer/middleware/textComposer/commands.ts +2 -2
  34. package/src/messageComposer/middleware/textComposer/mentions.ts +2 -2
  35. package/src/messageComposer/middleware/textComposer/types.ts +1 -1
  36. package/src/pagination/BasePaginator.ts +184 -0
  37. package/src/pagination/ReminderPaginator.ts +38 -0
  38. package/src/pagination/index.ts +2 -0
  39. package/src/reminders/Reminder.ts +89 -0
  40. package/src/reminders/ReminderManager.ts +284 -0
  41. package/src/reminders/ReminderTimer.ts +86 -0
  42. package/src/reminders/index.ts +3 -0
  43. package/src/search/BaseSearchSource.ts +227 -0
  44. package/src/search/ChannelSearchSource.ts +34 -0
  45. package/src/search/MessageSearchSource.ts +88 -0
  46. package/src/search/SearchController.ts +154 -0
  47. package/src/search/UserSearchSource.ts +35 -0
  48. package/src/search/index.ts +5 -0
  49. package/src/store.ts +237 -11
  50. package/src/token_manager.ts +3 -1
  51. package/src/types.ts +91 -1
  52. package/dist/types/search_controller.d.ts +0 -174
  53. package/src/search_controller.ts +0 -523
@@ -159,6 +159,7 @@ __export(index_exports, {
159
159
  AnyResource: () => AnyResource,
160
160
  AnyRole: () => AnyRole,
161
161
  AttachmentManager: () => AttachmentManager,
162
+ BasePaginator: () => BasePaginator,
162
163
  BaseSearchSource: () => BaseSearchSource,
163
164
  BuiltinPermissions: () => BuiltinPermissions,
164
165
  BuiltinRoles: () => BuiltinRoles,
@@ -176,6 +177,9 @@ __export(index_exports, {
176
177
  DEFAULT_CHANNEL_MANAGER_PAGINATION_OPTIONS: () => DEFAULT_CHANNEL_MANAGER_PAGINATION_OPTIONS,
177
178
  DEFAULT_COMPOSER_CONFIG: () => DEFAULT_COMPOSER_CONFIG,
178
179
  DEFAULT_LINK_PREVIEW_MANAGER_CONFIG: () => DEFAULT_LINK_PREVIEW_MANAGER_CONFIG,
180
+ DEFAULT_PAGINATION_OPTIONS: () => DEFAULT_PAGINATION_OPTIONS,
181
+ DEFAULT_REMINDER_MANAGER_CONFIG: () => DEFAULT_REMINDER_MANAGER_CONFIG,
182
+ DEFAULT_STOP_REFRESH_BOUNDARY_MS: () => DEFAULT_STOP_REFRESH_BOUNDARY_MS,
179
183
  DEFAULT_TEXT_COMPOSER_CONFIG: () => DEFAULT_TEXT_COMPOSER_CONFIG,
180
184
  Deny: () => Deny,
181
185
  DenyAll: () => DenyAll,
@@ -192,6 +196,7 @@ __export(index_exports, {
192
196
  MODERATION_ENTITY_TYPES: () => MODERATION_ENTITY_TYPES,
193
197
  MaxPriority: () => MaxPriority,
194
198
  MentionsSearchSource: () => MentionsSearchSource,
199
+ MergedStateStore: () => MergedStateStore,
195
200
  MessageComposer: () => MessageComposer,
196
201
  MessageComposerMiddlewareExecutor: () => MessageComposerMiddlewareExecutor,
197
202
  MessageDraftComposerMiddlewareExecutor: () => MessageDraftComposerMiddlewareExecutor,
@@ -207,6 +212,10 @@ __export(index_exports, {
207
212
  PollComposerCompositionMiddlewareExecutor: () => PollComposerCompositionMiddlewareExecutor,
208
213
  PollComposerStateMiddlewareExecutor: () => PollComposerStateMiddlewareExecutor,
209
214
  PollManager: () => PollManager,
215
+ Reminder: () => Reminder,
216
+ ReminderManager: () => ReminderManager,
217
+ ReminderPaginator: () => ReminderPaginator,
218
+ ReminderTimer: () => ReminderTimer,
210
219
  SearchController: () => SearchController,
211
220
  Segment: () => Segment,
212
221
  StableWSConnection: () => StableWSConnection,
@@ -294,7 +303,8 @@ __export(index_exports, {
294
303
  readFileAsArrayBuffer: () => readFileAsArrayBuffer,
295
304
  removeDiacritics: () => removeDiacritics,
296
305
  replaceWordWithEntity: () => replaceWordWithEntity,
297
- textIsEmpty: () => textIsEmpty
306
+ textIsEmpty: () => textIsEmpty,
307
+ timeLeftMs: () => timeLeftMs
298
308
  });
299
309
  module.exports = __toCommonJS(index_exports);
300
310
 
@@ -4048,26 +4058,14 @@ var ensureIsLocalAttachment = (attachment) => {
4048
4058
 
4049
4059
  // src/store.ts
4050
4060
  var isPatch = (value) => typeof value === "function";
4061
+ var noop2 = () => {
4062
+ };
4051
4063
  var StateStore = class {
4052
4064
  constructor(value) {
4053
4065
  this.value = value;
4054
- this.handlerSet = /* @__PURE__ */ new Set();
4055
- this.next = (newValueOrPatch) => {
4056
- const newValue = isPatch(newValueOrPatch) ? newValueOrPatch(this.value) : newValueOrPatch;
4057
- if (newValue === this.value) return;
4058
- const oldValue = this.value;
4059
- this.value = newValue;
4060
- this.handlerSet.forEach((handler) => handler(this.value, oldValue));
4061
- };
4066
+ this.handlers = /* @__PURE__ */ new Set();
4067
+ this.preprocessors = /* @__PURE__ */ new Set();
4062
4068
  this.partialNext = (partial) => this.next((current) => ({ ...current, ...partial }));
4063
- this.getLatestValue = () => this.value;
4064
- this.subscribe = (handler) => {
4065
- handler(this.value, void 0);
4066
- this.handlerSet.add(handler);
4067
- return () => {
4068
- this.handlerSet.delete(handler);
4069
- };
4070
- };
4071
4069
  this.subscribeWithSelector = (selector, handler) => {
4072
4070
  let previouslySelectedValues;
4073
4071
  const wrappedHandler = (nextValue) => {
@@ -4086,6 +4084,183 @@ var StateStore = class {
4086
4084
  return this.subscribe(wrappedHandler);
4087
4085
  };
4088
4086
  }
4087
+ /**
4088
+ * Allows merging two stores only if their keys differ otherwise there's no way to ensure the data type stability.
4089
+ * @experimental
4090
+ * This method is experimental and may change in future versions.
4091
+ */
4092
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4093
+ merge(stateStore) {
4094
+ return new MergedStateStore({
4095
+ original: this,
4096
+ merged: stateStore
4097
+ });
4098
+ }
4099
+ next(newValueOrPatch) {
4100
+ const newValue = isPatch(newValueOrPatch) ? newValueOrPatch(this.value) : newValueOrPatch;
4101
+ if (newValue === this.value) return;
4102
+ this.preprocessors.forEach((preprocessor) => preprocessor(newValue, this.value));
4103
+ const oldValue = this.value;
4104
+ this.value = newValue;
4105
+ this.handlers.forEach((handler) => handler(this.value, oldValue));
4106
+ }
4107
+ getLatestValue() {
4108
+ return this.value;
4109
+ }
4110
+ subscribe(handler) {
4111
+ handler(this.value, void 0);
4112
+ this.handlers.add(handler);
4113
+ return () => {
4114
+ this.handlers.delete(handler);
4115
+ };
4116
+ }
4117
+ /**
4118
+ * Registers a preprocessor function that will be called before the state is updated.
4119
+ *
4120
+ * Preprocessors are invoked with the new and previous values whenever `next` or `partialNext` methods
4121
+ * are called, allowing you to mutate or react to the new value before it is set. Preprocessors run in the
4122
+ * order they were registered.
4123
+ *
4124
+ * @example
4125
+ * ```ts
4126
+ * const store = new StateStore<{ count: number; isMaxValue: bool; }>({ count: 0, isMaxValue: false });
4127
+ *
4128
+ * store.addPreprocessor((nextValue, prevValue) => {
4129
+ * if (nextValue.count > 10) {
4130
+ * nextValue.count = 10; // Clamp the value to a maximum of 10
4131
+ * }
4132
+ *
4133
+ * if (nextValue.count === 10) {
4134
+ * nextValue.isMaxValue = true; // Set isMaxValue to true if count is 10
4135
+ * } else {
4136
+ * nextValue.isMaxValue = false; // Reset isMaxValue otherwise
4137
+ * }
4138
+ * });
4139
+ *
4140
+ * store.partialNext({ count: 15 });
4141
+ *
4142
+ * store.getLatestValue(); // { count: 10, isMaxValue: true }
4143
+ *
4144
+ * store.partialNext({ count: 5 });
4145
+ *
4146
+ * store.getLatestValue(); // { count: 5, isMaxValue: false }
4147
+ * ```
4148
+ *
4149
+ * @param preprocessor - The function to be called with the next and previous values before the state is updated.
4150
+ * @returns A `RemovePreprocessor` function that removes the preprocessor when called.
4151
+ */
4152
+ addPreprocessor(preprocessor) {
4153
+ this.preprocessors.add(preprocessor);
4154
+ return () => {
4155
+ this.preprocessors.delete(preprocessor);
4156
+ };
4157
+ }
4158
+ };
4159
+ var MergedStateStore = class _MergedStateStore extends StateStore {
4160
+ constructor({ original, merged }) {
4161
+ const originalValue = original.getLatestValue();
4162
+ const mergedValue = merged.getLatestValue();
4163
+ super({
4164
+ ...originalValue,
4165
+ ...mergedValue
4166
+ });
4167
+ // override original methods and "disable" them
4168
+ this.next = () => {
4169
+ console.warn(
4170
+ `${_MergedStateStore.name}.next is disabled, call original.next or merged.next instead`
4171
+ );
4172
+ };
4173
+ this.partialNext = () => {
4174
+ console.warn(
4175
+ `${_MergedStateStore.name}.partialNext is disabled, call original.partialNext or merged.partialNext instead`
4176
+ );
4177
+ };
4178
+ this.cachedOriginalValue = originalValue;
4179
+ this.cachedMergedValue = mergedValue;
4180
+ this.original = original;
4181
+ this.merged = merged;
4182
+ }
4183
+ /**
4184
+ * Subscribes to changes in the merged state store.
4185
+ *
4186
+ * This method extends the base subscribe functionality to handle the merged nature of this store:
4187
+ * 1. The first subscriber triggers registration of helper subscribers that listen to both source stores
4188
+ * 2. Changes from either source store are propagated to this merged store
4189
+ * 3. Source store values are cached to prevent unnecessary updates
4190
+ *
4191
+ * When the first subscriber is added, the method sets up listeners on both original and merged stores.
4192
+ * These listeners update the combined store value whenever either source store changes.
4193
+ * All subscriptions (helpers and the actual handler) are tracked so they can be properly cleaned up.
4194
+ *
4195
+ * @param handler - The callback function that will be executed when the state changes
4196
+ * @returns An unsubscribe function that, when called, removes the subscription and any helper subscriptions
4197
+ */
4198
+ subscribe(handler) {
4199
+ const unsubscribeFunctions = [];
4200
+ if (!this.handlers.size) {
4201
+ const base = (nextValue) => {
4202
+ super.next((currentValue) => ({
4203
+ ...currentValue,
4204
+ ...nextValue
4205
+ }));
4206
+ };
4207
+ unsubscribeFunctions.push(
4208
+ this.original.subscribe((nextValue) => {
4209
+ if (nextValue === this.cachedOriginalValue) return;
4210
+ this.cachedOriginalValue = nextValue;
4211
+ base(nextValue);
4212
+ }),
4213
+ this.merged.subscribe((nextValue) => {
4214
+ if (nextValue === this.cachedMergedValue) return;
4215
+ this.cachedMergedValue = nextValue;
4216
+ base(nextValue);
4217
+ })
4218
+ );
4219
+ }
4220
+ unsubscribeFunctions.push(super.subscribe(handler));
4221
+ return () => {
4222
+ unsubscribeFunctions.forEach((unsubscribe) => unsubscribe());
4223
+ };
4224
+ }
4225
+ /**
4226
+ * Retrieves the latest combined state from both original and merged stores.
4227
+ *
4228
+ * This method extends the base getLatestValue functionality to ensure the merged store
4229
+ * remains in sync with its source stores even when there are no active subscribers.
4230
+ *
4231
+ * When there are no handlers registered, the method:
4232
+ * 1. Fetches the latest values from both source stores
4233
+ * 2. Compares them with the cached values to detect changes
4234
+ * 3. If changes are detected, updates the internal value and caches
4235
+ * the new source values to maintain consistency
4236
+ *
4237
+ * This approach ensures that calling getLatestValue() always returns the most
4238
+ * up-to-date combined state, even if the merged store hasn't been actively
4239
+ * receiving updates through subscriptions.
4240
+ *
4241
+ * @returns The latest combined state from both original and merged stores
4242
+ */
4243
+ getLatestValue() {
4244
+ if (!this.handlers.size) {
4245
+ const originalValue = this.original.getLatestValue();
4246
+ const mergedValue = this.merged.getLatestValue();
4247
+ if (originalValue !== this.cachedOriginalValue || mergedValue !== this.cachedMergedValue) {
4248
+ this.value = {
4249
+ ...originalValue,
4250
+ ...mergedValue
4251
+ };
4252
+ this.cachedMergedValue = mergedValue;
4253
+ this.cachedOriginalValue = originalValue;
4254
+ }
4255
+ }
4256
+ return super.getLatestValue();
4257
+ }
4258
+ addPreprocessor() {
4259
+ console.warn(
4260
+ `${_MergedStateStore.name}.addPreprocessor is disabled, call original.addPreprocessor or merged.addPreprocessor instead`
4261
+ );
4262
+ return noop2;
4263
+ }
4089
4264
  };
4090
4265
 
4091
4266
  // src/utils/mergeWith/mergeWithCore.ts
@@ -5505,7 +5680,9 @@ var ErrorFromResponse = class extends Error {
5505
5680
  return {
5506
5681
  message: `(${joinable.join(", ")}) - ${this.message}`,
5507
5682
  stack: this.stack,
5508
- name: this.name
5683
+ name: this.name,
5684
+ code: this.code,
5685
+ status: this.status
5509
5686
  };
5510
5687
  }
5511
5688
  };
@@ -6073,7 +6250,7 @@ var MessageDraftComposerMiddlewareExecutor = class extends MiddlewareExecutor {
6073
6250
  }
6074
6251
  };
6075
6252
 
6076
- // src/search_controller.ts
6253
+ // src/search/BaseSearchSource.ts
6077
6254
  var DEFAULT_SEARCH_SOURCE_OPTIONS = {
6078
6255
  debounceMs: 300,
6079
6256
  pageSize: 10
@@ -6199,6 +6376,112 @@ var BaseSearchSource = class {
6199
6376
  this.activate();
6200
6377
  }
6201
6378
  };
6379
+
6380
+ // src/search/SearchController.ts
6381
+ var SearchController = class {
6382
+ constructor({ config, sources } = {}) {
6383
+ this.addSource = (source) => {
6384
+ this.state.partialNext({
6385
+ sources: [...this.sources, source]
6386
+ });
6387
+ };
6388
+ this.getSource = (sourceType) => this.sources.find((s) => s.type === sourceType);
6389
+ this.removeSource = (sourceType) => {
6390
+ const newSources = this.sources.filter((s) => s.type !== sourceType);
6391
+ if (newSources.length === this.sources.length) return;
6392
+ this.state.partialNext({ sources: newSources });
6393
+ };
6394
+ this.activateSource = (sourceType) => {
6395
+ const source = this.getSource(sourceType);
6396
+ if (!source || source.isActive) return;
6397
+ if (this.config.keepSingleActiveSource) {
6398
+ this.sources.forEach((s) => {
6399
+ if (s.type !== sourceType) {
6400
+ s.deactivate();
6401
+ }
6402
+ });
6403
+ }
6404
+ source.activate();
6405
+ this.state.partialNext({ sources: [...this.sources] });
6406
+ };
6407
+ this.deactivateSource = (sourceType) => {
6408
+ const source = this.getSource(sourceType);
6409
+ if (!source?.isActive) return;
6410
+ if (this.activeSources.length === 1) return;
6411
+ source.deactivate();
6412
+ this.state.partialNext({ sources: [...this.sources] });
6413
+ };
6414
+ this.activate = () => {
6415
+ if (!this.activeSources.length) {
6416
+ const sourcesToActivate = this.config.keepSingleActiveSource ? this.sources.slice(0, 1) : this.sources;
6417
+ sourcesToActivate.forEach((s) => s.activate());
6418
+ }
6419
+ if (this.isActive) return;
6420
+ this.state.partialNext({ isActive: true });
6421
+ };
6422
+ this.search = async (searchQuery) => {
6423
+ const searchedSources = this.activeSources;
6424
+ this.state.partialNext({
6425
+ searchQuery
6426
+ });
6427
+ await Promise.all(searchedSources.map((source) => source.search(searchQuery)));
6428
+ };
6429
+ this.cancelSearchQueries = () => {
6430
+ this.activeSources.forEach((s) => s.cancelScheduledQuery());
6431
+ };
6432
+ this.clear = () => {
6433
+ this.cancelSearchQueries();
6434
+ this.sources.forEach(
6435
+ (source) => source.state.next({ ...source.initialState, isActive: source.isActive })
6436
+ );
6437
+ this.state.next((current) => ({
6438
+ ...current,
6439
+ isActive: true,
6440
+ queriesInProgress: [],
6441
+ searchQuery: ""
6442
+ }));
6443
+ };
6444
+ this.exit = () => {
6445
+ this.cancelSearchQueries();
6446
+ this.sources.forEach(
6447
+ (source) => source.state.next({ ...source.initialState, isActive: source.isActive })
6448
+ );
6449
+ this.state.next((current) => ({
6450
+ ...current,
6451
+ isActive: false,
6452
+ queriesInProgress: [],
6453
+ searchQuery: ""
6454
+ }));
6455
+ };
6456
+ this.state = new StateStore({
6457
+ isActive: false,
6458
+ searchQuery: "",
6459
+ sources: sources ?? []
6460
+ });
6461
+ this._internalState = new StateStore({});
6462
+ this.config = { keepSingleActiveSource: true, ...config };
6463
+ }
6464
+ get hasNext() {
6465
+ return this.sources.some((source) => source.hasNext);
6466
+ }
6467
+ get sources() {
6468
+ return this.state.getLatestValue().sources;
6469
+ }
6470
+ get activeSources() {
6471
+ return this.state.getLatestValue().sources.filter((s) => s.isActive);
6472
+ }
6473
+ get isActive() {
6474
+ return this.state.getLatestValue().isActive;
6475
+ }
6476
+ get searchQuery() {
6477
+ return this.state.getLatestValue().searchQuery;
6478
+ }
6479
+ get searchSourceTypes() {
6480
+ return this.sources.map((s) => s.type);
6481
+ }
6482
+ };
6483
+
6484
+ // src/search/UserSearchSource.ts
6202
6485
  var UserSearchSource = class extends BaseSearchSource {
6203
6486
  constructor(client, options) {
6204
6487
  super(options);
@@ -6222,6 +6505,8 @@ var UserSearchSource = class extends BaseSearchSource {
6222
6505
  return items.filter((u) => u.id !== this.client.user?.id);
6223
6506
  }
6224
6507
  };
6508
+
6509
+ // src/search/ChannelSearchSource.ts
6225
6510
  var ChannelSearchSource = class extends BaseSearchSource {
6226
6511
  constructor(client, options) {
6227
6512
  super(options);
@@ -6243,6 +6528,8 @@ var ChannelSearchSource = class extends BaseSearchSource {
6243
6528
  return items;
6244
6529
  }
6245
6530
  };
6531
+
6532
+ // src/search/MessageSearchSource.ts
6246
6533
  var MessageSearchSource = class extends BaseSearchSource {
6247
6534
  constructor(client, options) {
6248
6535
  super(options);
@@ -6303,108 +6590,6 @@ var MessageSearchSource = class extends BaseSearchSource {
6303
6590
  return items;
6304
6591
  }
6305
6592
  };
6306
- var SearchController = class {
6307
- constructor({ config, sources } = {}) {
6308
- this.addSource = (source) => {
6309
- this.state.partialNext({
6310
- sources: [...this.sources, source]
6311
- });
6312
- };
6313
- this.getSource = (sourceType) => this.sources.find((s) => s.type === sourceType);
6314
- this.removeSource = (sourceType) => {
6315
- const newSources = this.sources.filter((s) => s.type !== sourceType);
6316
- if (newSources.length === this.sources.length) return;
6317
- this.state.partialNext({ sources: newSources });
6318
- };
6319
- this.activateSource = (sourceType) => {
6320
- const source = this.getSource(sourceType);
6321
- if (!source || source.isActive) return;
6322
- if (this.config.keepSingleActiveSource) {
6323
- this.sources.forEach((s) => {
6324
- if (s.type !== sourceType) {
6325
- s.deactivate();
6326
- }
6327
- });
6328
- }
6329
- source.activate();
6330
- this.state.partialNext({ sources: [...this.sources] });
6331
- };
6332
- this.deactivateSource = (sourceType) => {
6333
- const source = this.getSource(sourceType);
6334
- if (!source?.isActive) return;
6335
- if (this.activeSources.length === 1) return;
6336
- source.deactivate();
6337
- this.state.partialNext({ sources: [...this.sources] });
6338
- };
6339
- this.activate = () => {
6340
- if (!this.activeSources.length) {
6341
- const sourcesToActivate = this.config.keepSingleActiveSource ? this.sources.slice(0, 1) : this.sources;
6342
- sourcesToActivate.forEach((s) => s.activate());
6343
- }
6344
- if (this.isActive) return;
6345
- this.state.partialNext({ isActive: true });
6346
- };
6347
- this.search = async (searchQuery) => {
6348
- const searchedSources = this.activeSources;
6349
- this.state.partialNext({
6350
- searchQuery
6351
- });
6352
- await Promise.all(searchedSources.map((source) => source.search(searchQuery)));
6353
- };
6354
- this.cancelSearchQueries = () => {
6355
- this.activeSources.forEach((s) => s.cancelScheduledQuery());
6356
- };
6357
- this.clear = () => {
6358
- this.cancelSearchQueries();
6359
- this.sources.forEach(
6360
- (source) => source.state.next({ ...source.initialState, isActive: source.isActive })
6361
- );
6362
- this.state.next((current) => ({
6363
- ...current,
6364
- isActive: true,
6365
- queriesInProgress: [],
6366
- searchQuery: ""
6367
- }));
6368
- };
6369
- this.exit = () => {
6370
- this.cancelSearchQueries();
6371
- this.sources.forEach(
6372
- (source) => source.state.next({ ...source.initialState, isActive: source.isActive })
6373
- );
6374
- this.state.next((current) => ({
6375
- ...current,
6376
- isActive: false,
6377
- queriesInProgress: [],
6378
- searchQuery: ""
6379
- }));
6380
- };
6381
- this.state = new StateStore({
6382
- isActive: false,
6383
- searchQuery: "",
6384
- sources: sources ?? []
6385
- });
6386
- this._internalState = new StateStore({});
6387
- this.config = { keepSingleActiveSource: true, ...config };
6388
- }
6389
- get hasNext() {
6390
- return this.sources.some((source) => source.hasNext);
6391
- }
6392
- get sources() {
6393
- return this.state.getLatestValue().sources;
6394
- }
6395
- get activeSources() {
6396
- return this.state.getLatestValue().sources.filter((s) => s.isActive);
6397
- }
6398
- get isActive() {
6399
- return this.state.getLatestValue().isActive;
6400
- }
6401
- get searchQuery() {
6402
- return this.state.getLatestValue().searchQuery;
6403
- }
6404
- get searchSourceTypes() {
6405
- return this.sources.map((s) => s.type);
6406
- }
6407
- };
6408
6593
 
6409
6594
  // src/messageComposer/middleware/textComposer/textMiddlewareUtils.ts
6410
6595
  var getTriggerCharWithToken = ({
@@ -7638,7 +7823,7 @@ var initState5 = (composition) => {
7638
7823
  pollId: message.poll_id ?? null
7639
7824
  };
7640
7825
  };
7641
- var noop2 = () => void 0;
7826
+ var noop3 = () => void 0;
7642
7827
  var _MessageComposer = class _MessageComposer extends WithSubscriptions {
7643
7828
  // todo: mediaRecorder: MediaRecorderController;
7644
7829
  constructor({
@@ -7666,7 +7851,7 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
7666
7851
  this.initEditingAuditState = (composition) => initEditingAuditState(composition);
7667
7852
  this.registerSubscriptions = () => {
7668
7853
  if (this.hasSubscriptions) {
7669
- return noop2;
7854
+ return noop3;
7670
7855
  }
7671
7856
  this.addUnsubscribeFunction(this.subscribeMessageComposerSetupStateChange());
7672
7857
  this.addUnsubscribeFunction(this.subscribeMessageUpdated());
@@ -9183,6 +9368,7 @@ var Channel = class {
9183
9368
  })
9184
9369
  };
9185
9370
  this.getClient().polls.hydratePollCache(state.messages, true);
9371
+ this.getClient().reminders.hydrateState(state.messages);
9186
9372
  if (state.draft) {
9187
9373
  this.messageComposer.initState({ composition: state.draft });
9188
9374
  }
@@ -10474,7 +10660,9 @@ var TokenManager = class {
10474
10660
  try {
10475
10661
  this.token = await this.tokenProvider();
10476
10662
  } catch (e) {
10477
- return reject(new Error(`Call to tokenProvider failed with message: ${e}`));
10663
+ return reject(
10664
+ new Error(`Call to tokenProvider failed with message: ${e}`, { cause: e })
10665
+ );
10478
10666
  }
10479
10667
  resolve(this.token);
10480
10668
  }
@@ -12224,6 +12412,458 @@ var NotificationManager = class {
12224
12412
  }
12225
12413
  };
12226
12414
 
12415
+ // src/reminders/ReminderTimer.ts
12416
+ var oneMinute = 60 * 1e3;
12417
+ var oneHour = 60 * oneMinute;
12418
+ var oneDay = 24 * oneHour;
12419
+ var oneWeek = 7 * oneDay;
12420
+ var GROUP_BOUNDS = {
12421
+ minute: { lower: oneMinute, upper: oneHour },
12422
+ hour: { lower: oneHour, upper: oneDay },
12423
+ day: { lower: oneDay, upper: oneWeek }
12424
+ };
12425
+ var DEFAULT_STOP_REFRESH_BOUNDARY_MS = 2 * oneWeek;
12426
+ var ReminderTimer = class {
12427
+ constructor({
12428
+ reminder,
12429
+ config
12430
+ }) {
12431
+ this.timeout = null;
12432
+ this.stopRefreshBoundaryMs = DEFAULT_STOP_REFRESH_BOUNDARY_MS;
12433
+ this.getRefreshIntervalLength = () => {
12434
+ if (!this.reminder.remindAt) return null;
12435
+ const distanceFromDeadlineMs = Math.abs(timeLeftMs(this.reminder.remindAt.getTime()));
12436
+ let refreshInterval;
12437
+ if (distanceFromDeadlineMs === 0) {
12438
+ refreshInterval = oneMinute;
12439
+ } else if (distanceFromDeadlineMs < GROUP_BOUNDS.minute.lower) {
12440
+ refreshInterval = distanceFromDeadlineMs;
12441
+ } else if (distanceFromDeadlineMs <= GROUP_BOUNDS.minute.upper) {
12442
+ refreshInterval = oneMinute;
12443
+ } else if (distanceFromDeadlineMs <= GROUP_BOUNDS.hour.upper) {
12444
+ refreshInterval = oneHour;
12445
+ } else {
12446
+ refreshInterval = oneDay;
12447
+ }
12448
+ return refreshInterval;
12449
+ };
12450
+ this.init = () => {
12451
+ if (!this.reminder.remindAt) return null;
12452
+ const timeoutLength = this.getRefreshIntervalLength();
12453
+ if (timeoutLength === null) return null;
12454
+ const boundaryTimestamp = this.reminder.remindAt?.getTime() + this.stopRefreshBoundaryMs;
12455
+ const timeLeftToBoundary = boundaryTimestamp - Date.now();
12456
+ if (timeLeftToBoundary <= 0) {
12457
+ this.timeout = null;
12458
+ return;
12459
+ }
12460
+ if (this.timeout) clearTimeout(this.timeout);
12461
+ this.timeout = setTimeout(() => {
12462
+ this.reminder.refreshTimeLeft();
12463
+ this.init();
12464
+ }, timeoutLength);
12465
+ };
12466
+ this.clear = () => {
12467
+ if (this.timeout) {
12468
+ clearInterval(this.timeout);
12469
+ this.timeout = null;
12470
+ }
12471
+ };
12472
+ this.reminder = reminder;
12473
+ if (typeof config?.stopRefreshBoundaryMs === "number") {
12474
+ this.stopRefreshBoundaryMs = config.stopRefreshBoundaryMs;
12475
+ }
12476
+ }
12477
+ };
12478
+
12479
+ // src/reminders/Reminder.ts
12480
+ var timeLeftMs = (remindAt) => remindAt - (/* @__PURE__ */ new Date()).getTime();
12481
+ var _Reminder = class _Reminder {
12482
+ constructor({ data, config }) {
12483
+ this.setState = (data) => {
12484
+ this.state.next((current) => {
12485
+ const newState = { ...current, ..._Reminder.toStateValue(data) };
12486
+ if (newState.remind_at) {
12487
+ newState.timeLeftMs = timeLeftMs(newState.remind_at.getTime());
12488
+ }
12489
+ return newState;
12490
+ });
12491
+ if (data.remind_at) {
12492
+ this.initTimer();
12493
+ } else if (!data.remind_at) {
12494
+ this.clearTimer();
12495
+ }
12496
+ };
12497
+ this.refreshTimeLeft = () => {
12498
+ if (!this.remindAt) return;
12499
+ this.state.partialNext({ timeLeftMs: timeLeftMs(this.remindAt.getTime()) });
12500
+ };
12501
+ this.initTimer = () => {
12502
+ this.timer.init();
12503
+ };
12504
+ this.clearTimer = () => {
12505
+ this.timer.clear();
12506
+ };
12507
+ this.state = new StateStore(_Reminder.toStateValue(data));
12508
+ this.timer = new ReminderTimer({ reminder: this, config });
12509
+ this.initTimer();
12510
+ }
12511
+ get id() {
12512
+ return this.state.getLatestValue().message_id;
12513
+ }
12514
+ get remindAt() {
12515
+ return this.state.getLatestValue().remind_at;
12516
+ }
12517
+ get timeLeftMs() {
12518
+ return this.state.getLatestValue().timeLeftMs;
12519
+ }
12520
+ };
12521
+ _Reminder.toStateValue = (data) => ({
12522
+ ...data,
12523
+ created_at: new Date(data.created_at),
12524
+ message: data.message || null,
12525
+ remind_at: data.remind_at ? new Date(data.remind_at) : null,
12526
+ timeLeftMs: data.remind_at ? timeLeftMs(new Date(data.remind_at).getTime()) : null,
12527
+ updated_at: new Date(data.updated_at),
12528
+ user: data.user || null
12529
+ });
12530
+ var Reminder = _Reminder;
12531
+
12532
+ // src/pagination/BasePaginator.ts
12533
+ var DEFAULT_PAGINATION_OPTIONS = {
12534
+ debounceMs: 300,
12535
+ pageSize: 10
12536
+ };
12537
+ var BasePaginator = class {
12538
+ constructor(options) {
12539
+ this._isCursorPagination = false;
12540
+ this.setDebounceOptions = ({ debounceMs }) => {
12541
+ this._executeQueryDebounced = debounce(this.executeQuery.bind(this), debounceMs);
12542
+ };
12543
+ this.canExecuteQuery = (direction) => !this.isLoading && direction === "next" && this.hasNext || direction === "prev" && this.hasPrev;
12544
+ this.next = () => this.executeQuery({ direction: "next" });
12545
+ this.prev = () => this.executeQuery({ direction: "prev" });
12546
+ this.nextDebounced = () => {
12547
+ this._executeQueryDebounced({ direction: "next" });
12548
+ };
12549
+ this.prevDebounced = () => {
12550
+ this._executeQueryDebounced({ direction: "prev" });
12551
+ };
12552
+ const { debounceMs, pageSize } = { ...DEFAULT_PAGINATION_OPTIONS, ...options };
12553
+ this.pageSize = pageSize;
12554
+ this.state = new StateStore(this.initialState);
12555
+ this.setDebounceOptions({ debounceMs });
12556
+ }
12557
+ get lastQueryError() {
12558
+ return this.state.getLatestValue().lastQueryError;
12559
+ }
12560
+ get hasNext() {
12561
+ return this.state.getLatestValue().hasNext;
12562
+ }
12563
+ get hasPrev() {
12564
+ return this.state.getLatestValue().hasPrev;
12565
+ }
12566
+ get hasResults() {
12567
+ return Array.isArray(this.state.getLatestValue().items);
12568
+ }
12569
+ get isLoading() {
12570
+ return this.state.getLatestValue().isLoading;
12571
+ }
12572
+ get initialState() {
12573
+ return {
12574
+ hasNext: true,
12575
+ hasPrev: true,
12576
+ //todo: check if optimistic value does not cause problems in UI
12577
+ isLoading: false,
12578
+ items: void 0,
12579
+ lastQueryError: void 0,
12580
+ cursor: void 0,
12581
+ offset: 0
12582
+ };
12583
+ }
12584
+ get items() {
12585
+ return this.state.getLatestValue().items;
12586
+ }
12587
+ get cursor() {
12588
+ return this.state.getLatestValue().cursor;
12589
+ }
12590
+ get offset() {
12591
+ return this.state.getLatestValue().offset;
12592
+ }
12593
+ getStateBeforeFirstQuery() {
12594
+ return {
12595
+ ...this.initialState,
12596
+ isLoading: true
12597
+ };
12598
+ }
12599
+ getStateAfterQuery(stateUpdate, isFirstPage) {
12600
+ const current = this.state.getLatestValue();
12601
+ return {
12602
+ ...current,
12603
+ lastQueryError: void 0,
12604
+ // reset lastQueryError that can be overridden by the stateUpdate
12605
+ ...stateUpdate,
12606
+ isLoading: false,
12607
+ items: isFirstPage ? stateUpdate.items : [...this.items ?? [], ...stateUpdate.items || []]
12608
+ };
12609
+ }
12610
+ async executeQuery({ direction }) {
12611
+ if (!this.canExecuteQuery(direction)) return;
12612
+ const isFirstPage = typeof this.items === "undefined";
12613
+ if (isFirstPage) {
12614
+ this.state.next(this.getStateBeforeFirstQuery());
12615
+ } else {
12616
+ this.state.partialNext({ isLoading: true });
12617
+ }
12618
+ const stateUpdate = {};
12619
+ try {
12620
+ const results = await this.query({ direction });
12621
+ if (!results) return;
12622
+ const { items, next, prev } = results;
12623
+ if (isFirstPage && (next || prev)) {
12624
+ this._isCursorPagination = true;
12625
+ }
12626
+ if (this._isCursorPagination) {
12627
+ stateUpdate.cursor = { next: next || null, prev: prev || null };
12628
+ stateUpdate.hasNext = !!next;
12629
+ stateUpdate.hasPrev = !!prev;
12630
+ } else {
12631
+ stateUpdate.offset = (this.offset ?? 0) + items.length;
12632
+ stateUpdate.hasNext = items.length === this.pageSize;
12633
+ }
12634
+ stateUpdate.items = await this.filterQueryResults(items);
12635
+ } catch (e) {
12636
+ stateUpdate.lastQueryError = e;
12637
+ } finally {
12638
+ this.state.next(this.getStateAfterQuery(stateUpdate, isFirstPage));
12639
+ }
12640
+ }
12641
+ cancelScheduledQuery() {
12642
+ this._executeQueryDebounced.cancel();
12643
+ }
12644
+ resetState() {
12645
+ this.state.next(this.initialState);
12646
+ }
12647
+ };
12648
+
12649
+ // src/pagination/ReminderPaginator.ts
12650
+ var ReminderPaginator = class extends BasePaginator {
12651
+ constructor(client, options) {
12652
+ super(options);
12653
+ this.query = async ({
12654
+ direction
12655
+ }) => {
12656
+ const cursor = this.cursor?.[direction];
12657
+ const {
12658
+ reminders: items,
12659
+ next,
12660
+ prev
12661
+ } = await this.client.queryReminders({
12662
+ filter: this.filters,
12663
+ sort: this.sort,
12664
+ limit: this.pageSize,
12665
+ [direction]: cursor
12666
+ });
12667
+ return { items, next, prev };
12668
+ };
12669
+ this.filterQueryResults = (items) => items;
12670
+ this.client = client;
12671
+ }
12672
+ };
12673
+
12674
+ // src/reminders/ReminderManager.ts
12675
+ var oneMinute2 = 60 * 1e3;
12676
+ var oneHour2 = 60 * oneMinute2;
12677
+ var oneDay2 = 24 * oneHour2;
12678
+ var DEFAULT_REMINDER_MANAGER_CONFIG = {
12679
+ scheduledOffsetsMs: [
12680
+ 2 * oneMinute2,
12681
+ 30 * oneMinute2,
12682
+ oneHour2,
12683
+ 2 * oneHour2,
12684
+ 8 * oneHour2,
12685
+ oneDay2
12686
+ ]
12687
+ };
12688
+ var isReminderExistsError = (error) => error.message.match("already has reminder created for this message_id");
12689
+ var isReminderDoesNotExistError = (error) => error.message.match("reminder does not exist");
12690
+ var _ReminderManager = class _ReminderManager extends WithSubscriptions {
12691
+ constructor({ client, config }) {
12692
+ super();
12693
+ this.upsertToState = ({
12694
+ data,
12695
+ overwrite = true
12696
+ }) => {
12697
+ if (!this.client._cacheEnabled()) {
12698
+ return;
12699
+ }
12700
+ const cachedReminder = this.getFromState(data.message_id);
12701
+ if (!cachedReminder) {
12702
+ const reminder = new Reminder({
12703
+ data,
12704
+ config: { stopRefreshBoundaryMs: this.stopTimerRefreshBoundaryMs }
12705
+ });
12706
+ this.state.partialNext({
12707
+ reminders: new Map(this.reminders.set(data.message_id, reminder))
12708
+ });
12709
+ } else if (overwrite) {
12710
+ cachedReminder.setState(data);
12711
+ }
12712
+ return cachedReminder;
12713
+ };
12714
+ this.removeFromState = (messageId) => {
12715
+ const cachedReminder = this.getFromState(messageId);
12716
+ if (!cachedReminder) return;
12717
+ cachedReminder.clearTimer();
12718
+ const reminders = this.reminders;
12719
+ reminders.delete(messageId);
12720
+ this.state.partialNext({ reminders: new Map(reminders) });
12721
+ };
12722
+ this.hydrateState = (messages) => {
12723
+ messages.forEach(({ reminder }) => {
12724
+ if (reminder) {
12725
+ this.upsertToState({ data: reminder });
12726
+ }
12727
+ });
12728
+ };
12729
+ // State API END //
12730
+ // Timers API START //
12731
+ this.initTimers = () => {
12732
+ this.reminders.forEach((reminder) => reminder.initTimer());
12733
+ };
12734
+ this.clearTimers = () => {
12735
+ this.reminders.forEach((reminder) => reminder.clearTimer());
12736
+ };
12737
+ this.registerSubscriptions = () => {
12738
+ if (this.hasSubscriptions) return;
12739
+ this.addUnsubscribeFunction(this.subscribeReminderCreated());
12740
+ this.addUnsubscribeFunction(this.subscribeReminderUpdated());
12741
+ this.addUnsubscribeFunction(this.subscribeReminderDeleted());
12742
+ this.addUnsubscribeFunction(this.subscribeNotificationReminderDue());
12743
+ this.addUnsubscribeFunction(this.subscribeMessageDeleted());
12744
+ this.addUnsubscribeFunction(this.subscribeMessageUndeleted());
12745
+ this.addUnsubscribeFunction(this.subscribePaginatorStateUpdated());
12746
+ this.addUnsubscribeFunction(this.subscribeConfigStateUpdated());
12747
+ };
12748
+ this.subscribeReminderCreated = () => this.client.on("reminder.created", (event) => {
12749
+ if (!_ReminderManager.isReminderWsEventPayload(event)) return;
12750
+ const { reminder } = event;
12751
+ this.upsertToState({ data: reminder });
12752
+ }).unsubscribe;
12753
+ this.subscribeReminderUpdated = () => this.client.on("reminder.updated", (event) => {
12754
+ if (!_ReminderManager.isReminderWsEventPayload(event)) return;
12755
+ const { reminder } = event;
12756
+ this.upsertToState({ data: reminder });
12757
+ }).unsubscribe;
12758
+ this.subscribeReminderDeleted = () => this.client.on("reminder.deleted", (event) => {
12759
+ if (!_ReminderManager.isReminderWsEventPayload(event)) return;
12760
+ this.removeFromState(event.message_id);
12761
+ }).unsubscribe;
12762
+ this.subscribeMessageDeleted = () => this.client.on("message.deleted", (event) => {
12763
+ if (!event.message?.id) return;
12764
+ this.removeFromState(event.message.id);
12765
+ }).unsubscribe;
12766
+ this.subscribeMessageUndeleted = () => this.client.on("message.undeleted", (event) => {
12767
+ if (!event.message?.reminder) return;
12768
+ this.upsertToState({ data: event.message.reminder });
12769
+ }).unsubscribe;
12770
+ this.subscribeNotificationReminderDue = () => this.client.on("notification.reminder_due", () => null).unsubscribe;
12771
+ // todo: what should be performed on this event?
12772
+ this.subscribePaginatorStateUpdated = () => this.paginator.state.subscribeWithSelector(
12773
+ ({ items }) => [items],
12774
+ ([items]) => {
12775
+ if (!items) return;
12776
+ for (const reminder of items) {
12777
+ this.upsertToState({ data: reminder });
12778
+ }
12779
+ }
12780
+ );
12781
+ this.subscribeConfigStateUpdated = () => this.configState.subscribeWithSelector(
12782
+ ({ stopTimerRefreshBoundaryMs }) => ({ stopTimerRefreshBoundaryMs }),
12783
+ ({ stopTimerRefreshBoundaryMs }, previousValue) => {
12784
+ if (typeof stopTimerRefreshBoundaryMs === "number" && stopTimerRefreshBoundaryMs !== previousValue?.stopTimerRefreshBoundaryMs) {
12785
+ this.reminders.forEach((reminder) => {
12786
+ if (reminder.timer) {
12787
+ reminder.timer.stopRefreshBoundaryMs = stopTimerRefreshBoundaryMs;
12788
+ }
12789
+ });
12790
+ }
12791
+ }
12792
+ );
12793
+ // WS event handling END //
12794
+ // API calls START //
12795
+ this.upsertReminder = async (options) => {
12796
+ const { messageId } = options;
12797
+ if (this.getFromState(messageId)) {
12798
+ try {
12799
+ return await this.updateReminder(options);
12800
+ } catch (error) {
12801
+ if (isReminderDoesNotExistError(error)) {
12802
+ return await this.createReminder(options);
12803
+ }
12804
+ throw error;
12805
+ }
12806
+ } else {
12807
+ try {
12808
+ return await this.createReminder(options);
12809
+ } catch (error) {
12810
+ if (isReminderExistsError(error)) {
12811
+ return await this.updateReminder(options);
12812
+ }
12813
+ throw error;
12814
+ }
12815
+ }
12816
+ };
12817
+ this.createReminder = async (options) => {
12818
+ const { reminder } = await this.client.createReminder(options);
12819
+ return this.upsertToState({ data: reminder, overwrite: false });
12820
+ };
12821
+ this.updateReminder = async (options) => {
12822
+ const { reminder } = await this.client.updateReminder(options);
12823
+ return this.upsertToState({ data: reminder });
12824
+ };
12825
+ this.deleteReminder = async (messageId) => {
12826
+ await this.client.deleteReminder(messageId);
12827
+ this.removeFromState(messageId);
12828
+ };
12829
+ this.queryNextReminders = async () => {
12830
+ await this.paginator.next();
12831
+ };
12832
+ this.queryPreviousReminders = async () => {
12833
+ await this.paginator.prev();
12834
+ };
12835
+ this.client = client;
12836
+ this.configState = new StateStore({
12837
+ scheduledOffsetsMs: config?.scheduledOffsetsMs ?? DEFAULT_REMINDER_MANAGER_CONFIG.scheduledOffsetsMs
12838
+ });
12839
+ this.state = new StateStore({ reminders: /* @__PURE__ */ new Map() });
12840
+ this.paginator = new ReminderPaginator(client);
12841
+ }
12842
+ // Config API START //
12843
+ updateConfig(config) {
12844
+ this.configState.partialNext(config);
12845
+ }
12846
+ get stopTimerRefreshBoundaryMs() {
12847
+ return this.configState.getLatestValue().stopTimerRefreshBoundaryMs;
12848
+ }
12849
+ get scheduledOffsetsMs() {
12850
+ return this.configState.getLatestValue().scheduledOffsetsMs;
12851
+ }
12852
+ // Config API END //
12853
+ // State API START //
12854
+ get reminders() {
12855
+ return this.state.getLatestValue().reminders;
12856
+ }
12857
+ getFromState(messageId) {
12858
+ return this.reminders.get(messageId);
12859
+ }
12860
+ // API calls END //
12861
+ };
12862
+ // Timers API END //
12863
+ // WS event handling START //
12864
+ _ReminderManager.isReminderWsEventPayload = (event) => !!event.reminder && (event.type.startsWith("reminder.") || event.type === "notification.reminder_due");
12865
+ var ReminderManager = _ReminderManager;
12866
+
12227
12867
  // src/client.ts
12228
12868
  function isString3(x) {
12229
12869
  return typeof x === "string" || x instanceof String;
@@ -12239,6 +12879,9 @@ var StreamChat = class _StreamChat {
12239
12879
  });
12240
12880
  this._getConnectionID = () => this.wsConnection?.connectionID || this.wsFallback?.connectionID;
12241
12881
  this._hasConnectionID = () => Boolean(this._getConnectionID());
12882
+ this.setMessageComposerSetupFunction = (setupFunction) => {
12883
+ this._messageComposerSetupState.partialNext({ setupFunction });
12884
+ };
12242
12885
  /**
12243
12886
  * connectUser - Set the current user and open a WebSocket connection
12244
12887
  *
@@ -12807,9 +13450,6 @@ var StreamChat = class _StreamChat {
12807
13450
  device: this.options.device,
12808
13451
  client_request_id
12809
13452
  });
12810
- this.setMessageComposerSetupFunction = (setupFunction) => {
12811
- this._messageComposerSetupState.partialNext({ setupFunction });
12812
- };
12813
13453
  this.key = key;
12814
13454
  this.listeners = {};
12815
13455
  this.state = new ClientState({ client: this });
@@ -12864,6 +13504,7 @@ var StreamChat = class _StreamChat {
12864
13504
  this.recoverStateOnReconnect = this.options.recoverStateOnReconnect;
12865
13505
  this.threads = new ThreadManager({ client: this });
12866
13506
  this.polls = new PollManager({ client: this });
13507
+ this.reminders = new ReminderManager({ client: this });
12867
13508
  }
12868
13509
  static getInstance(key, secretOrOptions, options) {
12869
13510
  if (!_StreamChat._instance) {
@@ -12999,15 +13640,15 @@ var StreamChat = class _StreamChat {
12999
13640
  * @param {string} userID User ID. If user has no devices, it will error
13000
13641
  * @param {TestPushDataInput} [data] Overrides for push templates/message used
13001
13642
  * IE: {
13002
- messageID: 'id-of-message', // will error if message does not exist
13003
- apnTemplate: '{}', // if app doesn't have apn configured it will error
13004
- firebaseTemplate: '{}', // if app doesn't have firebase configured it will error
13005
- firebaseDataTemplate: '{}', // if app doesn't have firebase configured it will error
13006
- skipDevices: true, // skip config/device checks and sending to real devices
13007
- pushProviderName: 'staging' // one of your configured push providers
13008
- pushProviderType: 'apn' // one of supported provider types
13009
- }
13010
- */
13643
+ messageID: 'id-of-message', // will error if message does not exist
13644
+ apnTemplate: '{}', // if app doesn't have apn configured it will error
13645
+ firebaseTemplate: '{}', // if app doesn't have firebase configured it will error
13646
+ firebaseDataTemplate: '{}', // if app doesn't have firebase configured it will error
13647
+ skipDevices: true, // skip config/device checks and sending to real devices
13648
+ pushProviderName: 'staging' // one of your configured push providers
13649
+ pushProviderType: 'apn' // one of supported provider types
13650
+ }
13651
+ */
13011
13652
  async testPushSettings(userID, data = {}) {
13012
13653
  return await this.post(this.baseURL + "/check_push", {
13013
13654
  user_id: userID,
@@ -13025,10 +13666,10 @@ var StreamChat = class _StreamChat {
13025
13666
  *
13026
13667
  * @param {TestSQSDataInput} [data] Overrides SQS settings for testing if needed
13027
13668
  * IE: {
13028
- sqs_key: 'auth_key',
13029
- sqs_secret: 'auth_secret',
13030
- sqs_url: 'url_to_queue',
13031
- }
13669
+ sqs_key: 'auth_key',
13670
+ sqs_secret: 'auth_secret',
13671
+ sqs_url: 'url_to_queue',
13672
+ }
13032
13673
  */
13033
13674
  async testSQSSettings(data = {}) {
13034
13675
  return await this.post(this.baseURL + "/check_sqs", data);
@@ -13038,10 +13679,10 @@ var StreamChat = class _StreamChat {
13038
13679
  *
13039
13680
  * @param {TestSNSDataInput} [data] Overrides SNS settings for testing if needed
13040
13681
  * IE: {
13041
- sns_key: 'auth_key',
13042
- sns_secret: 'auth_secret',
13043
- sns_topic_arn: 'topic_to_publish_to',
13044
- }
13682
+ sns_key: 'auth_key',
13683
+ sns_secret: 'auth_secret',
13684
+ sns_topic_arn: 'topic_to_publish_to',
13685
+ }
13045
13686
  */
13046
13687
  async testSNSSettings(data = {}) {
13047
13688
  return await this.post(this.baseURL + "/check_sns", data);
@@ -13522,6 +14163,7 @@ var StreamChat = class _StreamChat {
13522
14163
  })
13523
14164
  };
13524
14165
  this.polls.hydratePollCache(channelState.messages, true);
14166
+ this.reminders.hydrateState(channelState.messages);
13525
14167
  }
13526
14168
  if (channelState.draft) {
13527
14169
  c.messageComposer.initState({ composition: channelState.draft });
@@ -14442,7 +15084,7 @@ var StreamChat = class _StreamChat {
14442
15084
  if (this.userAgent) {
14443
15085
  return this.userAgent;
14444
15086
  }
14445
- const version = "9.3.0";
15087
+ const version = "9.5.0";
14446
15088
  const clientBundle = "browser-cjs";
14447
15089
  let userAgentString = "";
14448
15090
  if (this.sdkIdentifier) {
@@ -15481,6 +16123,56 @@ var StreamChat = class _StreamChat {
15481
16123
  };
15482
16124
  return await this.post(this.baseURL + "/drafts/query", payload);
15483
16125
  }
16126
+ /**
16127
+ * createReminder - Creates a reminder for a message
16128
+ *
16129
+ * @param {CreateReminderOptions} options The options for creating the reminder
16130
+ * @returns {Promise<ReminderAPIResponse>}
16131
+ */
16132
+ async createReminder({ messageId, ...options }) {
16133
+ return await this.post(
16134
+ `${this.baseURL}/messages/${messageId}/reminders`,
16135
+ options
16136
+ );
16137
+ }
16138
+ /**
16139
+ * updateReminder - Updates an existing reminder for a message
16140
+ *
16141
+ * @param {UpdateReminderOptions} options The options for updating the reminder
16142
+ * @returns {Promise<ReminderAPIResponse>}
16143
+ */
16144
+ async updateReminder({ messageId, ...options }) {
16145
+ return await this.patch(
16146
+ `${this.baseURL}/messages/${messageId}/reminders`,
16147
+ options
16148
+ );
16149
+ }
16150
+ /**
16151
+ * deleteReminder - Deletes a reminder for a message
16152
+ *
16153
+ * @param {string} messageId The ID of the message whose reminder to delete
16154
+ * @param {string} [userId] Optional user ID, required for server-side operations
16155
+ * @returns {Promise<APIResponse>}
16156
+ */
16157
+ async deleteReminder(messageId, userId) {
16158
+ return await this.delete(
16159
+ `${this.baseURL}/messages/${messageId}/reminders`,
16160
+ userId ? { user_id: userId } : {}
16161
+ );
16162
+ }
16163
+ /**
16164
+ * queryReminders - Queries reminders based on given filters
16165
+ *
16166
+ * @param {QueryRemindersOptions} options The options for querying reminders
16167
+ * @returns {Promise<QueryRemindersResponse>}
16168
+ */
16169
+ async queryReminders({ filter: filter2, sort, ...rest } = {}) {
16170
+ return await this.post(`${this.baseURL}/reminders/query`, {
16171
+ filter_conditions: filter2,
16172
+ sort: sort && normalizeQuerySort(sort),
16173
+ ...rest
16174
+ });
16175
+ }
15484
16176
  };
15485
16177
 
15486
16178
  // src/events.ts
@@ -15547,7 +16239,12 @@ var EVENT_MAP = {
15547
16239
  "connection.changed": true,
15548
16240
  "connection.recovered": true,
15549
16241
  "transport.changed": true,
15550
- "capabilities.changed": true
16242
+ "capabilities.changed": true,
16243
+ // Reminder events
16244
+ "reminder.created": true,
16245
+ "reminder.updated": true,
16246
+ "reminder.deleted": true,
16247
+ "notification.reminder_due": true
15551
16248
  };
15552
16249
 
15553
16250
  // src/permissions.ts