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.
- package/dist/cjs/index.browser.js +19798 -14472
- package/dist/cjs/index.browser.js.map +4 -4
- package/dist/cjs/index.node.js +19817 -14482
- package/dist/cjs/index.node.js.map +4 -4
- package/dist/esm/index.mjs +19795 -14469
- package/dist/esm/index.mjs.map +4 -4
- package/dist/types/ChannelManager.d.ts +221 -0
- package/dist/types/EventHandlerPipeline.d.ts +104 -0
- package/dist/types/api-client.d.ts +26 -0
- package/dist/types/campaign.d.ts +0 -44
- package/dist/types/channel.d.ts +454 -479
- package/dist/types/channel_batch_updater.d.ts +0 -93
- package/dist/types/channel_state.d.ts +53 -201
- package/dist/types/client.d.ts +451 -1920
- package/dist/types/client_state.d.ts +4 -4
- package/dist/types/configuration/InstanceConfigurationService.d.ts +26 -0
- package/dist/types/configuration/index.d.ts +1 -0
- package/dist/types/configuration/types.d.ts +53 -0
- package/dist/types/connection.d.ts +49 -41
- package/dist/types/connection_fallback.d.ts +6 -4
- package/dist/types/constants.d.ts +0 -4
- package/dist/types/custom_types.d.ts +2 -0
- package/dist/types/entityStore/EntityStore.d.ts +111 -0
- package/dist/types/entityStore/StoreBackedItemIndex.d.ts +60 -0
- package/dist/types/entityStore/applyReactionLocally.d.ts +26 -0
- package/dist/types/entityStore/index.d.ts +2 -0
- package/dist/types/errors.d.ts +10 -2
- package/dist/types/gen/chat/ChannelApi.d.ts +45 -0
- package/dist/types/gen/chat/ChatApi.d.ts +334 -0
- package/dist/types/gen/model-decoders/decoders.d.ts +3 -0
- package/dist/types/gen/model-decoders/event-decoder-mapping.d.ts +6 -0
- package/dist/types/gen/models/index.d.ts +8836 -0
- package/dist/types/gen/moderation/ModerationApi.d.ts +50 -0
- package/dist/types/gen-imports.d.ts +3 -0
- package/dist/types/index.d.ts +8 -7
- package/dist/types/insights.d.ts +9 -8
- package/dist/types/logger.d.ts +9 -0
- package/dist/types/messageComposer/LocationComposer.d.ts +7 -4
- package/dist/types/messageComposer/attachmentIdentity.d.ts +2 -2
- package/dist/types/messageComposer/attachmentManager.d.ts +8 -4
- package/dist/types/messageComposer/configuration/types.d.ts +11 -11
- package/dist/types/messageComposer/linkPreviewsManager.d.ts +25 -13
- package/dist/types/messageComposer/messageComposer.d.ts +10 -10
- package/dist/types/messageComposer/middleware/messageComposer/types.d.ts +3 -3
- package/dist/types/messageComposer/middleware/pollComposer/types.d.ts +4 -7
- package/dist/types/messageComposer/middleware/textComposer/commandUtils.d.ts +3 -3
- package/dist/types/messageComposer/middleware/textComposer/commands.d.ts +7 -7
- package/dist/types/messageComposer/middleware/textComposer/mentions.d.ts +218 -4
- package/dist/types/messageComposer/middleware/textComposer/types.d.ts +9 -4
- package/dist/types/messageComposer/pollComposer.d.ts +5 -4
- package/dist/types/messageComposer/textComposer.d.ts +8 -3
- package/dist/types/messageComposer/types.d.ts +6 -28
- package/dist/types/messageDelivery/MessageDeliveryReporter.d.ts +40 -25
- package/dist/types/messageDelivery/MessageReceiptsTracker.d.ts +53 -12
- package/dist/types/messageOperations/MessageOperationStatePolicy.d.ts +19 -0
- package/dist/types/messageOperations/MessageOperations.d.ts +17 -0
- package/dist/types/messageOperations/index.d.ts +3 -0
- package/dist/types/messageOperations/types.d.ts +49 -0
- package/dist/types/moderation.d.ts +21 -203
- package/dist/types/notifications/types.d.ts +8 -7
- package/dist/types/offline-support/offline_support_api.d.ts +111 -87
- package/dist/types/offline-support/offline_sync_manager.d.ts +0 -7
- package/dist/types/offline-support/types.d.ts +19 -23
- package/dist/types/offline-support/util.d.ts +4 -2
- package/dist/types/pagination/FilterBuilder.d.ts +1 -1
- package/dist/types/pagination/ItemIndex.d.ts +25 -0
- package/dist/types/pagination/cursorDerivation/createdAtAroundPaginationFlags.d.ts +9 -0
- package/dist/types/pagination/cursorDerivation/idAroundPaginationFlags.d.ts +6 -0
- package/dist/types/pagination/cursorDerivation/index.d.ts +1 -0
- package/dist/types/pagination/cursorDerivation/linearPaginationFlags.d.ts +6 -0
- package/dist/types/pagination/filterCompiler.d.ts +7 -0
- package/dist/types/pagination/index.d.ts +1 -3
- package/dist/types/pagination/paginators/BasePaginator.d.ts +848 -0
- package/dist/types/pagination/paginators/ChannelPaginator.d.ts +212 -0
- package/dist/types/pagination/paginators/MessageIntervalPaginator.d.ts +282 -0
- package/dist/types/pagination/paginators/MessagePaginator.d.ts +208 -0
- package/dist/types/pagination/paginators/PinnedMessagePaginator.d.ts +39 -0
- package/dist/types/pagination/paginators/ReminderPaginator.d.ts +19 -0
- package/dist/types/pagination/paginators/UserGroupPaginator.d.ts +24 -0
- package/dist/types/pagination/paginators/index.d.ts +7 -0
- package/dist/types/pagination/paginators/stateThrottling.d.ts +2 -0
- package/dist/types/pagination/sortCompiler.d.ts +49 -0
- package/dist/types/pagination/types.normalization.d.ts +11 -0
- package/dist/types/pagination/utility.normalization.d.ts +18 -0
- package/dist/types/pagination/utility.queryChannel.d.ts +26 -0
- package/dist/types/pagination/utility.search.d.ts +13 -0
- package/dist/types/permissions.d.ts +1 -1
- package/dist/types/poll.d.ts +29 -32
- package/dist/types/poll_manager.d.ts +2 -2
- package/dist/types/reminders/Reminder.d.ts +2 -5
- package/dist/types/reminders/ReminderManager.d.ts +2 -9
- package/dist/types/search/MessageSearchSource.d.ts +4 -4
- package/dist/types/search/UserSearchSource.d.ts +1 -1
- package/dist/types/search/types.d.ts +3 -3
- package/dist/types/segment.d.ts +0 -34
- package/dist/types/signing.d.ts +105 -65
- package/dist/types/store.d.ts +1 -0
- package/dist/types/thread.d.ts +70 -34
- package/dist/types/thread_manager.d.ts +3 -3
- package/dist/types/token_manager.d.ts +15 -10
- package/dist/types/types.d.ts +197 -3404
- package/dist/types/utils/FixedSizeQueueCache.d.ts +12 -6
- package/dist/types/utils/WithSubscriptions.d.ts +2 -1
- package/dist/types/utils/concurrency.d.ts +4 -4
- package/dist/types/utils/mergeWith/mergeWith.d.ts +3 -3
- package/dist/types/utils/mergeWith/mergeWithCore.d.ts +8 -3
- package/dist/types/utils/retryable.d.ts +34 -0
- package/dist/types/utils/throttling/throttle.d.ts +36 -0
- package/dist/types/utils.d.ts +100 -194
- package/package.json +7 -3
- package/src/ChannelManager.ts +724 -0
- package/src/CooldownTimer.ts +2 -2
- package/src/EventHandlerPipeline.ts +228 -0
- package/src/LiveLocationManager.ts +12 -11
- package/src/api-client.ts +275 -0
- package/src/campaign.ts +1 -77
- package/src/channel.ts +1344 -1282
- package/src/channel_batch_updater.ts +1 -211
- package/src/channel_state.ts +144 -1013
- package/src/client.ts +936 -3995
- package/src/client_state.ts +4 -4
- package/src/configuration/InstanceConfigurationService.ts +73 -0
- package/src/configuration/index.ts +1 -0
- package/src/configuration/types.ts +81 -0
- package/src/connection.ts +145 -94
- package/src/connection_fallback.ts +29 -27
- package/src/constants.ts +1 -5
- package/src/custom_types.ts +4 -1
- package/src/entityStore/EntityStore.ts +208 -0
- package/src/entityStore/StoreBackedItemIndex.ts +115 -0
- package/src/entityStore/applyReactionLocally.ts +113 -0
- package/src/entityStore/index.ts +2 -0
- package/src/errors.ts +14 -2
- package/src/gen/chat/ChannelApi.ts +275 -0
- package/src/gen/chat/ChatApi.ts +2554 -0
- package/src/gen/model-decoders/decoders.ts +2680 -0
- package/src/gen/model-decoders/event-decoder-mapping.ts +198 -0
- package/src/gen/models/index.ts +12673 -0
- package/src/gen/moderation/ModerationApi.ts +607 -0
- package/src/gen-imports.ts +3 -0
- package/src/index.ts +11 -12
- package/src/insights.ts +6 -5
- package/src/logger.ts +28 -0
- package/src/messageComposer/LocationComposer.ts +9 -5
- package/src/messageComposer/MessageComposerEffectHandlers.ts +1 -0
- package/src/messageComposer/attachmentIdentity.ts +16 -9
- package/src/messageComposer/attachmentManager.ts +13 -8
- package/src/messageComposer/configuration/types.ts +11 -11
- package/src/messageComposer/linkPreviewsManager.ts +9 -10
- package/src/messageComposer/messageComposer.ts +57 -53
- package/src/messageComposer/middleware/messageComposer/attachments.ts +1 -2
- package/src/messageComposer/middleware/messageComposer/cleanData.ts +1 -1
- package/src/messageComposer/middleware/messageComposer/compositionValidation.ts +2 -2
- package/src/messageComposer/middleware/messageComposer/messageComposerState.ts +2 -2
- package/src/messageComposer/middleware/messageComposer/sharedLocation.ts +4 -3
- package/src/messageComposer/middleware/messageComposer/textComposer.ts +2 -2
- package/src/messageComposer/middleware/messageComposer/types.ts +3 -4
- package/src/messageComposer/middleware/messageComposer/userDataInjection.ts +9 -5
- package/src/messageComposer/middleware/pollComposer/state.ts +0 -2
- package/src/messageComposer/middleware/pollComposer/types.ts +4 -7
- package/src/messageComposer/middleware/textComposer/TextComposerMiddlewareExecutor.ts +10 -1
- package/src/messageComposer/middleware/textComposer/commandEffects.ts +4 -4
- package/src/messageComposer/middleware/textComposer/commandUtils.ts +3 -6
- package/src/messageComposer/middleware/textComposer/commands.ts +3 -3
- package/src/messageComposer/middleware/textComposer/mentionUtils.ts +1 -1
- package/src/messageComposer/middleware/textComposer/mentions.ts +31 -15
- package/src/messageComposer/middleware/textComposer/types.ts +9 -4
- package/src/messageComposer/pollComposer.ts +6 -8
- package/src/messageComposer/textComposer.ts +27 -2
- package/src/messageComposer/types.ts +6 -28
- package/src/messageDelivery/MessageDeliveryReporter.ts +101 -45
- package/src/messageDelivery/MessageReceiptsTracker.ts +294 -21
- package/src/messageOperations/MessageOperationStatePolicy.ts +77 -0
- package/src/messageOperations/MessageOperations.ts +212 -0
- package/src/messageOperations/index.ts +10 -0
- package/src/messageOperations/types.ts +64 -0
- package/src/moderation.ts +38 -431
- package/src/notifications/types.ts +8 -7
- package/src/offline-support/offline_support_api.ts +200 -133
- package/src/offline-support/offline_sync_manager.ts +23 -44
- package/src/offline-support/types.ts +23 -26
- package/src/offline-support/util.ts +5 -4
- package/src/pagination/FilterBuilder.ts +4 -1
- package/src/pagination/ItemIndex.ts +25 -0
- package/src/pagination/cursorDerivation/createdAtAroundPaginationFlags.ts +73 -0
- package/src/pagination/cursorDerivation/idAroundPaginationFlags.ts +53 -0
- package/src/pagination/cursorDerivation/index.ts +1 -0
- package/src/pagination/cursorDerivation/linearPaginationFlags.ts +86 -0
- package/src/pagination/filterCompiler.ts +196 -0
- package/src/pagination/index.ts +1 -3
- package/src/pagination/paginators/BasePaginator.ts +2859 -0
- package/src/pagination/paginators/ChannelPaginator.ts +729 -0
- package/src/pagination/paginators/MessageIntervalPaginator.ts +1116 -0
- package/src/pagination/paginators/MessagePaginator.ts +508 -0
- package/src/pagination/paginators/PinnedMessagePaginator.ts +108 -0
- package/src/pagination/paginators/ReminderPaginator.ts +107 -0
- package/src/pagination/paginators/UserGroupPaginator.ts +127 -0
- package/src/pagination/paginators/index.ts +7 -0
- package/src/pagination/paginators/stateThrottling.ts +31 -0
- package/src/pagination/sortCompiler.ts +193 -0
- package/src/pagination/types.normalization.ts +14 -0
- package/src/pagination/utility.normalization.ts +106 -0
- package/src/pagination/utility.queryChannel.ts +84 -0
- package/src/pagination/utility.search.ts +80 -0
- package/src/permissions.ts +7 -8
- package/src/poll.ts +101 -110
- package/src/poll_manager.ts +14 -8
- package/src/reminders/Reminder.ts +2 -5
- package/src/reminders/ReminderManager.ts +19 -21
- package/src/search/BaseSearchSource.ts +0 -3
- package/src/search/ChannelMemberSearchSource.ts +7 -1
- package/src/search/ChannelSearchSource.ts +10 -3
- package/src/search/MessageSearchSource.ts +29 -30
- package/src/search/UserSearchSource.ts +12 -8
- package/src/search/types.ts +3 -4
- package/src/segment.ts +1 -95
- package/src/signing.ts +107 -67
- package/src/store.ts +2 -1
- package/src/thread.ts +562 -238
- package/src/thread_manager.ts +37 -16
- package/src/token_manager.ts +21 -10
- package/src/types.ts +364 -4533
- package/src/uploadManager.ts +8 -0
- package/src/utils/FixedSizeQueueCache.ts +12 -6
- package/src/utils/WithSubscriptions.ts +2 -1
- package/src/utils/concurrency.ts +4 -4
- package/src/utils/mergeWith/mergeWith.ts +3 -3
- package/src/utils/mergeWith/mergeWithCore.ts +140 -164
- package/src/utils/mergeWith/mergeWithDiff.ts +3 -3
- package/src/utils/retryable.ts +117 -0
- package/src/utils/throttling/throttle.ts +130 -0
- package/src/utils.ts +208 -754
- package/dist/types/channel_manager.d.ts +0 -122
- package/dist/types/events.d.ts +0 -72
- package/dist/types/pagination/BasePaginator.d.ts +0 -69
- package/dist/types/pagination/ReminderPaginator.d.ts +0 -16
- package/dist/types/pagination/UserGroupPaginator.d.ts +0 -21
- package/src/channel_manager.ts +0 -830
- package/src/events.ts +0 -75
- package/src/pagination/BasePaginator.ts +0 -184
- package/src/pagination/ReminderPaginator.ts +0 -56
- 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
|
|
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
|
|
44
|
-
// the sync
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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<
|
|
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
|
-
|
|
224
|
-
|
|
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
|
-
|
|
12
|
+
PollResponse_old,
|
|
13
|
+
QueryChannelsRequest,
|
|
13
14
|
ReactionFilters,
|
|
14
15
|
ReactionResponse,
|
|
15
16
|
ReactionSort,
|
|
16
|
-
|
|
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
|
-
/**
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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?:
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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?:
|
|
305
|
+
truncated_at?: Date;
|
|
309
306
|
/** Whether to immediately execute the operation. */
|
|
310
307
|
execute?: boolean;
|
|
311
308
|
};
|
|
312
309
|
|
|
313
310
|
/**
|
|
314
|
-
*
|
|
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<
|
|
373
|
+
) => Promise<Omit<ChannelStateResponseFields, 'duration'>[] | null>;
|
|
377
374
|
getChannelsForQuery: (
|
|
378
375
|
options: DBGetChannelsForQueryType,
|
|
379
|
-
) => Promise<Omit<
|
|
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<
|
|
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
|
|
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
|
-
|
|
16
|
-
) =>
|
|
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<
|
|
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
|
+
};
|