@cendarsoss/pusher-js 8.4.15 → 8.4.17
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/node/pusher.js +47 -32
- package/dist/node/pusher.js.map +1 -1
- package/dist/web/pusher.mjs +47 -32
- package/dist/web/pusher.mjs.map +1 -1
- package/package.json +1 -1
- package/src/core/connection/protocol/protocol.ts +4 -3
- package/src/core/delta/manager.ts +58 -25
- package/src/core/pusher.ts +3 -21
package/package.json
CHANGED
|
@@ -40,15 +40,16 @@ const Protocol = {
|
|
|
40
40
|
}
|
|
41
41
|
// Copy sequence and conflation_key for delta compression
|
|
42
42
|
// Server sends these as __delta_seq and __conflation_key
|
|
43
|
-
const sequence = messageData.
|
|
44
|
-
const conflationKey =
|
|
45
|
-
|
|
43
|
+
const sequence = messageData.seq;
|
|
44
|
+
const conflationKey = messageData.conflation_key;
|
|
45
|
+
|
|
46
46
|
if (typeof sequence === 'number') {
|
|
47
47
|
(pusherEvent as any).sequence = sequence;
|
|
48
48
|
}
|
|
49
49
|
if (conflationKey !== undefined) {
|
|
50
50
|
(pusherEvent as any).conflation_key = conflationKey;
|
|
51
51
|
}
|
|
52
|
+
|
|
52
53
|
return pusherEvent;
|
|
53
54
|
} catch (e) {
|
|
54
55
|
throw { type: 'MessageParseError', error: e, data: messageEvent.data };
|
|
@@ -285,22 +285,31 @@ export default class DeltaCompressionManager {
|
|
|
285
285
|
'%',
|
|
286
286
|
});
|
|
287
287
|
|
|
288
|
-
// Parse and return the reconstructed
|
|
288
|
+
// Parse and return the reconstructed data payload
|
|
289
|
+
// reconstructedMessage is always a JSON string (from JSON.stringify),
|
|
290
|
+
// so we should always parse it before sending to event handlers
|
|
291
|
+
let reconstructedData: any;
|
|
289
292
|
try {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
293
|
+
reconstructedData = JSON.parse(JSON.parse(reconstructedMessage));
|
|
294
|
+
} catch (parseError) {
|
|
295
|
+
// This should not happen if the base message was valid JSON
|
|
296
|
+
// Log error but still return the data to avoid breaking the system
|
|
297
|
+
this.error('Failed to parse reconstructed message as JSON', {
|
|
298
|
+
channel,
|
|
299
|
+
event,
|
|
300
|
+
sequence,
|
|
301
|
+
parseError: (parseError as Error).message,
|
|
302
|
+
reconstructedMessageLength: reconstructedMessage.length,
|
|
303
|
+
});
|
|
304
|
+
// Return as string if parsing fails (fallback behavior)
|
|
305
|
+
reconstructedData = reconstructedMessage;
|
|
303
306
|
}
|
|
307
|
+
|
|
308
|
+
return {
|
|
309
|
+
event: event,
|
|
310
|
+
channel: channel,
|
|
311
|
+
data: reconstructedData,
|
|
312
|
+
};
|
|
304
313
|
} catch (error) {
|
|
305
314
|
this.error('Delta decode failed', {
|
|
306
315
|
channel,
|
|
@@ -327,14 +336,25 @@ export default class DeltaCompressionManager {
|
|
|
327
336
|
sequence?: number,
|
|
328
337
|
conflationKey?: string,
|
|
329
338
|
): void {
|
|
339
|
+
let parsedMessage: any;
|
|
340
|
+
try {
|
|
341
|
+
parsedMessage = JSON.parse(rawMessage);
|
|
342
|
+
} catch (e) {
|
|
343
|
+
this.log('handleFullMessage parse failed', {
|
|
344
|
+
channel,
|
|
345
|
+
hasSequence: sequence === 0 || !!sequence,
|
|
346
|
+
});
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
|
|
330
350
|
if (!sequence && sequence !== 0) {
|
|
331
351
|
// Attempt to extract __delta_seq from payload when not provided separately
|
|
332
352
|
try {
|
|
333
|
-
const parsed = JSON.parse(rawMessage);
|
|
334
353
|
const candidate =
|
|
335
|
-
typeof
|
|
336
|
-
? (JSON.parse(
|
|
337
|
-
|
|
354
|
+
typeof parsedMessage.data === 'string'
|
|
355
|
+
? (JSON.parse(parsedMessage.data).__delta_seq ??
|
|
356
|
+
parsedMessage.__delta_seq)
|
|
357
|
+
: (parsedMessage.data?.__delta_seq ?? parsedMessage.__delta_seq);
|
|
338
358
|
if (candidate === 0 || candidate) {
|
|
339
359
|
sequence = candidate;
|
|
340
360
|
} else {
|
|
@@ -353,7 +373,24 @@ export default class DeltaCompressionManager {
|
|
|
353
373
|
}
|
|
354
374
|
}
|
|
355
375
|
|
|
356
|
-
|
|
376
|
+
if (parsedMessage?.data === undefined) {
|
|
377
|
+
this.log('handleFullMessage missing data field, skipping', {
|
|
378
|
+
channel,
|
|
379
|
+
hasSequence: sequence === 0 || !!sequence,
|
|
380
|
+
});
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
const baseMessage = JSON.stringify(parsedMessage.data);
|
|
385
|
+
if (typeof baseMessage !== 'string') {
|
|
386
|
+
this.log('handleFullMessage base serialization failed, skipping', {
|
|
387
|
+
channel,
|
|
388
|
+
hasSequence: sequence === 0 || !!sequence,
|
|
389
|
+
});
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
const messageSize = baseMessage.length;
|
|
357
394
|
|
|
358
395
|
let channelState = this.channelStates.get(channel);
|
|
359
396
|
if (!channelState) {
|
|
@@ -361,10 +398,6 @@ export default class DeltaCompressionManager {
|
|
|
361
398
|
this.channelStates.set(channel, channelState);
|
|
362
399
|
}
|
|
363
400
|
|
|
364
|
-
// The rawMessage is already stripped of __delta_seq and __conflation_key by pusher.ts
|
|
365
|
-
// We use it directly as the base - NO re-parsing/re-stringifying to preserve exact bytes
|
|
366
|
-
// (JSON.parse/stringify can change float representations which breaks delta checksums)
|
|
367
|
-
|
|
368
401
|
// Use the provided conflationKey parameter (already extracted by pusher.ts from original message)
|
|
369
402
|
const finalConflationKey = conflationKey;
|
|
370
403
|
|
|
@@ -376,7 +409,7 @@ export default class DeltaCompressionManager {
|
|
|
376
409
|
if (channelState.conflationKey && finalConflationKey !== undefined) {
|
|
377
410
|
channelState.updateConflationCache(
|
|
378
411
|
finalConflationKey,
|
|
379
|
-
|
|
412
|
+
baseMessage,
|
|
380
413
|
sequence,
|
|
381
414
|
);
|
|
382
415
|
this.log('Stored full message (conflation)', {
|
|
@@ -386,7 +419,7 @@ export default class DeltaCompressionManager {
|
|
|
386
419
|
size: messageSize,
|
|
387
420
|
});
|
|
388
421
|
} else {
|
|
389
|
-
channelState.setBase(
|
|
422
|
+
channelState.setBase(baseMessage, sequence);
|
|
390
423
|
this.log('Stored full message', {
|
|
391
424
|
channel,
|
|
392
425
|
sequence,
|
package/src/core/pusher.ts
CHANGED
|
@@ -214,30 +214,12 @@ export default class Pusher {
|
|
|
214
214
|
conflationKey = (event as any).conflation_key;
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
-
// Use RAW message
|
|
218
|
-
|
|
219
|
-
// We MUST NOT use JSON.parse/stringify as it can change float representations
|
|
220
|
-
let fullMessage = event.rawMessage || '';
|
|
221
|
-
|
|
222
|
-
if (fullMessage && sequence !== undefined) {
|
|
223
|
-
// Strip metadata fields using regex to preserve exact bytes
|
|
224
|
-
// Pattern matches: ,"__delta_seq":NUMBER or "__delta_seq":NUMBER, at start
|
|
225
|
-
fullMessage = fullMessage.replace(/,"__delta_seq":\d+/g, '');
|
|
226
|
-
fullMessage = fullMessage.replace(/"__delta_seq":\d+,/g, '');
|
|
227
|
-
// Pattern matches: ,"__conflation_key":"..." or "__conflation_key":"...", at start
|
|
228
|
-
fullMessage = fullMessage.replace(
|
|
229
|
-
/,"__conflation_key":"[^"]*"/g,
|
|
230
|
-
'',
|
|
231
|
-
);
|
|
232
|
-
fullMessage = fullMessage.replace(
|
|
233
|
-
/"__conflation_key":"[^"]*",/g,
|
|
234
|
-
'',
|
|
235
|
-
);
|
|
236
|
-
}
|
|
217
|
+
// Use RAW message as the canonical source for data-only base
|
|
218
|
+
const rawMessage = event.rawMessage || '';
|
|
237
219
|
|
|
238
220
|
this.deltaCompression.handleFullMessage(
|
|
239
221
|
event.channel,
|
|
240
|
-
|
|
222
|
+
rawMessage,
|
|
241
223
|
sequence,
|
|
242
224
|
conflationKey,
|
|
243
225
|
);
|