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/cjs/index.node.js
CHANGED
|
@@ -71,6 +71,8 @@ __export(index_exports, {
|
|
|
71
71
|
FilterBuilder: () => FilterBuilder,
|
|
72
72
|
FixedSizeQueueCache: () => FixedSizeQueueCache,
|
|
73
73
|
InsightMetrics: () => InsightMetrics,
|
|
74
|
+
InvalidWebhookError: () => InvalidWebhookError,
|
|
75
|
+
InvalidWebhookErrorMessages: () => InvalidWebhookErrorMessages,
|
|
74
76
|
JWTServerToken: () => JWTServerToken,
|
|
75
77
|
JWTUserToken: () => JWTUserToken,
|
|
76
78
|
LinkPreviewStatus: () => LinkPreviewStatus,
|
|
@@ -157,6 +159,8 @@ __export(index_exports, {
|
|
|
157
159
|
createUploadConfigCheckMiddleware: () => createUploadConfigCheckMiddleware,
|
|
158
160
|
createUploadErrorHandlerMiddleware: () => createUploadErrorHandlerMiddleware,
|
|
159
161
|
decodeBase64: () => decodeBase64,
|
|
162
|
+
decodeSnsPayload: () => decodeSnsPayload,
|
|
163
|
+
decodeSqsPayload: () => decodeSqsPayload,
|
|
160
164
|
defaultPollFieldBlurEventValidators: () => defaultPollFieldBlurEventValidators,
|
|
161
165
|
defaultPollFieldChangeEventValidators: () => defaultPollFieldChangeEventValidators,
|
|
162
166
|
encodeBase64: () => encodeBase64,
|
|
@@ -172,6 +176,7 @@ __export(index_exports, {
|
|
|
172
176
|
getRawCommandName: () => getRawCommandName,
|
|
173
177
|
getTokenizedSuggestionDisplayName: () => getTokenizedSuggestionDisplayName,
|
|
174
178
|
getTriggerCharWithToken: () => getTriggerCharWithToken,
|
|
179
|
+
gunzipPayload: () => gunzipPayload,
|
|
175
180
|
insertItemWithTrigger: () => insertItemWithTrigger,
|
|
176
181
|
isAudioAttachment: () => isAudioAttachment,
|
|
177
182
|
isBlobButNotFile: () => isBlobButNotFile,
|
|
@@ -202,6 +207,9 @@ __export(index_exports, {
|
|
|
202
207
|
logChatPromiseExecution: () => logChatPromiseExecution,
|
|
203
208
|
mapPollStateToResponse: () => mapPollStateToResponse,
|
|
204
209
|
notifyCommandDisabled: () => notifyCommandDisabled,
|
|
210
|
+
parseEvent: () => parseEvent,
|
|
211
|
+
parseSns: () => parseSns,
|
|
212
|
+
parseSqs: () => parseSqs,
|
|
205
213
|
pollCompositionStateProcessors: () => pollCompositionStateProcessors,
|
|
206
214
|
pollStateChangeValidators: () => pollStateChangeValidators,
|
|
207
215
|
postInsights: () => postInsights,
|
|
@@ -211,7 +219,9 @@ __export(index_exports, {
|
|
|
211
219
|
replaceWordWithEntity: () => replaceWordWithEntity,
|
|
212
220
|
stripCommandFromText: () => stripCommandFromText,
|
|
213
221
|
textIsEmpty: () => textIsEmpty,
|
|
214
|
-
timeLeftMs: () => timeLeftMs
|
|
222
|
+
timeLeftMs: () => timeLeftMs,
|
|
223
|
+
verifyAndParseWebhook: () => verifyAndParseWebhook,
|
|
224
|
+
verifySignature: () => verifySignature
|
|
215
225
|
});
|
|
216
226
|
module.exports = __toCommonJS(index_exports);
|
|
217
227
|
|
|
@@ -823,7 +833,7 @@ var deleteUserMessages = ({
|
|
|
823
833
|
if (message.user?.id === user.id) {
|
|
824
834
|
messages[i] = message.type === "deleted" ? message : toDeletedMessage({ message, hardDelete, deletedAt });
|
|
825
835
|
}
|
|
826
|
-
if (message.quoted_message?.user?.id === user.id) {
|
|
836
|
+
if (messages[i].quoted_message && message.quoted_message?.user?.id === user.id) {
|
|
827
837
|
messages[i].quoted_message = message.quoted_message.type === "deleted" ? message.quoted_message : toDeletedMessage({
|
|
828
838
|
message: messages[i].quoted_message,
|
|
829
839
|
hardDelete,
|
|
@@ -7423,6 +7433,7 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
|
|
|
7423
7433
|
const draft = event.draft;
|
|
7424
7434
|
if (!draft || (draft.parent_id ?? null) !== (this.threadId ?? null) || draft.channel_cid !== this.channel.cid)
|
|
7425
7435
|
return;
|
|
7436
|
+
if (this.editedMessage) return;
|
|
7426
7437
|
this.initState({ composition: draft });
|
|
7427
7438
|
}).unsubscribe;
|
|
7428
7439
|
this.subscribeDraftDeleted = () => this.client.on("draft.deleted", (event) => {
|
|
@@ -7430,6 +7441,7 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
|
|
|
7430
7441
|
if (!draft || (draft.parent_id ?? null) !== (this.threadId ?? null) || draft.channel_cid !== this.channel.cid) {
|
|
7431
7442
|
return;
|
|
7432
7443
|
}
|
|
7444
|
+
if (this.editedMessage) return;
|
|
7433
7445
|
this.logDraftUpdateTimestamp();
|
|
7434
7446
|
if (this.compositionIsEmpty) {
|
|
7435
7447
|
return;
|
|
@@ -9473,7 +9485,7 @@ var Channel = class {
|
|
|
9473
9485
|
if (Array.isArray(this.data?.own_capabilities) && !this.data?.own_capabilities.includes("read-events")) {
|
|
9474
9486
|
return false;
|
|
9475
9487
|
}
|
|
9476
|
-
if (this.
|
|
9488
|
+
if (this.getClient()._muteStatus(this.cid).muted) return false;
|
|
9477
9489
|
return true;
|
|
9478
9490
|
}
|
|
9479
9491
|
/**
|
|
@@ -10984,6 +10996,7 @@ var UploadManager = class {
|
|
|
10984
10996
|
// src/signing.ts
|
|
10985
10997
|
var import_jsonwebtoken = __toESM(require("jsonwebtoken"));
|
|
10986
10998
|
var import_crypto = __toESM(require("crypto"));
|
|
10999
|
+
var import_zlib = __toESM(require("zlib"));
|
|
10987
11000
|
function JWTUserToken(apiSecret, userId, extraData = {}, jwtOptions = {}) {
|
|
10988
11001
|
if (typeof userId !== "string") {
|
|
10989
11002
|
throw new TypeError("userId should be a string");
|
|
@@ -11035,7 +11048,7 @@ function DevToken(userId) {
|
|
|
11035
11048
|
// hardcoded signature
|
|
11036
11049
|
].join(".");
|
|
11037
11050
|
}
|
|
11038
|
-
function
|
|
11051
|
+
function verifySignature(body, signature, secret) {
|
|
11039
11052
|
const key = Buffer.from(secret, "utf8");
|
|
11040
11053
|
const hash = import_crypto.default.createHmac("sha256", key).update(body).digest("hex");
|
|
11041
11054
|
try {
|
|
@@ -11044,6 +11057,86 @@ function CheckSignature(body, secret, signature) {
|
|
|
11044
11057
|
return false;
|
|
11045
11058
|
}
|
|
11046
11059
|
}
|
|
11060
|
+
function CheckSignature(body, secret, signature) {
|
|
11061
|
+
return verifySignature(body, signature, secret);
|
|
11062
|
+
}
|
|
11063
|
+
var InvalidWebhookErrorMessages = {
|
|
11064
|
+
signatureMismatch: "signature mismatch",
|
|
11065
|
+
invalidBase64: "invalid base64 encoding",
|
|
11066
|
+
gzipFailed: "gzip decompression failed",
|
|
11067
|
+
invalidJson: "invalid JSON payload"
|
|
11068
|
+
};
|
|
11069
|
+
var InvalidWebhookError = class extends Error {
|
|
11070
|
+
constructor(message = InvalidWebhookErrorMessages.signatureMismatch) {
|
|
11071
|
+
super(message);
|
|
11072
|
+
this.name = "InvalidWebhookError";
|
|
11073
|
+
}
|
|
11074
|
+
};
|
|
11075
|
+
function gunzipPayload(rawBody) {
|
|
11076
|
+
const GZIP_MAGIC = Buffer.from([31, 139]);
|
|
11077
|
+
const body = Buffer.isBuffer(rawBody) ? rawBody : Buffer.from(rawBody);
|
|
11078
|
+
if (body.length >= 2 && body.subarray(0, 2).equals(GZIP_MAGIC)) {
|
|
11079
|
+
try {
|
|
11080
|
+
return import_zlib.default.gunzipSync(body);
|
|
11081
|
+
} catch {
|
|
11082
|
+
throw new InvalidWebhookError(InvalidWebhookErrorMessages.gzipFailed);
|
|
11083
|
+
}
|
|
11084
|
+
}
|
|
11085
|
+
return body;
|
|
11086
|
+
}
|
|
11087
|
+
function decodeSqsPayload(body) {
|
|
11088
|
+
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(body) || body.length % 4 !== 0) {
|
|
11089
|
+
throw new InvalidWebhookError(InvalidWebhookErrorMessages.invalidBase64);
|
|
11090
|
+
}
|
|
11091
|
+
const decoded = Buffer.from(body, "base64");
|
|
11092
|
+
if (decoded.toString("base64").length !== body.length) {
|
|
11093
|
+
throw new InvalidWebhookError(InvalidWebhookErrorMessages.invalidBase64);
|
|
11094
|
+
}
|
|
11095
|
+
return gunzipPayload(decoded);
|
|
11096
|
+
}
|
|
11097
|
+
function decodeSnsPayload(notificationBody) {
|
|
11098
|
+
const inner = extractSnsMessage(notificationBody);
|
|
11099
|
+
return decodeSqsPayload(inner ?? notificationBody);
|
|
11100
|
+
}
|
|
11101
|
+
function extractSnsMessage(notificationBody) {
|
|
11102
|
+
const trimmed = notificationBody.replace(/^[\s\uFEFF]+/, "");
|
|
11103
|
+
if (!trimmed.startsWith("{")) {
|
|
11104
|
+
return null;
|
|
11105
|
+
}
|
|
11106
|
+
let parsed;
|
|
11107
|
+
try {
|
|
11108
|
+
parsed = JSON.parse(trimmed);
|
|
11109
|
+
} catch {
|
|
11110
|
+
return null;
|
|
11111
|
+
}
|
|
11112
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed) || typeof parsed.Message !== "string") {
|
|
11113
|
+
return null;
|
|
11114
|
+
}
|
|
11115
|
+
return parsed.Message;
|
|
11116
|
+
}
|
|
11117
|
+
function parseEvent(payload) {
|
|
11118
|
+
const text = Buffer.isBuffer(payload) ? payload.toString("utf8") : payload;
|
|
11119
|
+
try {
|
|
11120
|
+
return JSON.parse(text);
|
|
11121
|
+
} catch {
|
|
11122
|
+
throw new InvalidWebhookError(InvalidWebhookErrorMessages.invalidJson);
|
|
11123
|
+
}
|
|
11124
|
+
}
|
|
11125
|
+
function verifyAndParse(payload, signature, secret) {
|
|
11126
|
+
if (!verifySignature(payload, signature, secret)) {
|
|
11127
|
+
throw new InvalidWebhookError(InvalidWebhookErrorMessages.signatureMismatch);
|
|
11128
|
+
}
|
|
11129
|
+
return parseEvent(payload);
|
|
11130
|
+
}
|
|
11131
|
+
function verifyAndParseWebhook(rawBody, signature, secret) {
|
|
11132
|
+
return verifyAndParse(gunzipPayload(rawBody), signature, secret);
|
|
11133
|
+
}
|
|
11134
|
+
function parseSqs(messageBody) {
|
|
11135
|
+
return parseEvent(decodeSqsPayload(messageBody));
|
|
11136
|
+
}
|
|
11137
|
+
function parseSns(notificationBody) {
|
|
11138
|
+
return parseEvent(decodeSnsPayload(notificationBody));
|
|
11139
|
+
}
|
|
11047
11140
|
|
|
11048
11141
|
// src/token_manager.ts
|
|
11049
11142
|
var TokenManager = class {
|
|
@@ -12387,12 +12480,13 @@ var ChannelManager = class extends WithSubscriptions {
|
|
|
12387
12480
|
});
|
|
12388
12481
|
const {
|
|
12389
12482
|
channels,
|
|
12390
|
-
pagination: { filters, sort }
|
|
12483
|
+
pagination: { filters, options, sort }
|
|
12391
12484
|
} = this.state.getLatestValue();
|
|
12392
12485
|
this.client.offlineDb?.executeQuerySafely(
|
|
12393
12486
|
(db) => db.upsertCidsForQuery({
|
|
12394
12487
|
cids: channels.map((channel) => channel.cid),
|
|
12395
12488
|
filters,
|
|
12489
|
+
options,
|
|
12396
12490
|
sort
|
|
12397
12491
|
}),
|
|
12398
12492
|
{ method: "upsertCidsForQuery" }
|
|
@@ -12446,6 +12540,7 @@ var ChannelManager = class extends WithSubscriptions {
|
|
|
12446
12540
|
(db) => db.upsertCidsForQuery({
|
|
12447
12541
|
cids: channels.map((channel) => channel.cid),
|
|
12448
12542
|
filters: pagination.filters,
|
|
12543
|
+
options,
|
|
12449
12544
|
sort: pagination.sort
|
|
12450
12545
|
}),
|
|
12451
12546
|
{ method: "upsertCidsForQuery" }
|
|
@@ -12502,6 +12597,7 @@ var ChannelManager = class extends WithSubscriptions {
|
|
|
12502
12597
|
const channelsFromDB = await this.client.offlineDb.getChannelsForQuery({
|
|
12503
12598
|
userId: this.client.user.id,
|
|
12504
12599
|
filters,
|
|
12600
|
+
options,
|
|
12505
12601
|
sort
|
|
12506
12602
|
});
|
|
12507
12603
|
if (channelsFromDB) {
|
|
@@ -15647,7 +15743,7 @@ var StreamChat = class _StreamChat {
|
|
|
15647
15743
|
if (this.userAgent) {
|
|
15648
15744
|
return this.userAgent;
|
|
15649
15745
|
}
|
|
15650
|
-
const version = "9.
|
|
15746
|
+
const version = "9.44.1";
|
|
15651
15747
|
const clientBundle = "node-cjs";
|
|
15652
15748
|
let userAgentString = "";
|
|
15653
15749
|
if (this.sdkIdentifier) {
|
|
@@ -15740,7 +15836,50 @@ var StreamChat = class _StreamChat {
|
|
|
15740
15836
|
* @returns {boolean}
|
|
15741
15837
|
*/
|
|
15742
15838
|
verifyWebhook(requestBody, xSignature) {
|
|
15743
|
-
return !!this.secret &&
|
|
15839
|
+
return !!this.secret && verifySignature(requestBody, xSignature, this.secret);
|
|
15840
|
+
}
|
|
15841
|
+
/**
|
|
15842
|
+
* Verify and parse an HTTP webhook event.
|
|
15843
|
+
*
|
|
15844
|
+
* Decompresses `rawBody` when gzipped (detected from the body bytes),
|
|
15845
|
+
* verifies the `X-Signature` header against the app's API secret, and
|
|
15846
|
+
* returns the parsed `Event`. Works whether or not Stream is currently
|
|
15847
|
+
* compressing payloads for this app, and stays correct behind
|
|
15848
|
+
* middleware that auto-decompresses the request.
|
|
15849
|
+
*
|
|
15850
|
+
* @param rawBody Raw HTTP request body bytes Stream signed
|
|
15851
|
+
* @param signature Value of the `X-Signature` header
|
|
15852
|
+
* @throws {InvalidWebhookError} When the signature does not match or
|
|
15853
|
+
* the gzip envelope is malformed.
|
|
15854
|
+
*/
|
|
15855
|
+
verifyAndParseWebhook(rawBody, signature) {
|
|
15856
|
+
if (!this.secret) {
|
|
15857
|
+
throw new InvalidWebhookError(
|
|
15858
|
+
"cannot verify webhook signature without an API secret on the client"
|
|
15859
|
+
);
|
|
15860
|
+
}
|
|
15861
|
+
return verifyAndParseWebhook(rawBody, signature, this.secret);
|
|
15862
|
+
}
|
|
15863
|
+
/**
|
|
15864
|
+
* Parse an SQS firehose event: decodes the message `Body` (base64 +
|
|
15865
|
+
* optional gzip) and returns the parsed `Event`. No HMAC verification
|
|
15866
|
+
* (Stream does not sign SQS bodies).
|
|
15867
|
+
*
|
|
15868
|
+
* @param messageBody SQS message `Body` string
|
|
15869
|
+
* @throws {InvalidWebhookError} When the base64 / gzip envelope is malformed.
|
|
15870
|
+
*/
|
|
15871
|
+
parseSqs(messageBody) {
|
|
15872
|
+
return parseSqs(messageBody);
|
|
15873
|
+
}
|
|
15874
|
+
/**
|
|
15875
|
+
* Parse an SNS-delivered event (unwraps envelope JSON when needed, then
|
|
15876
|
+
* same decode path as SQS). No HMAC verification.
|
|
15877
|
+
*
|
|
15878
|
+
* @param notificationBody Raw SNS POST body or pre-extracted `Message` string
|
|
15879
|
+
* @throws {InvalidWebhookError} When the envelope cannot be decoded.
|
|
15880
|
+
*/
|
|
15881
|
+
parseSns(notificationBody) {
|
|
15882
|
+
return parseSns(notificationBody);
|
|
15744
15883
|
}
|
|
15745
15884
|
/** getPermission - gets the definition for a permission
|
|
15746
15885
|
*
|
|
@@ -18291,6 +18430,8 @@ var FixedSizeQueueCache = class {
|
|
|
18291
18430
|
FilterBuilder,
|
|
18292
18431
|
FixedSizeQueueCache,
|
|
18293
18432
|
InsightMetrics,
|
|
18433
|
+
InvalidWebhookError,
|
|
18434
|
+
InvalidWebhookErrorMessages,
|
|
18294
18435
|
JWTServerToken,
|
|
18295
18436
|
JWTUserToken,
|
|
18296
18437
|
LinkPreviewStatus,
|
|
@@ -18377,6 +18518,8 @@ var FixedSizeQueueCache = class {
|
|
|
18377
18518
|
createUploadConfigCheckMiddleware,
|
|
18378
18519
|
createUploadErrorHandlerMiddleware,
|
|
18379
18520
|
decodeBase64,
|
|
18521
|
+
decodeSnsPayload,
|
|
18522
|
+
decodeSqsPayload,
|
|
18380
18523
|
defaultPollFieldBlurEventValidators,
|
|
18381
18524
|
defaultPollFieldChangeEventValidators,
|
|
18382
18525
|
encodeBase64,
|
|
@@ -18392,6 +18535,7 @@ var FixedSizeQueueCache = class {
|
|
|
18392
18535
|
getRawCommandName,
|
|
18393
18536
|
getTokenizedSuggestionDisplayName,
|
|
18394
18537
|
getTriggerCharWithToken,
|
|
18538
|
+
gunzipPayload,
|
|
18395
18539
|
insertItemWithTrigger,
|
|
18396
18540
|
isAudioAttachment,
|
|
18397
18541
|
isBlobButNotFile,
|
|
@@ -18422,6 +18566,9 @@ var FixedSizeQueueCache = class {
|
|
|
18422
18566
|
logChatPromiseExecution,
|
|
18423
18567
|
mapPollStateToResponse,
|
|
18424
18568
|
notifyCommandDisabled,
|
|
18569
|
+
parseEvent,
|
|
18570
|
+
parseSns,
|
|
18571
|
+
parseSqs,
|
|
18425
18572
|
pollCompositionStateProcessors,
|
|
18426
18573
|
pollStateChangeValidators,
|
|
18427
18574
|
postInsights,
|
|
@@ -18431,6 +18578,8 @@ var FixedSizeQueueCache = class {
|
|
|
18431
18578
|
replaceWordWithEntity,
|
|
18432
18579
|
stripCommandFromText,
|
|
18433
18580
|
textIsEmpty,
|
|
18434
|
-
timeLeftMs
|
|
18581
|
+
timeLeftMs,
|
|
18582
|
+
verifyAndParseWebhook,
|
|
18583
|
+
verifySignature
|
|
18435
18584
|
});
|
|
18436
18585
|
//# sourceMappingURL=index.node.js.map
|