Skip to content

Commit e35c2a5

Browse files
Merge branch 'development' into main
2 parents fd47ac1 + 656306f commit e35c2a5

19 files changed

+138
-123
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,11 @@ import Legatus
140140
final class UsersApiRequest: DeserializeableRequest {
141141

142142
var path: String {
143-
return "users"
143+
"users"
144144
}
145145

146146
var deserializer: ResponseDeserializer<[User]> {
147-
return JSONDeserializer<User>.collectionDeserializer(keyPath: "results")
147+
JSONDeserializer<User>.collectionDeserializer(keyPath: "results")
148148
}
149149

150150
}
@@ -244,7 +244,7 @@ While working with SwiftUI, where most of UI updates based on *Combine* mechanis
244244
var subscriptions = Set<AnyCancellable>()
245245

246246
apiClient
247-
.requestPublisher(request: UsersApiRequest())
247+
.responsePublisher(request: UsersApiRequest())
248248
.catch { _ in return Just([User]())}
249249
.assign(to: \.users, on: self)
250250
.store(in: &subscriptions)

Sources/Legatus/APIClient.swift

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ open class APIClient {
3838
uploadProgressObserver: uploadProgressObserver))
3939
.retry(retries)
4040
.handleEvents(receiveCancel: {
41-
completion(.failure(APIClientError.requestCancelled))
41+
completion(.failure(APIClientError.requestCancelled))
4242
})
4343
.flatMap { self.handle(apiResponse: $0) }
4444
.subscribe(on: deserializationQueue)
@@ -61,11 +61,11 @@ open class APIClient {
6161
retries: Int = 0,
6262
uploadProgressObserver: ((Progress) -> Void)? = nil,
6363
completion: @escaping (Swift.Result<U, Error>) -> Void) -> AnyCancellable where U == T.ResponseType {
64-
return executeRequest(request,
65-
retries: retries,
66-
deserializer: request.deserializer,
67-
uploadProgressObserver: uploadProgressObserver,
68-
completion: completion)
64+
executeRequest(request,
65+
retries: retries,
66+
deserializer: request.deserializer,
67+
uploadProgressObserver: uploadProgressObserver,
68+
completion: completion)
6969
}
7070

7171
public func cancelAllRequests() {
@@ -95,19 +95,19 @@ open class APIClient {
9595
}
9696

9797
private func requestResponsePublisher(_ request: APIRequest) -> AnyPublisher<APIResponse, Error> {
98-
return Deferred<DataRequestPublisher> { [weak self] in
99-
return DataRequestPublisher(apiClient: self, apiRequest: request)
98+
Deferred<DataResponsePublisher> { [weak self] in
99+
DataResponsePublisher(apiClient: self, apiRequest: request)
100100
}.eraseToAnyPublisher()
101101
}
102102

103103
private func multipartRequestResponsePublisher(_ request: APIRequest,
104104
requestInputMultipartData: [String: URL],
105105
uploadProgressObserver: ((Progress) -> Void)? = nil) -> AnyPublisher<APIResponse, Error> {
106-
return Deferred { [weak self] in
107-
return MultipartRequestPublisher(apiClient: self,
108-
apiRequest: request,
109-
requestInputMultipartData: requestInputMultipartData,
110-
uploadProgressObserver: uploadProgressObserver)
106+
Deferred { [weak self] in
107+
MultipartResponsePublisher(apiClient: self,
108+
apiRequest: request,
109+
requestInputMultipartData: requestInputMultipartData,
110+
uploadProgressObserver: uploadProgressObserver)
111111
}.eraseToAnyPublisher()
112112
}
113113
}

Sources/Legatus/Deserializers/JSONDeserializer/JSONDecoderKeypath /KeyPathWrapper.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,11 @@ final class KeyPathWrapper<T: Decodable>: Decodable {
3737
}
3838

3939
/// Finds nested container and returns it and the key for object
40-
func objectContainer(for keyPath: [String],
41-
in currentContainer: KeyedContainer,
42-
key currentKey: Key) throws -> (KeyedContainer, Key) {
40+
func objectContainer(
41+
for keyPath: [String],
42+
in currentContainer: KeyedContainer,
43+
key currentKey: Key
44+
) throws -> (KeyedContainer, Key) {
4345
guard !keyPath.isEmpty else { return (currentContainer, currentKey) }
4446
let container = try currentContainer.nestedContainer(keyedBy: Key.self, forKey: currentKey)
4547
let key = try getKey(from: keyPath)

Sources/Legatus/Deserializers/JSONDeserializer/JSONDeserializer.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import Foundation
21
import Combine
2+
import Foundation
33

44
public enum JSONDeserializerError: Error {
55
case jsonDeserializableInitFailed(String)
@@ -13,13 +13,13 @@ open class JSONDeserializer<T>: ResponseDeserializer<T> {
1313
"Wrong result type: \(jsonObject.self). Expected \(T.self)"
1414
)
1515
}
16-
16+
1717
return object
1818
}
1919
}
20-
20+
2121
public override func deserialize(data: Data) -> Future<T, Error> {
22-
return Future { [weak self] promise in
22+
Future { [weak self] promise in
2323
guard let self = self else { return }
2424
do {
2525
let object = try self.transform(data)
@@ -32,12 +32,12 @@ open class JSONDeserializer<T>: ResponseDeserializer<T> {
3232
}
3333

3434
extension JSONDeserializer where T: Decodable {
35-
35+
3636
public class func singleObjectDeserializer(keyPath path: String...) -> JSONDeserializer<T> {
37-
return JSONDeserializer { jsonDataObject in
37+
JSONDeserializer { jsonDataObject in
3838
do {
3939
let jsonDecoder = JSONDecoder()
40-
40+
4141
return try path.isEmpty
4242
? jsonDecoder.decode(T.self, from: jsonDataObject)
4343
: jsonDecoder.decode(T.self, from: jsonDataObject, keyPath: path.joined(separator: "."))
@@ -48,12 +48,12 @@ extension JSONDeserializer where T: Decodable {
4848
}
4949
}
5050
}
51-
51+
5252
public class func collectionDeserializer(keyPath path: String...) -> JSONDeserializer<[T]> {
53-
return JSONDeserializer<[T]> { jsonDataObject in
53+
JSONDeserializer<[T]> { jsonDataObject in
5454
do {
5555
let jsonDecoder = JSONDecoder()
56-
56+
5757
return try path.isEmpty
5858
? jsonDecoder.decode([T].self, from: jsonDataObject)
5959
: jsonDecoder.decode([T].self, from: jsonDataObject, keyPath: path.joined(separator: "."))
@@ -64,5 +64,5 @@ extension JSONDeserializer where T: Decodable {
6464
}
6565
}
6666
}
67-
67+
6868
}

Sources/Legatus/Deserializers/ResponseDeserializer.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import Foundation
21
import Combine
2+
import Foundation
33

44
open class ResponseDeserializer<T> {
55
typealias Transform = ((Data) throws -> T)
@@ -17,15 +17,15 @@ open class ResponseDeserializer<T> {
1717

1818
open class EmptyDeserializer: ResponseDeserializer<Void> {
1919
public override func deserialize(data: Data) -> Future<Void, Error> {
20-
return Future { promise in
20+
Future { promise in
2121
promise(.success(()))
2222
}
2323
}
2424
}
2525

2626
open class RawDataDeserializer: ResponseDeserializer<Data> {
2727
public override func deserialize(data: Data) -> Future<Data, Error> {
28-
return Future { promise in
28+
Future { promise in
2929
promise(.success(data))
3030
}
3131
}

Sources/Legatus/Deserializers/XMLDeserializer/XMLDeserializer.swift

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import Foundation
21
import Combine
2+
import Foundation
33
import SWXMLHash
44

55
public protocol XMLDeserializable {
@@ -16,7 +16,8 @@ open class XMLDeserializer<T>: ResponseDeserializer<T> {
1616
if let xmlObject = xmlObject as? T {
1717
return xmlObject
1818
}
19-
throw XMLDeserializerError.jsonDeserializableInitFailed("Wrong result type: \(xmlObject.self). Expected \(T.self)")
19+
throw XMLDeserializerError.jsonDeserializableInitFailed(
20+
"Wrong result type: \(xmlObject.self). Expected \(T.self)")
2021
}
2122
}
2223

@@ -33,26 +34,28 @@ open class XMLDeserializer<T>: ResponseDeserializer<T> {
3334
}
3435
}
3536

36-
public extension XMLDeserializer where T: XMLDeserializable {
37+
extension XMLDeserializer where T: XMLDeserializable {
3738

38-
class func singleObjectDeserializer(keyPath path: String...) -> XMLDeserializer<T> {
39-
return XMLDeserializer { xmlDataObject in
39+
public class func singleObjectDeserializer(keyPath path: String...) -> XMLDeserializer<T> {
40+
XMLDeserializer { xmlDataObject in
4041
let xml = SWXMLHash.lazy(xmlDataObject)
4142
guard let deserializedObject = T(xmlIndexer: xml[path]) else {
42-
throw XMLDeserializerError.jsonDeserializableInitFailed("Failed to create \(T.self) object.")
43+
throw XMLDeserializerError.jsonDeserializableInitFailed(
44+
"Failed to create \(T.self) object.")
4345
}
4446
return deserializedObject
4547
}
4648
}
4749

48-
class func collectionDeserializer(keyPath path: String...) -> XMLDeserializer<[T]> {
49-
return XMLDeserializer<[T]>(transform: { xmlDataObject in
50+
public class func collectionDeserializer(keyPath path: String...) -> XMLDeserializer<[T]> {
51+
XMLDeserializer<[T]>(transform: { xmlDataObject in
5052
let xml = SWXMLHash.lazy(xmlDataObject)
5153

5254
let deserializedObjects = xml[path].all.map { T(xmlIndexer: $0) }
5355

5456
if deserializedObjects.contains(where: { $0 == nil }) {
55-
throw XMLDeserializerError.jsonDeserializableInitFailed("Failed to create array of \(T.self) objects.")
57+
throw XMLDeserializerError.jsonDeserializableInitFailed(
58+
"Failed to create array of \(T.self) objects.")
5659
}
5760

5861
return deserializedObjects.compactMap { $0 }

Sources/Legatus/Extensions/APIClient+Extensions.swift

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,51 @@
1-
import Foundation
21
import Combine
2+
import Foundation
33

4-
public extension APIClient {
4+
extension APIClient {
55

6-
func requestPublisher<T>(_ request: APIRequest,
7-
deserializer: ResponseDeserializer<T>,
8-
uploadProgressObserver: ((Progress) -> Void)? = nil) -> AnyPublisher<T, Error> {
9-
return Deferred {
10-
return Future { [weak self] promise in
6+
public func responsePublisher<T>(
7+
request: APIRequest,
8+
deserializer: ResponseDeserializer<T>,
9+
uploadProgressObserver: ((Progress) -> Void)? = nil
10+
) -> AnyPublisher<T, Error> {
11+
Deferred {
12+
Future { [weak self] promise in
1113
guard let self = self else { return }
1214

13-
self.executeRequest(request,
14-
deserializer: deserializer,
15-
uploadProgressObserver: uploadProgressObserver) { result in
16-
switch result {
17-
case .success(let deserializedObjects):
18-
promise(.success(deserializedObjects))
19-
case .failure(let error):
20-
promise(.failure(error))
21-
}
15+
self.executeRequest(
16+
request,
17+
deserializer: deserializer,
18+
uploadProgressObserver: uploadProgressObserver
19+
) { result in
20+
switch result {
21+
case .success(let deserializedObjects):
22+
promise(.success(deserializedObjects))
23+
case .failure(let error):
24+
promise(.failure(error))
25+
}
2226
}
2327
}
2428
}.eraseToAnyPublisher()
2529
}
2630

27-
func requestPublisher<T: DeserializeableRequest, U>(request: T,
28-
uploadProgressObserver: ((Progress) -> Void)? = nil) -> AnyPublisher<U, Error> where U == T.ResponseType {
29-
return Deferred {
30-
return Future { [weak self] promise in
31+
public func responsePublisher<T: DeserializeableRequest, U>(
32+
request: T,
33+
uploadProgressObserver: ((Progress) -> Void)? = nil
34+
) -> AnyPublisher<U, Error> where U == T.ResponseType {
35+
Deferred {
36+
Future { [weak self] promise in
3137
guard let self = self else { return }
3238

33-
self.executeRequest(request: request,
34-
uploadProgressObserver: uploadProgressObserver) { result in
35-
switch result {
36-
case .success(let deserializedObjects):
37-
promise(.success(deserializedObjects))
38-
case .failure(let error):
39-
promise(.failure(error))
40-
}
39+
self.executeRequest(
40+
request: request,
41+
uploadProgressObserver: uploadProgressObserver
42+
) { result in
43+
switch result {
44+
case .success(let deserializedObjects):
45+
promise(.success(deserializedObjects))
46+
case .failure(let error):
47+
promise(.failure(error))
48+
}
4149
}
4250
}
4351
}.eraseToAnyPublisher()

Sources/Legatus/RequestPublishers/DataRequestPublisher.swift

Lines changed: 0 additions & 26 deletions
This file was deleted.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import Alamofire
2+
import Combine
3+
import Foundation
4+
5+
public struct DataResponsePublisher: Publisher {
6+
public typealias Output = APIResponse
7+
public typealias Failure = Error
8+
9+
private let apiClient: APIClient?
10+
private let apiRequest: APIRequest
11+
12+
init(apiClient: APIClient?, apiRequest: APIRequest) {
13+
self.apiClient = apiClient
14+
self.apiRequest = apiRequest
15+
}
16+
17+
public func receive<S: Subscriber>(subscriber: S) where Failure == S.Failure, Output == S.Input {
18+
guard let apiClient = apiClient else { return }
19+
let dataRequestSubscription = DataResponseSubscription(
20+
subscriber: subscriber,
21+
apiClient: apiClient,
22+
apiRequest: apiRequest)
23+
24+
subscriber.receive(subscription: dataRequestSubscription)
25+
}
26+
27+
}

Sources/Legatus/RequestPublishers/MultipartRequestPublisher.swift renamed to Sources/Legatus/ResponsePublishers/MultipartResponsePublisher.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Foundation
22
import Combine
33
import Alamofire
44

5-
public struct MultipartRequestPublisher: Publisher {
5+
public struct MultipartResponsePublisher: Publisher {
66
public typealias Output = APIResponse
77
public typealias Failure = Error
88

@@ -23,7 +23,7 @@ public struct MultipartRequestPublisher: Publisher {
2323

2424
public func receive<S: Subscriber>(subscriber: S) where Failure == S.Failure, Output == S.Input {
2525
guard let apiClient = apiClient else { return }
26-
let multipartRequestSubsription = MultipartRequestSubscription(subscriber: subscriber,
26+
let multipartRequestSubsription = MultipartResponseSubscription(subscriber: subscriber,
2727
apiClient: apiClient,
2828
apiRequest: apiRequest,
2929
requestInputMultipartData: requestInputMultipartData,

Sources/Legatus/RequestSubscriptions/DataRequestSubscription.swift renamed to Sources/Legatus/ResponseSubscriptions/DataResponseSubscription.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Foundation
22
import Combine
33
import Alamofire
44

5-
public final class DataRequestSubscription<S: Subscriber>: Subscription where S.Input == APIResponse, S.Failure == Error {
5+
public final class DataResponseSubscription<S: Subscriber>: Subscription where S.Input == APIResponse, S.Failure == Error {
66
private let apiClient: APIClient
77
private let apiRequest: APIRequest
88
private var dataRequest: DataRequest?

0 commit comments

Comments
 (0)