stream-chat 9.50.2 → 9.50.3

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.
@@ -58,6 +58,13 @@ export declare class OfflineDBSyncManager {
58
58
  private sync;
59
59
  /**
60
60
  * Executes any tasks that were queued while offline and then performs a sync.
61
+ *
62
+ * Each step is isolated so a failure in one does not prevent the other, and
63
+ * neither can escape to the callers (init + the connection.changed handler).
64
+ * This guarantees the subsequent invokeSyncStatusListeners(true) always runs,
65
+ * so syncStatus recovers to true and gated channel queries are unblocked.
66
+ * Failed syncs degrade to "possibly stale data until the next query" rather
67
+ * than freezing all future queries. See issue #1816.
61
68
  */
62
69
  private syncAndExecutePendingTasks;
63
70
  }
@@ -121,6 +121,7 @@ export type AppSettingsAPIResponse = APIResponse & {
121
121
  moderation_dashboard_preferences?: Record<string, unknown> | null;
122
122
  moderation_audio_call_moderation_enabled?: boolean;
123
123
  moderation_enabled?: boolean;
124
+ moderation_flood_rules_enabled?: boolean;
124
125
  moderation_llm_configurability_enabled?: boolean;
125
126
  moderation_multitenant_blocklist_enabled?: boolean;
126
127
  moderation_video_call_moderation_enabled?: boolean;
@@ -259,6 +260,8 @@ export type QueryFutureChannelBansOptions = {
259
260
  };
260
261
  export type BlockListResponse = BlockList & {
261
262
  created_at?: string;
263
+ id?: string;
264
+ owner_user_id?: string;
262
265
  type?: string;
263
266
  updated_at?: string;
264
267
  };
@@ -878,6 +881,8 @@ export type UserResponse = CustomUserData & {
878
881
  anon?: boolean;
879
882
  banned?: boolean;
880
883
  blocked_user_ids?: string[];
884
+ /** Set on the user of a read event, marking when they last read the event's channel. */
885
+ channel_last_read_at?: string;
881
886
  created_at?: string;
882
887
  deactivated_at?: string;
883
888
  deleted_at?: string;
@@ -2032,6 +2037,7 @@ export type BlockList = {
2032
2037
  is_confusable_folding_enabled?: boolean;
2033
2038
  is_leet_check_enabled?: boolean;
2034
2039
  is_plural_check_enabled?: boolean;
2040
+ is_substring_matching_enabled?: boolean;
2035
2041
  };
2036
2042
  export type ChannelConfig = ChannelConfigFields & CreatedAtUpdatedAt & {
2037
2043
  commands?: CommandVariants[];
@@ -2326,6 +2332,8 @@ export type PermissionAPIObject = {
2326
2332
  level?: string;
2327
2333
  name?: string;
2328
2334
  owner?: boolean;
2335
+ /** Resource type that defines ownership for this permission's action, e.g. 'Channel' for CreateMessage. */
2336
+ owner_resource?: string;
2329
2337
  same_team?: boolean;
2330
2338
  tags?: string[];
2331
2339
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stream-chat",
3
- "version": "9.50.2",
3
+ "version": "9.50.3",
4
4
  "description": "JS SDK for the Stream Chat API",
5
5
  "homepage": "https://getstream.io/chat/",
6
6
  "author": {
@@ -111,14 +111,27 @@ export class OfflineDBSyncManager {
111
111
  */
112
112
  private invokeSyncStatusListeners = async (status: boolean) => {
113
113
  this.syncStatus = status;
114
- this.syncStatusListeners.forEach((l) => l(status));
114
+ this.syncStatusListeners.forEach((l) => {
115
+ try {
116
+ l(status);
117
+ } catch (error) {
118
+ console.log('Error in a sync status listener.', error);
119
+ }
120
+ });
115
121
 
116
122
  if (status) {
117
- const promises = Array.from(this.scheduledSyncStatusCallbacks.values()).map((cb) =>
118
- cb(),
123
+ const promises = Array.from(this.scheduledSyncStatusCallbacks.values()).map(
124
+ async (cb) => {
125
+ try {
126
+ await cb();
127
+ } catch (error) {
128
+ console.log('Error executing a scheduled sync status callback.', error);
129
+ }
130
+ },
119
131
  );
132
+ // Every callback is isolated above, so Promise.all never rejects and clear()
133
+ // always runs (no double-execution on the next sync).
120
134
  await Promise.all(promises);
121
-
122
135
  this.scheduledSyncStatusCallbacks.clear();
123
136
  }
124
137
  };
@@ -198,9 +211,27 @@ export class OfflineDBSyncManager {
198
211
 
199
212
  /**
200
213
  * Executes any tasks that were queued while offline and then performs a sync.
214
+ *
215
+ * Each step is isolated so a failure in one does not prevent the other, and
216
+ * neither can escape to the callers (init + the connection.changed handler).
217
+ * This guarantees the subsequent invokeSyncStatusListeners(true) always runs,
218
+ * so syncStatus recovers to true and gated channel queries are unblocked.
219
+ * Failed syncs degrade to "possibly stale data until the next query" rather
220
+ * than freezing all future queries. See issue #1816.
201
221
  */
202
222
  private syncAndExecutePendingTasks = async () => {
203
- await this.offlineDb.executePendingTasks();
204
- await this.sync();
223
+ try {
224
+ await this.offlineDb.executePendingTasks();
225
+ } catch (error) {
226
+ console.log('Error executing pending tasks during sync.', error);
227
+ }
228
+ // Note: sync() has its own try/catch, but its catch block calls resetDB(),
229
+ // which can itself throw on a corrupted DB and re-reject. This outer guard
230
+ // absorbs that case.
231
+ try {
232
+ await this.sync();
233
+ } catch (error) {
234
+ console.log('Error while syncing the DB.', error);
235
+ }
205
236
  };
206
237
  }
package/src/types.ts CHANGED
@@ -167,6 +167,7 @@ export type AppSettingsAPIResponse = APIResponse & {
167
167
  moderation_dashboard_preferences?: Record<string, unknown> | null;
168
168
  moderation_audio_call_moderation_enabled?: boolean;
169
169
  moderation_enabled?: boolean;
170
+ moderation_flood_rules_enabled?: boolean;
170
171
  moderation_llm_configurability_enabled?: boolean;
171
172
  moderation_multitenant_blocklist_enabled?: boolean;
172
173
  moderation_video_call_moderation_enabled?: boolean;
@@ -319,6 +320,8 @@ export type QueryFutureChannelBansOptions = {
319
320
 
320
321
  export type BlockListResponse = BlockList & {
321
322
  created_at?: string;
323
+ id?: string;
324
+ owner_user_id?: string;
322
325
  type?: string;
323
326
  updated_at?: string;
324
327
  };
@@ -1045,6 +1048,8 @@ export type UserResponse = CustomUserData & {
1045
1048
  anon?: boolean;
1046
1049
  banned?: boolean;
1047
1050
  blocked_user_ids?: string[];
1051
+ /** Set on the user of a read event, marking when they last read the event's channel. */
1052
+ channel_last_read_at?: string;
1048
1053
  created_at?: string;
1049
1054
  deactivated_at?: string;
1050
1055
  deleted_at?: string;
@@ -2588,6 +2593,7 @@ export type BlockList = {
2588
2593
  is_confusable_folding_enabled?: boolean;
2589
2594
  is_leet_check_enabled?: boolean;
2590
2595
  is_plural_check_enabled?: boolean;
2596
+ is_substring_matching_enabled?: boolean;
2591
2597
  };
2592
2598
 
2593
2599
  export type ChannelConfig = ChannelConfigFields &
@@ -3098,6 +3104,8 @@ export type PermissionAPIObject = {
3098
3104
  level?: string;
3099
3105
  name?: string;
3100
3106
  owner?: boolean;
3107
+ /** Resource type that defines ownership for this permission's action, e.g. 'Channel' for CreateMessage. */
3108
+ owner_resource?: string;
3101
3109
  same_team?: boolean;
3102
3110
  tags?: string[];
3103
3111
  };