@cendarsoss/pusher-js 8.4.16 → 8.4.18

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.
@@ -4,6 +4,7 @@ const base64 = require("@stablelib/base64");
4
4
  const fayeWebsocket = require("faye-websocket");
5
5
  const xmlhttprequest = require("xmlhttprequest");
6
6
  const crypto = require("crypto");
7
+ const lruCache = require("lru-cache");
7
8
  const fossilDelta = require("fossil-delta");
8
9
  const vcdiffDecoder = require("@ably/vcdiff-decoder");
9
10
  function encode(s) {
@@ -840,8 +841,8 @@ const Protocol = {
840
841
  if (messageData.user_id) {
841
842
  pusherEvent.user_id = messageData.user_id;
842
843
  }
843
- const sequence = messageData.__delta_seq ?? messageData.sequence;
844
- const conflationKey = messageData.__conflation_key ?? messageData.conflation_key;
844
+ const sequence = messageData.seq;
845
+ const conflationKey = messageData.conflation_key;
845
846
  if (typeof sequence === "number") {
846
847
  pusherEvent.sequence = sequence;
847
848
  }
@@ -3545,12 +3546,15 @@ class UserFacade extends Dispatcher {
3545
3546
  this._signinDoneResolve = resolve;
3546
3547
  }
3547
3548
  }
3549
+ const MAX_CONFLATION_CACHE_KEYS = 2e3;
3548
3550
  class ChannelState {
3549
3551
  constructor(channelName) {
3550
3552
  this.channelName = channelName;
3551
3553
  this.conflationKey = null;
3552
3554
  this.maxMessagesPerKey = 30;
3553
- this.conflationCaches = /* @__PURE__ */ new Map();
3555
+ this.conflationCaches = new lruCache.LRUCache({
3556
+ max: MAX_CONFLATION_CACHE_KEYS
3557
+ });
3554
3558
  this.baseMessage = null;
3555
3559
  this.baseSequence = null;
3556
3560
  this.lastSequence = null;
@@ -3591,7 +3595,7 @@ class ChannelState {
3591
3595
  return this.baseMessage;
3592
3596
  }
3593
3597
  const key = conflationKeyValue || "";
3594
- const cache = this.conflationCaches.get(key);
3598
+ const cache = this.conflationCaches.peek(key);
3595
3599
  if (!cache || baseIndex === void 0) {
3596
3600
  console.error("[ChannelState] No cache or baseIndex undefined", {
3597
3601
  hasCache: !!cache,
@@ -3611,6 +3615,7 @@ class ChannelState {
3611
3615
  });
3612
3616
  return null;
3613
3617
  }
3618
+ this.conflationCaches.get(key);
3614
3619
  return message.content;
3615
3620
  }
3616
3621
  /**
@@ -3618,10 +3623,9 @@ class ChannelState {
3618
3623
  */
3619
3624
  updateConflationCache(conflationKeyValue, message, sequence) {
3620
3625
  const key = conflationKeyValue || "";
3621
- let cache = this.conflationCaches.get(key);
3626
+ let cache = this.conflationCaches.peek(key);
3622
3627
  if (!cache) {
3623
3628
  cache = [];
3624
- this.conflationCaches.set(key, cache);
3625
3629
  }
3626
3630
  if (cache.length > 0) {
3627
3631
  const lastCacheItem = cache[cache.length - 1];
@@ -3633,6 +3637,7 @@ class ChannelState {
3633
3637
  while (cache.length > this.maxMessagesPerKey) {
3634
3638
  cache.shift();
3635
3639
  }
3640
+ this.conflationCaches.set(key, cache);
3636
3641
  }
3637
3642
  /**
3638
3643
  * Check if we have a valid base
@@ -3959,27 +3964,24 @@ class DeltaCompressionManager {
3959
3964
  deltaSize: deltaBytes.length,
3960
3965
  compressionRatio: (deltaBytes.length / reconstructedMessage.length * 100).toFixed(1) + "%"
3961
3966
  });
3967
+ let reconstructedData;
3962
3968
  try {
3963
- const parsedMessage = JSON.parse(reconstructedMessage);
3964
- let data = parsedMessage.data || parsedMessage;
3965
- if (typeof data === "string") {
3966
- try {
3967
- data = JSON.parse(data);
3968
- } catch (e) {
3969
- }
3970
- }
3971
- return {
3972
- event,
3969
+ reconstructedData = JSON.parse(JSON.parse(reconstructedMessage));
3970
+ } catch (parseError) {
3971
+ this.error("Failed to parse reconstructed message as JSON", {
3973
3972
  channel,
3974
- data
3975
- };
3976
- } catch (e) {
3977
- return {
3978
3973
  event,
3979
- channel,
3980
- data: reconstructedMessage
3981
- };
3974
+ sequence,
3975
+ parseError: parseError.message,
3976
+ reconstructedMessageLength: reconstructedMessage.length
3977
+ });
3978
+ reconstructedData = reconstructedMessage;
3982
3979
  }
3980
+ return {
3981
+ event,
3982
+ channel,
3983
+ data: reconstructedData
3984
+ };
3983
3985
  } catch (error) {
3984
3986
  this.error("Delta decode failed", {
3985
3987
  channel,
@@ -4000,10 +4002,19 @@ class DeltaCompressionManager {
4000
4002
  * Handle regular (full) message with delta sequence markers
4001
4003
  */
4002
4004
  handleFullMessage(channel, rawMessage, sequence, conflationKey) {
4005
+ let parsedMessage;
4006
+ try {
4007
+ parsedMessage = JSON.parse(rawMessage);
4008
+ } catch (e) {
4009
+ this.log("handleFullMessage parse failed", {
4010
+ channel,
4011
+ hasSequence: sequence === 0 || !!sequence
4012
+ });
4013
+ return;
4014
+ }
4003
4015
  if (!sequence && sequence !== 0) {
4004
4016
  try {
4005
- const parsed = JSON.parse(rawMessage);
4006
- const candidate = typeof parsed.data === "string" ? JSON.parse(parsed.data).__delta_seq ?? parsed.__delta_seq : parsed.data?.__delta_seq ?? parsed.__delta_seq;
4017
+ const candidate = typeof parsedMessage.data === "string" ? JSON.parse(parsedMessage.data).__delta_seq ?? parsedMessage.__delta_seq : parsedMessage.data?.__delta_seq ?? parsedMessage.__delta_seq;
4007
4018
  if (candidate === 0 || candidate) {
4008
4019
  sequence = candidate;
4009
4020
  } else {
@@ -4021,7 +4032,22 @@ class DeltaCompressionManager {
4021
4032
  return;
4022
4033
  }
4023
4034
  }
4024
- const messageSize = rawMessage.length;
4035
+ if (parsedMessage?.data === void 0) {
4036
+ this.log("handleFullMessage missing data field, skipping", {
4037
+ channel,
4038
+ hasSequence: sequence === 0 || !!sequence
4039
+ });
4040
+ return;
4041
+ }
4042
+ const baseMessage = JSON.stringify(parsedMessage.data);
4043
+ if (typeof baseMessage !== "string") {
4044
+ this.log("handleFullMessage base serialization failed, skipping", {
4045
+ channel,
4046
+ hasSequence: sequence === 0 || !!sequence
4047
+ });
4048
+ return;
4049
+ }
4050
+ const messageSize = baseMessage.length;
4025
4051
  let channelState = this.channelStates.get(channel);
4026
4052
  if (!channelState) {
4027
4053
  channelState = new ChannelState(channel);
@@ -4034,8 +4060,7 @@ class DeltaCompressionManager {
4034
4060
  if (channelState.conflationKey && finalConflationKey !== void 0) {
4035
4061
  channelState.updateConflationCache(
4036
4062
  finalConflationKey,
4037
- rawMessage,
4038
- // Store raw message directly
4063
+ baseMessage,
4039
4064
  sequence
4040
4065
  );
4041
4066
  this.log("Stored full message (conflation)", {
@@ -4045,7 +4070,7 @@ class DeltaCompressionManager {
4045
4070
  size: messageSize
4046
4071
  });
4047
4072
  } else {
4048
- channelState.setBase(rawMessage, sequence);
4073
+ channelState.setBase(baseMessage, sequence);
4049
4074
  this.log("Stored full message", {
4050
4075
  channel,
4051
4076
  sequence,
@@ -4287,22 +4312,10 @@ class Pusher {
4287
4312
  if (typeof event.conflation_key === "string") {
4288
4313
  conflationKey = event.conflation_key;
4289
4314
  }
4290
- let fullMessage = event.rawMessage || "";
4291
- if (fullMessage && sequence !== void 0) {
4292
- fullMessage = fullMessage.replace(/,"__delta_seq":\d+/g, "");
4293
- fullMessage = fullMessage.replace(/"__delta_seq":\d+,/g, "");
4294
- fullMessage = fullMessage.replace(
4295
- /,"__conflation_key":"[^"]*"/g,
4296
- ""
4297
- );
4298
- fullMessage = fullMessage.replace(
4299
- /"__conflation_key":"[^"]*",/g,
4300
- ""
4301
- );
4302
- }
4315
+ const rawMessage = event.rawMessage || "";
4303
4316
  this.deltaCompression.handleFullMessage(
4304
4317
  event.channel,
4305
- fullMessage,
4318
+ rawMessage,
4306
4319
  sequence,
4307
4320
  conflationKey
4308
4321
  );