164 lines · 5.0 KB · Swift
RawDownload
import CodexBarCoreimport Foundation#if canImport(FoundationNetworking)import FoundationNetworking#endif struct ProviderPayload: Encodable {    let provider: String    let account: String?    let cacheAccountKey: String?    let version: String?    let source: String    let status: ProviderStatusPayload?    let usage: UsageSnapshot?    let credits: CreditsSnapshot?    let antigravityPlanInfo: AntigravityPlanInfoSummary?    let openaiDashboard: OpenAIDashboardSnapshot?    let error: ProviderErrorPayload?     private enum CodingKeys: String, CodingKey {        case provider        case account        case version        case source        case status        case usage        case credits        case antigravityPlanInfo        case openaiDashboard        case error    }     init(        provider: UsageProvider,        account: String?,        cacheAccountKey: String? = nil,        version: String?,        source: String,        status: ProviderStatusPayload?,        usage: UsageSnapshot?,        credits: CreditsSnapshot?,        antigravityPlanInfo: AntigravityPlanInfoSummary?,        openaiDashboard: OpenAIDashboardSnapshot?,        error: ProviderErrorPayload?)    {        self.provider = provider.rawValue        self.account = account        self.cacheAccountKey = cacheAccountKey        self.version = version        self.source = source        self.status = status        self.usage = usage        self.credits = credits        self.antigravityPlanInfo = antigravityPlanInfo        self.openaiDashboard = openaiDashboard        self.error = error    }     init(        providerID: String,        account: String?,        cacheAccountKey: String? = nil,        version: String?,        source: String,        status: ProviderStatusPayload?,        usage: UsageSnapshot?,        credits: CreditsSnapshot?,        antigravityPlanInfo: AntigravityPlanInfoSummary?,        openaiDashboard: OpenAIDashboardSnapshot?,        error: ProviderErrorPayload?)    {        self.provider = providerID        self.account = account        self.cacheAccountKey = cacheAccountKey        self.version = version        self.source = source        self.status = status        self.usage = usage        self.credits = credits        self.antigravityPlanInfo = antigravityPlanInfo        self.openaiDashboard = openaiDashboard        self.error = error    }} struct ProviderStatusPayload: Encodable {    let indicator: ProviderStatusIndicator    let description: String?    let updatedAt: Date?    let url: String     enum ProviderStatusIndicator: String, Encodable {        case none        case minor        case major        case critical        case maintenance        case unknown         var label: String {            switch self {            case .none: "Operational"            case .minor: "Partial outage"            case .major: "Major outage"            case .critical: "Critical issue"            case .maintenance: "Maintenance"            case .unknown: "Status unknown"            }        }    }     var descriptionSuffix: String {        guard let description, !description.isEmpty else { return "" }        return " – \(description)"    }} enum StatusFetcher {    static func fetch(from baseURL: URL) async throws -> ProviderStatusPayload {        let apiURL = baseURL.appendingPathComponent("api/v2/status.json")        var request = URLRequest(url: apiURL)        request.timeoutInterval = 10         let (data, _) = try await URLSession.shared.data(for: request)         struct Response: Decodable {            struct Status: Decodable {                let indicator: String                let description: String?            }             struct Page: Decodable {                let updatedAt: Date?                 private enum CodingKeys: String, CodingKey {                    case updatedAt = "updated_at"                }            }             let page: Page?            let status: Status        }         let decoder = JSONDecoder()        decoder.dateDecodingStrategy = .custom { decoder in            let container = try decoder.singleValueContainer()            let raw = try container.decode(String.self)            let formatter = ISO8601DateFormatter()            formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]            if let date = formatter.date(from: raw) { return date }            formatter.formatOptions = [.withInternetDateTime]            if let date = formatter.date(from: raw) { return date }            throw DecodingError.dataCorruptedError(in: container, debugDescription: "Invalid ISO8601 date")        }         let response = try decoder.decode(Response.self, from: data)        let indicator = ProviderStatusPayload.ProviderStatusIndicator(rawValue: response.status.indicator) ?? .unknown        return ProviderStatusPayload(            indicator: indicator,            description: response.status.description,            updatedAt: response.page?.updatedAt,            url: baseURL.absoluteString)    }}