learning_ai_common_plat/packages/swift-platform-sdk/Sources/ByteLystPlatform.swift
saravanakumardb1 6856d23a2e fix(swift-sdk): resolve BLAuditLogger + BLCrashReporter build errors in ByteLystPlatform
- BLAuditLogger is an enum (static API) — cannot be constructed; use .Type reference + configure()
- BLCrashReporter is @MainActor — defer construction to start() via Task { @MainActor }
2026-03-20 23:28:47 -07:00

123 lines
4.3 KiB
Swift

// ByteLystPlatform
// Unified entry point for the ByteLyst platform SDK.
// Creates and wires all platform services from a single config.
//
// Usage:
// let platform = ByteLystPlatform(config: .init(
// productId: "peakpulse",
// baseURL: "https://api.peakpulse.app",
// bundleId: "com.saravana.peakpulse"
// ))
//
// platform.start() // Start telemetry + flags + kill switch
// platform.telemetry.trackScreen("home") // Track events
// let isNew = platform.flags.isEnabled("new_feature")
// platform.stop() // Flush + stop timers
import Foundation
/// Unified entry point that wires all ByteLyst platform services together.
/// Create one instance at app launch and access services via properties.
public final class ByteLystPlatform {
/// Platform configuration.
public let config: BLPlatformConfig
/// HTTP client shared by all services.
public let client: BLPlatformClient
/// Telemetry event tracking.
public let telemetry: BLTelemetryClient
/// Feature flag polling.
public let flags: BLFeatureFlagClient
/// Kill switch checker.
public let killSwitch: BLKillSwitchClient
/// Crash reporter (MetricKit). Created lazily on MainActor.
public private(set) var crashReporter: BLCrashReporter?
/// Keychain access (via bundleId as service).
public let keychain: BLKeychainAccessor
/// Audit logger type (static API call BLAuditLogger.log()).
public let auditLog: BLAuditLogger.Type = BLAuditLogger.self
/// Auth client.
public let auth: BLAuthClient
/// Whether `start()` has been called.
public private(set) var isStarted = false
public init(config: BLPlatformConfig) {
self.config = config
self.client = BLPlatformClient(config: config)
self.telemetry = BLTelemetryClient(config: config, client: client)
self.flags = BLFeatureFlagClient(config: config, client: client)
self.killSwitch = BLKillSwitchClient(config: config)
self.keychain = BLKeychainAccessor(service: config.bundleId)
self.auth = BLAuthClient(config: config, client: client)
BLAuditLogger.configure(fileName: "\(config.productId)_audit_log.json")
}
/// Test-only initializer that accepts a custom URLSessionConfiguration.
public init(config: BLPlatformConfig, sessionConfiguration: URLSessionConfiguration) {
self.config = config
self.client = BLPlatformClient(config: config, sessionConfiguration: sessionConfiguration)
self.telemetry = BLTelemetryClient(config: config, client: client)
self.flags = BLFeatureFlagClient(config: config, client: client)
self.killSwitch = BLKillSwitchClient(config: config)
self.keychain = BLKeychainAccessor(service: config.bundleId)
self.auth = BLAuthClient(config: config, client: client)
BLAuditLogger.configure(fileName: "\(config.productId)_audit_log.json")
}
// MARK: - Lifecycle
/// Start all services: telemetry flush timer, feature flag polling, kill switch check.
public func start(userId: String? = nil) {
guard !isStarted else { return }
isStarted = true
telemetry.start()
flags.start(userId: userId)
Task { await killSwitch.check() }
Task { @MainActor in
self.crashReporter = BLCrashReporter(productId: config.productId)
}
}
/// Stop all services: flush telemetry, stop flag polling.
public func stop() {
guard isStarted else { return }
isStarted = false
telemetry.stop()
flags.stop()
}
}
// MARK: - Keychain Accessor
/// Convenience wrapper around BLKeychain that binds to a specific service (bundleId).
public struct BLKeychainAccessor {
private let service: String
public init(service: String) {
self.service = service
}
@discardableResult
public func save(key: String, value: String) -> Bool {
BLKeychain.save(service: service, key: key, value: value)
}
public func read(key: String) -> String? {
BLKeychain.read(service: service, key: key)
}
@discardableResult
public func delete(key: String) -> Bool {
BLKeychain.delete(service: service, key: key)
}
}