import Foundation /// The `dashboard` command: the same account aggregate as the web /// dashboard, in one read. Newer arrays default empty so an updated app /// can still talk to a server from before the dashboard parity contract. nonisolated struct DashboardData: Decodable, Sendable, Hashable { let reviewQueue: [DashboardItem] let assignedIssues: [DashboardItem] let openMRs: [DashboardItem] let openIssues: [DashboardItem] /// Pinned repos share `repo list`'s row shape. let pinned: [RepoSummary] let recentActivity: [FeedEvent] /// Retained by the CLI for compatibility; builds are not a web /// dashboard section. let builds: [DashboardBuild] enum CodingKeys: String, CodingKey { case pinned, builds case reviewQueue = "review_queue" case openMRs = "open_mrs" case assignedIssues = "assigned_issues" case openIssues = "open_issues" case recentActivity = "recent_activity" } init(from decoder: any Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) reviewQueue = try values.decodeIfPresent([DashboardItem].self, forKey: .reviewQueue) ?? [] assignedIssues = try values.decodeIfPresent([DashboardItem].self, forKey: .assignedIssues) ?? [] openMRs = try values.decodeIfPresent([DashboardItem].self, forKey: .openMRs) ?? [] openIssues = try values.decodeIfPresent([DashboardItem].self, forKey: .openIssues) ?? [] pinned = try values.decodeIfPresent([RepoSummary].self, forKey: .pinned) ?? [] recentActivity = try values.decodeIfPresent([FeedEvent].self, forKey: .recentActivity) ?? [] builds = try values.decodeIfPresent([DashboardBuild].self, forKey: .builds) ?? [] } } /// One open issue or MR row, repo resolved server-side. nonisolated struct DashboardItem: Decodable, Sendable, Hashable, Identifiable { let repo: String let number: Int64 let title: String let author: String let state: String let updatedAt: Date enum CodingKeys: String, CodingKey { case repo, number, title, author, state case updatedAt = "updated_at" } var id: String { "\(repo)#\(number)" } } /// One build row with its repo attached. nonisolated struct DashboardBuild: Decodable, Sendable, Hashable, Identifiable { let repo: String let number: Int64 let job: String let status: String let sha: String let ref: String let createdAt: Date let finishedAt: Date? enum CodingKeys: String, CodingKey { case repo, number, job, status, sha, ref case createdAt = "created_at" case finishedAt = "finished_at" } var id: String { "\(repo)#\(number)" } }