stream-chat 9.2.0 → 9.4.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.
@@ -9631,7 +9631,7 @@ var require_common = __commonJS({
9631
9631
  createDebug.namespaces = namespaces;
9632
9632
  createDebug.names = [];
9633
9633
  createDebug.skips = [];
9634
- const split = (typeof namespaces === "string" ? namespaces : "").trim().replace(" ", ",").split(",").filter(Boolean);
9634
+ const split = (typeof namespaces === "string" ? namespaces : "").trim().replace(/\s+/g, ",").split(",").filter(Boolean);
9635
9635
  for (const ns of split) {
9636
9636
  if (ns[0] === "-") {
9637
9637
  createDebug.skips.push(ns.slice(1));
@@ -9849,7 +9849,7 @@ var require_browser = __commonJS({
9849
9849
  function load() {
9850
9850
  let r;
9851
9851
  try {
9852
- r = exports2.storage.getItem("debug");
9852
+ r = exports2.storage.getItem("debug") || exports2.storage.getItem("DEBUG");
9853
9853
  } catch (error) {
9854
9854
  }
9855
9855
  if (!r && typeof process !== "undefined" && "env" in process) {
@@ -10233,7 +10233,7 @@ var require_follow_redirects = __commonJS({
10233
10233
  "ERR_STREAM_WRITE_AFTER_END",
10234
10234
  "write after end"
10235
10235
  );
10236
- var destroy = Writable.prototype.destroy || noop3;
10236
+ var destroy = Writable.prototype.destroy || noop4;
10237
10237
  function RedirectableRequest(options, responseCallback) {
10238
10238
  Writable.call(this);
10239
10239
  this._sanitizeOptions(options);
@@ -10585,7 +10585,7 @@ var require_follow_redirects = __commonJS({
10585
10585
  });
10586
10586
  return exports3;
10587
10587
  }
10588
- function noop3() {
10588
+ function noop4() {
10589
10589
  }
10590
10590
  function urlToOptions(urlObject) {
10591
10591
  var options = {
@@ -10631,7 +10631,7 @@ var require_follow_redirects = __commonJS({
10631
10631
  for (var event of events) {
10632
10632
  request.removeListener(event, eventHandlers[event]);
10633
10633
  }
10634
- request.on("error", noop3);
10634
+ request.on("error", noop4);
10635
10635
  request.destroy(error);
10636
10636
  }
10637
10637
  function isSubdomain(subdomain, domain) {
@@ -10703,6 +10703,7 @@ __export(index_exports, {
10703
10703
  MODERATION_ENTITY_TYPES: () => MODERATION_ENTITY_TYPES,
10704
10704
  MaxPriority: () => MaxPriority,
10705
10705
  MentionsSearchSource: () => MentionsSearchSource,
10706
+ MergedStateStore: () => MergedStateStore,
10706
10707
  MessageComposer: () => MessageComposer,
10707
10708
  MessageComposerMiddlewareExecutor: () => MessageComposerMiddlewareExecutor,
10708
10709
  MessageDraftComposerMiddlewareExecutor: () => MessageDraftComposerMiddlewareExecutor,
@@ -10711,6 +10712,7 @@ __export(index_exports, {
10711
10712
  MinPriority: () => MinPriority,
10712
10713
  Moderation: () => Moderation,
10713
10714
  OfflineDBSyncManager: () => OfflineDBSyncManager,
10715
+ OfflineError: () => OfflineError,
10714
10716
  Permission: () => Permission,
10715
10717
  Poll: () => Poll,
10716
10718
  PollComposer: () => PollComposer,
@@ -15390,26 +15392,14 @@ var ensureIsLocalAttachment = (attachment) => {
15390
15392
 
15391
15393
  // src/store.ts
15392
15394
  var isPatch = (value) => typeof value === "function";
15395
+ var noop2 = () => {
15396
+ };
15393
15397
  var StateStore = class {
15394
15398
  constructor(value) {
15395
15399
  this.value = value;
15396
- this.handlerSet = /* @__PURE__ */ new Set();
15397
- this.next = (newValueOrPatch) => {
15398
- const newValue = isPatch(newValueOrPatch) ? newValueOrPatch(this.value) : newValueOrPatch;
15399
- if (newValue === this.value) return;
15400
- const oldValue = this.value;
15401
- this.value = newValue;
15402
- this.handlerSet.forEach((handler) => handler(this.value, oldValue));
15403
- };
15400
+ this.handlers = /* @__PURE__ */ new Set();
15401
+ this.preprocessors = /* @__PURE__ */ new Set();
15404
15402
  this.partialNext = (partial) => this.next((current) => ({ ...current, ...partial }));
15405
- this.getLatestValue = () => this.value;
15406
- this.subscribe = (handler) => {
15407
- handler(this.value, void 0);
15408
- this.handlerSet.add(handler);
15409
- return () => {
15410
- this.handlerSet.delete(handler);
15411
- };
15412
- };
15413
15403
  this.subscribeWithSelector = (selector, handler) => {
15414
15404
  let previouslySelectedValues;
15415
15405
  const wrappedHandler = (nextValue) => {
@@ -15428,6 +15418,183 @@ var StateStore = class {
15428
15418
  return this.subscribe(wrappedHandler);
15429
15419
  };
15430
15420
  }
15421
+ /**
15422
+ * Allows merging two stores only if their keys differ otherwise there's no way to ensure the data type stability.
15423
+ * @experimental
15424
+ * This method is experimental and may change in future versions.
15425
+ */
15426
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
15427
+ merge(stateStore) {
15428
+ return new MergedStateStore({
15429
+ original: this,
15430
+ merged: stateStore
15431
+ });
15432
+ }
15433
+ next(newValueOrPatch) {
15434
+ const newValue = isPatch(newValueOrPatch) ? newValueOrPatch(this.value) : newValueOrPatch;
15435
+ if (newValue === this.value) return;
15436
+ this.preprocessors.forEach((preprocessor) => preprocessor(newValue, this.value));
15437
+ const oldValue = this.value;
15438
+ this.value = newValue;
15439
+ this.handlers.forEach((handler) => handler(this.value, oldValue));
15440
+ }
15441
+ getLatestValue() {
15442
+ return this.value;
15443
+ }
15444
+ subscribe(handler) {
15445
+ handler(this.value, void 0);
15446
+ this.handlers.add(handler);
15447
+ return () => {
15448
+ this.handlers.delete(handler);
15449
+ };
15450
+ }
15451
+ /**
15452
+ * Registers a preprocessor function that will be called before the state is updated.
15453
+ *
15454
+ * Preprocessors are invoked with the new and previous values whenever `next` or `partialNext` methods
15455
+ * are called, allowing you to mutate or react to the new value before it is set. Preprocessors run in the
15456
+ * order they were registered.
15457
+ *
15458
+ * @example
15459
+ * ```ts
15460
+ * const store = new StateStore<{ count: number; isMaxValue: bool; }>({ count: 0, isMaxValue: false });
15461
+ *
15462
+ * store.addPreprocessor((nextValue, prevValue) => {
15463
+ * if (nextValue.count > 10) {
15464
+ * nextValue.count = 10; // Clamp the value to a maximum of 10
15465
+ * }
15466
+ *
15467
+ * if (nextValue.count === 10) {
15468
+ * nextValue.isMaxValue = true; // Set isMaxValue to true if count is 10
15469
+ * } else {
15470
+ * nextValue.isMaxValue = false; // Reset isMaxValue otherwise
15471
+ * }
15472
+ * });
15473
+ *
15474
+ * store.partialNext({ count: 15 });
15475
+ *
15476
+ * store.getLatestValue(); // { count: 10, isMaxValue: true }
15477
+ *
15478
+ * store.partialNext({ count: 5 });
15479
+ *
15480
+ * store.getLatestValue(); // { count: 5, isMaxValue: false }
15481
+ * ```
15482
+ *
15483
+ * @param preprocessor - The function to be called with the next and previous values before the state is updated.
15484
+ * @returns A `RemovePreprocessor` function that removes the preprocessor when called.
15485
+ */
15486
+ addPreprocessor(preprocessor) {
15487
+ this.preprocessors.add(preprocessor);
15488
+ return () => {
15489
+ this.preprocessors.delete(preprocessor);
15490
+ };
15491
+ }
15492
+ };
15493
+ var MergedStateStore = class _MergedStateStore extends StateStore {
15494
+ constructor({ original, merged }) {
15495
+ const originalValue = original.getLatestValue();
15496
+ const mergedValue = merged.getLatestValue();
15497
+ super({
15498
+ ...originalValue,
15499
+ ...mergedValue
15500
+ });
15501
+ // override original methods and "disable" them
15502
+ this.next = () => {
15503
+ console.warn(
15504
+ `${_MergedStateStore.name}.next is disabled, call original.next or merged.next instead`
15505
+ );
15506
+ };
15507
+ this.partialNext = () => {
15508
+ console.warn(
15509
+ `${_MergedStateStore.name}.partialNext is disabled, call original.partialNext or merged.partialNext instead`
15510
+ );
15511
+ };
15512
+ this.cachedOriginalValue = originalValue;
15513
+ this.cachedMergedValue = mergedValue;
15514
+ this.original = original;
15515
+ this.merged = merged;
15516
+ }
15517
+ /**
15518
+ * Subscribes to changes in the merged state store.
15519
+ *
15520
+ * This method extends the base subscribe functionality to handle the merged nature of this store:
15521
+ * 1. The first subscriber triggers registration of helper subscribers that listen to both source stores
15522
+ * 2. Changes from either source store are propagated to this merged store
15523
+ * 3. Source store values are cached to prevent unnecessary updates
15524
+ *
15525
+ * When the first subscriber is added, the method sets up listeners on both original and merged stores.
15526
+ * These listeners update the combined store value whenever either source store changes.
15527
+ * All subscriptions (helpers and the actual handler) are tracked so they can be properly cleaned up.
15528
+ *
15529
+ * @param handler - The callback function that will be executed when the state changes
15530
+ * @returns An unsubscribe function that, when called, removes the subscription and any helper subscriptions
15531
+ */
15532
+ subscribe(handler) {
15533
+ const unsubscribeFunctions = [];
15534
+ if (!this.handlers.size) {
15535
+ const base = (nextValue) => {
15536
+ super.next((currentValue) => ({
15537
+ ...currentValue,
15538
+ ...nextValue
15539
+ }));
15540
+ };
15541
+ unsubscribeFunctions.push(
15542
+ this.original.subscribe((nextValue) => {
15543
+ if (nextValue === this.cachedOriginalValue) return;
15544
+ this.cachedOriginalValue = nextValue;
15545
+ base(nextValue);
15546
+ }),
15547
+ this.merged.subscribe((nextValue) => {
15548
+ if (nextValue === this.cachedMergedValue) return;
15549
+ this.cachedMergedValue = nextValue;
15550
+ base(nextValue);
15551
+ })
15552
+ );
15553
+ }
15554
+ unsubscribeFunctions.push(super.subscribe(handler));
15555
+ return () => {
15556
+ unsubscribeFunctions.forEach((unsubscribe) => unsubscribe());
15557
+ };
15558
+ }
15559
+ /**
15560
+ * Retrieves the latest combined state from both original and merged stores.
15561
+ *
15562
+ * This method extends the base getLatestValue functionality to ensure the merged store
15563
+ * remains in sync with its source stores even when there are no active subscribers.
15564
+ *
15565
+ * When there are no handlers registered, the method:
15566
+ * 1. Fetches the latest values from both source stores
15567
+ * 2. Compares them with the cached values to detect changes
15568
+ * 3. If changes are detected, updates the internal value and caches
15569
+ * the new source values to maintain consistency
15570
+ *
15571
+ * This approach ensures that calling getLatestValue() always returns the most
15572
+ * up-to-date combined state, even if the merged store hasn't been actively
15573
+ * receiving updates through subscriptions.
15574
+ *
15575
+ * @returns The latest combined state from both original and merged stores
15576
+ */
15577
+ getLatestValue() {
15578
+ if (!this.handlers.size) {
15579
+ const originalValue = this.original.getLatestValue();
15580
+ const mergedValue = this.merged.getLatestValue();
15581
+ if (originalValue !== this.cachedOriginalValue || mergedValue !== this.cachedMergedValue) {
15582
+ this.value = {
15583
+ ...originalValue,
15584
+ ...mergedValue
15585
+ };
15586
+ this.cachedMergedValue = mergedValue;
15587
+ this.cachedOriginalValue = originalValue;
15588
+ }
15589
+ }
15590
+ return super.getLatestValue();
15591
+ }
15592
+ addPreprocessor() {
15593
+ console.warn(
15594
+ `${_MergedStateStore.name}.addPreprocessor is disabled, call original.addPreprocessor or merged.addPreprocessor instead`
15595
+ );
15596
+ return noop2;
15597
+ }
15431
15598
  };
15432
15599
 
15433
15600
  // src/utils/mergeWith/mergeWithCore.ts
@@ -15672,6 +15839,12 @@ function createMergeCore(options = {}) {
15672
15839
  return false;
15673
15840
  }
15674
15841
  function createNewTarget(targetValue, srcValue) {
15842
+ if (targetValue === null || typeof targetValue === "undefined") {
15843
+ return srcValue;
15844
+ }
15845
+ if (!Array.isArray(targetValue) && typeof targetValue !== "object") {
15846
+ return srcValue;
15847
+ }
15675
15848
  if (targetValue && typeof targetValue === "object") {
15676
15849
  const isTargetClassInstance = isClassInstance(targetValue);
15677
15850
  const isSourceClassInstance = isClassInstance(srcValue);
@@ -16841,7 +17014,9 @@ var ErrorFromResponse = class extends Error {
16841
17014
  return {
16842
17015
  message: `(${joinable.join(", ")}) - ${this.message}`,
16843
17016
  stack: this.stack,
16844
- name: this.name
17017
+ name: this.name,
17018
+ code: this.code,
17019
+ status: this.status
16845
17020
  };
16846
17021
  }
16847
17022
  };
@@ -18974,7 +19149,7 @@ var initState5 = (composition) => {
18974
19149
  pollId: message.poll_id ?? null
18975
19150
  };
18976
19151
  };
18977
- var noop2 = () => void 0;
19152
+ var noop3 = () => void 0;
18978
19153
  var _MessageComposer = class _MessageComposer extends WithSubscriptions {
18979
19154
  // todo: mediaRecorder: MediaRecorderController;
18980
19155
  constructor({
@@ -19002,7 +19177,7 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
19002
19177
  this.initEditingAuditState = (composition) => initEditingAuditState(composition);
19003
19178
  this.registerSubscriptions = () => {
19004
19179
  if (this.hasSubscriptions) {
19005
- return noop2;
19180
+ return noop3;
19006
19181
  }
19007
19182
  this.addUnsubscribeFunction(this.subscribeMessageComposerSetupStateChange());
19008
19183
  this.addUnsubscribeFunction(this.subscribeMessageUpdated());
@@ -24243,7 +24418,24 @@ var StreamChat = class _StreamChat {
24243
24418
  'data_template': 'data handlebars template',
24244
24419
  'apn_template': 'apn notification handlebars template under v2'
24245
24420
  },
24246
- 'webhook_url': 'https://acme.com/my/awesome/webhook/'
24421
+ 'webhook_url': 'https://acme.com/my/awesome/webhook/',
24422
+ 'event_hooks': [
24423
+ {
24424
+ 'hook_type': 'webhook',
24425
+ 'enabled': true,
24426
+ 'event_types': ['message.new'],
24427
+ 'webhook_url': 'https://acme.com/my/awesome/webhook/'
24428
+ },
24429
+ {
24430
+ 'hook_type': 'sqs',
24431
+ 'enabled': true,
24432
+ 'event_types': ['message.new'],
24433
+ 'sqs_url': 'https://sqs.us-east-1.amazonaws.com/1234567890/my-queue',
24434
+ 'sqs_auth_type': 'key',
24435
+ 'sqs_key': 'my-access-key',
24436
+ 'sqs_secret': 'my-secret-key'
24437
+ }
24438
+ ]
24247
24439
  }
24248
24440
  */
24249
24441
  async updateAppSettings(options) {
@@ -25587,13 +25779,15 @@ var StreamChat = class _StreamChat {
25587
25779
  } else {
25588
25780
  await this.offlineDb.softDeleteMessage({ id: messageID });
25589
25781
  }
25590
- return await this.offlineDb.queueTask({
25591
- task: {
25592
- messageId: messageID,
25593
- payload: [messageID, hardDelete],
25594
- type: "delete-message"
25782
+ return await this.offlineDb.queueTask(
25783
+ {
25784
+ task: {
25785
+ messageId: messageID,
25786
+ payload: [messageID, hardDelete],
25787
+ type: "delete-message"
25788
+ }
25595
25789
  }
25596
- });
25790
+ );
25597
25791
  }
25598
25792
  } catch (error) {
25599
25793
  this.logger("error", `offlineDb:deleteMessage`, {
@@ -25747,7 +25941,7 @@ var StreamChat = class _StreamChat {
25747
25941
  if (this.userAgent) {
25748
25942
  return this.userAgent;
25749
25943
  }
25750
- const version = "9.2.0";
25944
+ const version = "9.4.0";
25751
25945
  const clientBundle = "node-cjs";
25752
25946
  let userAgentString = "";
25753
25947
  if (this.sdkIdentifier) {
@@ -26923,6 +27117,26 @@ var BuiltinPermissions = {
26923
27117
  UseFrozenChannel: "Send messages and reactions to frozen channels"
26924
27118
  };
26925
27119
 
27120
+ // src/offline-support/types.ts
27121
+ var OfflineError = class extends Error {
27122
+ constructor(message, {
27123
+ type
27124
+ }) {
27125
+ super(message);
27126
+ this.name = "OfflineError";
27127
+ this.type = type;
27128
+ }
27129
+ // Vitest helper (serialized errors are too large to read)
27130
+ // https://github.com/vitest-dev/vitest/blob/v3.1.3/packages/utils/src/error.ts#L60-L62
27131
+ toJSON() {
27132
+ return {
27133
+ message: `${this.type} - ${this.message}`,
27134
+ stack: this.stack,
27135
+ name: this.name
27136
+ };
27137
+ }
27138
+ };
27139
+
26926
27140
  // src/offline-support/offline_sync_manager.ts
26927
27141
  var OfflineDBSyncManager = class {
26928
27142
  constructor({
@@ -27528,20 +27742,23 @@ var AbstractOfflineDB = class {
27528
27742
  * @param task - the pending task we want to execute
27529
27743
  */
27530
27744
  this.queueTask = async ({ task }) => {
27531
- let response;
27532
- try {
27745
+ const attemptTaskExecution = async () => {
27533
27746
  if (!this.client.wsConnection?.isHealthy) {
27534
- await this.addPendingTask(task);
27535
- return;
27747
+ throw new OfflineError(
27748
+ "Cannot execute task because the connection has been lost.",
27749
+ { type: "connection:lost" }
27750
+ );
27536
27751
  }
27537
- response = await this.executeTask({ task });
27752
+ return await this.executeTask({ task });
27753
+ };
27754
+ try {
27755
+ return await attemptTaskExecution();
27538
27756
  } catch (e) {
27539
27757
  if (!this.shouldSkipQueueingTask(e)) {
27540
27758
  await this.addPendingTask(task);
27541
- throw e;
27542
27759
  }
27760
+ throw e;
27543
27761
  }
27544
- return response;
27545
27762
  };
27546
27763
  /**
27547
27764
  * A utility method that determines if a failed task should be added to the
@@ -27735,6 +27952,7 @@ var FixedSizeQueueCache = class {
27735
27952
  MODERATION_ENTITY_TYPES,
27736
27953
  MaxPriority,
27737
27954
  MentionsSearchSource,
27955
+ MergedStateStore,
27738
27956
  MessageComposer,
27739
27957
  MessageComposerMiddlewareExecutor,
27740
27958
  MessageDraftComposerMiddlewareExecutor,
@@ -27743,6 +27961,7 @@ var FixedSizeQueueCache = class {
27743
27961
  MinPriority,
27744
27962
  Moderation,
27745
27963
  OfflineDBSyncManager,
27964
+ OfflineError,
27746
27965
  Permission,
27747
27966
  Poll,
27748
27967
  PollComposer,