krz/moonrise

Night-sky companion for iPhone, Apple Watch and Vision Pro: what's up tonight, the Moon, planets, launches and missions, and a Library of the solar system. SwiftUI app with a Cloudflare Workers backend. astronomy cloudflare-workers ios night-sky space swiftui visionos watchos

Packages/MoonriseKit/Sources/Feeds/Launches.swift

04b2b1d914788057bcd20945b876847386eb8f65
moonrise/Packages/MoonriseKit/Sources/Feeds/Launches.swift history · blame · raw

49 lines · 1818 bytes

5 symbols in this file
 1import Foundation
 2
 3/// An upcoming launch as served by the Moonrise backend (from Launch Library 2).
 4public struct Launch: Codable, Sendable, Identifiable, Hashable {
 5    public var id: String
 6    public var name: String
 7    public var net: Date
 8    public var windowStart: Date?
 9    public var windowEnd: Date?
10    /// Launch Library 2 status abbreviation: Go, TBC, TBD, Hold, Success, Failure, …
11    public var status: String
12    public var statusName: String
13    public var provider: String
14    public var rocket: String
15    public var mission: String?
16    public var missionType: String?
17    public var missionDescription: String?
18    public var orbit: String?
19    public var pad: String
20    public var location: String
21    public var padLatitude: Double?
22    public var padLongitude: Double?
23}
24
25public struct LaunchList: Codable, Sendable {
26    public var fetchedAt: Date?
27    public var launches: [Launch]
28}
29
30public enum LaunchFeed {
31    static let decoder: JSONDecoder = {
32        let d = JSONDecoder()
33        d.dateDecodingStrategy = .custom { decoder in
34            let s = try decoder.singleValueContainer().decode(String.self)
35            if let date = try? Date(s, strategy: .iso8601) { return date }
36            if let date = try? Date(s, strategy: Date.ISO8601FormatStyle(includingFractionalSeconds: true)) { return date }
37            throw DecodingError.dataCorrupted(.init(codingPath: decoder.codingPath, debugDescription: "bad date \(s)"))
38        }
39        return d
40    }()
41
42    public static func decode(_ data: Data) throws -> LaunchList {
43        try decoder.decode(LaunchList.self, from: data)
44    }
45
46    public static func fetch(base: URL, session: URLSession = .shared) async throws -> LaunchList {
47        try decode(await session.data(from: base.appending(path: "v1/launches")).0)
48    }
49}