Fix TypeScript-in-JS, security, and timing bugs in sports use-case snippets - #520
Conversation
…ippets The platform review found that every sports/media/entertainment snippet file cast errors with `as PubNubError`, which is TypeScript syntax and fails a plain-JS parser when the docs extract these regions as JavaScript. Some files also carried type annotations, `type`/`interface` declarations, and `as` casts inside the extracted regions. Replace the cast pattern everywhere with a runtime `instanceof Error && 'status' in error` check, drop now-unused `PubNubError` imports, and remove or rework every other type-only construct inside a snippet marker (Map instead of a `Record<...>`-annotated object, default-valued parameters instead of typed ones, `typeof`/`in`-narrowed property reads instead of `as` casts on a subscribed message). Fix the specific defects the review's SDK-review findings pointed at: - live-commentary.ts: `unsubscribe()` was top-level code that ran the moment the file loaded. Move it into a `SIGINT` handler, and add a status listener that logs on `PNConnectedCategory` so the docs can tell the reader when the viewer is actually ready to receive. - fan-behavior-management.ts: mute and ban only revoked the most recently issued token, leaving any earlier writable token usable. Track every token issued per fan in a small JSON file store, revoke every writable one on mute and every token on ban, and refuse to grant write back while muted or the fan at all while banned. Add real `process.argv` dispatch (`grant`/`mute`/`unmute`/`ban`) and a `fan.js` that actually parses its token argument, installs its status listener before subscribing, and reports a rejected publish from its own `try`/`catch` rather than the status listener. - game-chat-moderation.ts: any client with write access to `game.chat` could publish the same `moderation`/`hidden` message action a moderator would, since Access Manager scopes permissions to channels, not to action type/value strings. Move the hide decision to its own `game.chat.moderation` channel that only a moderator-scoped token can write to, and fetch that channel's history alongside `game.chat`'s so a late-joining client still renders the hide. Also stop rounding a 17-digit timetoken through `Number` arithmetic before the single-message delete; keep it as a string and use `BigInt` for the exclusive-start calculation. - fan-re-engagement.ts: the occupancy/leave logic ran under the same `userId` it was checking, and the alert published unconditionally to a shared channel every registered device received. Separate the monitoring identity from any fan's, gate the publish behind a `whereNow` check for the specific fan who triggered the presence event, and target a per-fan `game.moment-alerts.<userId>` channel instead of a shared one. Add a `fan-viewer.js` so the two-client case (one fan stays, one leaves) is actually runnable. - score-alerts.ts: device registration set `environment: 'production'` while the notification payload's APNs target left `environment` at its SDK default of `'development'`, so a registered device could never receive what got published. Introduce one `APNS_ENVIRONMENT` constant used by registration, the payload target, and new APNs-specific listing and removal snippets. Verified with `npm run test:snippets` (tsc against the whole docs-snippets tree) and by replicating EmbeddedCode's exact snippet extraction to `node --check` every region, and the per-page combined assembly, for all 11 sports use-case pages. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A failed revokeToken call dropped the token from the registry, leaving a valid writable token untracked. Mute also saved its status only after the read-only grant succeeded. Record the status first and keep unrevoked tokens so a repeated mute or ban retries them. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Important Review skippedReview was skipped due to path filters ⛔ Files ignored due to path filters (4)
CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including ⚙️ Run configurationConfiguration used: Repository: pubnub/javascript/.coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
What
Fixes defects found by the Platform documentation release review (preview 961) in
docs-snippets/use-cases/, which feeds the 11 Use cases → Sports, Media & Entertainment pages.javascript).(error as PubNubError)casts, type annotations,typedeclarations, andRecord<>generics removed.npm run test:snippetsstill type-checks every file.live-commentary.tsunsubscribe()moved into aSIGINThandler. A status listener logs readiness onPNConnectedCategorybefore the reader starts the publisher.fan-behavior-management.tsserver.js(grant,mute,unmute,banviaprocess.argv) andfan.js(node fan.js <token>). A JSON-file token registry survives separate CLI runs. Mute revokes every tracked writable token, ban revokes every token, grant refuses writable tokens while muted and any token while banned. A failed revoke keeps the token tracked so a repeated command retries it. The status listener is installed before subscribing, and publish has its owntry/catch.game-chat-moderation.tsgame.chat.moderation, write granted only to the moderator token). Live and history views both read it, instead of trusting any client'smoderation/hiddenmessage action.game-chat-moderation.ts(BigInt(timetoken) - BigInt(1)).toString(), with the timetoken kept as a string. The start/end direction is unchanged and is under separate review.fan-re-engagement.tsmatch-service. The alert is published only whenwhereNowshows the fan is absent, to a per-user channelgame.moment-alerts.<userId>. Newfan-viewer.jsfor a two-client test.score-alerts.tsAPNS_ENVIRONMENTconstant is used for registration, listing, removal, and the payload target. The list and remove snippets are split into FCM and APNs variants.New snippet names that the docs pages already reference:
fanBehaviorStateStore,fanBehaviorBanFan,fanBehaviorUnmuteFan,fanBehaviorServerDispatch,fanBehaviorSubscribeAndPublish,reEngagementFanViewer,chatModerationGrantControlChannelAccess,chatModerationApplyModeratorToken,scoreAlertsEnvironmentConstant,scoreAlertsListDeviceRegistrationsAPNs,scoreAlertsListDeviceRegistrationsFCM,scoreAlertsRemoveDeviceRegistrationAPNs,scoreAlertsRemoveDeviceRegistrationFCM.Validation
npm run test:snippetspasses.extractSnippetsfrom this branch and passnode --checkas ES modules.noderuns sharing the state file, a failed revoke being retried, and the three-process re-engagement test (only the absent fan is alerted).Docs dependency
The docs pages point at
refs/heads/master. Four pages (fan-behavior-management, fan-re-engagement, game-chat-moderation, real-time-score-alerts) reference the new snippet names above, so this needs to merge before those docs changes ship.