@cendarsoss/pusher-js 8.4.16 → 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 -39
- package/dist/node/pusher.js.map +1 -1
- package/dist/web/pusher.mjs +47 -39
- 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 -32
- 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,29 +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
|
-
|
|
303
|
-
} catch (e) {
|
|
304
|
-
// If not JSON, return as-is
|
|
305
|
-
return {
|
|
306
|
-
event: event,
|
|
307
|
-
channel: channel,
|
|
308
|
-
data: reconstructedMessage,
|
|
309
|
-
};
|
|
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;
|
|
310
306
|
}
|
|
307
|
+
|
|
308
|
+
return {
|
|
309
|
+
event: event,
|
|
310
|
+
channel: channel,
|
|
311
|
+
data: reconstructedData,
|
|
312
|
+
};
|
|
311
313
|
} catch (error) {
|
|
312
314
|
this.error('Delta decode failed', {
|
|
313
315
|
channel,
|
|
@@ -334,14 +336,25 @@ export default class DeltaCompressionManager {
|
|
|
334
336
|
sequence?: number,
|
|
335
337
|
conflationKey?: string,
|
|
336
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
|
+
|
|
337
350
|
if (!sequence && sequence !== 0) {
|
|
338
351
|
// Attempt to extract __delta_seq from payload when not provided separately
|
|
339
352
|
try {
|
|
340
|
-
const parsed = JSON.parse(rawMessage);
|
|
341
353
|
const candidate =
|
|
342
|
-
typeof
|
|
343
|
-
? (JSON.parse(
|
|
344
|
-
|
|
354
|
+
typeof parsedMessage.data === 'string'
|
|
355
|
+
? (JSON.parse(parsedMessage.data).__delta_seq ??
|
|
356
|
+
parsedMessage.__delta_seq)
|
|
357
|
+
: (parsedMessage.data?.__delta_seq ?? parsedMessage.__delta_seq);
|
|
345
358
|
if (candidate === 0 || candidate) {
|
|
346
359
|
sequence = candidate;
|
|
347
360
|
} else {
|
|
@@ -360,7 +373,24 @@ export default class DeltaCompressionManager {
|
|
|
360
373
|
}
|
|
361
374
|
}
|
|
362
375
|
|
|
363
|
-
|
|
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;
|
|
364
394
|
|
|
365
395
|
let channelState = this.channelStates.get(channel);
|
|
366
396
|
if (!channelState) {
|
|
@@ -368,10 +398,6 @@ export default class DeltaCompressionManager {
|
|
|
368
398
|
this.channelStates.set(channel, channelState);
|
|
369
399
|
}
|
|
370
400
|
|
|
371
|
-
// The rawMessage is already stripped of __delta_seq and __conflation_key by pusher.ts
|
|
372
|
-
// We use it directly as the base - NO re-parsing/re-stringifying to preserve exact bytes
|
|
373
|
-
// (JSON.parse/stringify can change float representations which breaks delta checksums)
|
|
374
|
-
|
|
375
401
|
// Use the provided conflationKey parameter (already extracted by pusher.ts from original message)
|
|
376
402
|
const finalConflationKey = conflationKey;
|
|
377
403
|
|
|
@@ -383,7 +409,7 @@ export default class DeltaCompressionManager {
|
|
|
383
409
|
if (channelState.conflationKey && finalConflationKey !== undefined) {
|
|
384
410
|
channelState.updateConflationCache(
|
|
385
411
|
finalConflationKey,
|
|
386
|
-
|
|
412
|
+
baseMessage,
|
|
387
413
|
sequence,
|
|
388
414
|
);
|
|
389
415
|
this.log('Stored full message (conflation)', {
|
|
@@ -393,7 +419,7 @@ export default class DeltaCompressionManager {
|
|
|
393
419
|
size: messageSize,
|
|
394
420
|
});
|
|
395
421
|
} else {
|
|
396
|
-
channelState.setBase(
|
|
422
|
+
channelState.setBase(baseMessage, sequence);
|
|
397
423
|
this.log('Stored full message', {
|
|
398
424
|
channel,
|
|
399
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
|
);
|