Files
SwiftUI/Other Projects/GitHub Search/GitHubSearchWithSwiftUI/Model/RepositoryAPI.swift
John Holdsworth 8018d0c2a0 Combine examples
2019-07-10 00:57:54 +01:00

52 lines
1.8 KiB
Swift
Executable File

//
// RepositoryModel.swift
// GitHubSearchWithSwiftUI
//
// Created by marty-suzuki on 2019/06/06.
// Copyright © 2019 jp.marty-suzuki. All rights reserved.
//
import Combine
import Foundation
enum RepositoryAPI {
typealias SearchResponse = AnyPublisher<Result<[Repository], ErrorResponse>, Never>
typealias SendRequest = (URLRequest) -> AnyPublisher<Data, URLSessionError>
static func search(query: String) -> SearchResponse {
search(query: query, sendRequest: URLSession.shared.combine.send)
}
static func search(query: String, sendRequest: SendRequest) -> SearchResponse {
guard var components = URLComponents(string: "https://api.github.com/search/repositories") else {
return .empty()
}
components.queryItems = [URLQueryItem(name: "q", value: query)]
guard let url = components.url else {
return .empty()
}
var request = URLRequest(url: url)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
return sendRequest(request)
.decode(type: ItemResponse<Repository>.self, decoder: decoder)
.map { Result<[Repository], ErrorResponse>.success($0.items) }
.catch { error -> SearchResponse in
guard case let .serverErrorMessage(_, data)? = error as? URLSessionError else {
return .just(.success([]))
}
do {
let response = try JSONDecoder().decode(ErrorResponse.self, from: data)
return .just(.failure(response))
} catch _ {
return .just(.success([]))
}
}
.eraseToAnyPublisher()
}
}