stream-chat 9.43.2 → 9.44.0

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.
@@ -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.muteStatus().muted) return false;
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 CheckSignature(body, secret, signature) {
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 {
@@ -15647,7 +15740,7 @@ var StreamChat = class _StreamChat {
15647
15740
  if (this.userAgent) {
15648
15741
  return this.userAgent;
15649
15742
  }
15650
- const version = "9.43.2";
15743
+ const version = "9.44.0";
15651
15744
  const clientBundle = "node-cjs";
15652
15745
  let userAgentString = "";
15653
15746
  if (this.sdkIdentifier) {
@@ -15740,7 +15833,50 @@ var StreamChat = class _StreamChat {
15740
15833
  * @returns {boolean}
15741
15834
  */
15742
15835
  verifyWebhook(requestBody, xSignature) {
15743
- return !!this.secret && CheckSignature(requestBody, this.secret, xSignature);
15836
+ return !!this.secret && verifySignature(requestBody, xSignature, this.secret);
15837
+ }
15838
+ /**
15839
+ * Verify and parse an HTTP webhook event.
15840
+ *
15841
+ * Decompresses `rawBody` when gzipped (detected from the body bytes),
15842
+ * verifies the `X-Signature` header against the app's API secret, and
15843
+ * returns the parsed `Event`. Works whether or not Stream is currently
15844
+ * compressing payloads for this app, and stays correct behind
15845
+ * middleware that auto-decompresses the request.
15846
+ *
15847
+ * @param rawBody Raw HTTP request body bytes Stream signed
15848
+ * @param signature Value of the `X-Signature` header
15849
+ * @throws {InvalidWebhookError} When the signature does not match or
15850
+ * the gzip envelope is malformed.
15851
+ */
15852
+ verifyAndParseWebhook(rawBody, signature) {
15853
+ if (!this.secret) {
15854
+ throw new InvalidWebhookError(
15855
+ "cannot verify webhook signature without an API secret on the client"
15856
+ );
15857
+ }
15858
+ return verifyAndParseWebhook(rawBody, signature, this.secret);
15859
+ }
15860
+ /**
15861
+ * Parse an SQS firehose event: decodes the message `Body` (base64 +
15862
+ * optional gzip) and returns the parsed `Event`. No HMAC verification
15863
+ * (Stream does not sign SQS bodies).
15864
+ *
15865
+ * @param messageBody SQS message `Body` string
15866
+ * @throws {InvalidWebhookError} When the base64 / gzip envelope is malformed.
15867
+ */
15868
+ parseSqs(messageBody) {
15869
+ return parseSqs(messageBody);
15870
+ }
15871
+ /**
15872
+ * Parse an SNS-delivered event (unwraps envelope JSON when needed, then
15873
+ * same decode path as SQS). No HMAC verification.
15874
+ *
15875
+ * @param notificationBody Raw SNS POST body or pre-extracted `Message` string
15876
+ * @throws {InvalidWebhookError} When the envelope cannot be decoded.
15877
+ */
15878
+ parseSns(notificationBody) {
15879
+ return parseSns(notificationBody);
15744
15880
  }
15745
15881
  /** getPermission - gets the definition for a permission
15746
15882
  *
@@ -18291,6 +18427,8 @@ var FixedSizeQueueCache = class {
18291
18427
  FilterBuilder,
18292
18428
  FixedSizeQueueCache,
18293
18429
  InsightMetrics,
18430
+ InvalidWebhookError,
18431
+ InvalidWebhookErrorMessages,
18294
18432
  JWTServerToken,
18295
18433
  JWTUserToken,
18296
18434
  LinkPreviewStatus,
@@ -18377,6 +18515,8 @@ var FixedSizeQueueCache = class {
18377
18515
  createUploadConfigCheckMiddleware,
18378
18516
  createUploadErrorHandlerMiddleware,
18379
18517
  decodeBase64,
18518
+ decodeSnsPayload,
18519
+ decodeSqsPayload,
18380
18520
  defaultPollFieldBlurEventValidators,
18381
18521
  defaultPollFieldChangeEventValidators,
18382
18522
  encodeBase64,
@@ -18392,6 +18532,7 @@ var FixedSizeQueueCache = class {
18392
18532
  getRawCommandName,
18393
18533
  getTokenizedSuggestionDisplayName,
18394
18534
  getTriggerCharWithToken,
18535
+ gunzipPayload,
18395
18536
  insertItemWithTrigger,
18396
18537
  isAudioAttachment,
18397
18538
  isBlobButNotFile,
@@ -18422,6 +18563,9 @@ var FixedSizeQueueCache = class {
18422
18563
  logChatPromiseExecution,
18423
18564
  mapPollStateToResponse,
18424
18565
  notifyCommandDisabled,
18566
+ parseEvent,
18567
+ parseSns,
18568
+ parseSqs,
18425
18569
  pollCompositionStateProcessors,
18426
18570
  pollStateChangeValidators,
18427
18571
  postInsights,
@@ -18431,6 +18575,8 @@ var FixedSizeQueueCache = class {
18431
18575
  replaceWordWithEntity,
18432
18576
  stripCommandFromText,
18433
18577
  textIsEmpty,
18434
- timeLeftMs
18578
+ timeLeftMs,
18579
+ verifyAndParseWebhook,
18580
+ verifySignature
18435
18581
  });
18436
18582
  //# sourceMappingURL=index.node.js.map