Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@TamHuynhTee
Copy link
Collaborator

@TamHuynhTee TamHuynhTee commented Oct 19, 2025

Note

Adds browser detection (with Brave heuristic) to event context and refactors event creation/queueing to async, updating types and call sites; bumps UMD size limit.

  • Analytics/Event Context:
    • Adds browser detection via src/lib/browser/browsers.ts and includes browser in generated event context.
    • Declares navigator.brave.isBrave() in src/global.d.ts for Brave detection.
  • Event Pipeline (Async refactor):
    • Makes EventFactory context/enrichment and all generate*/create methods async; imports and uses detectBrowser().
    • Updates EventManager.addEvent to async and awaits factory create.
    • Updates FormoAnalytics to await eventManager.addEvent and align with async tracking flows.
  • Build:
    • Increases size-limit for dist/index.umd.min.js to 36 KB.

Written by Cursor Bugbot for commit 4514bdd. This will update automatically on new commits. Configure here.

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Greptile Overview

Greptile Summary

This PR adds Brave browser detection capability to the analytics SDK by introducing an asynchronous check for the Brave browser's native API (navigator.brave.isBrave()). The core implementation resides in EventFactory's new isBraveBrowser() method, which checks for the Brave-specific navigator property and calls its async detection method. This detection is performed during context generation for every event, adding Brave identification to the analytics context object. Since Brave's detection API is inherently asynchronous, this required converting the entire event creation pipeline from synchronous to asynchronous - propagating through EventFactory.create() → EventManager.addEvent() → FormoAnalytics tracking methods. TypeScript type definitions were added to the global Navigator interface to support the Brave API. The change includes code formatting standardization (double quotes) and proper error handling for the detection logic. This fits into the SDK's broader goal of enriching analytics events with browser context information, which is particularly valuable given Brave's unique privacy features and tracking prevention mechanisms.

Changed Files
Filename Score Overview
src/global.d.ts 5/5 Added TypeScript type definitions for Brave browser detection by extending Navigator interface with optional brave property
src/lib/event/type.ts 4/5 Changed IEventManager and IEventFactory interface signatures from synchronous to asynchronous (breaking change)
src/lib/event/EventFactory.ts 4/5 Added async isBraveBrowser() method and converted entire class from sync to async to support detection on every event
src/lib/event/EventManager.ts 4/5 Converted addEvent method to async to support awaiting EventFactory's now-async create() method
src/FormoAnalytics.ts 4/5 Updated to await eventManager.addEvent() calls and applied formatting standardization throughout the file

Confidence score: 4/5

  • This PR requires careful review but appears safe to merge with moderate risk due to breaking API changes
  • Score reflects the breaking change to public interfaces (sync to async), potential performance impact from detection on every event, and the need to verify all call sites properly handle the new async nature; no critical bugs detected but the architectural impact is significant
  • Pay close attention to src/lib/event/type.ts (interface breaking changes), src/lib/event/EventFactory.ts (detection implementation called on every event), and verify all consumers of these APIs throughout the codebase properly await the now-async methods

Sequence Diagram

sequenceDiagram
    participant User
    participant FormoAnalytics
    participant EventFactory
    participant Navigator
    participant EventQueue

    User->>FormoAnalytics: "Initialize SDK or Trigger Event"
    FormoAnalytics->>EventFactory: "generateContext()"
    EventFactory->>Navigator: "navigator.brave?.isBrave()"
    alt Brave Browser
        Navigator-->>EventFactory: "true"
    else Not Brave
        Navigator-->>EventFactory: "false"
    end
    EventFactory->>EventFactory: "Set is_brave_browser in context"
    EventFactory-->>FormoAnalytics: "Return enriched context with is_brave_browser"
    FormoAnalytics->>EventFactory: "create(event, address, userId)"
    EventFactory->>EventFactory: "Generate event with context including is_brave_browser"
    EventFactory-->>FormoAnalytics: "Return IFormoEvent"
    FormoAnalytics->>EventQueue: "enqueue(formoEvent)"
    EventQueue-->>User: "Event tracked with Brave detection"
Loading

5 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@TamHuynhTee TamHuynhTee force-pushed the feature/add-brave-browser-detection branch from 55837d3 to e1619d5 Compare October 19, 2025 11:59
@yosriady
Copy link
Contributor

bugbot run

@yosriady
Copy link
Contributor

@greptile

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Greptile Overview

Greptile Summary

This PR adds Brave browser detection capability to the analytics SDK by introducing asynchronous browser identification. The changes convert the entire event generation pipeline from synchronous to asynchronous to accommodate Brave's promise-based navigator.brave.isBrave() API. TypeScript type definitions are added in global.d.ts to properly type the Brave API, while EventFactory implements the detection logic with a caching mechanism to avoid repeated API calls. The asynchronous nature propagates through IEventFactory and IEventManager interfaces, requiring EventManager.addEvent() and all factory methods to return Promises. Finally, FormoAnalytics.trackEvent() now properly awaits event addition. The implementation adds an is_brave_browser boolean field to all event contexts, enabling the analytics platform to track Brave browser usage alongside other browser metrics.

Changed Files
Filename Score Overview
src/global.d.ts 5/5 Adds TypeScript type definitions for Brave's browser detection API to the Navigator interface
src/lib/event/type.ts 4/5 Updates interfaces to make event creation and management methods asynchronous
src/lib/event/EventFactory.ts 4/5 Implements Brave browser detection with caching and converts all event generation methods to async
src/lib/event/EventManager.ts 4/5 Converts addEvent method to async and awaits eventFactory.create()
src/FormoAnalytics.ts 4/5 Adds await to eventManager.addEvent() call plus extensive formatting improvements

Confidence score: 4/5

  • This PR requires careful review as it introduces a breaking API change by converting synchronous methods to asynchronous throughout the event pipeline.
  • Score reflects that while the implementation is sound with proper error handling and caching, the architectural shift from sync to async affects the entire event generation flow. Points deducted for: (1) Breaking change in public interfaces requiring all consumers to update their code to await these methods, (2) Potential issues if existing code calling addEvent() doesn't properly handle the returned Promise, (3) The async nature adds overhead to every event generation call even with caching.
  • Pay close attention to src/lib/event/type.ts (interface changes), src/lib/event/EventFactory.ts (core detection logic), and src/lib/event/EventManager.ts (async propagation). Verify that all callers of these methods throughout the codebase have been updated to handle Promises correctly.

Sequence Diagram

sequenceDiagram
    participant User
    participant FormoAnalytics
    participant EventFactory
    participant Navigator
    participant EventManager
    participant EventQueue

    User->>FormoAnalytics: trackEvent(type, payload)
    FormoAnalytics->>EventManager: addEvent(event, address, userId)
    EventManager->>EventFactory: create(event, address, userId)
    EventFactory->>EventFactory: generateContext(context)
    EventFactory->>Navigator: navigator.brave?.isBrave()
    alt Brave browser detected
        Navigator-->>EventFactory: true
    else Not Brave or unavailable
        Navigator-->>EventFactory: false/undefined
    end
    EventFactory->>EventFactory: Cache result in cachedIsBrave
    EventFactory->>EventFactory: Merge context with is_brave_browser flag
    EventFactory-->>EventManager: return IFormoEvent
    EventManager->>EventQueue: enqueue(formoEvent, callback)
    EventQueue-->>User: callback(err, _, data)
Loading

5 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

cursor[bot]

This comment was marked as outdated.

@TamHuynhTee
Copy link
Collaborator Author

bugbot run

@cursor
Copy link

cursor bot commented Oct 26, 2025

Skipping Bugbot: Bugbot is disabled for this repository

@TamHuynhTee
Copy link
Collaborator Author

@greptile

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Greptile Overview

Greptile Summary

This PR adds Brave browser detection to the analytics SDK and refactors the event generation pipeline to be async. The implementation introduces a new browsers.ts module with cached browser detection using multiple heuristics (navigator.brave.isBrave(), userAgentData.brands, and user-agent string matching). All EventFactory methods were converted from synchronous to async to support the browser detection call in generateContext().

Key changes:

  • New detectBrowser() function with module-level caching and in-flight request deduplication
  • Browser name added to event context for all tracked events
  • Type interfaces updated to return Promise types across IEventFactory and IEventManager
  • Bundle size limit increased from 32KB to 36KB (12.5% increase)

Implementation strengths:

  • Robust caching strategy prevents redundant API calls (browser type doesn't change during session)
  • Multiple detection heuristics with proper fallbacks
  • Comprehensive error handling with try-catch blocks
  • In-flight promise tracking prevents race conditions on concurrent calls

Confidence Score: 4/5

  • This PR is safe to merge with minimal risk; well-structured refactor with good error handling
  • Score reflects solid implementation with caching, error handling, and comprehensive async refactor. The 12.5% bundle size increase is notable but acceptable for the feature value. No critical bugs identified, though the async conversion is a significant API surface change that should be monitored in production.
  • No files require special attention - all changes follow consistent patterns with proper error handling

Important Files Changed

File Analysis

Filename Score Overview
src/lib/browser/browsers.ts 4/5 New browser detection module with caching and multi-heuristic Brave detection; handles edge cases well with proper error handling
src/lib/event/EventFactory.ts 4/5 Converted all event generation methods to async to support browser detection; properly awaits detectBrowser() in context generation
package.json 5/5 Bundle size limit increased from 32KB to 36KB to accommodate new browser detection feature

Sequence Diagram

sequenceDiagram
    participant App as Application
    participant FA as FormoAnalytics
    participant EM as EventManager
    participant EF as EventFactory
    participant BD as detectBrowser()
    participant Nav as Navigator API
    participant EQ as EventQueue

    App->>FA: trackEvent()
    FA->>EM: addEvent(event, address, userId)
    EM->>EF: create(event, address, userId)
    EF->>EF: generateContext()
    EF->>BD: detectBrowser()
    
    alt First call (not cached)
        BD->>Nav: navigator.brave?.isBrave()
        Nav-->>BD: Promise<boolean>
        BD->>BD: Cache result
        BD-->>EF: browserName
    else Subsequent calls (cached)
        BD-->>EF: browserName (from cache)
    end
    
    EF->>EF: Enrich context with browser
    EF-->>EM: IFormoEvent
    EM->>EQ: enqueue(formoEvent)
    EQ-->>EM: queued
    EM-->>FA: void
    FA-->>App: Promise<void>
Loading

3 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

@TamHuynhTee TamHuynhTee merged commit 6ef3cc2 into main Oct 26, 2025
6 checks passed
@TamHuynhTee TamHuynhTee deleted the feature/add-brave-browser-detection branch October 26, 2025 10:15
@yosriady
Copy link
Contributor

bugbot run

@github-actions
Copy link

🎉 This PR is included in version 1.21.0 🎉

params,
undefined,
capturedChainId
),
Copy link

Choose a reason for hiding this comment

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

Bug: Unhandled Promises in Fire-and-Forget Calls

Async method this.signature() is called without await inside a fire-and-forget async IIFE. Since signature() now returns Promise<void> (because it calls async trackEvent()), the returned promise is not being awaited. This breaks error handling - errors in the async chain won't be caught by the try-catch block, potentially leading to unhandled promise rejections. The same issue occurs for this.transaction() calls at lines 1364, 1382, and similar locations.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants