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
package/dist/esm/index.js CHANGED
@@ -3900,26 +3900,14 @@ var ensureIsLocalAttachment = (attachment) => {
3900
3900
 
3901
3901
  // src/store.ts
3902
3902
  var isPatch = (value) => typeof value === "function";
3903
+ var noop2 = () => {
3904
+ };
3903
3905
  var StateStore = class {
3904
3906
  constructor(value) {
3905
3907
  this.value = value;
3906
- this.handlerSet = /* @__PURE__ */ new Set();
3907
- this.next = (newValueOrPatch) => {
3908
- const newValue = isPatch(newValueOrPatch) ? newValueOrPatch(this.value) : newValueOrPatch;
3909
- if (newValue === this.value) return;
3910
- const oldValue = this.value;
3911
- this.value = newValue;
3912
- this.handlerSet.forEach((handler) => handler(this.value, oldValue));
3913
- };
3908
+ this.handlers = /* @__PURE__ */ new Set();
3909
+ this.preprocessors = /* @__PURE__ */ new Set();
3914
3910
  this.partialNext = (partial) => this.next((current) => ({ ...current, ...partial }));
3915
- this.getLatestValue = () => this.value;
3916
- this.subscribe = (handler) => {
3917
- handler(this.value, void 0);
3918
- this.handlerSet.add(handler);
3919
- return () => {
3920
- this.handlerSet.delete(handler);
3921
- };
3922
- };
3923
3911
  this.subscribeWithSelector = (selector, handler) => {
3924
3912
  let previouslySelectedValues;
3925
3913
  const wrappedHandler = (nextValue) => {
@@ -3938,6 +3926,183 @@ var StateStore = class {
3938
3926
  return this.subscribe(wrappedHandler);
3939
3927
  };
3940
3928
  }
3929
+ /**
3930
+ * Allows merging two stores only if their keys differ otherwise there's no way to ensure the data type stability.
3931
+ * @experimental
3932
+ * This method is experimental and may change in future versions.
3933
+ */
3934
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3935
+ merge(stateStore) {
3936
+ return new MergedStateStore({
3937
+ original: this,
3938
+ merged: stateStore
3939
+ });
3940
+ }
3941
+ next(newValueOrPatch) {
3942
+ const newValue = isPatch(newValueOrPatch) ? newValueOrPatch(this.value) : newValueOrPatch;
3943
+ if (newValue === this.value) return;
3944
+ this.preprocessors.forEach((preprocessor) => preprocessor(newValue, this.value));
3945
+ const oldValue = this.value;
3946
+ this.value = newValue;
3947
+ this.handlers.forEach((handler) => handler(this.value, oldValue));
3948
+ }
3949
+ getLatestValue() {
3950
+ return this.value;
3951
+ }
3952
+ subscribe(handler) {
3953
+ handler(this.value, void 0);
3954
+ this.handlers.add(handler);
3955
+ return () => {
3956
+ this.handlers.delete(handler);
3957
+ };
3958
+ }
3959
+ /**
3960
+ * Registers a preprocessor function that will be called before the state is updated.
3961
+ *
3962
+ * Preprocessors are invoked with the new and previous values whenever `next` or `partialNext` methods
3963
+ * are called, allowing you to mutate or react to the new value before it is set. Preprocessors run in the
3964
+ * order they were registered.
3965
+ *
3966
+ * @example
3967
+ * ```ts
3968
+ * const store = new StateStore<{ count: number; isMaxValue: bool; }>({ count: 0, isMaxValue: false });
3969
+ *
3970
+ * store.addPreprocessor((nextValue, prevValue) => {
3971
+ * if (nextValue.count > 10) {
3972
+ * nextValue.count = 10; // Clamp the value to a maximum of 10
3973
+ * }
3974
+ *
3975
+ * if (nextValue.count === 10) {
3976
+ * nextValue.isMaxValue = true; // Set isMaxValue to true if count is 10
3977
+ * } else {
3978
+ * nextValue.isMaxValue = false; // Reset isMaxValue otherwise
3979
+ * }
3980
+ * });
3981
+ *
3982
+ * store.partialNext({ count: 15 });
3983
+ *
3984
+ * store.getLatestValue(); // { count: 10, isMaxValue: true }
3985
+ *
3986
+ * store.partialNext({ count: 5 });
3987
+ *
3988
+ * store.getLatestValue(); // { count: 5, isMaxValue: false }
3989
+ * ```
3990
+ *
3991
+ * @param preprocessor - The function to be called with the next and previous values before the state is updated.
3992
+ * @returns A `RemovePreprocessor` function that removes the preprocessor when called.
3993
+ */
3994
+ addPreprocessor(preprocessor) {
3995
+ this.preprocessors.add(preprocessor);
3996
+ return () => {
3997
+ this.preprocessors.delete(preprocessor);
3998
+ };
3999
+ }
4000
+ };
4001
+ var MergedStateStore = class _MergedStateStore extends StateStore {
4002
+ constructor({ original, merged }) {
4003
+ const originalValue = original.getLatestValue();
4004
+ const mergedValue = merged.getLatestValue();
4005
+ super({
4006
+ ...originalValue,
4007
+ ...mergedValue
4008
+ });
4009
+ // override original methods and "disable" them
4010
+ this.next = () => {
4011
+ console.warn(
4012
+ `${_MergedStateStore.name}.next is disabled, call original.next or merged.next instead`
4013
+ );
4014
+ };
4015
+ this.partialNext = () => {
4016
+ console.warn(
4017
+ `${_MergedStateStore.name}.partialNext is disabled, call original.partialNext or merged.partialNext instead`
4018
+ );
4019
+ };
4020
+ this.cachedOriginalValue = originalValue;
4021
+ this.cachedMergedValue = mergedValue;
4022
+ this.original = original;
4023
+ this.merged = merged;
4024
+ }
4025
+ /**
4026
+ * Subscribes to changes in the merged state store.
4027
+ *
4028
+ * This method extends the base subscribe functionality to handle the merged nature of this store:
4029
+ * 1. The first subscriber triggers registration of helper subscribers that listen to both source stores
4030
+ * 2. Changes from either source store are propagated to this merged store
4031
+ * 3. Source store values are cached to prevent unnecessary updates
4032
+ *
4033
+ * When the first subscriber is added, the method sets up listeners on both original and merged stores.
4034
+ * These listeners update the combined store value whenever either source store changes.
4035
+ * All subscriptions (helpers and the actual handler) are tracked so they can be properly cleaned up.
4036
+ *
4037
+ * @param handler - The callback function that will be executed when the state changes
4038
+ * @returns An unsubscribe function that, when called, removes the subscription and any helper subscriptions
4039
+ */
4040
+ subscribe(handler) {
4041
+ const unsubscribeFunctions = [];
4042
+ if (!this.handlers.size) {
4043
+ const base = (nextValue) => {
4044
+ super.next((currentValue) => ({
4045
+ ...currentValue,
4046
+ ...nextValue
4047
+ }));
4048
+ };
4049
+ unsubscribeFunctions.push(
4050
+ this.original.subscribe((nextValue) => {
4051
+ if (nextValue === this.cachedOriginalValue) return;
4052
+ this.cachedOriginalValue = nextValue;
4053
+ base(nextValue);
4054
+ }),
4055
+ this.merged.subscribe((nextValue) => {
4056
+ if (nextValue === this.cachedMergedValue) return;
4057
+ this.cachedMergedValue = nextValue;
4058
+ base(nextValue);
4059
+ })
4060
+ );
4061
+ }
4062
+ unsubscribeFunctions.push(super.subscribe(handler));
4063
+ return () => {
4064
+ unsubscribeFunctions.forEach((unsubscribe) => unsubscribe());
4065
+ };
4066
+ }
4067
+ /**
4068
+ * Retrieves the latest combined state from both original and merged stores.
4069
+ *
4070
+ * This method extends the base getLatestValue functionality to ensure the merged store
4071
+ * remains in sync with its source stores even when there are no active subscribers.
4072
+ *
4073
+ * When there are no handlers registered, the method:
4074
+ * 1. Fetches the latest values from both source stores
4075
+ * 2. Compares them with the cached values to detect changes
4076
+ * 3. If changes are detected, updates the internal value and caches
4077
+ * the new source values to maintain consistency
4078
+ *
4079
+ * This approach ensures that calling getLatestValue() always returns the most
4080
+ * up-to-date combined state, even if the merged store hasn't been actively
4081
+ * receiving updates through subscriptions.
4082
+ *
4083
+ * @returns The latest combined state from both original and merged stores
4084
+ */
4085
+ getLatestValue() {
4086
+ if (!this.handlers.size) {
4087
+ const originalValue = this.original.getLatestValue();
4088
+ const mergedValue = this.merged.getLatestValue();
4089
+ if (originalValue !== this.cachedOriginalValue || mergedValue !== this.cachedMergedValue) {
4090
+ this.value = {
4091
+ ...originalValue,
4092
+ ...mergedValue
4093
+ };
4094
+ this.cachedMergedValue = mergedValue;
4095
+ this.cachedOriginalValue = originalValue;
4096
+ }
4097
+ }
4098
+ return super.getLatestValue();
4099
+ }
4100
+ addPreprocessor() {
4101
+ console.warn(
4102
+ `${_MergedStateStore.name}.addPreprocessor is disabled, call original.addPreprocessor or merged.addPreprocessor instead`
4103
+ );
4104
+ return noop2;
4105
+ }
3941
4106
  };
3942
4107
 
3943
4108
  // src/utils/mergeWith/mergeWithCore.ts
@@ -5289,8 +5454,8 @@ function decodeTlds(encoded) {
5289
5454
  var defaults2 = {
5290
5455
  defaultProtocol: "http",
5291
5456
  events: null,
5292
- format: noop2,
5293
- formatHref: noop2,
5457
+ format: noop3,
5458
+ formatHref: noop3,
5294
5459
  nl2br: false,
5295
5460
  tagName: "a",
5296
5461
  target: null,
@@ -5395,7 +5560,7 @@ Options.prototype = {
5395
5560
  return renderFn(ir, token.t, token);
5396
5561
  }
5397
5562
  };
5398
- function noop2(val) {
5563
+ function noop3(val) {
5399
5564
  return val;
5400
5565
  }
5401
5566
  function MultiToken(value, tokens) {
@@ -6486,7 +6651,9 @@ var ErrorFromResponse = class extends Error {
6486
6651
  return {
6487
6652
  message: `(${joinable.join(", ")}) - ${this.message}`,
6488
6653
  stack: this.stack,
6489
- name: this.name
6654
+ name: this.name,
6655
+ code: this.code,
6656
+ status: this.status
6490
6657
  };
6491
6658
  }
6492
6659
  };
@@ -7054,7 +7221,7 @@ var MessageDraftComposerMiddlewareExecutor = class extends MiddlewareExecutor {
7054
7221
  }
7055
7222
  };
7056
7223
 
7057
- // src/search_controller.ts
7224
+ // src/search/BaseSearchSource.ts
7058
7225
  var DEFAULT_SEARCH_SOURCE_OPTIONS = {
7059
7226
  debounceMs: 300,
7060
7227
  pageSize: 10
@@ -7180,6 +7347,112 @@ var BaseSearchSource = class {
7180
7347
  this.activate();
7181
7348
  }
7182
7349
  };
7350
+
7351
+ // src/search/SearchController.ts
7352
+ var SearchController = class {
7353
+ constructor({ config, sources } = {}) {
7354
+ this.addSource = (source) => {
7355
+ this.state.partialNext({
7356
+ sources: [...this.sources, source]
7357
+ });
7358
+ };
7359
+ this.getSource = (sourceType) => this.sources.find((s) => s.type === sourceType);
7360
+ this.removeSource = (sourceType) => {
7361
+ const newSources = this.sources.filter((s) => s.type !== sourceType);
7362
+ if (newSources.length === this.sources.length) return;
7363
+ this.state.partialNext({ sources: newSources });
7364
+ };
7365
+ this.activateSource = (sourceType) => {
7366
+ const source = this.getSource(sourceType);
7367
+ if (!source || source.isActive) return;
7368
+ if (this.config.keepSingleActiveSource) {
7369
+ this.sources.forEach((s) => {
7370
+ if (s.type !== sourceType) {
7371
+ s.deactivate();
7372
+ }
7373
+ });
7374
+ }
7375
+ source.activate();
7376
+ this.state.partialNext({ sources: [...this.sources] });
7377
+ };
7378
+ this.deactivateSource = (sourceType) => {
7379
+ const source = this.getSource(sourceType);
7380
+ if (!source?.isActive) return;
7381
+ if (this.activeSources.length === 1) return;
7382
+ source.deactivate();
7383
+ this.state.partialNext({ sources: [...this.sources] });
7384
+ };
7385
+ this.activate = () => {
7386
+ if (!this.activeSources.length) {
7387
+ const sourcesToActivate = this.config.keepSingleActiveSource ? this.sources.slice(0, 1) : this.sources;
7388
+ sourcesToActivate.forEach((s) => s.activate());
7389
+ }
7390
+ if (this.isActive) return;
7391
+ this.state.partialNext({ isActive: true });
7392
+ };
7393
+ this.search = async (searchQuery) => {
7394
+ const searchedSources = this.activeSources;
7395
+ this.state.partialNext({
7396
+ searchQuery
7397
+ });
7398
+ await Promise.all(searchedSources.map((source) => source.search(searchQuery)));
7399
+ };
7400
+ this.cancelSearchQueries = () => {
7401
+ this.activeSources.forEach((s) => s.cancelScheduledQuery());
7402
+ };
7403
+ this.clear = () => {
7404
+ this.cancelSearchQueries();
7405
+ this.sources.forEach(
7406
+ (source) => source.state.next({ ...source.initialState, isActive: source.isActive })
7407
+ );
7408
+ this.state.next((current) => ({
7409
+ ...current,
7410
+ isActive: true,
7411
+ queriesInProgress: [],
7412
+ searchQuery: ""
7413
+ }));
7414
+ };
7415
+ this.exit = () => {
7416
+ this.cancelSearchQueries();
7417
+ this.sources.forEach(
7418
+ (source) => source.state.next({ ...source.initialState, isActive: source.isActive })
7419
+ );
7420
+ this.state.next((current) => ({
7421
+ ...current,
7422
+ isActive: false,
7423
+ queriesInProgress: [],
7424
+ searchQuery: ""
7425
+ }));
7426
+ };
7427
+ this.state = new StateStore({
7428
+ isActive: false,
7429
+ searchQuery: "",
7430
+ sources: sources ?? []
7431
+ });
7432
+ this._internalState = new StateStore({});
7433
+ this.config = { keepSingleActiveSource: true, ...config };
7434
+ }
7435
+ get hasNext() {
7436
+ return this.sources.some((source) => source.hasNext);
7437
+ }
7438
+ get sources() {
7439
+ return this.state.getLatestValue().sources;
7440
+ }
7441
+ get activeSources() {
7442
+ return this.state.getLatestValue().sources.filter((s) => s.isActive);
7443
+ }
7444
+ get isActive() {
7445
+ return this.state.getLatestValue().isActive;
7446
+ }
7447
+ get searchQuery() {
7448
+ return this.state.getLatestValue().searchQuery;
7449
+ }
7450
+ get searchSourceTypes() {
7451
+ return this.sources.map((s) => s.type);
7452
+ }
7453
+ };
7454
+
7455
+ // src/search/UserSearchSource.ts
7183
7456
  var UserSearchSource = class extends BaseSearchSource {
7184
7457
  constructor(client, options) {
7185
7458
  super(options);
@@ -7203,6 +7476,8 @@ var UserSearchSource = class extends BaseSearchSource {
7203
7476
  return items.filter((u) => u.id !== this.client.user?.id);
7204
7477
  }
7205
7478
  };
7479
+
7480
+ // src/search/ChannelSearchSource.ts
7206
7481
  var ChannelSearchSource = class extends BaseSearchSource {
7207
7482
  constructor(client, options) {
7208
7483
  super(options);
@@ -7224,6 +7499,8 @@ var ChannelSearchSource = class extends BaseSearchSource {
7224
7499
  return items;
7225
7500
  }
7226
7501
  };
7502
+
7503
+ // src/search/MessageSearchSource.ts
7227
7504
  var MessageSearchSource = class extends BaseSearchSource {
7228
7505
  constructor(client, options) {
7229
7506
  super(options);
@@ -7284,108 +7561,6 @@ var MessageSearchSource = class extends BaseSearchSource {
7284
7561
  return items;
7285
7562
  }
7286
7563
  };
7287
- var SearchController = class {
7288
- constructor({ config, sources } = {}) {
7289
- this.addSource = (source) => {
7290
- this.state.partialNext({
7291
- sources: [...this.sources, source]
7292
- });
7293
- };
7294
- this.getSource = (sourceType) => this.sources.find((s) => s.type === sourceType);
7295
- this.removeSource = (sourceType) => {
7296
- const newSources = this.sources.filter((s) => s.type !== sourceType);
7297
- if (newSources.length === this.sources.length) return;
7298
- this.state.partialNext({ sources: newSources });
7299
- };
7300
- this.activateSource = (sourceType) => {
7301
- const source = this.getSource(sourceType);
7302
- if (!source || source.isActive) return;
7303
- if (this.config.keepSingleActiveSource) {
7304
- this.sources.forEach((s) => {
7305
- if (s.type !== sourceType) {
7306
- s.deactivate();
7307
- }
7308
- });
7309
- }
7310
- source.activate();
7311
- this.state.partialNext({ sources: [...this.sources] });
7312
- };
7313
- this.deactivateSource = (sourceType) => {
7314
- const source = this.getSource(sourceType);
7315
- if (!source?.isActive) return;
7316
- if (this.activeSources.length === 1) return;
7317
- source.deactivate();
7318
- this.state.partialNext({ sources: [...this.sources] });
7319
- };
7320
- this.activate = () => {
7321
- if (!this.activeSources.length) {
7322
- const sourcesToActivate = this.config.keepSingleActiveSource ? this.sources.slice(0, 1) : this.sources;
7323
- sourcesToActivate.forEach((s) => s.activate());
7324
- }
7325
- if (this.isActive) return;
7326
- this.state.partialNext({ isActive: true });
7327
- };
7328
- this.search = async (searchQuery) => {
7329
- const searchedSources = this.activeSources;
7330
- this.state.partialNext({
7331
- searchQuery
7332
- });
7333
- await Promise.all(searchedSources.map((source) => source.search(searchQuery)));
7334
- };
7335
- this.cancelSearchQueries = () => {
7336
- this.activeSources.forEach((s) => s.cancelScheduledQuery());
7337
- };
7338
- this.clear = () => {
7339
- this.cancelSearchQueries();
7340
- this.sources.forEach(
7341
- (source) => source.state.next({ ...source.initialState, isActive: source.isActive })
7342
- );
7343
- this.state.next((current) => ({
7344
- ...current,
7345
- isActive: true,
7346
- queriesInProgress: [],
7347
- searchQuery: ""
7348
- }));
7349
- };
7350
- this.exit = () => {
7351
- this.cancelSearchQueries();
7352
- this.sources.forEach(
7353
- (source) => source.state.next({ ...source.initialState, isActive: source.isActive })
7354
- );
7355
- this.state.next((current) => ({
7356
- ...current,
7357
- isActive: false,
7358
- queriesInProgress: [],
7359
- searchQuery: ""
7360
- }));
7361
- };
7362
- this.state = new StateStore({
7363
- isActive: false,
7364
- searchQuery: "",
7365
- sources: sources ?? []
7366
- });
7367
- this._internalState = new StateStore({});
7368
- this.config = { keepSingleActiveSource: true, ...config };
7369
- }
7370
- get hasNext() {
7371
- return this.sources.some((source) => source.hasNext);
7372
- }
7373
- get sources() {
7374
- return this.state.getLatestValue().sources;
7375
- }
7376
- get activeSources() {
7377
- return this.state.getLatestValue().sources.filter((s) => s.isActive);
7378
- }
7379
- get isActive() {
7380
- return this.state.getLatestValue().isActive;
7381
- }
7382
- get searchQuery() {
7383
- return this.state.getLatestValue().searchQuery;
7384
- }
7385
- get searchSourceTypes() {
7386
- return this.sources.map((s) => s.type);
7387
- }
7388
- };
7389
7564
 
7390
7565
  // src/messageComposer/middleware/textComposer/textMiddlewareUtils.ts
7391
7566
  var getTriggerCharWithToken = ({
@@ -8619,7 +8794,7 @@ var initState5 = (composition) => {
8619
8794
  pollId: message.poll_id ?? null
8620
8795
  };
8621
8796
  };
8622
- var noop3 = () => void 0;
8797
+ var noop4 = () => void 0;
8623
8798
  var _MessageComposer = class _MessageComposer extends WithSubscriptions {
8624
8799
  // todo: mediaRecorder: MediaRecorderController;
8625
8800
  constructor({
@@ -8647,7 +8822,7 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
8647
8822
  this.initEditingAuditState = (composition) => initEditingAuditState(composition);
8648
8823
  this.registerSubscriptions = () => {
8649
8824
  if (this.hasSubscriptions) {
8650
- return noop3;
8825
+ return noop4;
8651
8826
  }
8652
8827
  this.addUnsubscribeFunction(this.subscribeMessageComposerSetupStateChange());
8653
8828
  this.addUnsubscribeFunction(this.subscribeMessageUpdated());
@@ -10164,6 +10339,7 @@ var Channel = class {
10164
10339
  })
10165
10340
  };
10166
10341
  this.getClient().polls.hydratePollCache(state.messages, true);
10342
+ this.getClient().reminders.hydrateState(state.messages);
10167
10343
  if (state.draft) {
10168
10344
  this.messageComposer.initState({ composition: state.draft });
10169
10345
  }
@@ -11455,7 +11631,9 @@ var TokenManager = class {
11455
11631
  try {
11456
11632
  this.token = await this.tokenProvider();
11457
11633
  } catch (e) {
11458
- return reject(new Error(`Call to tokenProvider failed with message: ${e}`));
11634
+ return reject(
11635
+ new Error(`Call to tokenProvider failed with message: ${e}`, { cause: e })
11636
+ );
11459
11637
  }
11460
11638
  resolve(this.token);
11461
11639
  }
@@ -13205,6 +13383,458 @@ var NotificationManager = class {
13205
13383
  }
13206
13384
  };
13207
13385
 
13386
+ // src/reminders/ReminderTimer.ts
13387
+ var oneMinute = 60 * 1e3;
13388
+ var oneHour = 60 * oneMinute;
13389
+ var oneDay = 24 * oneHour;
13390
+ var oneWeek = 7 * oneDay;
13391
+ var GROUP_BOUNDS = {
13392
+ minute: { lower: oneMinute, upper: oneHour },
13393
+ hour: { lower: oneHour, upper: oneDay },
13394
+ day: { lower: oneDay, upper: oneWeek }
13395
+ };
13396
+ var DEFAULT_STOP_REFRESH_BOUNDARY_MS = 2 * oneWeek;
13397
+ var ReminderTimer = class {
13398
+ constructor({
13399
+ reminder,
13400
+ config
13401
+ }) {
13402
+ this.timeout = null;
13403
+ this.stopRefreshBoundaryMs = DEFAULT_STOP_REFRESH_BOUNDARY_MS;
13404
+ this.getRefreshIntervalLength = () => {
13405
+ if (!this.reminder.remindAt) return null;
13406
+ const distanceFromDeadlineMs = Math.abs(timeLeftMs(this.reminder.remindAt.getTime()));
13407
+ let refreshInterval;
13408
+ if (distanceFromDeadlineMs === 0) {
13409
+ refreshInterval = oneMinute;
13410
+ } else if (distanceFromDeadlineMs < GROUP_BOUNDS.minute.lower) {
13411
+ refreshInterval = distanceFromDeadlineMs;
13412
+ } else if (distanceFromDeadlineMs <= GROUP_BOUNDS.minute.upper) {
13413
+ refreshInterval = oneMinute;
13414
+ } else if (distanceFromDeadlineMs <= GROUP_BOUNDS.hour.upper) {
13415
+ refreshInterval = oneHour;
13416
+ } else {
13417
+ refreshInterval = oneDay;
13418
+ }
13419
+ return refreshInterval;
13420
+ };
13421
+ this.init = () => {
13422
+ if (!this.reminder.remindAt) return null;
13423
+ const timeoutLength = this.getRefreshIntervalLength();
13424
+ if (timeoutLength === null) return null;
13425
+ const boundaryTimestamp = this.reminder.remindAt?.getTime() + this.stopRefreshBoundaryMs;
13426
+ const timeLeftToBoundary = boundaryTimestamp - Date.now();
13427
+ if (timeLeftToBoundary <= 0) {
13428
+ this.timeout = null;
13429
+ return;
13430
+ }
13431
+ if (this.timeout) clearTimeout(this.timeout);
13432
+ this.timeout = setTimeout(() => {
13433
+ this.reminder.refreshTimeLeft();
13434
+ this.init();
13435
+ }, timeoutLength);
13436
+ };
13437
+ this.clear = () => {
13438
+ if (this.timeout) {
13439
+ clearInterval(this.timeout);
13440
+ this.timeout = null;
13441
+ }
13442
+ };
13443
+ this.reminder = reminder;
13444
+ if (typeof config?.stopRefreshBoundaryMs === "number") {
13445
+ this.stopRefreshBoundaryMs = config.stopRefreshBoundaryMs;
13446
+ }
13447
+ }
13448
+ };
13449
+
13450
+ // src/reminders/Reminder.ts
13451
+ var timeLeftMs = (remindAt) => remindAt - (/* @__PURE__ */ new Date()).getTime();
13452
+ var _Reminder = class _Reminder {
13453
+ constructor({ data, config }) {
13454
+ this.setState = (data) => {
13455
+ this.state.next((current) => {
13456
+ const newState = { ...current, ..._Reminder.toStateValue(data) };
13457
+ if (newState.remind_at) {
13458
+ newState.timeLeftMs = timeLeftMs(newState.remind_at.getTime());
13459
+ }
13460
+ return newState;
13461
+ });
13462
+ if (data.remind_at) {
13463
+ this.initTimer();
13464
+ } else if (!data.remind_at) {
13465
+ this.clearTimer();
13466
+ }
13467
+ };
13468
+ this.refreshTimeLeft = () => {
13469
+ if (!this.remindAt) return;
13470
+ this.state.partialNext({ timeLeftMs: timeLeftMs(this.remindAt.getTime()) });
13471
+ };
13472
+ this.initTimer = () => {
13473
+ this.timer.init();
13474
+ };
13475
+ this.clearTimer = () => {
13476
+ this.timer.clear();
13477
+ };
13478
+ this.state = new StateStore(_Reminder.toStateValue(data));
13479
+ this.timer = new ReminderTimer({ reminder: this, config });
13480
+ this.initTimer();
13481
+ }
13482
+ get id() {
13483
+ return this.state.getLatestValue().message_id;
13484
+ }
13485
+ get remindAt() {
13486
+ return this.state.getLatestValue().remind_at;
13487
+ }
13488
+ get timeLeftMs() {
13489
+ return this.state.getLatestValue().timeLeftMs;
13490
+ }
13491
+ };
13492
+ _Reminder.toStateValue = (data) => ({
13493
+ ...data,
13494
+ created_at: new Date(data.created_at),
13495
+ message: data.message || null,
13496
+ remind_at: data.remind_at ? new Date(data.remind_at) : null,
13497
+ timeLeftMs: data.remind_at ? timeLeftMs(new Date(data.remind_at).getTime()) : null,
13498
+ updated_at: new Date(data.updated_at),
13499
+ user: data.user || null
13500
+ });
13501
+ var Reminder = _Reminder;
13502
+
13503
+ // src/pagination/BasePaginator.ts
13504
+ var DEFAULT_PAGINATION_OPTIONS = {
13505
+ debounceMs: 300,
13506
+ pageSize: 10
13507
+ };
13508
+ var BasePaginator = class {
13509
+ constructor(options) {
13510
+ this._isCursorPagination = false;
13511
+ this.setDebounceOptions = ({ debounceMs }) => {
13512
+ this._executeQueryDebounced = debounce(this.executeQuery.bind(this), debounceMs);
13513
+ };
13514
+ this.canExecuteQuery = (direction) => !this.isLoading && direction === "next" && this.hasNext || direction === "prev" && this.hasPrev;
13515
+ this.next = () => this.executeQuery({ direction: "next" });
13516
+ this.prev = () => this.executeQuery({ direction: "prev" });
13517
+ this.nextDebounced = () => {
13518
+ this._executeQueryDebounced({ direction: "next" });
13519
+ };
13520
+ this.prevDebounced = () => {
13521
+ this._executeQueryDebounced({ direction: "prev" });
13522
+ };
13523
+ const { debounceMs, pageSize } = { ...DEFAULT_PAGINATION_OPTIONS, ...options };
13524
+ this.pageSize = pageSize;
13525
+ this.state = new StateStore(this.initialState);
13526
+ this.setDebounceOptions({ debounceMs });
13527
+ }
13528
+ get lastQueryError() {
13529
+ return this.state.getLatestValue().lastQueryError;
13530
+ }
13531
+ get hasNext() {
13532
+ return this.state.getLatestValue().hasNext;
13533
+ }
13534
+ get hasPrev() {
13535
+ return this.state.getLatestValue().hasPrev;
13536
+ }
13537
+ get hasResults() {
13538
+ return Array.isArray(this.state.getLatestValue().items);
13539
+ }
13540
+ get isLoading() {
13541
+ return this.state.getLatestValue().isLoading;
13542
+ }
13543
+ get initialState() {
13544
+ return {
13545
+ hasNext: true,
13546
+ hasPrev: true,
13547
+ //todo: check if optimistic value does not cause problems in UI
13548
+ isLoading: false,
13549
+ items: void 0,
13550
+ lastQueryError: void 0,
13551
+ cursor: void 0,
13552
+ offset: 0
13553
+ };
13554
+ }
13555
+ get items() {
13556
+ return this.state.getLatestValue().items;
13557
+ }
13558
+ get cursor() {
13559
+ return this.state.getLatestValue().cursor;
13560
+ }
13561
+ get offset() {
13562
+ return this.state.getLatestValue().offset;
13563
+ }
13564
+ getStateBeforeFirstQuery() {
13565
+ return {
13566
+ ...this.initialState,
13567
+ isLoading: true
13568
+ };
13569
+ }
13570
+ getStateAfterQuery(stateUpdate, isFirstPage) {
13571
+ const current = this.state.getLatestValue();
13572
+ return {
13573
+ ...current,
13574
+ lastQueryError: void 0,
13575
+ // reset lastQueryError that can be overridden by the stateUpdate
13576
+ ...stateUpdate,
13577
+ isLoading: false,
13578
+ items: isFirstPage ? stateUpdate.items : [...this.items ?? [], ...stateUpdate.items || []]
13579
+ };
13580
+ }
13581
+ async executeQuery({ direction }) {
13582
+ if (!this.canExecuteQuery(direction)) return;
13583
+ const isFirstPage = typeof this.items === "undefined";
13584
+ if (isFirstPage) {
13585
+ this.state.next(this.getStateBeforeFirstQuery());
13586
+ } else {
13587
+ this.state.partialNext({ isLoading: true });
13588
+ }
13589
+ const stateUpdate = {};
13590
+ try {
13591
+ const results = await this.query({ direction });
13592
+ if (!results) return;
13593
+ const { items, next, prev } = results;
13594
+ if (isFirstPage && (next || prev)) {
13595
+ this._isCursorPagination = true;
13596
+ }
13597
+ if (this._isCursorPagination) {
13598
+ stateUpdate.cursor = { next: next || null, prev: prev || null };
13599
+ stateUpdate.hasNext = !!next;
13600
+ stateUpdate.hasPrev = !!prev;
13601
+ } else {
13602
+ stateUpdate.offset = (this.offset ?? 0) + items.length;
13603
+ stateUpdate.hasNext = items.length === this.pageSize;
13604
+ }
13605
+ stateUpdate.items = await this.filterQueryResults(items);
13606
+ } catch (e) {
13607
+ stateUpdate.lastQueryError = e;
13608
+ } finally {
13609
+ this.state.next(this.getStateAfterQuery(stateUpdate, isFirstPage));
13610
+ }
13611
+ }
13612
+ cancelScheduledQuery() {
13613
+ this._executeQueryDebounced.cancel();
13614
+ }
13615
+ resetState() {
13616
+ this.state.next(this.initialState);
13617
+ }
13618
+ };
13619
+
13620
+ // src/pagination/ReminderPaginator.ts
13621
+ var ReminderPaginator = class extends BasePaginator {
13622
+ constructor(client, options) {
13623
+ super(options);
13624
+ this.query = async ({
13625
+ direction
13626
+ }) => {
13627
+ const cursor = this.cursor?.[direction];
13628
+ const {
13629
+ reminders: items,
13630
+ next,
13631
+ prev
13632
+ } = await this.client.queryReminders({
13633
+ filter: this.filters,
13634
+ sort: this.sort,
13635
+ limit: this.pageSize,
13636
+ [direction]: cursor
13637
+ });
13638
+ return { items, next, prev };
13639
+ };
13640
+ this.filterQueryResults = (items) => items;
13641
+ this.client = client;
13642
+ }
13643
+ };
13644
+
13645
+ // src/reminders/ReminderManager.ts
13646
+ var oneMinute2 = 60 * 1e3;
13647
+ var oneHour2 = 60 * oneMinute2;
13648
+ var oneDay2 = 24 * oneHour2;
13649
+ var DEFAULT_REMINDER_MANAGER_CONFIG = {
13650
+ scheduledOffsetsMs: [
13651
+ 2 * oneMinute2,
13652
+ 30 * oneMinute2,
13653
+ oneHour2,
13654
+ 2 * oneHour2,
13655
+ 8 * oneHour2,
13656
+ oneDay2
13657
+ ]
13658
+ };
13659
+ var isReminderExistsError = (error) => error.message.match("already has reminder created for this message_id");
13660
+ var isReminderDoesNotExistError = (error) => error.message.match("reminder does not exist");
13661
+ var _ReminderManager = class _ReminderManager extends WithSubscriptions {
13662
+ constructor({ client, config }) {
13663
+ super();
13664
+ this.upsertToState = ({
13665
+ data,
13666
+ overwrite = true
13667
+ }) => {
13668
+ if (!this.client._cacheEnabled()) {
13669
+ return;
13670
+ }
13671
+ const cachedReminder = this.getFromState(data.message_id);
13672
+ if (!cachedReminder) {
13673
+ const reminder = new Reminder({
13674
+ data,
13675
+ config: { stopRefreshBoundaryMs: this.stopTimerRefreshBoundaryMs }
13676
+ });
13677
+ this.state.partialNext({
13678
+ reminders: new Map(this.reminders.set(data.message_id, reminder))
13679
+ });
13680
+ } else if (overwrite) {
13681
+ cachedReminder.setState(data);
13682
+ }
13683
+ return cachedReminder;
13684
+ };
13685
+ this.removeFromState = (messageId) => {
13686
+ const cachedReminder = this.getFromState(messageId);
13687
+ if (!cachedReminder) return;
13688
+ cachedReminder.clearTimer();
13689
+ const reminders = this.reminders;
13690
+ reminders.delete(messageId);
13691
+ this.state.partialNext({ reminders: new Map(reminders) });
13692
+ };
13693
+ this.hydrateState = (messages) => {
13694
+ messages.forEach(({ reminder }) => {
13695
+ if (reminder) {
13696
+ this.upsertToState({ data: reminder });
13697
+ }
13698
+ });
13699
+ };
13700
+ // State API END //
13701
+ // Timers API START //
13702
+ this.initTimers = () => {
13703
+ this.reminders.forEach((reminder) => reminder.initTimer());
13704
+ };
13705
+ this.clearTimers = () => {
13706
+ this.reminders.forEach((reminder) => reminder.clearTimer());
13707
+ };
13708
+ this.registerSubscriptions = () => {
13709
+ if (this.hasSubscriptions) return;
13710
+ this.addUnsubscribeFunction(this.subscribeReminderCreated());
13711
+ this.addUnsubscribeFunction(this.subscribeReminderUpdated());
13712
+ this.addUnsubscribeFunction(this.subscribeReminderDeleted());
13713
+ this.addUnsubscribeFunction(this.subscribeNotificationReminderDue());
13714
+ this.addUnsubscribeFunction(this.subscribeMessageDeleted());
13715
+ this.addUnsubscribeFunction(this.subscribeMessageUndeleted());
13716
+ this.addUnsubscribeFunction(this.subscribePaginatorStateUpdated());
13717
+ this.addUnsubscribeFunction(this.subscribeConfigStateUpdated());
13718
+ };
13719
+ this.subscribeReminderCreated = () => this.client.on("reminder.created", (event) => {
13720
+ if (!_ReminderManager.isReminderWsEventPayload(event)) return;
13721
+ const { reminder } = event;
13722
+ this.upsertToState({ data: reminder });
13723
+ }).unsubscribe;
13724
+ this.subscribeReminderUpdated = () => this.client.on("reminder.updated", (event) => {
13725
+ if (!_ReminderManager.isReminderWsEventPayload(event)) return;
13726
+ const { reminder } = event;
13727
+ this.upsertToState({ data: reminder });
13728
+ }).unsubscribe;
13729
+ this.subscribeReminderDeleted = () => this.client.on("reminder.deleted", (event) => {
13730
+ if (!_ReminderManager.isReminderWsEventPayload(event)) return;
13731
+ this.removeFromState(event.message_id);
13732
+ }).unsubscribe;
13733
+ this.subscribeMessageDeleted = () => this.client.on("message.deleted", (event) => {
13734
+ if (!event.message?.id) return;
13735
+ this.removeFromState(event.message.id);
13736
+ }).unsubscribe;
13737
+ this.subscribeMessageUndeleted = () => this.client.on("message.undeleted", (event) => {
13738
+ if (!event.message?.reminder) return;
13739
+ this.upsertToState({ data: event.message.reminder });
13740
+ }).unsubscribe;
13741
+ this.subscribeNotificationReminderDue = () => this.client.on("notification.reminder_due", () => null).unsubscribe;
13742
+ // todo: what should be performed on this event?
13743
+ this.subscribePaginatorStateUpdated = () => this.paginator.state.subscribeWithSelector(
13744
+ ({ items }) => [items],
13745
+ ([items]) => {
13746
+ if (!items) return;
13747
+ for (const reminder of items) {
13748
+ this.upsertToState({ data: reminder });
13749
+ }
13750
+ }
13751
+ );
13752
+ this.subscribeConfigStateUpdated = () => this.configState.subscribeWithSelector(
13753
+ ({ stopTimerRefreshBoundaryMs }) => ({ stopTimerRefreshBoundaryMs }),
13754
+ ({ stopTimerRefreshBoundaryMs }, previousValue) => {
13755
+ if (typeof stopTimerRefreshBoundaryMs === "number" && stopTimerRefreshBoundaryMs !== previousValue?.stopTimerRefreshBoundaryMs) {
13756
+ this.reminders.forEach((reminder) => {
13757
+ if (reminder.timer) {
13758
+ reminder.timer.stopRefreshBoundaryMs = stopTimerRefreshBoundaryMs;
13759
+ }
13760
+ });
13761
+ }
13762
+ }
13763
+ );
13764
+ // WS event handling END //
13765
+ // API calls START //
13766
+ this.upsertReminder = async (options) => {
13767
+ const { messageId } = options;
13768
+ if (this.getFromState(messageId)) {
13769
+ try {
13770
+ return await this.updateReminder(options);
13771
+ } catch (error) {
13772
+ if (isReminderDoesNotExistError(error)) {
13773
+ return await this.createReminder(options);
13774
+ }
13775
+ throw error;
13776
+ }
13777
+ } else {
13778
+ try {
13779
+ return await this.createReminder(options);
13780
+ } catch (error) {
13781
+ if (isReminderExistsError(error)) {
13782
+ return await this.updateReminder(options);
13783
+ }
13784
+ throw error;
13785
+ }
13786
+ }
13787
+ };
13788
+ this.createReminder = async (options) => {
13789
+ const { reminder } = await this.client.createReminder(options);
13790
+ return this.upsertToState({ data: reminder, overwrite: false });
13791
+ };
13792
+ this.updateReminder = async (options) => {
13793
+ const { reminder } = await this.client.updateReminder(options);
13794
+ return this.upsertToState({ data: reminder });
13795
+ };
13796
+ this.deleteReminder = async (messageId) => {
13797
+ await this.client.deleteReminder(messageId);
13798
+ this.removeFromState(messageId);
13799
+ };
13800
+ this.queryNextReminders = async () => {
13801
+ await this.paginator.next();
13802
+ };
13803
+ this.queryPreviousReminders = async () => {
13804
+ await this.paginator.prev();
13805
+ };
13806
+ this.client = client;
13807
+ this.configState = new StateStore({
13808
+ scheduledOffsetsMs: config?.scheduledOffsetsMs ?? DEFAULT_REMINDER_MANAGER_CONFIG.scheduledOffsetsMs
13809
+ });
13810
+ this.state = new StateStore({ reminders: /* @__PURE__ */ new Map() });
13811
+ this.paginator = new ReminderPaginator(client);
13812
+ }
13813
+ // Config API START //
13814
+ updateConfig(config) {
13815
+ this.configState.partialNext(config);
13816
+ }
13817
+ get stopTimerRefreshBoundaryMs() {
13818
+ return this.configState.getLatestValue().stopTimerRefreshBoundaryMs;
13819
+ }
13820
+ get scheduledOffsetsMs() {
13821
+ return this.configState.getLatestValue().scheduledOffsetsMs;
13822
+ }
13823
+ // Config API END //
13824
+ // State API START //
13825
+ get reminders() {
13826
+ return this.state.getLatestValue().reminders;
13827
+ }
13828
+ getFromState(messageId) {
13829
+ return this.reminders.get(messageId);
13830
+ }
13831
+ // API calls END //
13832
+ };
13833
+ // Timers API END //
13834
+ // WS event handling START //
13835
+ _ReminderManager.isReminderWsEventPayload = (event) => !!event.reminder && (event.type.startsWith("reminder.") || event.type === "notification.reminder_due");
13836
+ var ReminderManager = _ReminderManager;
13837
+
13208
13838
  // src/client.ts
13209
13839
  function isString3(x) {
13210
13840
  return typeof x === "string" || x instanceof String;
@@ -13220,6 +13850,9 @@ var StreamChat = class _StreamChat {
13220
13850
  });
13221
13851
  this._getConnectionID = () => this.wsConnection?.connectionID || this.wsFallback?.connectionID;
13222
13852
  this._hasConnectionID = () => Boolean(this._getConnectionID());
13853
+ this.setMessageComposerSetupFunction = (setupFunction) => {
13854
+ this._messageComposerSetupState.partialNext({ setupFunction });
13855
+ };
13223
13856
  /**
13224
13857
  * connectUser - Set the current user and open a WebSocket connection
13225
13858
  *
@@ -13788,9 +14421,6 @@ var StreamChat = class _StreamChat {
13788
14421
  device: this.options.device,
13789
14422
  client_request_id
13790
14423
  });
13791
- this.setMessageComposerSetupFunction = (setupFunction) => {
13792
- this._messageComposerSetupState.partialNext({ setupFunction });
13793
- };
13794
14424
  this.key = key;
13795
14425
  this.listeners = {};
13796
14426
  this.state = new ClientState({ client: this });
@@ -13845,6 +14475,7 @@ var StreamChat = class _StreamChat {
13845
14475
  this.recoverStateOnReconnect = this.options.recoverStateOnReconnect;
13846
14476
  this.threads = new ThreadManager({ client: this });
13847
14477
  this.polls = new PollManager({ client: this });
14478
+ this.reminders = new ReminderManager({ client: this });
13848
14479
  }
13849
14480
  static getInstance(key, secretOrOptions, options) {
13850
14481
  if (!_StreamChat._instance) {
@@ -13980,15 +14611,15 @@ var StreamChat = class _StreamChat {
13980
14611
  * @param {string} userID User ID. If user has no devices, it will error
13981
14612
  * @param {TestPushDataInput} [data] Overrides for push templates/message used
13982
14613
  * IE: {
13983
- messageID: 'id-of-message', // will error if message does not exist
13984
- apnTemplate: '{}', // if app doesn't have apn configured it will error
13985
- firebaseTemplate: '{}', // if app doesn't have firebase configured it will error
13986
- firebaseDataTemplate: '{}', // if app doesn't have firebase configured it will error
13987
- skipDevices: true, // skip config/device checks and sending to real devices
13988
- pushProviderName: 'staging' // one of your configured push providers
13989
- pushProviderType: 'apn' // one of supported provider types
13990
- }
13991
- */
14614
+ messageID: 'id-of-message', // will error if message does not exist
14615
+ apnTemplate: '{}', // if app doesn't have apn configured it will error
14616
+ firebaseTemplate: '{}', // if app doesn't have firebase configured it will error
14617
+ firebaseDataTemplate: '{}', // if app doesn't have firebase configured it will error
14618
+ skipDevices: true, // skip config/device checks and sending to real devices
14619
+ pushProviderName: 'staging' // one of your configured push providers
14620
+ pushProviderType: 'apn' // one of supported provider types
14621
+ }
14622
+ */
13992
14623
  async testPushSettings(userID, data = {}) {
13993
14624
  return await this.post(this.baseURL + "/check_push", {
13994
14625
  user_id: userID,
@@ -14006,10 +14637,10 @@ var StreamChat = class _StreamChat {
14006
14637
  *
14007
14638
  * @param {TestSQSDataInput} [data] Overrides SQS settings for testing if needed
14008
14639
  * IE: {
14009
- sqs_key: 'auth_key',
14010
- sqs_secret: 'auth_secret',
14011
- sqs_url: 'url_to_queue',
14012
- }
14640
+ sqs_key: 'auth_key',
14641
+ sqs_secret: 'auth_secret',
14642
+ sqs_url: 'url_to_queue',
14643
+ }
14013
14644
  */
14014
14645
  async testSQSSettings(data = {}) {
14015
14646
  return await this.post(this.baseURL + "/check_sqs", data);
@@ -14019,10 +14650,10 @@ var StreamChat = class _StreamChat {
14019
14650
  *
14020
14651
  * @param {TestSNSDataInput} [data] Overrides SNS settings for testing if needed
14021
14652
  * IE: {
14022
- sns_key: 'auth_key',
14023
- sns_secret: 'auth_secret',
14024
- sns_topic_arn: 'topic_to_publish_to',
14025
- }
14653
+ sns_key: 'auth_key',
14654
+ sns_secret: 'auth_secret',
14655
+ sns_topic_arn: 'topic_to_publish_to',
14656
+ }
14026
14657
  */
14027
14658
  async testSNSSettings(data = {}) {
14028
14659
  return await this.post(this.baseURL + "/check_sns", data);
@@ -14503,6 +15134,7 @@ var StreamChat = class _StreamChat {
14503
15134
  })
14504
15135
  };
14505
15136
  this.polls.hydratePollCache(channelState.messages, true);
15137
+ this.reminders.hydrateState(channelState.messages);
14506
15138
  }
14507
15139
  if (channelState.draft) {
14508
15140
  c.messageComposer.initState({ composition: channelState.draft });
@@ -15423,7 +16055,7 @@ var StreamChat = class _StreamChat {
15423
16055
  if (this.userAgent) {
15424
16056
  return this.userAgent;
15425
16057
  }
15426
- const version = "9.3.0";
16058
+ const version = "9.5.0";
15427
16059
  const clientBundle = "browser-esm";
15428
16060
  let userAgentString = "";
15429
16061
  if (this.sdkIdentifier) {
@@ -16462,6 +17094,56 @@ var StreamChat = class _StreamChat {
16462
17094
  };
16463
17095
  return await this.post(this.baseURL + "/drafts/query", payload);
16464
17096
  }
17097
+ /**
17098
+ * createReminder - Creates a reminder for a message
17099
+ *
17100
+ * @param {CreateReminderOptions} options The options for creating the reminder
17101
+ * @returns {Promise<ReminderAPIResponse>}
17102
+ */
17103
+ async createReminder({ messageId, ...options }) {
17104
+ return await this.post(
17105
+ `${this.baseURL}/messages/${messageId}/reminders`,
17106
+ options
17107
+ );
17108
+ }
17109
+ /**
17110
+ * updateReminder - Updates an existing reminder for a message
17111
+ *
17112
+ * @param {UpdateReminderOptions} options The options for updating the reminder
17113
+ * @returns {Promise<ReminderAPIResponse>}
17114
+ */
17115
+ async updateReminder({ messageId, ...options }) {
17116
+ return await this.patch(
17117
+ `${this.baseURL}/messages/${messageId}/reminders`,
17118
+ options
17119
+ );
17120
+ }
17121
+ /**
17122
+ * deleteReminder - Deletes a reminder for a message
17123
+ *
17124
+ * @param {string} messageId The ID of the message whose reminder to delete
17125
+ * @param {string} [userId] Optional user ID, required for server-side operations
17126
+ * @returns {Promise<APIResponse>}
17127
+ */
17128
+ async deleteReminder(messageId, userId) {
17129
+ return await this.delete(
17130
+ `${this.baseURL}/messages/${messageId}/reminders`,
17131
+ userId ? { user_id: userId } : {}
17132
+ );
17133
+ }
17134
+ /**
17135
+ * queryReminders - Queries reminders based on given filters
17136
+ *
17137
+ * @param {QueryRemindersOptions} options The options for querying reminders
17138
+ * @returns {Promise<QueryRemindersResponse>}
17139
+ */
17140
+ async queryReminders({ filter: filter2, sort, ...rest } = {}) {
17141
+ return await this.post(`${this.baseURL}/reminders/query`, {
17142
+ filter_conditions: filter2,
17143
+ sort: sort && normalizeQuerySort(sort),
17144
+ ...rest
17145
+ });
17146
+ }
16465
17147
  };
16466
17148
 
16467
17149
  // src/events.ts
@@ -16528,7 +17210,12 @@ var EVENT_MAP = {
16528
17210
  "connection.changed": true,
16529
17211
  "connection.recovered": true,
16530
17212
  "transport.changed": true,
16531
- "capabilities.changed": true
17213
+ "capabilities.changed": true,
17214
+ // Reminder events
17215
+ "reminder.created": true,
17216
+ "reminder.updated": true,
17217
+ "reminder.deleted": true,
17218
+ "notification.reminder_due": true
16532
17219
  };
16533
17220
 
16534
17221
  // src/permissions.ts
@@ -17400,6 +18087,7 @@ export {
17400
18087
  AnyResource,
17401
18088
  AnyRole,
17402
18089
  AttachmentManager,
18090
+ BasePaginator,
17403
18091
  BaseSearchSource,
17404
18092
  BuiltinPermissions,
17405
18093
  BuiltinRoles,
@@ -17417,6 +18105,9 @@ export {
17417
18105
  DEFAULT_CHANNEL_MANAGER_PAGINATION_OPTIONS,
17418
18106
  DEFAULT_COMPOSER_CONFIG,
17419
18107
  DEFAULT_LINK_PREVIEW_MANAGER_CONFIG,
18108
+ DEFAULT_PAGINATION_OPTIONS,
18109
+ DEFAULT_REMINDER_MANAGER_CONFIG,
18110
+ DEFAULT_STOP_REFRESH_BOUNDARY_MS,
17420
18111
  DEFAULT_TEXT_COMPOSER_CONFIG,
17421
18112
  Deny,
17422
18113
  DenyAll,
@@ -17433,6 +18124,7 @@ export {
17433
18124
  MODERATION_ENTITY_TYPES,
17434
18125
  MaxPriority,
17435
18126
  MentionsSearchSource,
18127
+ MergedStateStore,
17436
18128
  MessageComposer,
17437
18129
  MessageComposerMiddlewareExecutor,
17438
18130
  MessageDraftComposerMiddlewareExecutor,
@@ -17448,6 +18140,10 @@ export {
17448
18140
  PollComposerCompositionMiddlewareExecutor,
17449
18141
  PollComposerStateMiddlewareExecutor,
17450
18142
  PollManager,
18143
+ Reminder,
18144
+ ReminderManager,
18145
+ ReminderPaginator,
18146
+ ReminderTimer,
17451
18147
  SearchController,
17452
18148
  Segment,
17453
18149
  StableWSConnection,
@@ -17535,6 +18231,7 @@ export {
17535
18231
  readFileAsArrayBuffer,
17536
18232
  removeDiacritics,
17537
18233
  replaceWordWithEntity,
17538
- textIsEmpty
18234
+ textIsEmpty,
18235
+ timeLeftMs
17539
18236
  };
17540
18237
  //# sourceMappingURL=index.js.map