Skip to content

Commit f48acec

Browse files
authored
Merge branch 'master' into fix/prevent-retry-nonRetryable
2 parents 6867312 + e8362c3 commit f48acec

20 files changed

Lines changed: 324 additions & 77 deletions

File tree

.pubnub.yml

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,25 @@
11
---
22
changelog:
3+
- date: 2025-12-16
4+
version: v10.2.5
5+
changes:
6+
- type: improvement
7+
text: "Use `fast-text-encoding` for react native instead of outdated `fast-encoding` polyfill."
8+
- date: 2025-12-04
9+
version: v10.2.4
10+
changes:
11+
- type: improvement
12+
text: "Prevent resubscribe to previously subscribed entities."
13+
- date: 2025-11-20
14+
version: v10.2.3
15+
changes:
16+
- type: improvement
17+
text: "Enforce use of the `fetch` function from the context, which is not affected by APM monkey patching."
18+
- date: 2025-11-19
19+
version: v10.2.2
20+
changes:
21+
- type: improvement
22+
text: "Replace `gcm` with `fcm` for push notification gateway type."
323
- date: 2025-11-03
424
version: v10.2.1
525
changes:
@@ -1359,7 +1379,7 @@ supported-platforms:
13591379
- 'Ubuntu 14.04 and up'
13601380
- 'Windows 7 and up'
13611381
version: 'Pubnub Javascript for Node'
1362-
version: '10.2.1'
1382+
version: '10.2.5'
13631383
sdks:
13641384
- full-name: PubNub Javascript SDK
13651385
short-name: Javascript
@@ -1375,7 +1395,7 @@ sdks:
13751395
- distribution-type: source
13761396
distribution-repository: GitHub release
13771397
package-name: pubnub.js
1378-
location: https://github.com/pubnub/javascript/archive/refs/tags/v10.2.1.zip
1398+
location: https://github.com/pubnub/javascript/archive/refs/tags/v10.2.5.zip
13791399
requires:
13801400
- name: 'agentkeepalive'
13811401
min-version: '3.5.2'
@@ -2046,7 +2066,7 @@ sdks:
20462066
- distribution-type: library
20472067
distribution-repository: GitHub release
20482068
package-name: pubnub.js
2049-
location: https://github.com/pubnub/javascript/releases/download/v10.2.1/pubnub.10.2.1.js
2069+
location: https://github.com/pubnub/javascript/releases/download/v10.2.5/pubnub.10.2.5.js
20502070
requires:
20512071
- name: 'agentkeepalive'
20522072
min-version: '3.5.2'

CHANGELOG.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,27 @@
1+
## v10.2.5
2+
December 16 2025
3+
4+
#### Modified
5+
- Use `fast-text-encoding` for react native instead of outdated `fast-encoding` polyfill.
6+
7+
## v10.2.4
8+
December 04 2025
9+
10+
#### Modified
11+
- Prevent resubscribe to previously subscribed entities.
12+
13+
## v10.2.3
14+
November 20 2025
15+
16+
#### Modified
17+
- Enforce use of the `fetch` function from the context, which is not affected by APM monkey patching.
18+
19+
## v10.2.2
20+
November 19 2025
21+
22+
#### Modified
23+
- Replace `gcm` with `fcm` for push notification gateway type.
24+
125
## v10.2.1
226
November 03 2025
327

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ Watch [Getting Started with PubNub JS SDK](https://app.dashcam.io/replay/64ee0d2
2727
npm install pubnub
2828
```
2929
* or download one of our builds from our CDN:
30-
* https://cdn.pubnub.com/sdk/javascript/pubnub.10.2.1.js
31-
* https://cdn.pubnub.com/sdk/javascript/pubnub.10.2.1.min.js
30+
* https://cdn.pubnub.com/sdk/javascript/pubnub.10.2.5.js
31+
* https://cdn.pubnub.com/sdk/javascript/pubnub.10.2.5.min.js
3232
3333
2. Configure your keys:
3434

dist/web/pubnub.js

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5436,7 +5436,7 @@
54365436
return base.PubNubFile;
54375437
},
54385438
get version() {
5439-
return '10.2.1';
5439+
return '10.2.5';
54405440
},
54415441
getVersion() {
54425442
return this.version;
@@ -5913,19 +5913,11 @@
59135913
}
59145914
if (this.transport !== 'fetch')
59155915
return;
5916-
// Keeping reference on current `window.fetch` function.
5917-
WebTransport.originalFetch = fetch.bind(window);
5916+
// Storing reference on original `fetch` function implementation as protection against APM lib monkey patching.
5917+
WebTransport.originalFetch = WebTransport.getOriginalFetch();
59185918
// Check whether `fetch` has been monkey patched or not.
5919-
if (this.isFetchMonkeyPatched()) {
5920-
WebTransport.originalFetch = WebTransport.getOriginalFetch();
5919+
if (this.isFetchMonkeyPatched())
59215920
logger.warn('WebTransport', "Native Web Fetch API 'fetch' function monkey patched.");
5922-
if (!this.isFetchMonkeyPatched(WebTransport.originalFetch)) {
5923-
logger.info('WebTransport', "Use native Web Fetch API 'fetch' implementation from iframe as APM workaround.");
5924-
}
5925-
else {
5926-
logger.warn('WebTransport', 'Unable receive native Web Fetch API. There can be issues with subscribe long-poll cancellation');
5927-
}
5928-
}
59295921
}
59305922
makeSendable(req) {
59315923
const abortController = new AbortController();
@@ -8160,7 +8152,7 @@
81608152
if (platforms.includes('fcm')) {
81618153
const fcmPayload = this.fcm.toObject();
81628154
if (fcmPayload && Object.keys(fcmPayload).length)
8163-
payload.pn_gcm = fcmPayload;
8155+
payload.pn_fcm = fcmPayload;
81648156
}
81658157
if (Object.keys(payload).length && this._debugging)
81668158
payload.pn_debug = true;
@@ -9574,6 +9566,11 @@
95749566
return subscriptionTimetokenFromReference(currentTimetoken, referenceTimetoken !== null && referenceTimetoken !== void 0 ? referenceTimetoken : '0');
95759567
}
95769568
subscribe({ channels, channelGroups, timetoken, withPresence, }) {
9569+
var _a;
9570+
// check if the channels and groups are already subscribed
9571+
const hasNewChannels = channels === null || channels === void 0 ? void 0 : channels.some((channel) => !this.channels.includes(channel));
9572+
const hasNewGroups = channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.some((group) => !this.groups.includes(group));
9573+
const hasNewSubscriptions = hasNewChannels || hasNewGroups;
95779574
this.channels = [...this.channels, ...(channels !== null && channels !== void 0 ? channels : [])];
95789575
this.groups = [...this.groups, ...(channelGroups !== null && channelGroups !== void 0 ? channelGroups : [])];
95799576
if (withPresence) {
@@ -9584,7 +9581,29 @@
95849581
this.engine.transition(restore(Array.from(new Set([...this.channels, ...(channels !== null && channels !== void 0 ? channels : [])])), Array.from(new Set([...this.groups, ...(channelGroups !== null && channelGroups !== void 0 ? channelGroups : [])])), timetoken));
95859582
}
95869583
else {
9587-
this.engine.transition(subscriptionChange(Array.from(new Set([...this.channels, ...(channels !== null && channels !== void 0 ? channels : [])])), Array.from(new Set([...this.groups, ...(channelGroups !== null && channelGroups !== void 0 ? channelGroups : [])]))));
9584+
if (hasNewSubscriptions) {
9585+
this.engine.transition(subscriptionChange(Array.from(new Set([...this.channels, ...(channels !== null && channels !== void 0 ? channels : [])])), Array.from(new Set([...this.groups, ...(channelGroups !== null && channelGroups !== void 0 ? channelGroups : [])]))));
9586+
}
9587+
else {
9588+
this.dependencies.config
9589+
.logger()
9590+
.debug('EventEngine', 'Skipping state transition - all channels/groups already subscribed. Emitting SubscriptionChanged event.');
9591+
// Get current timetoken from state context
9592+
const currentState = this.engine.currentState;
9593+
const currentContext = this.engine.currentContext;
9594+
let currentTimetoken = '0';
9595+
if ((currentState === null || currentState === void 0 ? void 0 : currentState.label) === ReceivingState.label && currentContext) {
9596+
const receivingContext = currentContext;
9597+
currentTimetoken = (_a = receivingContext.cursor) === null || _a === void 0 ? void 0 : _a.timetoken;
9598+
}
9599+
// Manually emit SubscriptionChanged status event
9600+
this.dependencies.emitStatus({
9601+
category: StatusCategory$1.PNSubscriptionChangedCategory,
9602+
affectedChannels: Array.from(new Set(this.channels)),
9603+
affectedChannelGroups: Array.from(new Set(this.groups)),
9604+
currentTimetoken,
9605+
});
9606+
}
95889607
}
95899608
if (this.dependencies.join) {
95909609
this.dependencies.join({

dist/web/pubnub.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/core/components/configuration.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ const makeConfiguration = (base, setupCryptoModule) => {
168168
return base.PubNubFile;
169169
},
170170
get version() {
171-
return '10.2.1';
171+
return '10.2.5';
172172
},
173173
getVersion() {
174174
return this.version;

lib/core/components/push_payload.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,7 @@ class NotificationsPayload {
613613
if (platforms.includes('fcm')) {
614614
const fcmPayload = this.fcm.toObject();
615615
if (fcmPayload && Object.keys(fcmPayload).length)
616-
payload.pn_gcm = fcmPayload;
616+
payload.pn_fcm = fcmPayload;
617617
}
618618
if (Object.keys(payload).length && this._debugging)
619619
payload.pn_debug = true;

lib/event-engine/index.js

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,17 @@ var __importStar = (this && this.__importStar) || (function () {
3737
return result;
3838
};
3939
})();
40+
var __importDefault = (this && this.__importDefault) || function (mod) {
41+
return (mod && mod.__esModule) ? mod : { "default": mod };
42+
};
4043
Object.defineProperty(exports, "__esModule", { value: true });
4144
exports.EventEngine = void 0;
4245
const receiving_1 = require("./states/receiving");
4346
const dispatcher_1 = require("./dispatcher");
4447
const utils_1 = require("../core/utils");
4548
const unsubscribed_1 = require("./states/unsubscribed");
4649
const core_1 = require("./core");
50+
const categories_1 = __importDefault(require("../core/constants/categories"));
4751
const utils = __importStar(require("../core/utils"));
4852
const events = __importStar(require("./events"));
4953
/**
@@ -88,6 +92,11 @@ class EventEngine {
8892
return (0, utils_1.subscriptionTimetokenFromReference)(currentTimetoken, referenceTimetoken !== null && referenceTimetoken !== void 0 ? referenceTimetoken : '0');
8993
}
9094
subscribe({ channels, channelGroups, timetoken, withPresence, }) {
95+
var _a;
96+
// check if the channels and groups are already subscribed
97+
const hasNewChannels = channels === null || channels === void 0 ? void 0 : channels.some((channel) => !this.channels.includes(channel));
98+
const hasNewGroups = channelGroups === null || channelGroups === void 0 ? void 0 : channelGroups.some((group) => !this.groups.includes(group));
99+
const hasNewSubscriptions = hasNewChannels || hasNewGroups;
91100
this.channels = [...this.channels, ...(channels !== null && channels !== void 0 ? channels : [])];
92101
this.groups = [...this.groups, ...(channelGroups !== null && channelGroups !== void 0 ? channelGroups : [])];
93102
if (withPresence) {
@@ -98,7 +107,29 @@ class EventEngine {
98107
this.engine.transition(events.restore(Array.from(new Set([...this.channels, ...(channels !== null && channels !== void 0 ? channels : [])])), Array.from(new Set([...this.groups, ...(channelGroups !== null && channelGroups !== void 0 ? channelGroups : [])])), timetoken));
99108
}
100109
else {
101-
this.engine.transition(events.subscriptionChange(Array.from(new Set([...this.channels, ...(channels !== null && channels !== void 0 ? channels : [])])), Array.from(new Set([...this.groups, ...(channelGroups !== null && channelGroups !== void 0 ? channelGroups : [])]))));
110+
if (hasNewSubscriptions) {
111+
this.engine.transition(events.subscriptionChange(Array.from(new Set([...this.channels, ...(channels !== null && channels !== void 0 ? channels : [])])), Array.from(new Set([...this.groups, ...(channelGroups !== null && channelGroups !== void 0 ? channelGroups : [])]))));
112+
}
113+
else {
114+
this.dependencies.config
115+
.logger()
116+
.debug('EventEngine', 'Skipping state transition - all channels/groups already subscribed. Emitting SubscriptionChanged event.');
117+
// Get current timetoken from state context
118+
const currentState = this.engine.currentState;
119+
const currentContext = this.engine.currentContext;
120+
let currentTimetoken = '0';
121+
if ((currentState === null || currentState === void 0 ? void 0 : currentState.label) === receiving_1.ReceivingState.label && currentContext) {
122+
const receivingContext = currentContext;
123+
currentTimetoken = (_a = receivingContext.cursor) === null || _a === void 0 ? void 0 : _a.timetoken;
124+
}
125+
// Manually emit SubscriptionChanged status event
126+
this.dependencies.emitStatus({
127+
category: categories_1.default.PNSubscriptionChangedCategory,
128+
affectedChannels: Array.from(new Set(this.channels)),
129+
affectedChannelGroups: Array.from(new Set(this.groups)),
130+
currentTimetoken,
131+
});
132+
}
102133
}
103134
if (this.dependencies.join) {
104135
this.dependencies.join({

lib/react_native/index.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
33
return (mod && mod.__esModule) ? mod : { "default": mod };
44
};
55
Object.defineProperty(exports, "__esModule", { value: true });
6-
const text_encoding_1 = require("text-encoding");
76
require("react-native-url-polyfill/auto");
7+
require("fast-text-encoding");
88
const cbor_js_1 = __importDefault(require("cbor-js"));
99
const buffer_1 = require("buffer");
1010
const stringify_buffer_keys_1 = require("../core/components/stringify_buffer_keys");
@@ -19,9 +19,7 @@ const LegacyCryptoModule_1 = __importDefault(require("../crypto/modules/LegacyCr
1919
const pubnub_common_1 = require("../core/pubnub-common");
2020
const configuration_2 = require("./configuration");
2121
const common_1 = __importDefault(require("../cbor/common"));
22-
// Polyfill global environment
23-
global.TextEncoder = global.TextEncoder || text_encoding_1.TextEncoder;
24-
global.TextDecoder = global.TextDecoder || text_encoding_1.TextDecoder;
22+
// Polyfill global Buffer for React Native environment
2523
global.Buffer = global.Buffer || buffer_1.Buffer;
2624
/**
2725
* PubNub client for React Native platform.

lib/types/index.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4006,7 +4006,7 @@ declare namespace PubNub {
40064006
};
40074007

40084008
/**
4009-
* Payload for `pn_gcm` field in published message.
4009+
* Payload for `pn_fcm` field in published message.
40104010
*/
40114011
type FCMPayload = {
40124012
/**
@@ -4400,7 +4400,7 @@ declare namespace PubNub {
44004400
*/
44014401
buildPayload(platforms: ('apns' | 'apns2' | 'fcm')[]): {
44024402
pn_apns?: APNSPayload;
4403-
pn_gcm?: FCMPayload;
4403+
pn_fcm?: FCMPayload;
44044404
pn_debug?: boolean;
44054405
};
44064406
}

0 commit comments

Comments
 (0)