// // CatFacts.swift // CatFactsKit // import Foundation public struct CatFacts: Sendable { public let baseURL: URL let urlSession: URLSession public init(baseURL: URL, urlSession: URLSession = .shared) { self.baseURL = baseURL self.urlSession = urlSession } public func getFacts(count: Int? = nil) async throws -> [String] { let params = count.map { ["count": $0] } ?? [:] let request = try generateRequest(path: "/", params: params) let response: FactsResponse = try await decodeRequest(request: request) return response.data } // MARK: - Private functionality private func generateRequest(path: String, params: [String: CustomStringConvertible] = [:]) throws -> URLRequest { guard let url = URL(string: path, relativeTo: baseURL) else { throw CatFactsError.requestError("Couldn't generate URL from path: \(path), baseURL: \(baseURL)") } let queryItems = params .compactMap { URLQueryItem(name: $0, value: $1.description) } .sorted { a, b in a.name < b.name } return queryItems.count > 0 ? URLRequest(url: url.appending(queryItems: queryItems)) : URLRequest(url: url) } private func decodeRequest(request: URLRequest) async throws -> T { let (data, response) = try await urlSession.data(for: request) guard let response = response as? HTTPURLResponse else { throw CatFactsError.connectionError("Couldn't get HTTP response from request \(request)") } guard response.statusCode < 300 else { let body = String(data: data, encoding: .utf8) throw CatFactsError.responseError(response.statusCode, body ?? "unknown error") } return try JSONDecoder().decode(T.self, from: data) } }