stream-chat 9.51.0 → 9.52.1
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 +418 -215
- package/dist/cjs/index.browser.js.map +4 -4
- package/dist/cjs/index.node.js +427 -216
- package/dist/cjs/index.node.js.map +4 -4
- package/dist/esm/index.mjs +416 -213
- package/dist/esm/index.mjs.map +4 -4
- package/dist/types/channel.d.ts +5 -3
- package/dist/types/client.d.ts +10 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/messageComposer/attachmentIdentity.d.ts +4 -0
- package/dist/types/messageComposer/attachmentManager.d.ts +8 -0
- package/dist/types/messageComposer/messageComposer.d.ts +13 -0
- package/dist/types/messageComposer/middleware/attachmentManager/postUpload/attachmentEnrichment.d.ts +20 -1
- package/dist/types/messageComposer/middleware/messageComposer/MessageComposerMiddlewareExecutor.d.ts +6 -1
- package/dist/types/messageComposer/middleware/messageComposer/attachments.d.ts +24 -0
- package/dist/types/messageComposer/middleware/messageComposer/types.d.ts +22 -1
- package/dist/types/messageComposer/types.d.ts +5 -0
- package/dist/types/middleware.d.ts +8 -0
- package/dist/types/uploadManager.d.ts +30 -0
- package/dist/types/utils.d.ts +29 -6
- package/package.json +1 -1
- package/src/channel.ts +42 -26
- package/src/client.ts +27 -14
- package/src/index.ts +12 -0
- package/src/messageComposer/attachmentIdentity.ts +27 -0
- package/src/messageComposer/attachmentManager.ts +61 -12
- package/src/messageComposer/messageComposer.ts +43 -8
- package/src/messageComposer/middleware/attachmentManager/postUpload/AttachmentPostUploadMiddlewareExecutor.ts +1 -1
- package/src/messageComposer/middleware/attachmentManager/postUpload/attachmentEnrichment.ts +58 -33
- package/src/messageComposer/middleware/attachmentManager/postUpload/uploadErrorHandler.ts +4 -0
- package/src/messageComposer/middleware/messageComposer/MessageComposerMiddlewareExecutor.ts +9 -0
- package/src/messageComposer/middleware/messageComposer/attachments.ts +109 -0
- package/src/messageComposer/middleware/messageComposer/types.ts +22 -1
- package/src/messageComposer/types.ts +5 -0
- package/src/messageDelivery/MessageDeliveryReporter.ts +5 -4
- package/src/middleware.ts +11 -0
- package/src/offline-support/offline_support_api.ts +4 -0
- package/src/uploadManager.ts +45 -0
- package/src/utils.ts +102 -7
package/src/utils.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import FormData from 'form-data';
|
|
2
2
|
import type {
|
|
3
3
|
AscDesc,
|
|
4
|
+
Attachment,
|
|
4
5
|
ChannelFilters,
|
|
5
6
|
ChannelQueryOptions,
|
|
6
7
|
ChannelSort,
|
|
@@ -40,6 +41,36 @@ export function logChatPromiseExecution<T>(promise: Promise<T>, name: string) {
|
|
|
40
41
|
});
|
|
41
42
|
}
|
|
42
43
|
|
|
44
|
+
/**
|
|
45
|
+
* The default no-op client logger.
|
|
46
|
+
*/
|
|
47
|
+
export const noopLogger: Logger = () => null;
|
|
48
|
+
|
|
49
|
+
const logError = <T>(logger: Logger, error: unknown, event: T) => {
|
|
50
|
+
const message = 'Unhandled error in event listener';
|
|
51
|
+
logger('error', message, { error, event });
|
|
52
|
+
if (logger === noopLogger) console.error(message, error, event);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Invokes a single event listener in isolation, so that a faulty listener cannot
|
|
57
|
+
* abort the dispatch loop or the bookkeeping that follows it.
|
|
58
|
+
*/
|
|
59
|
+
export const invokeEventListener = <T>(
|
|
60
|
+
listener: (event: T) => unknown,
|
|
61
|
+
event: T,
|
|
62
|
+
logger: Logger,
|
|
63
|
+
) => {
|
|
64
|
+
try {
|
|
65
|
+
const result = listener(event);
|
|
66
|
+
if (result && typeof (result as PromiseLike<unknown>).then === 'function') {
|
|
67
|
+
Promise.resolve(result).catch((error) => logError(logger, error, event));
|
|
68
|
+
}
|
|
69
|
+
} catch (error) {
|
|
70
|
+
logError(logger, error, event);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
43
74
|
export const sleep = (m: number): Promise<void> => new Promise((r) => setTimeout(r, m));
|
|
44
75
|
|
|
45
76
|
export function isFunction(value: unknown): value is (...args: unknown[]) => unknown {
|
|
@@ -125,13 +156,6 @@ export const channelTracksReadLocally = (channel?: Channel) =>
|
|
|
125
156
|
!channelHasReadEvents(channel) &&
|
|
126
157
|
!!channel?.getClient().options.isLocalUnreadCountEnabled;
|
|
127
158
|
|
|
128
|
-
/**
|
|
129
|
-
* userHasReadReceipts - Whether the current user allows read receipts, per their privacy settings.
|
|
130
|
-
* Read receipts are treated as enabled unless the user has explicitly disabled them.
|
|
131
|
-
*/
|
|
132
|
-
export const userHasReadReceipts = (client: StreamChat) =>
|
|
133
|
-
client.user?.privacy_settings?.read_receipts?.enabled ?? true;
|
|
134
|
-
|
|
135
159
|
export function addFileToFormData(
|
|
136
160
|
uri: string | NodeJS.ReadableStream | Buffer | File,
|
|
137
161
|
name?: string,
|
|
@@ -382,6 +406,77 @@ export function unformatMessage(message: LocalMessage): MessageResponse {
|
|
|
382
406
|
} as MessageResponse;
|
|
383
407
|
}
|
|
384
408
|
|
|
409
|
+
/**
|
|
410
|
+
* Whether a URL points at something the API and other devices can actually fetch.
|
|
411
|
+
*/
|
|
412
|
+
const isRemoteUrl = (url?: string) => !!url && /^https?:\/\//i.test(url.trim());
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Strips composer-internal state from a message's attachments, and drops any whose upload never
|
|
416
|
+
* resolved.
|
|
417
|
+
*
|
|
418
|
+
* `localMetadata` is how `AttachmentManager` tracks an upload (its id, the `File`, the local
|
|
419
|
+
* preview); it must never reach the API. An attachment that still carries it and has no remote
|
|
420
|
+
* URL was never settled — which is what happens when
|
|
421
|
+
* `createSendWithPendingUploadsAttachmentsMiddleware` is installed by a UI SDK that does not
|
|
422
|
+
* implement the rest of the flow (awaiting those uploads before sending). Sending it would store
|
|
423
|
+
* an attachment pointing at nothing, so it is dropped and logged instead.
|
|
424
|
+
*
|
|
425
|
+
* Returns the same message object when there was nothing to change.
|
|
426
|
+
*/
|
|
427
|
+
export const sanitizeOutgoingAttachments = <T extends { attachments?: Attachment[] }>({
|
|
428
|
+
client,
|
|
429
|
+
message,
|
|
430
|
+
}: {
|
|
431
|
+
client: StreamChat;
|
|
432
|
+
message: T;
|
|
433
|
+
}): T => {
|
|
434
|
+
const attachments = message.attachments;
|
|
435
|
+
if (!attachments?.length) return message;
|
|
436
|
+
|
|
437
|
+
const unresolved: Attachment[] = [];
|
|
438
|
+
let changed = false;
|
|
439
|
+
|
|
440
|
+
const sanitized = attachments.reduce<Attachment[]>((acc, attachment) => {
|
|
441
|
+
const { localMetadata, ...rest } = attachment as Attachment & {
|
|
442
|
+
localMetadata?: Record<string, unknown>;
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
if (!localMetadata) {
|
|
446
|
+
acc.push(attachment);
|
|
447
|
+
return acc;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
changed = true;
|
|
451
|
+
|
|
452
|
+
// Any of these pointing at a remote URL means the attachment resolved to something the API
|
|
453
|
+
// can store and other devices can load.
|
|
454
|
+
const hasRemoteSource =
|
|
455
|
+
isRemoteUrl(rest.asset_url) ||
|
|
456
|
+
isRemoteUrl(rest.image_url) ||
|
|
457
|
+
isRemoteUrl(rest.og_scrape_url) ||
|
|
458
|
+
isRemoteUrl(rest.title_link);
|
|
459
|
+
|
|
460
|
+
if (hasRemoteSource) {
|
|
461
|
+
acc.push(rest as Attachment);
|
|
462
|
+
} else {
|
|
463
|
+
unresolved.push(rest as Attachment);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
return acc;
|
|
467
|
+
}, []);
|
|
468
|
+
|
|
469
|
+
if (unresolved.length) {
|
|
470
|
+
const text = `Dropped ${unresolved.length} attachment(s) whose upload never completed. Composing with pending uploads requires awaiting them before sending.`;
|
|
471
|
+
const extraData = { attachments: unresolved, message, tags: ['attachments'] };
|
|
472
|
+
|
|
473
|
+
client.logger('warn', text, extraData);
|
|
474
|
+
console.warn(text, extraData);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
return changed ? { ...message, attachments: sanitized } : message;
|
|
478
|
+
};
|
|
479
|
+
|
|
385
480
|
export const localMessageToNewMessagePayload = (localMessage: LocalMessage): Message => {
|
|
386
481
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
387
482
|
const {
|