stream-chat 9.43.2 → 9.44.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/README.md +1 -1
- package/dist/cjs/index.browser.js +152 -7
- package/dist/cjs/index.browser.js.map +3 -3
- package/dist/cjs/index.node.js +157 -8
- package/dist/cjs/index.node.js.map +3 -3
- package/dist/esm/index.mjs +152 -7
- package/dist/esm/index.mjs.map +3 -3
- package/dist/types/client.d.ts +32 -0
- package/dist/types/offline-support/types.d.ts +5 -1
- package/dist/types/signing.d.ts +99 -5
- package/package.json +2 -1
- package/src/channel.ts +3 -1
- package/src/channel_manager.ts +4 -1
- package/src/client.ts +56 -2
- package/src/messageComposer/messageComposer.ts +2 -0
- package/src/offline-support/types.ts +5 -0
- package/src/signing.ts +195 -7
- package/src/utils.ts +1 -1
package/dist/esm/index.mjs
CHANGED
|
@@ -42,6 +42,12 @@ var require_crypto = __commonJS({
|
|
|
42
42
|
}
|
|
43
43
|
});
|
|
44
44
|
|
|
45
|
+
// (disabled):zlib
|
|
46
|
+
var require_zlib = __commonJS({
|
|
47
|
+
"(disabled):zlib"() {
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
45
51
|
// src/base64.ts
|
|
46
52
|
import { fromByteArray } from "base64-js";
|
|
47
53
|
function isString(arrayOrString) {
|
|
@@ -650,7 +656,7 @@ var deleteUserMessages = ({
|
|
|
650
656
|
if (message.user?.id === user.id) {
|
|
651
657
|
messages[i] = message.type === "deleted" ? message : toDeletedMessage({ message, hardDelete, deletedAt });
|
|
652
658
|
}
|
|
653
|
-
if (message.quoted_message?.user?.id === user.id) {
|
|
659
|
+
if (messages[i].quoted_message && message.quoted_message?.user?.id === user.id) {
|
|
654
660
|
messages[i].quoted_message = message.quoted_message.type === "deleted" ? message.quoted_message : toDeletedMessage({
|
|
655
661
|
message: messages[i].quoted_message,
|
|
656
662
|
hardDelete,
|
|
@@ -7250,6 +7256,7 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
|
|
|
7250
7256
|
const draft = event.draft;
|
|
7251
7257
|
if (!draft || (draft.parent_id ?? null) !== (this.threadId ?? null) || draft.channel_cid !== this.channel.cid)
|
|
7252
7258
|
return;
|
|
7259
|
+
if (this.editedMessage) return;
|
|
7253
7260
|
this.initState({ composition: draft });
|
|
7254
7261
|
}).unsubscribe;
|
|
7255
7262
|
this.subscribeDraftDeleted = () => this.client.on("draft.deleted", (event) => {
|
|
@@ -7257,6 +7264,7 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
|
|
|
7257
7264
|
if (!draft || (draft.parent_id ?? null) !== (this.threadId ?? null) || draft.channel_cid !== this.channel.cid) {
|
|
7258
7265
|
return;
|
|
7259
7266
|
}
|
|
7267
|
+
if (this.editedMessage) return;
|
|
7260
7268
|
this.logDraftUpdateTimestamp();
|
|
7261
7269
|
if (this.compositionIsEmpty) {
|
|
7262
7270
|
return;
|
|
@@ -9300,7 +9308,7 @@ var Channel = class {
|
|
|
9300
9308
|
if (Array.isArray(this.data?.own_capabilities) && !this.data?.own_capabilities.includes("read-events")) {
|
|
9301
9309
|
return false;
|
|
9302
9310
|
}
|
|
9303
|
-
if (this.
|
|
9311
|
+
if (this.getClient()._muteStatus(this.cid).muted) return false;
|
|
9304
9312
|
return true;
|
|
9305
9313
|
}
|
|
9306
9314
|
/**
|
|
@@ -10811,6 +10819,7 @@ var UploadManager = class {
|
|
|
10811
10819
|
// src/signing.ts
|
|
10812
10820
|
var import_jsonwebtoken = __toESM(require_jsonwebtoken());
|
|
10813
10821
|
var import_crypto = __toESM(require_crypto());
|
|
10822
|
+
var import_zlib = __toESM(require_zlib());
|
|
10814
10823
|
function JWTUserToken(apiSecret, userId, extraData = {}, jwtOptions = {}) {
|
|
10815
10824
|
if (typeof userId !== "string") {
|
|
10816
10825
|
throw new TypeError("userId should be a string");
|
|
@@ -10862,7 +10871,7 @@ function DevToken(userId) {
|
|
|
10862
10871
|
// hardcoded signature
|
|
10863
10872
|
].join(".");
|
|
10864
10873
|
}
|
|
10865
|
-
function
|
|
10874
|
+
function verifySignature(body, signature, secret) {
|
|
10866
10875
|
const key = Buffer.from(secret, "utf8");
|
|
10867
10876
|
const hash = import_crypto.default.createHmac("sha256", key).update(body).digest("hex");
|
|
10868
10877
|
try {
|
|
@@ -10871,6 +10880,86 @@ function CheckSignature(body, secret, signature) {
|
|
|
10871
10880
|
return false;
|
|
10872
10881
|
}
|
|
10873
10882
|
}
|
|
10883
|
+
function CheckSignature(body, secret, signature) {
|
|
10884
|
+
return verifySignature(body, signature, secret);
|
|
10885
|
+
}
|
|
10886
|
+
var InvalidWebhookErrorMessages = {
|
|
10887
|
+
signatureMismatch: "signature mismatch",
|
|
10888
|
+
invalidBase64: "invalid base64 encoding",
|
|
10889
|
+
gzipFailed: "gzip decompression failed",
|
|
10890
|
+
invalidJson: "invalid JSON payload"
|
|
10891
|
+
};
|
|
10892
|
+
var InvalidWebhookError = class extends Error {
|
|
10893
|
+
constructor(message = InvalidWebhookErrorMessages.signatureMismatch) {
|
|
10894
|
+
super(message);
|
|
10895
|
+
this.name = "InvalidWebhookError";
|
|
10896
|
+
}
|
|
10897
|
+
};
|
|
10898
|
+
function gunzipPayload(rawBody) {
|
|
10899
|
+
const GZIP_MAGIC = Buffer.from([31, 139]);
|
|
10900
|
+
const body = Buffer.isBuffer(rawBody) ? rawBody : Buffer.from(rawBody);
|
|
10901
|
+
if (body.length >= 2 && body.subarray(0, 2).equals(GZIP_MAGIC)) {
|
|
10902
|
+
try {
|
|
10903
|
+
return import_zlib.default.gunzipSync(body);
|
|
10904
|
+
} catch {
|
|
10905
|
+
throw new InvalidWebhookError(InvalidWebhookErrorMessages.gzipFailed);
|
|
10906
|
+
}
|
|
10907
|
+
}
|
|
10908
|
+
return body;
|
|
10909
|
+
}
|
|
10910
|
+
function decodeSqsPayload(body) {
|
|
10911
|
+
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(body) || body.length % 4 !== 0) {
|
|
10912
|
+
throw new InvalidWebhookError(InvalidWebhookErrorMessages.invalidBase64);
|
|
10913
|
+
}
|
|
10914
|
+
const decoded = Buffer.from(body, "base64");
|
|
10915
|
+
if (decoded.toString("base64").length !== body.length) {
|
|
10916
|
+
throw new InvalidWebhookError(InvalidWebhookErrorMessages.invalidBase64);
|
|
10917
|
+
}
|
|
10918
|
+
return gunzipPayload(decoded);
|
|
10919
|
+
}
|
|
10920
|
+
function decodeSnsPayload(notificationBody) {
|
|
10921
|
+
const inner = extractSnsMessage(notificationBody);
|
|
10922
|
+
return decodeSqsPayload(inner ?? notificationBody);
|
|
10923
|
+
}
|
|
10924
|
+
function extractSnsMessage(notificationBody) {
|
|
10925
|
+
const trimmed = notificationBody.replace(/^[\s\uFEFF]+/, "");
|
|
10926
|
+
if (!trimmed.startsWith("{")) {
|
|
10927
|
+
return null;
|
|
10928
|
+
}
|
|
10929
|
+
let parsed;
|
|
10930
|
+
try {
|
|
10931
|
+
parsed = JSON.parse(trimmed);
|
|
10932
|
+
} catch {
|
|
10933
|
+
return null;
|
|
10934
|
+
}
|
|
10935
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed) || typeof parsed.Message !== "string") {
|
|
10936
|
+
return null;
|
|
10937
|
+
}
|
|
10938
|
+
return parsed.Message;
|
|
10939
|
+
}
|
|
10940
|
+
function parseEvent(payload) {
|
|
10941
|
+
const text = Buffer.isBuffer(payload) ? payload.toString("utf8") : payload;
|
|
10942
|
+
try {
|
|
10943
|
+
return JSON.parse(text);
|
|
10944
|
+
} catch {
|
|
10945
|
+
throw new InvalidWebhookError(InvalidWebhookErrorMessages.invalidJson);
|
|
10946
|
+
}
|
|
10947
|
+
}
|
|
10948
|
+
function verifyAndParse(payload, signature, secret) {
|
|
10949
|
+
if (!verifySignature(payload, signature, secret)) {
|
|
10950
|
+
throw new InvalidWebhookError(InvalidWebhookErrorMessages.signatureMismatch);
|
|
10951
|
+
}
|
|
10952
|
+
return parseEvent(payload);
|
|
10953
|
+
}
|
|
10954
|
+
function verifyAndParseWebhook(rawBody, signature, secret) {
|
|
10955
|
+
return verifyAndParse(gunzipPayload(rawBody), signature, secret);
|
|
10956
|
+
}
|
|
10957
|
+
function parseSqs(messageBody) {
|
|
10958
|
+
return parseEvent(decodeSqsPayload(messageBody));
|
|
10959
|
+
}
|
|
10960
|
+
function parseSns(notificationBody) {
|
|
10961
|
+
return parseEvent(decodeSnsPayload(notificationBody));
|
|
10962
|
+
}
|
|
10874
10963
|
|
|
10875
10964
|
// src/token_manager.ts
|
|
10876
10965
|
var TokenManager = class {
|
|
@@ -12214,12 +12303,13 @@ var ChannelManager = class extends WithSubscriptions {
|
|
|
12214
12303
|
});
|
|
12215
12304
|
const {
|
|
12216
12305
|
channels,
|
|
12217
|
-
pagination: { filters, sort }
|
|
12306
|
+
pagination: { filters, options, sort }
|
|
12218
12307
|
} = this.state.getLatestValue();
|
|
12219
12308
|
this.client.offlineDb?.executeQuerySafely(
|
|
12220
12309
|
(db) => db.upsertCidsForQuery({
|
|
12221
12310
|
cids: channels.map((channel) => channel.cid),
|
|
12222
12311
|
filters,
|
|
12312
|
+
options,
|
|
12223
12313
|
sort
|
|
12224
12314
|
}),
|
|
12225
12315
|
{ method: "upsertCidsForQuery" }
|
|
@@ -12273,6 +12363,7 @@ var ChannelManager = class extends WithSubscriptions {
|
|
|
12273
12363
|
(db) => db.upsertCidsForQuery({
|
|
12274
12364
|
cids: channels.map((channel) => channel.cid),
|
|
12275
12365
|
filters: pagination.filters,
|
|
12366
|
+
options,
|
|
12276
12367
|
sort: pagination.sort
|
|
12277
12368
|
}),
|
|
12278
12369
|
{ method: "upsertCidsForQuery" }
|
|
@@ -12329,6 +12420,7 @@ var ChannelManager = class extends WithSubscriptions {
|
|
|
12329
12420
|
const channelsFromDB = await this.client.offlineDb.getChannelsForQuery({
|
|
12330
12421
|
userId: this.client.user.id,
|
|
12331
12422
|
filters,
|
|
12423
|
+
options,
|
|
12332
12424
|
sort
|
|
12333
12425
|
});
|
|
12334
12426
|
if (channelsFromDB) {
|
|
@@ -15474,7 +15566,7 @@ var StreamChat = class _StreamChat {
|
|
|
15474
15566
|
if (this.userAgent) {
|
|
15475
15567
|
return this.userAgent;
|
|
15476
15568
|
}
|
|
15477
|
-
const version = "9.
|
|
15569
|
+
const version = "9.44.1";
|
|
15478
15570
|
const clientBundle = "browser-esm";
|
|
15479
15571
|
let userAgentString = "";
|
|
15480
15572
|
if (this.sdkIdentifier) {
|
|
@@ -15567,7 +15659,50 @@ var StreamChat = class _StreamChat {
|
|
|
15567
15659
|
* @returns {boolean}
|
|
15568
15660
|
*/
|
|
15569
15661
|
verifyWebhook(requestBody, xSignature) {
|
|
15570
|
-
return !!this.secret &&
|
|
15662
|
+
return !!this.secret && verifySignature(requestBody, xSignature, this.secret);
|
|
15663
|
+
}
|
|
15664
|
+
/**
|
|
15665
|
+
* Verify and parse an HTTP webhook event.
|
|
15666
|
+
*
|
|
15667
|
+
* Decompresses `rawBody` when gzipped (detected from the body bytes),
|
|
15668
|
+
* verifies the `X-Signature` header against the app's API secret, and
|
|
15669
|
+
* returns the parsed `Event`. Works whether or not Stream is currently
|
|
15670
|
+
* compressing payloads for this app, and stays correct behind
|
|
15671
|
+
* middleware that auto-decompresses the request.
|
|
15672
|
+
*
|
|
15673
|
+
* @param rawBody Raw HTTP request body bytes Stream signed
|
|
15674
|
+
* @param signature Value of the `X-Signature` header
|
|
15675
|
+
* @throws {InvalidWebhookError} When the signature does not match or
|
|
15676
|
+
* the gzip envelope is malformed.
|
|
15677
|
+
*/
|
|
15678
|
+
verifyAndParseWebhook(rawBody, signature) {
|
|
15679
|
+
if (!this.secret) {
|
|
15680
|
+
throw new InvalidWebhookError(
|
|
15681
|
+
"cannot verify webhook signature without an API secret on the client"
|
|
15682
|
+
);
|
|
15683
|
+
}
|
|
15684
|
+
return verifyAndParseWebhook(rawBody, signature, this.secret);
|
|
15685
|
+
}
|
|
15686
|
+
/**
|
|
15687
|
+
* Parse an SQS firehose event: decodes the message `Body` (base64 +
|
|
15688
|
+
* optional gzip) and returns the parsed `Event`. No HMAC verification
|
|
15689
|
+
* (Stream does not sign SQS bodies).
|
|
15690
|
+
*
|
|
15691
|
+
* @param messageBody SQS message `Body` string
|
|
15692
|
+
* @throws {InvalidWebhookError} When the base64 / gzip envelope is malformed.
|
|
15693
|
+
*/
|
|
15694
|
+
parseSqs(messageBody) {
|
|
15695
|
+
return parseSqs(messageBody);
|
|
15696
|
+
}
|
|
15697
|
+
/**
|
|
15698
|
+
* Parse an SNS-delivered event (unwraps envelope JSON when needed, then
|
|
15699
|
+
* same decode path as SQS). No HMAC verification.
|
|
15700
|
+
*
|
|
15701
|
+
* @param notificationBody Raw SNS POST body or pre-extracted `Message` string
|
|
15702
|
+
* @throws {InvalidWebhookError} When the envelope cannot be decoded.
|
|
15703
|
+
*/
|
|
15704
|
+
parseSns(notificationBody) {
|
|
15705
|
+
return parseSns(notificationBody);
|
|
15571
15706
|
}
|
|
15572
15707
|
/** getPermission - gets the definition for a permission
|
|
15573
15708
|
*
|
|
@@ -18117,6 +18252,8 @@ export {
|
|
|
18117
18252
|
FilterBuilder,
|
|
18118
18253
|
FixedSizeQueueCache,
|
|
18119
18254
|
InsightMetrics,
|
|
18255
|
+
InvalidWebhookError,
|
|
18256
|
+
InvalidWebhookErrorMessages,
|
|
18120
18257
|
JWTServerToken,
|
|
18121
18258
|
JWTUserToken,
|
|
18122
18259
|
LinkPreviewStatus,
|
|
@@ -18203,6 +18340,8 @@ export {
|
|
|
18203
18340
|
createUploadConfigCheckMiddleware,
|
|
18204
18341
|
createUploadErrorHandlerMiddleware,
|
|
18205
18342
|
decodeBase64,
|
|
18343
|
+
decodeSnsPayload,
|
|
18344
|
+
decodeSqsPayload,
|
|
18206
18345
|
defaultPollFieldBlurEventValidators,
|
|
18207
18346
|
defaultPollFieldChangeEventValidators,
|
|
18208
18347
|
encodeBase64,
|
|
@@ -18218,6 +18357,7 @@ export {
|
|
|
18218
18357
|
getRawCommandName,
|
|
18219
18358
|
getTokenizedSuggestionDisplayName,
|
|
18220
18359
|
getTriggerCharWithToken,
|
|
18360
|
+
gunzipPayload,
|
|
18221
18361
|
insertItemWithTrigger,
|
|
18222
18362
|
isAudioAttachment,
|
|
18223
18363
|
isBlobButNotFile,
|
|
@@ -18248,6 +18388,9 @@ export {
|
|
|
18248
18388
|
logChatPromiseExecution,
|
|
18249
18389
|
mapPollStateToResponse,
|
|
18250
18390
|
notifyCommandDisabled,
|
|
18391
|
+
parseEvent,
|
|
18392
|
+
parseSns,
|
|
18393
|
+
parseSqs,
|
|
18251
18394
|
pollCompositionStateProcessors,
|
|
18252
18395
|
pollStateChangeValidators,
|
|
18253
18396
|
postInsights,
|
|
@@ -18257,6 +18400,8 @@ export {
|
|
|
18257
18400
|
replaceWordWithEntity,
|
|
18258
18401
|
stripCommandFromText,
|
|
18259
18402
|
textIsEmpty,
|
|
18260
|
-
timeLeftMs
|
|
18403
|
+
timeLeftMs,
|
|
18404
|
+
verifyAndParseWebhook,
|
|
18405
|
+
verifySignature
|
|
18261
18406
|
};
|
|
18262
18407
|
//# sourceMappingURL=index.mjs.map
|