- BLAuditLogger is an enum (static API) — cannot be constructed; use .Type reference + configure()
- BLCrashReporter is @MainActor — defer construction to start() via Task { @MainActor }
123 lines
4.3 KiB
Swift
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)
|
|
}
|
|
}
|