merge with main

sync2
Laurent 9 months ago
commit 70cb758dba
  1. 71
      LeStorage/ApiCallCollection.swift
  2. 29
      LeStorage/Services.swift

@ -238,38 +238,40 @@ actor ApiCallCollection<T: SyncedStorable>: SomeCallCollection {
fileprivate func _call(method: HTTPMethod, instance: T? = nil) async throws -> ApiCall<T>? {
if let instance {
return try await self._callForInstance(method, instance: instance)
return try await self._callForInstance(instance, method: method)
} else {
if self.items.contains(where: { $0.method == .get }) {
return nil
} else {
return try self._createCall(.get)
return try self._createGetCall()
}
}
}
fileprivate func _callForInstance(_ method: HTTPMethod, instance: T) async throws -> ApiCall<T>? {
fileprivate func _callForInstance(_ instance: T, method: HTTPMethod, transactionId: String? = nil) async throws -> ApiCall<T> {
// cleanup
let existingCalls = self.items.filter { $0.dataId == instance.stringId }
self._deleteCalls(existingCalls)
if let existingCall = self.items.first(where: { $0.dataId == instance.stringId }) {
switch method {
case .delete:
self.deleteById(existingCall.id) // delete the existing call as we don't need it
if existingCall.method == HTTPMethod.post {
return nil // if the post has not been done, we can just stop here
} else {
return try self._createCall(method, instance: instance) // otherwise it's a put and we want to send the delete
}
default: // here we should only trying to PUT, so we update the existing POST/PUT with the instance new values
existingCall.body = try instance.jsonString()
return existingCall
}
} else {
return try self._createCall(method, instance: instance)
// create
let call = try self._createCall(method, instance: instance, transactionId: transactionId)
self._prepareCall(apiCall: call)
return call
}
fileprivate func _deleteCalls(_ calls: [ApiCall<T>]) {
for call in calls {
self.deleteById(call.id)
}
}
fileprivate func _createGetCall() throws -> ApiCall<T> {
return try self._createCall(.get, instance: nil)
}
/// Creates an API call for the Storable [instance] and an HTTP [method]
fileprivate func _createCall(_ method: HTTPMethod, instance: T? = nil, transactionId: String? = nil) throws -> ApiCall<T> {
fileprivate func _createCall(_ method: HTTPMethod, instance: T?, transactionId: String? = nil) throws -> ApiCall<T> {
if let instance {
let jsonString = try instance.jsonString()
return ApiCall(method: method, dataId: instance.stringId, body: jsonString, transactionId: transactionId)
@ -302,31 +304,34 @@ actor ApiCallCollection<T: SyncedStorable>: SomeCallCollection {
var apiCalls: [ApiCall<T>] = []
let transactionId = Store.randomId()
for insert in batch.inserts {
let call = try self._createCall(.post, instance: insert, transactionId: transactionId)
self._prepareCall(apiCall: call)
let call = try await self._callForInstance(insert, method: .post, transactionId: transactionId)
apiCalls.append(call)
}
for update in batch.updates {
let call = try self._createCall(.put, instance: update, transactionId: transactionId)
self._prepareCall(apiCall: call)
let call = try await self._callForInstance(update, method: .put, transactionId: transactionId)
apiCalls.append(call)
}
for delete in batch.deletes {
let call = try self._createCall(.delete, instance: delete, transactionId: transactionId)
self._prepareCall(apiCall: call)
let call = try await self._callForInstance(delete, method: .delete, transactionId: transactionId)
apiCalls.append(call)
}
return try await self._executeApiCalls(apiCalls)
}
/// Initiates the process of sending the data with the server
fileprivate func _sendServerRequest<V: Decodable>(_ method: HTTPMethod, instance: T? = nil) async throws -> V? {
if let apiCall = try await self._call(method: method, instance: instance) {
return try await self._prepareAndSendCall(apiCall)
} else {
return nil
}
}
// /// Initiates the process of sending the data with the server
//<<<<<<< HEAD
// fileprivate func _sendServerRequest<V: Decodable>(_ method: HTTPMethod, instance: T? = nil) async throws -> V? {
// if let apiCall = try await self._call(method: method, instance: instance) {
// return try await self._prepareAndSendCall(apiCall)
//=======
// fileprivate func _synchronize<V: Decodable>(_ instance: T, method: HTTPMethod) async throws -> V? {
// if let apiCall = try await self._callForInstance(instance, method: method) {
// return try await self._executeApiCall(apiCall)
//>>>>>>> main
// } else {
// return nil
// }
// }
fileprivate func _prepareAndSendCall<V: Decodable>(_ apiCall: ApiCall<T>) async throws -> V? {
self._prepareCall(apiCall: apiCall)

@ -331,12 +331,12 @@ public class Services {
/// - Parameters:
/// - apiCall: An ApiCall instance to configure the returned request
fileprivate func _syncGetRequest<T: SyncedStorable>(from apiCall: ApiCall<T>) throws -> URLRequest {
var urlString = baseURL + "data/"
if let urlParameters = apiCall.formattedURLParameters() {
urlString.append(urlParameters)
}
guard let url = URL(string: urlString) else {
throw ServiceError.urlCreationError(url: urlString)
}
@ -344,14 +344,35 @@ public class Services {
var request = URLRequest(url: url)
request.httpMethod = HTTPMethod.get.rawValue
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
if self._isTokenRequired(type: T.self, method: apiCall.method) {
let token = try self.keychainStore.getValue()
request.addValue("Token \(token)", forHTTPHeaderField: "Authorization")
}
return request
}
//=======
//
// /// Executes a PUT request
// public func put<T: Storable>(_ instance: T) async throws -> T {
// var postRequest = try self._putRequest(type: T.self, id: instance.stringId)
// postRequest.httpBody = try jsonEncoder.encode(instance)
// return try await self._runRequest(postRequest)
// }
//
// public func delete<T: Storable>(_ instance: T) async throws -> T {
// let deleteRequest = try self._deleteRequest(type: T.self, id: instance.stringId)
// return try await self._runRequest(deleteRequest)
// }
//
// /// Executes an ApiCall
// func runApiCall<T: Storable, V: Decodable>(_ apiCall: ApiCall<T>) async throws -> V {
// let request = try self._request(from: apiCall)
// print("HTTP \(request.httpMethod ?? "") : id = \(apiCall.dataId)")
// return try await self._runRequest(request, apiCall: apiCall)
//>>>>>>> main
// }
/// Returns the URLRequest for an ApiCall
/// - Parameters:

Loading…
Cancel
Save