Skip to content
Merged
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
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,23 @@ Calls to `track`, `identify`, etc. are **buffered in-memory** by the proxy and r
- On fatal config errors (`401/403/404`), the client enters **disabled** state and drops subsequent calls.
- `sentAt` is stamped when the batch is prepared for transmission (just before network send). If you need the original occurrence time, pass your own `timestamp` on each event.

### MetaRouter.Analytics.shared

Property-style accessor for the live proxy, matching Apple SDK convention (`URLSession.shared`, `UserDefaults.standard`, etc.). Returns the same proxy that `initialize(with:)` returns — call it from anywhere in your app once the SDK has been initialized:

```swift
// Initialize once at app launch
MetaRouter.Analytics.initialize(with: options)

// Use anywhere — no need to thread the proxy through your code
MetaRouter.Analytics.shared.track("Button Tapped")
MetaRouter.Analytics.shared.identify("user123")
```

`.shared` is safe to call before `initialize(with:)` — the proxy buffers calls until binding completes (same FIFO + replay-on-ready semantics described above). Use the proxy returned from `initialize(with:)` if you prefer dependency-injection style; both refer to the same underlying instance.

> **Note:** `MetaRouter.Analytics.client()` is deprecated as of this release; use `.shared` instead. Existing call sites will continue to work (with a yellow deprecation warning) until the next major version.

### Analytics Interface

The analytics client provides the following methods:
Expand Down
8 changes: 8 additions & 0 deletions Sources/MetaRouter/MetaRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ public enum MetaRouter {
}


/// Idiomatic singleton-style accessor matching Apple SDK conventions
/// (`URLSession.shared`, `UserDefaults.standard`, `FileManager.default`).
/// Returns the same buffered proxy `initialize(with:)` returns — calls
/// made before `initialize` are queued and replayed on bind.
public static var shared: AnalyticsInterface { proxy }

@available(*, deprecated, renamed: "shared",
message: "Use MetaRouter.Analytics.shared. client() will be removed in v2.0.")
public static func client() -> AnalyticsInterface { proxy }

public static func reset() {
Expand Down
12 changes: 6 additions & 6 deletions Tests/MetaRouterTests/MetaRouterIntegrationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ final class MetaRouterIntegrationTests: XCTestCase {
let options = TestDataFactory.makeInitOptions()

// Get the proxy (before initialization)
let proxy = MetaRouter.Analytics.client()
let proxy = MetaRouter.Analytics.shared

// Make calls before initialization (should be queued)
proxy.track("queued_event", properties: nil)
Expand All @@ -83,7 +83,7 @@ final class MetaRouterIntegrationTests: XCTestCase {
// Multiple initialize calls should return the same proxy
let client1 = MetaRouter.Analytics.initialize(with: options)
let client2 = MetaRouter.Analytics.initialize(with: options)
let client3 = MetaRouter.Analytics.client()
let client3 = MetaRouter.Analytics.shared

XCTAssertTrue(client1 === client2, "Multiple initialize calls should return same proxy")
XCTAssertTrue(client1 === client3, "Client() should return same proxy as initialize")
Expand Down Expand Up @@ -309,7 +309,7 @@ final class MetaRouterIntegrationTests: XCTestCase {
await fulfillment(of: [expectation], timeout: 5.0)

// Verify final state is consistent
let client = MetaRouter.Analytics.client()
let client = MetaRouter.Analytics.shared
let debugInfo = await client.getDebugInfo()
XCTAssertNotNil(debugInfo)
}
Expand All @@ -334,7 +334,7 @@ final class MetaRouterIntegrationTests: XCTestCase {
await fulfillment(of: [expectation], timeout: 5.0)

// Should be in a valid state after all operations
let finalClient = MetaRouter.Analytics.client()
let finalClient = MetaRouter.Analytics.shared
XCTAssertNotNil(finalClient)
}

Expand Down Expand Up @@ -485,7 +485,7 @@ final class MetaRouterIntegrationTests: XCTestCase {

func testSetAdvertisingIdWithProxy() async {
// Get proxy before initialization
let proxy = MetaRouter.Analytics.client()
let proxy = MetaRouter.Analytics.shared

// Set advertising ID before initialization (should be queued)
proxy.setAdvertisingId("QUEUED-IDFA")
Expand Down Expand Up @@ -555,7 +555,7 @@ final class MetaRouterIntegrationTests: XCTestCase {

func testClearAdvertisingIdWithProxyIntegration() async {
// Get proxy before initialization
let proxy = MetaRouter.Analytics.client()
let proxy = MetaRouter.Analytics.shared

// Set advertising ID before initialization (should be queued)
proxy.setAdvertisingId("QUEUED-IDFA")
Expand Down
4 changes: 2 additions & 2 deletions Tests/MetaRouterTests/MetaRouterTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ final class MetaRouterTests: XCTestCase {
func testClientAndProxyAreConnected() {
let options = InitOptions(writeKey: "test-key", ingestionHost: "https://test.com")

let initialProxy = MetaRouter.Analytics.client()
let initialProxy = MetaRouter.Analytics.shared
let afterInit = MetaRouter.Analytics.initialize(with: options)
let againProxy = MetaRouter.Analytics.client()
let againProxy = MetaRouter.Analytics.shared

XCTAssertTrue(initialProxy === afterInit, "Initialize should return same proxy")
XCTAssertTrue(afterInit === againProxy, "Client should return same proxy")
Expand Down
Loading