Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions .coderabbit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

language: en-US

reviews:
# Enable high-level summary of changes
high_level_summary: false

# Add a poem... just kidding, disable it
poem: false

# Collapse walkthrough to keep PR comments clean
collapse_walkthrough: true

# Auto-review on every push
auto_review:
enabled: true
drafts: true

# Path-based review instructions
path_instructions:
- path: "src/core/**"
instructions: |
This is the core SDK module. Pay close attention to:
- Backward compatibility of public API changes
- Proper TypeScript typing (strict mode is enabled)
- No platform-specific code (Node.js, Web, React Native specifics belong in their respective platform directories)
- Thread safety considerations for shared state
- path: "src/core/endpoints/**"
instructions: |
These are REST API endpoint implementations. Review for:
- Correct request/response type definitions
- Proper error handling and status code mapping
- Consistent parameter validation
- Adherence to PubNub REST API contracts
- path: "src/core/types/**"
instructions: |
TypeScript type definitions. Ensure:
- Types are precise and not overly permissive (avoid `any`)
- Exported types maintain backward compatibility
- Proper use of generics and utility types
- path: "src/event-engine/**"
instructions: |
State-machine-based subscription management. Review for:
- Correct state transitions and edge cases
- No leaked subscriptions or event listeners
- Proper cleanup on state exit
- path: "src/entities/**"
instructions: |
High-level subscription API (Channel, ChannelGroup, etc.). Review for:
- Proper event handler lifecycle management
- Memory leak prevention (listener cleanup)
- path: "src/transport/**"
instructions: |
Platform-specific HTTP transport implementations. Review for:
- Proper timeout and cancellation handling
- Correct header management
- Error propagation consistency across platforms
- path: "src/node/**"
instructions: "Node.js platform implementation. Ensure no browser/DOM APIs are used."
- path: "src/web/**"
instructions: "Browser platform implementation. Ensure no Node.js-specific APIs (fs, crypto, etc.) are used."
- path: "src/react_native/**"
instructions: "React Native platform implementation. Verify compatibility with RN runtime."
- path: "test/**"
instructions: |
Test files. Review for:
- Adequate coverage of edge cases
- Proper use of mocks/stubs (Sinon + Nock)
- No flaky patterns (hardcoded timeouts, race conditions)
- Tests that actually assert meaningful behavior

# Tools configuration
tools:
# Enable GitHub checks integration
github-checks:
enabled: true
timeout_ms: 120000

chat:
auto_reply: true

knowledge_base:
mcp:
usage: enabled

# Path filters - ignore generated/vendored/build output
path_filters:
# Build outputs
- "!dist/**"
- "!lib/**"
- "!upload/**"

# Dependencies
- "!node_modules/**"

# Lock files - too noisy, low review value
- "!package-lock.json"

# Config/metadata that rarely needs review
- "!.pubnub.yml"
- "!.vscode/**"

# Generated type bundles
- "!lib/types/**"
Comment on lines +87 to +105
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

path_filters is at the wrong nesting level — filters will not apply.

Per the CodeRabbit configuration schema, path_filters lives under reviews, not at the top level. As written here, these exclusions are effectively ignored, so dist/**, lib/**, node_modules/**, package-lock.json, etc. will still be pulled into reviews — defeating the intent of this block.

🛠️ Proposed fix: move path_filters under reviews
   # Tools configuration
   tools:
     # Enable GitHub checks integration
     github-checks:
       enabled: true
       timeout_ms: 120000
 
+  # Path filters - ignore generated/vendored/build output
+  path_filters:
+    # Build outputs
+    - "!dist/**"
+    - "!lib/**"
+    - "!upload/**"
+    # Dependencies
+    - "!node_modules/**"
+    # Lock files - too noisy, low review value
+    - "!package-lock.json"
+    # Config/metadata that rarely needs review
+    - "!.pubnub.yml"
+    - "!.vscode/**"
+    # Generated type bundles
+    - "!lib/types/**"
+
 chat:
   auto_reply: true
 
 knowledge_base:
   mcp:
     usage: enabled
-
-# Path filters - ignore generated/vendored/build output
-path_filters:
-  # Build outputs
-  - "!dist/**"
-  - "!lib/**"
-  - "!upload/**"
-
-  # Dependencies
-  - "!node_modules/**"
-
-  # Lock files - too noisy, low review value
-  - "!package-lock.json"
-
-  # Config/metadata that rarely needs review
-  - "!.pubnub.yml"
-  - "!.vscode/**"
-
-  # Generated type bundles
-  - "!lib/types/**"

Also worth noting: !lib/** already covers !lib/types/**, so the last entry is redundant once relocated.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Path filters - ignore generated/vendored/build output
path_filters:
# Build outputs
- "!dist/**"
- "!lib/**"
- "!upload/**"
# Dependencies
- "!node_modules/**"
# Lock files - too noisy, low review value
- "!package-lock.json"
# Config/metadata that rarely needs review
- "!.pubnub.yml"
- "!.vscode/**"
# Generated type bundles
- "!lib/types/**"
# Path filters - ignore generated/vendored/build output
path_filters:
# Build outputs
- "!dist/**"
- "!lib/**"
- "!upload/**"
# Dependencies
- "!node_modules/**"
# Lock files - too noisy, low review value
- "!package-lock.json"
# Config/metadata that rarely needs review
- "!.pubnub.yml"
- "!.vscode/**"
# Generated type bundles
- "!lib/types/**"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.coderabbit.yaml around lines 87 - 105, The path_filters block is defined at
top-level so it is ignored; move the existing path_filters mapping under the
reviews key (i.e., make reviews: { path_filters: [...] }) so the exclusions
(path patterns like "!dist/**", "!lib/**", "!node_modules/**",
"!package-lock.json", "!.pubnub.yml", "!.vscode/**") are applied; after moving,
remove the redundant "!lib/types/**" entry since "!lib/**" already covers it.

26 changes: 15 additions & 11 deletions dist/web/pubnub.js
Original file line number Diff line number Diff line change
Expand Up @@ -4068,7 +4068,7 @@
/**
* Whether PubNub client should catch up subscription after network issues.
*/
const RESTORE = false;
const RESTORE = true;
/**
* Whether network availability change should be announced with `PNNetworkDownCategory` and
* `PNNetworkUpCategory` state or not.
Expand All @@ -4089,7 +4089,7 @@
/**
* Whether subscription event engine should be used or not.
*/
const ENABLE_EVENT_ENGINE = false;
const ENABLE_EVENT_ENGINE = true;
/**
* Whether configured user presence state should be maintained by the PubNub client or not.
*/
Expand Down Expand Up @@ -4991,8 +4991,6 @@
validate() {
if (this.delay < 2)
throw new Error('Delay can not be set less than 2 seconds for retry');
if (this.maximumRetry > 10)
throw new Error('Maximum retry for linear retry policy can not be more than 10');
},
};
}
Expand All @@ -5017,10 +5015,6 @@
validate() {
if (this.minimumDelay < 2)
throw new Error('Minimum delay can not be set less than 2 seconds for retry');
else if (this.maximumDelay > 150)
throw new Error('Maximum delay can not be set more than 150 seconds for' + ' retry');
else if (this.maximumRetry > 6)
throw new Error('Maximum retry for exponential retry policy can not be more than 6');
},
};
}
Expand Down Expand Up @@ -9307,6 +9301,7 @@
category: StatusCategory$1.PNConnectedCategory,
affectedChannels: context.channels.slice(0),
affectedChannelGroups: context.groups.slice(0),
operation: RequestOperation$1.PNSubscribeOperation,
currentTimetoken: !!((_d = context.cursor) === null || _d === void 0 ? void 0 : _d.timetoken) ? (_e = context.cursor) === null || _e === void 0 ? void 0 : _e.timetoken : payload.timetoken,
}),
]);
Expand Down Expand Up @@ -9464,7 +9459,7 @@
return UnsubscribedState.with(undefined, [
emitStatus(Object.assign({ category: !payload.isOffline
? StatusCategory$1.PNDisconnectedCategory
: StatusCategory$1.PNDisconnectedUnexpectedlyCategory }, (errorCategory ? { error: errorCategory } : {}))),
: StatusCategory$1.PNDisconnectedUnexpectedlyCategory, operation: RequestOperation$1.PNUnsubscribeOperation }, (errorCategory ? { error: errorCategory } : {}))),
]);
}
return ReceivingState.with({
Expand Down Expand Up @@ -9510,20 +9505,29 @@
var _a;
if (!event.payload.isOffline) {
return ReceiveStoppedState.with(Object.assign({}, context), [
emitStatus({ category: StatusCategory$1.PNDisconnectedCategory }),
emitStatus({
category: StatusCategory$1.PNDisconnectedCategory,
operation: RequestOperation$1.PNUnsubscribeOperation,
}),
]);
}
else {
const errorReason = PubNubAPIError.create(new Error('Network connection error')).toPubNubError(RequestOperation$1.PNSubscribeOperation);
return ReceiveFailedState.with(Object.assign(Object.assign({}, context), { reason: errorReason }), [
emitStatus({
category: StatusCategory$1.PNDisconnectedUnexpectedlyCategory,
operation: RequestOperation$1.PNUnsubscribeOperation,
error: (_a = errorReason.status) === null || _a === void 0 ? void 0 : _a.category,
}),
]);
}
});
ReceivingState.on(unsubscribeAll.type, (_) => UnsubscribedState.with(undefined, [emitStatus({ category: StatusCategory$1.PNDisconnectedCategory })]));
ReceivingState.on(unsubscribeAll.type, (_) => UnsubscribedState.with(undefined, [
emitStatus({
category: StatusCategory$1.PNDisconnectedCategory,
operation: RequestOperation$1.PNUnsubscribeOperation,
}),
]));

/**
* Subscribe Event Engine effects dispatcher.
Expand Down
4 changes: 2 additions & 2 deletions dist/web/pubnub.min.js

Large diffs are not rendered by default.

6 changes: 0 additions & 6 deletions lib/core/components/retry-policy.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,6 @@ class RetryPolicy {
validate() {
if (this.delay < 2)
throw new Error('Delay can not be set less than 2 seconds for retry');
if (this.maximumRetry > 10)
throw new Error('Maximum retry for linear retry policy can not be more than 10');
},
};
}
Expand All @@ -179,10 +177,6 @@ class RetryPolicy {
validate() {
if (this.minimumDelay < 2)
throw new Error('Minimum delay can not be set less than 2 seconds for retry');
else if (this.maximumDelay > 150)
throw new Error('Maximum delay can not be set more than 150 seconds for' + ' retry');
else if (this.maximumRetry > 6)
throw new Error('Maximum retry for exponential retry policy can not be more than 6');
},
};
}
Expand Down
4 changes: 2 additions & 2 deletions lib/core/interfaces/configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const USE_SSL = true;
/**
* Whether PubNub client should catch up subscription after network issues.
*/
const RESTORE = false;
const RESTORE = true;
/**
* Whether network availability change should be announced with `PNNetworkDownCategory` and
* `PNNetworkUpCategory` state or not.
Expand All @@ -37,7 +37,7 @@ const FILE_PUBLISH_RETRY_LIMIT = 5;
/**
* Whether subscription event engine should be used or not.
*/
const ENABLE_EVENT_ENGINE = false;
const ENABLE_EVENT_ENGINE = true;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check that tests and docs were updated for the new default, and look for any spots
# that still hardcode or assume enableEventEngine=false as the default.
rg -nP -C2 'enableEventEngine' --type=ts --type=js -g '!**/node_modules/**' -g '!dist/**'
rg -nP -C2 'ENABLE_EVENT_ENGINE\s*=' -g '!**/node_modules/**'
fd -i 'changelog|migration' -t f | head -20

Repository: pubnub/javascript

Length of output: 18640


🏁 Script executed:

# Check CHANGELOG.md for BREAKING CHANGE note about ENABLE_EVENT_ENGINE
head -100 CHANGELOG.md | grep -A 5 -B 5 -i "breaking\|event.engine"

# Look for migration guides
fd -i 'migration\|upgrade\|guide' -t f | head -20

# Check if lib/ files are generated (look for build scripts)
cat -n package.json | head -50

# Compare timestamps of src and lib files to verify regeneration
ls -la src/core/interfaces/configuration.ts lib/core/interfaces/configuration.js 2>/dev/null || echo "Files not found"
stat src/core/interfaces/configuration.ts lib/core/interfaces/configuration.js 2>/dev/null | grep -E "File|Modify"

Repository: pubnub/javascript

Length of output: 4667


🏁 Script executed:

# Search entire CHANGELOG for enableEventEngine or event engine breaking change
grep -i "enableeventengine\|event.engine" CHANGELOG.md | head -20

# Search more broadly for breaking changes in recent versions
grep -B2 -A5 "BREAKING CHANGE" CHANGELOG.md | head -40

# Look for docs directory with migration/guide info
fd -i 'docs' -t d | head -10

# Check if there's a docs directory with migration guides
find . -type f -name "*.md" -path "*/docs/*" 2>/dev/null | grep -i "migrat\|upgrade\|guide\|breaking" | head -20

# Count tests with enableEventEngine: true vs false
echo "=== Tests with enableEventEngine: true ==="
rg 'enableEventEngine:\s*true' --type=ts --type=js test/ -c
echo "=== Tests with enableEventEngine: false ==="
rg 'enableEventEngine:\s*false' --type=ts --type=js test/ -c

Repository: pubnub/javascript

Length of output: 2212


Add explicit "BREAKING CHANGE" documentation for enableEventEngine default flip in CHANGELOG and migration guide.

The three behavioral cascades identified are correctly implemented:

  1. Subscription loop switches to event-engine workflow when enabled
  2. ExponentialRetryPolicy auto-applied when enableEventEngine: true and no retryConfiguration supplied
  3. Presence state auto-maintained during subscribe calls

Tests provide coverage for both enableEventEngine: true and false modes across event engine, shared-worker, and subscription manager suites. The lib/ artifacts are properly regenerated from src/ via the build process.

However, CHANGELOG.md lacks an explicit "BREAKING CHANGE" note for this default flip—recent entries document other breaking changes (pagination, SubscriptionSet, objects v1 removal) but not this one. A migration guide with the opt-out recipe (enableEventEngine: false) is also not present in the repository.

Add these documentation updates to surface the behavioral change to users upgrading to this version.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/core/interfaces/configuration.js` at line 40, Add an explicit "BREAKING
CHANGE" entry to CHANGELOG.md describing the default flip of enableEventEngine
(previously false, now true) and link to a new migration guide that shows how to
opt out by setting enableEventEngine: false; mention the three behavioral
cascades (subscription loop switching to event-engine workflow,
ExponentialRetryPolicy being auto-applied when enableEventEngine is true and no
retryConfiguration is provided, and presence state auto-maintenance during
subscribe calls) so users can assess impact, and add a short migration recipe
showing the exact config snippet to set enableEventEngine: false and how to
retain previous retry/presence behavior referencing ENABLE_EVENT_ENGINE /
enableEventEngine, ExponentialRetryPolicy, and subscribe/SubscriptionSet
semantics.

/**
* Whether configured user presence state should be maintained by the PubNub client or not.
*/
Expand Down
1 change: 1 addition & 0 deletions lib/event-engine/states/handshaking.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ exports.HandshakingState.on(events_1.handshakeSuccess.type, (context, { payload
category: categories_1.default.PNConnectedCategory,
affectedChannels: context.channels.slice(0),
affectedChannelGroups: context.groups.slice(0),
operation: operations_1.default.PNSubscribeOperation,
currentTimetoken: !!((_d = context.cursor) === null || _d === void 0 ? void 0 : _d.timetoken) ? (_e = context.cursor) === null || _e === void 0 ? void 0 : _e.timetoken : payload.timetoken,
}),
]);
Expand Down
15 changes: 12 additions & 3 deletions lib/event-engine/states/receiving.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ exports.ReceivingState.on(events_1.subscriptionChange.type, (context, { payload
return unsubscribed_1.UnsubscribedState.with(undefined, [
(0, effects_1.emitStatus)(Object.assign({ category: !payload.isOffline
? categories_1.default.PNDisconnectedCategory
: categories_1.default.PNDisconnectedUnexpectedlyCategory }, (errorCategory ? { error: errorCategory } : {}))),
: categories_1.default.PNDisconnectedUnexpectedlyCategory, operation: operations_1.default.PNUnsubscribeOperation }, (errorCategory ? { error: errorCategory } : {}))),
]);
}
return exports.ReceivingState.with({
Expand Down Expand Up @@ -90,17 +90,26 @@ exports.ReceivingState.on(events_1.disconnect.type, (context, event) => {
var _a;
if (!event.payload.isOffline) {
return receive_stopped_1.ReceiveStoppedState.with(Object.assign({}, context), [
(0, effects_1.emitStatus)({ category: categories_1.default.PNDisconnectedCategory }),
(0, effects_1.emitStatus)({
category: categories_1.default.PNDisconnectedCategory,
operation: operations_1.default.PNUnsubscribeOperation,
}),
]);
}
else {
const errorReason = pubnub_api_error_1.PubNubAPIError.create(new Error('Network connection error')).toPubNubError(operations_1.default.PNSubscribeOperation);
return receive_failed_1.ReceiveFailedState.with(Object.assign(Object.assign({}, context), { reason: errorReason }), [
(0, effects_1.emitStatus)({
category: categories_1.default.PNDisconnectedUnexpectedlyCategory,
operation: operations_1.default.PNUnsubscribeOperation,
error: (_a = errorReason.status) === null || _a === void 0 ? void 0 : _a.category,
}),
]);
}
});
exports.ReceivingState.on(events_1.unsubscribeAll.type, (_) => unsubscribed_1.UnsubscribedState.with(undefined, [(0, effects_1.emitStatus)({ category: categories_1.default.PNDisconnectedCategory })]));
exports.ReceivingState.on(events_1.unsubscribeAll.type, (_) => unsubscribed_1.UnsubscribedState.with(undefined, [
(0, effects_1.emitStatus)({
category: categories_1.default.PNDisconnectedCategory,
operation: operations_1.default.PNUnsubscribeOperation,
}),
]));
4 changes: 2 additions & 2 deletions lib/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2638,7 +2638,7 @@ declare namespace PubNub {
/**
* `true` to allow catch up on the front-end applications.
*
* @default `false`
* @default `true`
*/
restore?: boolean;
/**
Expand Down Expand Up @@ -2685,7 +2685,7 @@ declare namespace PubNub {
* param description in this table.
*
*
* @default `false`
* @default `true`
*/
enableEventEngine?: boolean;
/**
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 0 additions & 5 deletions src/core/components/retry-policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,6 @@ export class RetryPolicy {

validate() {
if (this.delay < 2) throw new Error('Delay can not be set less than 2 seconds for retry');
if (this.maximumRetry > 10) throw new Error('Maximum retry for linear retry policy can not be more than 10');
},
};
}
Expand Down Expand Up @@ -283,10 +282,6 @@ export class RetryPolicy {

validate() {
if (this.minimumDelay < 2) throw new Error('Minimum delay can not be set less than 2 seconds for retry');
else if (this.maximumDelay > 150)
throw new Error('Maximum delay can not be set more than 150 seconds for' + ' retry');
else if (this.maximumRetry > 6)
throw new Error('Maximum retry for exponential retry policy can not be more than 6');
},
};
}
Expand Down
8 changes: 4 additions & 4 deletions src/core/interfaces/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const USE_SSL = true;
/**
* Whether PubNub client should catch up subscription after network issues.
*/
const RESTORE = false;
const RESTORE = true;

/**
* Whether network availability change should be announced with `PNNetworkDownCategory` and
Expand All @@ -49,7 +49,7 @@ const FILE_PUBLISH_RETRY_LIMIT = 5;
/**
* Whether subscription event engine should be used or not.
*/
const ENABLE_EVENT_ENGINE = false;
const ENABLE_EVENT_ENGINE = true;

/**
* Whether configured user presence state should be maintained by the PubNub client or not.
Expand Down Expand Up @@ -250,7 +250,7 @@ export type UserConfiguration = {
/**
* `true` to allow catch up on the front-end applications.
*
* @default `false`
* @default `true`
*/
restore?: boolean;

Expand Down Expand Up @@ -303,7 +303,7 @@ export type UserConfiguration = {
* param description in this table.
*
*
* @default `false`
* @default `true`
*/
enableEventEngine?: boolean;

Expand Down
1 change: 1 addition & 0 deletions src/event-engine/states/handshaking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ HandshakingState.on(handshakeSuccess.type, (context, { payload }) =>
category: categoryConstants.PNConnectedCategory,
affectedChannels: context.channels.slice(0),
affectedChannelGroups: context.groups.slice(0),
operation: RequestOperation.PNSubscribeOperation,
currentTimetoken: !!context.cursor?.timetoken ? context.cursor?.timetoken : payload.timetoken,
}),
],
Expand Down
Loading
Loading