You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
57 lines
1.7 KiB
57 lines
1.7 KiB
import SwiftUI
|
|
import Combine
|
|
|
|
enum URLSessionError: Error {
|
|
case invalidResponse
|
|
case serverErrorMessage(statusCode: Int, data: Data)
|
|
case urlError(URLError)
|
|
}
|
|
|
|
extension URLSession {
|
|
func send(request: URLRequest) -> AnyPublisher<Data, URLSessionError> {
|
|
|
|
dataTaskPublisher(for: request)
|
|
.mapError { URLSessionError.urlError($0) }
|
|
.flatMap { data, response -> AnyPublisher<Data, URLSessionError> in
|
|
guard let response = response as? HTTPURLResponse else {
|
|
return .fail(.invalidResponse)
|
|
}
|
|
|
|
guard 200..<300 ~= response.statusCode else {
|
|
return .fail(.serverErrorMessage(statusCode: response.statusCode,
|
|
data: data))
|
|
}
|
|
|
|
return .just(data)
|
|
}.eraseToAnyPublisher()
|
|
}
|
|
}
|
|
|
|
extension JSONDecoder: TopLevelDecoder {}
|
|
|
|
extension Publisher {
|
|
|
|
/// - seealso: https://twitter.com/peres/status/1136132104020881408
|
|
func flatMapLatest<T: Publisher>(_ transform: @escaping (Self.Output) -> T) -> Publishers.SwitchToLatest<T, Publishers.Map<Self, T>> where T.Failure == Self.Failure {
|
|
map(transform).switchToLatest()
|
|
}
|
|
}
|
|
|
|
extension Publisher {
|
|
|
|
static func empty() -> AnyPublisher<Output, Failure> {
|
|
return Empty()
|
|
.eraseToAnyPublisher()
|
|
}
|
|
|
|
static func just(_ output: Output) -> AnyPublisher<Output, Failure> {
|
|
return Just(output)
|
|
.catch { _ in AnyPublisher<Output, Failure>.empty() }
|
|
.eraseToAnyPublisher()
|
|
}
|
|
|
|
static func fail(_ error: Failure) -> AnyPublisher<Output, Failure> {
|
|
return Fail(error: error)
|
|
.eraseToAnyPublisher()
|
|
}
|
|
}
|
|
|