stream-chat 9.50.3 → 10.0.0-rc.2

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 (242) hide show
  1. package/dist/cjs/index.browser.js +19798 -14472
  2. package/dist/cjs/index.browser.js.map +4 -4
  3. package/dist/cjs/index.node.js +19817 -14482
  4. package/dist/cjs/index.node.js.map +4 -4
  5. package/dist/esm/index.mjs +19795 -14469
  6. package/dist/esm/index.mjs.map +4 -4
  7. package/dist/types/ChannelManager.d.ts +221 -0
  8. package/dist/types/EventHandlerPipeline.d.ts +104 -0
  9. package/dist/types/api-client.d.ts +26 -0
  10. package/dist/types/campaign.d.ts +0 -44
  11. package/dist/types/channel.d.ts +454 -479
  12. package/dist/types/channel_batch_updater.d.ts +0 -93
  13. package/dist/types/channel_state.d.ts +53 -201
  14. package/dist/types/client.d.ts +451 -1920
  15. package/dist/types/client_state.d.ts +4 -4
  16. package/dist/types/configuration/InstanceConfigurationService.d.ts +26 -0
  17. package/dist/types/configuration/index.d.ts +1 -0
  18. package/dist/types/configuration/types.d.ts +53 -0
  19. package/dist/types/connection.d.ts +49 -41
  20. package/dist/types/connection_fallback.d.ts +6 -4
  21. package/dist/types/constants.d.ts +0 -4
  22. package/dist/types/custom_types.d.ts +2 -0
  23. package/dist/types/entityStore/EntityStore.d.ts +111 -0
  24. package/dist/types/entityStore/StoreBackedItemIndex.d.ts +60 -0
  25. package/dist/types/entityStore/applyReactionLocally.d.ts +26 -0
  26. package/dist/types/entityStore/index.d.ts +2 -0
  27. package/dist/types/errors.d.ts +10 -2
  28. package/dist/types/gen/chat/ChannelApi.d.ts +45 -0
  29. package/dist/types/gen/chat/ChatApi.d.ts +334 -0
  30. package/dist/types/gen/model-decoders/decoders.d.ts +3 -0
  31. package/dist/types/gen/model-decoders/event-decoder-mapping.d.ts +6 -0
  32. package/dist/types/gen/models/index.d.ts +8836 -0
  33. package/dist/types/gen/moderation/ModerationApi.d.ts +50 -0
  34. package/dist/types/gen-imports.d.ts +3 -0
  35. package/dist/types/index.d.ts +8 -7
  36. package/dist/types/insights.d.ts +9 -8
  37. package/dist/types/logger.d.ts +9 -0
  38. package/dist/types/messageComposer/LocationComposer.d.ts +7 -4
  39. package/dist/types/messageComposer/attachmentIdentity.d.ts +2 -2
  40. package/dist/types/messageComposer/attachmentManager.d.ts +8 -4
  41. package/dist/types/messageComposer/configuration/types.d.ts +11 -11
  42. package/dist/types/messageComposer/linkPreviewsManager.d.ts +25 -13
  43. package/dist/types/messageComposer/messageComposer.d.ts +10 -10
  44. package/dist/types/messageComposer/middleware/messageComposer/types.d.ts +3 -3
  45. package/dist/types/messageComposer/middleware/pollComposer/types.d.ts +4 -7
  46. package/dist/types/messageComposer/middleware/textComposer/commandUtils.d.ts +3 -3
  47. package/dist/types/messageComposer/middleware/textComposer/commands.d.ts +7 -7
  48. package/dist/types/messageComposer/middleware/textComposer/mentions.d.ts +218 -4
  49. package/dist/types/messageComposer/middleware/textComposer/types.d.ts +9 -4
  50. package/dist/types/messageComposer/pollComposer.d.ts +5 -4
  51. package/dist/types/messageComposer/textComposer.d.ts +8 -3
  52. package/dist/types/messageComposer/types.d.ts +6 -28
  53. package/dist/types/messageDelivery/MessageDeliveryReporter.d.ts +40 -25
  54. package/dist/types/messageDelivery/MessageReceiptsTracker.d.ts +53 -12
  55. package/dist/types/messageOperations/MessageOperationStatePolicy.d.ts +19 -0
  56. package/dist/types/messageOperations/MessageOperations.d.ts +17 -0
  57. package/dist/types/messageOperations/index.d.ts +3 -0
  58. package/dist/types/messageOperations/types.d.ts +49 -0
  59. package/dist/types/moderation.d.ts +21 -203
  60. package/dist/types/notifications/types.d.ts +8 -7
  61. package/dist/types/offline-support/offline_support_api.d.ts +111 -87
  62. package/dist/types/offline-support/offline_sync_manager.d.ts +0 -7
  63. package/dist/types/offline-support/types.d.ts +19 -23
  64. package/dist/types/offline-support/util.d.ts +4 -2
  65. package/dist/types/pagination/FilterBuilder.d.ts +1 -1
  66. package/dist/types/pagination/ItemIndex.d.ts +25 -0
  67. package/dist/types/pagination/cursorDerivation/createdAtAroundPaginationFlags.d.ts +9 -0
  68. package/dist/types/pagination/cursorDerivation/idAroundPaginationFlags.d.ts +6 -0
  69. package/dist/types/pagination/cursorDerivation/index.d.ts +1 -0
  70. package/dist/types/pagination/cursorDerivation/linearPaginationFlags.d.ts +6 -0
  71. package/dist/types/pagination/filterCompiler.d.ts +7 -0
  72. package/dist/types/pagination/index.d.ts +1 -3
  73. package/dist/types/pagination/paginators/BasePaginator.d.ts +848 -0
  74. package/dist/types/pagination/paginators/ChannelPaginator.d.ts +212 -0
  75. package/dist/types/pagination/paginators/MessageIntervalPaginator.d.ts +282 -0
  76. package/dist/types/pagination/paginators/MessagePaginator.d.ts +208 -0
  77. package/dist/types/pagination/paginators/PinnedMessagePaginator.d.ts +39 -0
  78. package/dist/types/pagination/paginators/ReminderPaginator.d.ts +19 -0
  79. package/dist/types/pagination/paginators/UserGroupPaginator.d.ts +24 -0
  80. package/dist/types/pagination/paginators/index.d.ts +7 -0
  81. package/dist/types/pagination/paginators/stateThrottling.d.ts +2 -0
  82. package/dist/types/pagination/sortCompiler.d.ts +49 -0
  83. package/dist/types/pagination/types.normalization.d.ts +11 -0
  84. package/dist/types/pagination/utility.normalization.d.ts +18 -0
  85. package/dist/types/pagination/utility.queryChannel.d.ts +26 -0
  86. package/dist/types/pagination/utility.search.d.ts +13 -0
  87. package/dist/types/permissions.d.ts +1 -1
  88. package/dist/types/poll.d.ts +29 -32
  89. package/dist/types/poll_manager.d.ts +2 -2
  90. package/dist/types/reminders/Reminder.d.ts +2 -5
  91. package/dist/types/reminders/ReminderManager.d.ts +2 -9
  92. package/dist/types/search/MessageSearchSource.d.ts +4 -4
  93. package/dist/types/search/UserSearchSource.d.ts +1 -1
  94. package/dist/types/search/types.d.ts +3 -3
  95. package/dist/types/segment.d.ts +0 -34
  96. package/dist/types/signing.d.ts +105 -65
  97. package/dist/types/store.d.ts +1 -0
  98. package/dist/types/thread.d.ts +70 -34
  99. package/dist/types/thread_manager.d.ts +3 -3
  100. package/dist/types/token_manager.d.ts +15 -10
  101. package/dist/types/types.d.ts +197 -3404
  102. package/dist/types/utils/FixedSizeQueueCache.d.ts +12 -6
  103. package/dist/types/utils/WithSubscriptions.d.ts +2 -1
  104. package/dist/types/utils/concurrency.d.ts +4 -4
  105. package/dist/types/utils/mergeWith/mergeWith.d.ts +3 -3
  106. package/dist/types/utils/mergeWith/mergeWithCore.d.ts +8 -3
  107. package/dist/types/utils/retryable.d.ts +34 -0
  108. package/dist/types/utils/throttling/throttle.d.ts +36 -0
  109. package/dist/types/utils.d.ts +100 -194
  110. package/package.json +7 -3
  111. package/src/ChannelManager.ts +724 -0
  112. package/src/CooldownTimer.ts +2 -2
  113. package/src/EventHandlerPipeline.ts +228 -0
  114. package/src/LiveLocationManager.ts +12 -11
  115. package/src/api-client.ts +275 -0
  116. package/src/campaign.ts +1 -77
  117. package/src/channel.ts +1344 -1282
  118. package/src/channel_batch_updater.ts +1 -211
  119. package/src/channel_state.ts +144 -1013
  120. package/src/client.ts +936 -3995
  121. package/src/client_state.ts +4 -4
  122. package/src/configuration/InstanceConfigurationService.ts +73 -0
  123. package/src/configuration/index.ts +1 -0
  124. package/src/configuration/types.ts +81 -0
  125. package/src/connection.ts +145 -94
  126. package/src/connection_fallback.ts +29 -27
  127. package/src/constants.ts +1 -5
  128. package/src/custom_types.ts +4 -1
  129. package/src/entityStore/EntityStore.ts +208 -0
  130. package/src/entityStore/StoreBackedItemIndex.ts +115 -0
  131. package/src/entityStore/applyReactionLocally.ts +113 -0
  132. package/src/entityStore/index.ts +2 -0
  133. package/src/errors.ts +14 -2
  134. package/src/gen/chat/ChannelApi.ts +275 -0
  135. package/src/gen/chat/ChatApi.ts +2554 -0
  136. package/src/gen/model-decoders/decoders.ts +2680 -0
  137. package/src/gen/model-decoders/event-decoder-mapping.ts +198 -0
  138. package/src/gen/models/index.ts +12673 -0
  139. package/src/gen/moderation/ModerationApi.ts +607 -0
  140. package/src/gen-imports.ts +3 -0
  141. package/src/index.ts +11 -12
  142. package/src/insights.ts +6 -5
  143. package/src/logger.ts +28 -0
  144. package/src/messageComposer/LocationComposer.ts +9 -5
  145. package/src/messageComposer/MessageComposerEffectHandlers.ts +1 -0
  146. package/src/messageComposer/attachmentIdentity.ts +16 -9
  147. package/src/messageComposer/attachmentManager.ts +13 -8
  148. package/src/messageComposer/configuration/types.ts +11 -11
  149. package/src/messageComposer/linkPreviewsManager.ts +9 -10
  150. package/src/messageComposer/messageComposer.ts +57 -53
  151. package/src/messageComposer/middleware/messageComposer/attachments.ts +1 -2
  152. package/src/messageComposer/middleware/messageComposer/cleanData.ts +1 -1
  153. package/src/messageComposer/middleware/messageComposer/compositionValidation.ts +2 -2
  154. package/src/messageComposer/middleware/messageComposer/messageComposerState.ts +2 -2
  155. package/src/messageComposer/middleware/messageComposer/sharedLocation.ts +4 -3
  156. package/src/messageComposer/middleware/messageComposer/textComposer.ts +2 -2
  157. package/src/messageComposer/middleware/messageComposer/types.ts +3 -4
  158. package/src/messageComposer/middleware/messageComposer/userDataInjection.ts +9 -5
  159. package/src/messageComposer/middleware/pollComposer/state.ts +0 -2
  160. package/src/messageComposer/middleware/pollComposer/types.ts +4 -7
  161. package/src/messageComposer/middleware/textComposer/TextComposerMiddlewareExecutor.ts +10 -1
  162. package/src/messageComposer/middleware/textComposer/commandEffects.ts +4 -4
  163. package/src/messageComposer/middleware/textComposer/commandUtils.ts +3 -6
  164. package/src/messageComposer/middleware/textComposer/commands.ts +3 -3
  165. package/src/messageComposer/middleware/textComposer/mentionUtils.ts +1 -1
  166. package/src/messageComposer/middleware/textComposer/mentions.ts +31 -15
  167. package/src/messageComposer/middleware/textComposer/types.ts +9 -4
  168. package/src/messageComposer/pollComposer.ts +6 -8
  169. package/src/messageComposer/textComposer.ts +27 -2
  170. package/src/messageComposer/types.ts +6 -28
  171. package/src/messageDelivery/MessageDeliveryReporter.ts +101 -45
  172. package/src/messageDelivery/MessageReceiptsTracker.ts +294 -21
  173. package/src/messageOperations/MessageOperationStatePolicy.ts +77 -0
  174. package/src/messageOperations/MessageOperations.ts +212 -0
  175. package/src/messageOperations/index.ts +10 -0
  176. package/src/messageOperations/types.ts +64 -0
  177. package/src/moderation.ts +38 -431
  178. package/src/notifications/types.ts +8 -7
  179. package/src/offline-support/offline_support_api.ts +200 -133
  180. package/src/offline-support/offline_sync_manager.ts +23 -44
  181. package/src/offline-support/types.ts +23 -26
  182. package/src/offline-support/util.ts +5 -4
  183. package/src/pagination/FilterBuilder.ts +4 -1
  184. package/src/pagination/ItemIndex.ts +25 -0
  185. package/src/pagination/cursorDerivation/createdAtAroundPaginationFlags.ts +73 -0
  186. package/src/pagination/cursorDerivation/idAroundPaginationFlags.ts +53 -0
  187. package/src/pagination/cursorDerivation/index.ts +1 -0
  188. package/src/pagination/cursorDerivation/linearPaginationFlags.ts +86 -0
  189. package/src/pagination/filterCompiler.ts +196 -0
  190. package/src/pagination/index.ts +1 -3
  191. package/src/pagination/paginators/BasePaginator.ts +2859 -0
  192. package/src/pagination/paginators/ChannelPaginator.ts +729 -0
  193. package/src/pagination/paginators/MessageIntervalPaginator.ts +1116 -0
  194. package/src/pagination/paginators/MessagePaginator.ts +508 -0
  195. package/src/pagination/paginators/PinnedMessagePaginator.ts +108 -0
  196. package/src/pagination/paginators/ReminderPaginator.ts +107 -0
  197. package/src/pagination/paginators/UserGroupPaginator.ts +127 -0
  198. package/src/pagination/paginators/index.ts +7 -0
  199. package/src/pagination/paginators/stateThrottling.ts +31 -0
  200. package/src/pagination/sortCompiler.ts +193 -0
  201. package/src/pagination/types.normalization.ts +14 -0
  202. package/src/pagination/utility.normalization.ts +106 -0
  203. package/src/pagination/utility.queryChannel.ts +84 -0
  204. package/src/pagination/utility.search.ts +80 -0
  205. package/src/permissions.ts +7 -8
  206. package/src/poll.ts +101 -110
  207. package/src/poll_manager.ts +14 -8
  208. package/src/reminders/Reminder.ts +2 -5
  209. package/src/reminders/ReminderManager.ts +19 -21
  210. package/src/search/BaseSearchSource.ts +0 -3
  211. package/src/search/ChannelMemberSearchSource.ts +7 -1
  212. package/src/search/ChannelSearchSource.ts +10 -3
  213. package/src/search/MessageSearchSource.ts +29 -30
  214. package/src/search/UserSearchSource.ts +12 -8
  215. package/src/search/types.ts +3 -4
  216. package/src/segment.ts +1 -95
  217. package/src/signing.ts +107 -67
  218. package/src/store.ts +2 -1
  219. package/src/thread.ts +562 -238
  220. package/src/thread_manager.ts +37 -16
  221. package/src/token_manager.ts +21 -10
  222. package/src/types.ts +364 -4533
  223. package/src/uploadManager.ts +8 -0
  224. package/src/utils/FixedSizeQueueCache.ts +12 -6
  225. package/src/utils/WithSubscriptions.ts +2 -1
  226. package/src/utils/concurrency.ts +4 -4
  227. package/src/utils/mergeWith/mergeWith.ts +3 -3
  228. package/src/utils/mergeWith/mergeWithCore.ts +140 -164
  229. package/src/utils/mergeWith/mergeWithDiff.ts +3 -3
  230. package/src/utils/retryable.ts +117 -0
  231. package/src/utils/throttling/throttle.ts +130 -0
  232. package/src/utils.ts +208 -754
  233. package/dist/types/channel_manager.d.ts +0 -122
  234. package/dist/types/events.d.ts +0 -72
  235. package/dist/types/pagination/BasePaginator.d.ts +0 -69
  236. package/dist/types/pagination/ReminderPaginator.d.ts +0 -16
  237. package/dist/types/pagination/UserGroupPaginator.d.ts +0 -21
  238. package/src/channel_manager.ts +0 -830
  239. package/src/events.ts +0 -75
  240. package/src/pagination/BasePaginator.ts +0 -184
  241. package/src/pagination/ReminderPaginator.ts +0 -56
  242. package/src/pagination/UserGroupPaginator.ts +0 -93
@@ -3,7 +3,10 @@ import type { StreamChat } from '../client';
3
3
  import type { AbstractOfflineDB } from './offline_support_api';
4
4
  import type { AxiosError } from 'axios';
5
5
  import { isAxiosError } from 'axios';
6
- import type { APIErrorResponse } from '../types';
6
+ import { chatLoggerSystem } from '../logger';
7
+ import type { APIError } from '../types';
8
+
9
+ const logger = chatLoggerSystem.getLogger('offline-db');
7
10
 
8
11
  /**
9
12
  * Manages synchronization between the local offline database and the Stream backend.
@@ -40,8 +43,8 @@ export class OfflineDBSyncManager {
40
43
  */
41
44
  public init = async () => {
42
45
  try {
43
- // If the websocket connection is already active, then call
44
- // the sync api straight away and also execute pending api calls.
46
+ // If the WebSocket connection is already active, then call
47
+ // the sync API straight away and also execute pending API calls.
45
48
  // Otherwise wait for the `connection.changed` event.
46
49
  if (this.client.user?.id && this.client.wsConnection?.isHealthy) {
47
50
  await this.syncAndExecutePendingTasks();
@@ -69,7 +72,9 @@ export class OfflineDBSyncManager {
69
72
  },
70
73
  );
71
74
  } catch (error) {
72
- console.log('Error in DBSyncManager.init: ', error);
75
+ logger
76
+ .withExtraTags('init')
77
+ .error('Failed to initialize the offline DB sync manager.', { error });
73
78
  }
74
79
  };
75
80
 
@@ -111,27 +116,14 @@ export class OfflineDBSyncManager {
111
116
  */
112
117
  private invokeSyncStatusListeners = async (status: boolean) => {
113
118
  this.syncStatus = 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
- });
119
+ this.syncStatusListeners.forEach((l) => l(status));
121
120
 
122
121
  if (status) {
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
- },
122
+ const promises = Array.from(this.scheduledSyncStatusCallbacks.values()).map((cb) =>
123
+ cb(),
131
124
  );
132
- // Every callback is isolated above, so Promise.all never rejects and clear()
133
- // always runs (no double-execution on the next sync).
134
125
  await Promise.all(promises);
126
+
135
127
  this.scheduledSyncStatusCallbacks.clear();
136
128
  }
137
129
  };
@@ -172,7 +164,10 @@ export class OfflineDBSyncManager {
172
164
  // In that case reset the entire DB and start fresh.
173
165
  await this.offlineDb.resetDB();
174
166
  } else {
175
- const result = await this.client.sync(cids, lastSyncedAtDate.toISOString());
167
+ const result = await this.client.sync({
168
+ channel_cids: cids,
169
+ last_sync_at: lastSyncedAtDate,
170
+ });
176
171
  const queryPromises = result.events.map((event) =>
177
172
  this.offlineDb.handleEvent({ event, execute: false }),
178
173
  );
@@ -189,14 +184,16 @@ export class OfflineDBSyncManager {
189
184
  lastSyncedAt: new Date().toString(),
190
185
  });
191
186
  } catch (e) {
192
- console.log('An error has occurred while syncing the DB.', e);
187
+ logger
188
+ .withExtraTags('syncAndExecutePendingTasks')
189
+ .error('An error occurred while syncing the database.', { error: e });
193
190
 
194
191
  if (isAxiosError(e) && e.code === 'ECONNABORTED') {
195
192
  // If the sync was aborted due to timeout, we can simply return
196
193
  return;
197
194
  }
198
195
 
199
- const error = e as AxiosError<APIErrorResponse>;
196
+ const error = e as AxiosError<APIError>;
200
197
 
201
198
  if (error.response?.data?.code === 23) {
202
199
  return;
@@ -211,27 +208,9 @@ export class OfflineDBSyncManager {
211
208
 
212
209
  /**
213
210
  * 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.
221
211
  */
222
212
  private syncAndExecutePendingTasks = async () => {
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
- }
213
+ await this.offlineDb.executePendingTasks();
214
+ await this.sync();
236
215
  };
237
216
  }
@@ -1,19 +1,20 @@
1
1
  import type {
2
- AppSettingsAPIResponse,
3
- ChannelAPIResponse,
4
2
  ChannelFilters,
5
3
  ChannelMemberResponse,
6
4
  ChannelOptions,
7
5
  ChannelResponse,
8
6
  ChannelSort,
7
+ ChannelStateResponseFields,
9
8
  DraftResponse,
9
+ GetApplicationResponse,
10
10
  LocalMessage,
11
11
  MessageResponse,
12
- PollResponse,
12
+ PollResponse_old,
13
+ QueryChannelsRequest,
13
14
  ReactionFilters,
14
15
  ReactionResponse,
15
16
  ReactionSort,
16
- ReadResponse,
17
+ ReadStateResponse,
17
18
  } from '../types';
18
19
  import type { Channel } from '../channel';
19
20
  import type { StreamChat } from '../client';
@@ -26,7 +27,7 @@ export type PrepareBatchDBQueries =
26
27
  * Options to insert a reaction into a message.
27
28
  */
28
29
  export type DBInsertReactionType = {
29
- /** Message to which the reaction is applied. */
30
+ /** MessageRequest to which the reaction is applied. */
30
31
  message: MessageResponse | LocalMessage;
31
32
  /** The reaction to insert. */
32
33
  reaction: ReactionResponse;
@@ -55,7 +56,7 @@ export type DBUpsertCidsForQueryType = {
55
56
  */
56
57
  export type DBUpsertChannelsType = {
57
58
  /** Array of channel API responses. */
58
- channels: ChannelAPIResponse[];
59
+ channels: ChannelStateResponseFields[];
59
60
  /** Whether to immediately execute the operation. */
60
61
  execute?: boolean;
61
62
  /** If true, marks that the latest messages are already set. */
@@ -67,7 +68,7 @@ export type DBUpsertChannelsType = {
67
68
  */
68
69
  export type DBUpsertAppSettingsType = {
69
70
  /** App settings data. */
70
- appSettings: AppSettingsAPIResponse;
71
+ appSettings: GetApplicationResponse;
71
72
  /** ID of the user the settings belong to. */
72
73
  userId: string;
73
74
  /** Whether to immediately execute the operation. */
@@ -91,7 +92,7 @@ export type DBUpsertUserSyncStatusType = {
91
92
  */
92
93
  export type DBUpsertPollType = {
93
94
  /** Poll data to be stored. */
94
- poll: PollResponse;
95
+ poll: PollResponse_old;
95
96
  /** Whether to immediately execute the operation. */
96
97
  execute?: boolean;
97
98
  };
@@ -113,7 +114,7 @@ export type DBUpsertReadsType = {
113
114
  /** Channel ID. */
114
115
  cid: string;
115
116
  /** Array of read statuses. */
116
- reads: ReadResponse[];
117
+ reads: ReadStateResponse[];
117
118
  /** Whether to immediately execute the operation. */
118
119
  execute?: boolean;
119
120
  };
@@ -144,7 +145,7 @@ export type DBUpsertMembersType = {
144
145
  * Options to update a reaction.
145
146
  */
146
147
  export type DBUpdateReactionType = {
147
- /** Message associated with the reaction. */
148
+ /** MessageRequest associated with the reaction. */
148
149
  message: MessageResponse | LocalMessage;
149
150
  /** The updated reaction. */
150
151
  reaction: ReactionResponse;
@@ -156,7 +157,7 @@ export type DBUpdateReactionType = {
156
157
  * Options to update a message.
157
158
  */
158
159
  export type DBUpdateMessageType = {
159
- /** Message to update. */
160
+ /** MessageRequest to update. */
160
161
  message: MessageResponse | LocalMessage;
161
162
  /** Whether to immediately execute the operation. */
162
163
  execute?: boolean;
@@ -179,15 +180,11 @@ export type DBGetChannelsForQueryType = {
179
180
  /** ID of the user. */
180
181
  userId: string;
181
182
  /** Optional filters for channels. */
182
- filters?: ChannelFilters;
183
- /** Optional full query options for channels. */
184
- options?: ChannelOptions;
185
- /** Optional sorting for the channels. */
186
- sort?: ChannelSort;
183
+ options?: QueryChannelsRequest;
187
184
  };
188
185
 
189
186
  /**
190
- * Get the last sync timestamp for a user.
187
+ * Payload for retrieving the last sync timestamp for a user.
191
188
  */
192
189
  export type DBGetLastSyncedAtType = {
193
190
  /** ID of the user. */
@@ -203,7 +200,7 @@ export type DBGetPendingTasksType = {
203
200
  };
204
201
 
205
202
  /**
206
- * Get application settings for a user.
203
+ * Payload for retrieving application settings for a user.
207
204
  */
208
205
  export type DBGetAppSettingsType = {
209
206
  /** ID of the user. */
@@ -217,7 +214,7 @@ export type DBGetReactionsType = {
217
214
  /** ID of the message. */
218
215
  messageId: string;
219
216
  /** Optional filter to apply to reactions. */
220
- filters?: Pick<ReactionFilters, 'type'>;
217
+ filters?: ReactionFilters;
221
218
  /** Optional sorting for reactions. */
222
219
  sort?: ReactionSort;
223
220
  /** Optional maximum number of reactions to return. */
@@ -225,7 +222,7 @@ export type DBGetReactionsType = {
225
222
  };
226
223
 
227
224
  /**
228
- * Delete a pending task by ID.
225
+ * Payload for deleting a pending task by ID.
229
226
  */
230
227
  export type DBDeletePendingTaskType = {
231
228
  /** ID of the pending task. */
@@ -233,7 +230,7 @@ export type DBDeletePendingTaskType = {
233
230
  };
234
231
 
235
232
  /**
236
- * Update a pending task by ID.
233
+ * Payload for updating a pending task by ID.
237
234
  */
238
235
  export type DBUpdatePendingTaskType = {
239
236
  /** ID of the pending task. */
@@ -305,13 +302,13 @@ export type DBDeleteMessagesForChannelType = {
305
302
  /** Channel ID. */
306
303
  cid: string;
307
304
  /** Timestamp before which messages are deleted. */
308
- truncated_at?: string;
305
+ truncated_at?: Date;
309
306
  /** Whether to immediately execute the operation. */
310
307
  execute?: boolean;
311
308
  };
312
309
 
313
310
  /**
314
- * Check if a channel exists by ID.
311
+ * Payload for checking whether a channel exists by ID.
315
312
  */
316
313
  export type DBChannelExistsType = {
317
314
  /** Channel ID. */
@@ -373,15 +370,15 @@ export interface OfflineDBApi {
373
370
  getDraft: (options: DBGetDraftType) => Promise<DraftResponse | null>;
374
371
  getChannels: (
375
372
  options: DBGetChannelsType,
376
- ) => Promise<Omit<ChannelAPIResponse, 'duration'>[] | null>;
373
+ ) => Promise<Omit<ChannelStateResponseFields, 'duration'>[] | null>;
377
374
  getChannelsForQuery: (
378
375
  options: DBGetChannelsForQueryType,
379
- ) => Promise<Omit<ChannelAPIResponse, 'duration'>[] | null>;
376
+ ) => Promise<Omit<ChannelStateResponseFields, 'duration'>[] | null>;
380
377
  getAllChannelCids: () => Promise<string[]>;
381
378
  getLastSyncedAt: (options: DBGetLastSyncedAtType) => Promise<string | undefined>;
382
379
  getAppSettings: (
383
380
  options: DBGetAppSettingsType,
384
- ) => Promise<AppSettingsAPIResponse | null>;
381
+ ) => Promise<GetApplicationResponse | null>;
385
382
  getReactions: (options: DBGetReactionsType) => Promise<ReactionResponse[] | null>;
386
383
  executeSqlBatch: (queries: ExecuteBatchDBQueriesType) => Promise<unknown>;
387
384
  addPendingTask: (task: PendingTask) => Promise<() => Promise<void>>;
@@ -1,4 +1,4 @@
1
- import type { Attachment, LocalMessage, MessageResponse } from '../types';
1
+ import type { Attachment } from '../types';
2
2
 
3
3
  export const isLocalUrl = (value: string | undefined) =>
4
4
  !!value && !value.startsWith('http');
@@ -11,9 +11,10 @@ export const isAttachmentReplayable = (attachment: Attachment) => {
11
11
  return !isLocalUrl(attachment.asset_url) && !isLocalUrl(attachment.image_url);
12
12
  };
13
13
 
14
- export const isMessageUpdateReplayable = (
15
- message: LocalMessage | Partial<MessageResponse>,
16
- ) => !message.attachments?.some((attachment) => !isAttachmentReplayable(attachment));
14
+ export const isMessageUpdateReplayable = (minimalMessage: {
15
+ attachments?: Attachment[];
16
+ }) =>
17
+ !minimalMessage.attachments?.some((attachment) => !isAttachmentReplayable(attachment));
17
18
 
18
19
  export const getPendingTaskChannelData = (cid?: string) => {
19
20
  if (!cid) {
@@ -31,7 +31,10 @@ export type FilterBuilderGenerators<
31
31
  };
32
32
  };
33
33
 
34
- export type FilterBuilderOptions<TFilters, TContext extends Record<string, unknown>> = {
34
+ export type FilterBuilderOptions<
35
+ TFilters,
36
+ TContext extends Record<string, unknown> = Record<string, unknown>,
37
+ > = {
35
38
  initialFilterConfig?: FilterBuilderGenerators<TFilters, TContext>;
36
39
  initialContext?: TContext;
37
40
  };
@@ -0,0 +1,25 @@
1
+ /**
2
+ * The minimal CRUD surface a paginator relies on from its item index.
3
+ *
4
+ * The sole implementation is {@link StoreBackedItemIndex}: backed by a shared, client-global store
5
+ * it dedupes content across collections and fans changes out to every holder; backed by a private
6
+ * store (the default, owner-less mode) it behaves as a plain per-instance index. Keeping this as an
7
+ * interface lets `BasePaginator` stay agnostic to which backing a given paginator uses.
8
+ *
9
+ * @template T The domain item type managed by the index.
10
+ */
11
+ export interface ItemIndexApi<T> {
12
+ setMany(items: T[]): void;
13
+ setOne(item: T): void;
14
+ get(id: string): T | undefined;
15
+ has(id: string): boolean;
16
+ remove(id: string): void;
17
+ clear(): void;
18
+ entries(): [string, T][];
19
+ values(): T[];
20
+ /**
21
+ * Runs `fn`, coalescing any change notifications it produces into a single flush. A private-store
22
+ * (owner-less) index has nothing to fan out and simply runs `fn`.
23
+ */
24
+ batch<R>(fn: () => R): R;
25
+ }
@@ -0,0 +1,73 @@
1
+ import { binarySearch } from '../sortCompiler';
2
+ import type { BasePaginator, CursorDeriveContext, PaginationFlags } from '../paginators';
3
+ import { ComparisonResult } from '../types.normalization';
4
+
5
+ export const deriveCreatedAtAroundPaginationFlags = <
6
+ T extends { id: string; created_at: Date },
7
+ Q extends { created_at_around?: Date | string },
8
+ P extends BasePaginator<T, Q>,
9
+ >({
10
+ hasMoreHead,
11
+ hasMoreTail,
12
+ interval,
13
+ page,
14
+ paginator,
15
+ queryShape,
16
+ requestedPageSize,
17
+ }: CursorDeriveContext<T, Q> & { paginator: P }): PaginationFlags => {
18
+ let flags: PaginationFlags = { hasMoreHead, hasMoreTail };
19
+ if (!queryShape?.created_at_around) return flags;
20
+ const createdAtAroundDate = new Date(queryShape.created_at_around);
21
+ const [firstPageItem, lastPageItem] = [page[0], page.slice(-1)[0]];
22
+
23
+ // expect ASC order (from oldest to newest)
24
+ const isAboveHeadBound =
25
+ paginator.sortComparator({ created_at: createdAtAroundDate } as T, lastPageItem) ===
26
+ ComparisonResult.A_PRECEDES_B;
27
+ const isBelowTailBound =
28
+ paginator.sortComparator(firstPageItem, { created_at: createdAtAroundDate } as T) ===
29
+ ComparisonResult.A_PRECEDES_B;
30
+
31
+ const requestedPageSizeNotMet =
32
+ requestedPageSize > interval.itemIds.length && requestedPageSize > page.length;
33
+ const noMoreMessages =
34
+ (requestedPageSize > interval.itemIds.length ||
35
+ interval.itemIds.length >= page.length) &&
36
+ requestedPageSize > page.length;
37
+
38
+ if (isAboveHeadBound) {
39
+ flags.hasMoreHead = false;
40
+ if (requestedPageSizeNotMet) {
41
+ flags.hasMoreTail = false;
42
+ }
43
+ } else if (isBelowTailBound) {
44
+ flags.hasMoreTail = false;
45
+ if (requestedPageSizeNotMet) {
46
+ flags.hasMoreHead = false;
47
+ }
48
+ } else if (noMoreMessages) {
49
+ flags = { hasMoreHead: false, hasMoreTail: false };
50
+ } else {
51
+ const [firstPageMsgIsFirstInSet, lastPageMsgIsLastInSet] = [
52
+ firstPageItem?.id && firstPageItem.id === interval.itemIds[0],
53
+ lastPageItem?.id && lastPageItem.id === interval.itemIds.slice(-1)[0],
54
+ ];
55
+
56
+ const midPointByCount = Math.floor(page.length / 2);
57
+ const { insertionIndex } = binarySearch({
58
+ needle: { created_at: createdAtAroundDate } as T,
59
+ length: page.length,
60
+ getItemAt: (index) => page[index],
61
+ compare: (a, b) => a.created_at?.getTime() - b.created_at.getTime(),
62
+ itemIdentityEquals: (a, b) => a.created_at?.getTime() === b.created_at?.getTime(),
63
+ plateauScan: false,
64
+ });
65
+
66
+ if (insertionIndex !== -1) {
67
+ if (firstPageMsgIsFirstInSet) flags.hasMoreTail = midPointByCount <= insertionIndex;
68
+ if (lastPageMsgIsLastInSet) flags.hasMoreHead = midPointByCount >= insertionIndex;
69
+ }
70
+ }
71
+
72
+ return flags;
73
+ };
@@ -0,0 +1,53 @@
1
+ import type { CursorDeriveContext, PaginationFlags } from '../paginators';
2
+
3
+ export const deriveIdAroundPaginationFlags = <
4
+ T extends { id: string },
5
+ Q extends { id_around?: string },
6
+ >({
7
+ hasMoreHead,
8
+ hasMoreTail,
9
+ interval,
10
+ page,
11
+ queryShape,
12
+ requestedPageSize,
13
+ }: CursorDeriveContext<T, Q>): PaginationFlags => {
14
+ let flags: PaginationFlags = { hasMoreHead, hasMoreTail };
15
+ if (!queryShape?.id_around) return flags;
16
+ const { id_around } = queryShape;
17
+
18
+ const [firstPageMsg, lastPageMsg] = [page[0], page.slice(-1)[0]];
19
+ const [firstPageMsgIsFirstInSet, lastPageMsgIsLastInSet] = [
20
+ firstPageMsg?.id === interval.itemIds[0],
21
+ lastPageMsg?.id === interval.itemIds.slice(-1)[0],
22
+ ];
23
+
24
+ const midPoint = Math.floor(page.length / 2);
25
+ const noMoreMessages =
26
+ (requestedPageSize > interval.itemIds.length ||
27
+ interval.itemIds.length >= page.length) &&
28
+ requestedPageSize > page.length;
29
+
30
+ if (noMoreMessages) {
31
+ flags = { hasMoreHead: false, hasMoreTail: false };
32
+ } else if (!page[midPoint]) {
33
+ return flags;
34
+ } else if (page[midPoint].id === id_around) {
35
+ flags = { hasMoreHead: true, hasMoreTail: true };
36
+ } else {
37
+ const halves = [page.slice(0, midPoint), page.slice(midPoint)];
38
+ if (firstPageMsgIsFirstInSet) {
39
+ const targetMsg = halves[0].find((message) => message.id === id_around);
40
+ if (targetMsg) {
41
+ flags.hasMoreTail = false;
42
+ }
43
+ }
44
+ if (lastPageMsgIsLastInSet) {
45
+ const targetMsg = halves[1].find((message) => message.id === id_around);
46
+ if (targetMsg) {
47
+ flags.hasMoreHead = false;
48
+ }
49
+ }
50
+ }
51
+
52
+ return flags;
53
+ };
@@ -0,0 +1 @@
1
+ export * from './createdAtAroundPaginationFlags';
@@ -0,0 +1,86 @@
1
+ import type { CursorDeriveContext, PaginationFlags } from '../paginators';
2
+ import type { MessagePaginationOptions, PaginationOptions } from '../../types';
3
+
4
+ const TAILWARD_QUERY_PROPERTIES: Array<keyof PaginationOptions> = [
5
+ 'created_at_before_or_equal',
6
+ 'created_at_before',
7
+ 'id_lt',
8
+ 'id_lte',
9
+ 'offset',
10
+ ];
11
+
12
+ const HEADWARD_QUERY_PROPERTIES: Array<keyof PaginationOptions> = [
13
+ 'created_at_after_or_equal',
14
+ 'created_at_after',
15
+ 'id_gt',
16
+ 'id_gte',
17
+ ];
18
+ export const deriveLinearPaginationFlags = <
19
+ T extends { id: string; created_at: Date },
20
+ Q extends PaginationOptions,
21
+ >({
22
+ direction,
23
+ hasMoreHead,
24
+ hasMoreTail,
25
+ interval,
26
+ page,
27
+ queryShape,
28
+ requestedPageSize,
29
+ }: CursorDeriveContext<T, Q>): PaginationFlags => {
30
+ const flags: PaginationFlags = { hasMoreHead, hasMoreTail };
31
+ const [firstPageMsg, lastPageMsg] = [page[0], page.slice(-1)[0]];
32
+ const [firstPageMsgIsFirstInSet, lastPageMsgIsLastInSet] = [
33
+ firstPageMsg?.id && firstPageMsg.id === interval.itemIds[0],
34
+ lastPageMsg?.id && lastPageMsg.id === interval.itemIds.slice(-1)[0],
35
+ ];
36
+
37
+ const containsCursorPaginationProperties =
38
+ !!queryShape &&
39
+ HEADWARD_QUERY_PROPERTIES.concat(TAILWARD_QUERY_PROPERTIES).some(
40
+ (p) => typeof queryShape[p] !== 'undefined',
41
+ );
42
+
43
+ const queriedMessagesTowardsHead =
44
+ direction === 'headward' ||
45
+ (!!queryShape &&
46
+ HEADWARD_QUERY_PROPERTIES.some((p) => typeof queryShape[p] !== 'undefined'));
47
+
48
+ const queriedMessagesTowardsTail =
49
+ direction === 'tailward' ||
50
+ typeof queryShape === 'undefined' ||
51
+ TAILWARD_QUERY_PROPERTIES.some((p) => typeof queryShape[p] !== 'undefined');
52
+
53
+ const containsNonLinearPaginationProperties =
54
+ !!(queryShape as MessagePaginationOptions)?.id_around ||
55
+ !!(queryShape as MessagePaginationOptions)?.created_at_around;
56
+
57
+ const containsUnrecognizedOptionsOnly =
58
+ !queriedMessagesTowardsHead &&
59
+ !queriedMessagesTowardsTail &&
60
+ !containsNonLinearPaginationProperties;
61
+
62
+ const isFirstPage = !containsCursorPaginationProperties;
63
+
64
+ const hasMore = page.length >= requestedPageSize;
65
+
66
+ if (
67
+ typeof queriedMessagesTowardsTail !== 'undefined' ||
68
+ containsUnrecognizedOptionsOnly
69
+ ) {
70
+ // Without the isFirstPage branch, a partial first page (e.g. an
71
+ // offline prehydrate returning fewer than `requestedPageSize`) latches `hasMoreTail`
72
+ // to `false` and a subsequent full network first page can never restore it.
73
+ hasMoreTail = isFirstPage ? hasMore : !hasMoreTail ? false : hasMore;
74
+ }
75
+ if (typeof queriedMessagesTowardsHead !== 'undefined') {
76
+ hasMoreHead = !hasMoreHead || isFirstPage ? false : hasMore;
77
+ }
78
+ const pageIsEmpty = page.length === 0;
79
+
80
+ if ((firstPageMsgIsFirstInSet || pageIsEmpty) && typeof hasMoreTail !== 'undefined')
81
+ flags.hasMoreTail = hasMoreTail;
82
+ if ((lastPageMsgIsLastInSet || pageIsEmpty) && typeof hasMoreHead !== 'undefined')
83
+ flags.hasMoreHead = hasMoreHead;
84
+
85
+ return flags;
86
+ };