first draft

sync
Laurent 1 year ago
parent ecc4791342
commit 22753ae230
  1. 86
      LeStorage/Services.swift
  2. 8
      LeStorage/Utils/Errors.swift

@ -7,6 +7,15 @@
import Foundation
public enum ServiceError: Error {
case urlCreationError(url: String)
case cantConvertToUUID(id: String)
case missingUserName
case missingUserId
case responseError(response: String)
case cantDecodeData(content: String)
}
public enum HTTPMethod: String, CaseIterable, Codable {
case get = "GET"
case post = "POST"
@ -206,6 +215,30 @@ public class Services {
return try self._baseRequest(servicePath: call.path, method: call.method, requiresToken: call.requiresToken)
}
/// Returns a base request for a path and method
/// - Parameters:
/// - servicePath: the path to add to the API base URL
/// - method: the HTTP method to execute
/// - requiresToken: An optional boolean to indicate if the token is required
/// - identifier: an optional StoreIdentifier that allows to filter GET requests with the StoreIdentifier values
fileprivate func _baseSyncRequest(method: HTTPMethod, payload: Encodable) throws -> URLRequest {
let urlString = baseURL + "data/"
guard let url = URL(string: urlString) else {
throw ServiceError.urlCreationError(url: urlString)
}
var request = URLRequest(url: url)
request.httpMethod = method.rawValue
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try jsonEncoder.encode(payload)
let token = try self.keychainStore.getValue()
request.addValue("Token \(token)", forHTTPHeaderField: "Authorization")
return request
}
/// Returns a base request for a path and method
/// - Parameters:
/// - servicePath: the path to add to the API base URL
@ -240,9 +273,15 @@ public class Services {
/// Executes a POST request
public func post<T: Storable>(_ instance: T) async throws -> T {
var postRequest = try self._postRequest(type: T.self)
postRequest.httpBody = try jsonEncoder.encode(instance)
return try await self._runRequest(postRequest)
let method: HTTPMethod = .post
let payload = SyncPayload(operation: method.rawValue, modelName: T.resourceName(), data: instance)
let syncRequest = try self._baseSyncRequest(method: .post, payload: payload)
return try await self._runRequest(syncRequest)
// var postRequest = try self._postRequest(type: T.self)
// postRequest.httpBody = try jsonEncoder.encode(instance)
// return try await self._runRequest(postRequest)
}
/// Executes a PUT request
@ -254,11 +293,43 @@ public class Services {
/// Executes an ApiCall
func runApiCall<T: Storable>(_ apiCall: ApiCall<T>) async throws -> T {
let request = try self._request(from: apiCall)
let request = try self._syncRequest(from: apiCall)
print("HTTP \(request.httpMethod ?? "") : id = \(apiCall.dataId)")
return try await self._runRequest(request, apiCallId: apiCall.id)
}
/// Returns the URLRequest for an ApiCall
/// - Parameters:
/// - apiCall: An ApiCall instance to configure the returned request
fileprivate func _syncRequest<T: Storable>(from apiCall: ApiCall<T>) throws -> URLRequest {
let urlString = baseURL + "data/"
guard let url = URL(string: urlString) else {
throw ServiceError.urlCreationError(url: urlString)
}
guard let bodyData = apiCall.body.data(using: .utf8) else {
throw ServiceError.cantDecodeData(content: apiCall.body)
}
var request = URLRequest(url: url)
request.httpMethod = HTTPMethod.post.rawValue
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
// moyennement fan de decoder pour recoder derriere
let data = try jsonDecoder.decode(T.self, from: bodyData)
let payload = SyncPayload(operation: apiCall.method.rawValue, modelName: T.resourceName(), data: data)
request.httpBody = try jsonEncoder.encode(payload)
if self._isTokenRequired(type: T.self, method: apiCall.method) {
let token = try self.keychainStore.getValue()
request.addValue("Token \(token)", forHTTPHeaderField: "Authorization")
}
return request
}
/// Returns the URLRequest for an ApiCall
/// - Parameters:
/// - apiCall: An ApiCall instance to configure the returned request
@ -280,6 +351,7 @@ public class Services {
return request
}
/// Returns the URL corresponding to the ApiCall
/// - Parameters:
@ -460,6 +532,12 @@ public class Services {
}
struct SyncPayload<T: Encodable>: Encodable {
var operation: String
var modelName: String
var data: T
}
struct ErrorMessage {
let error: String
let domain: String

@ -20,14 +20,6 @@ public class ErrorUtils {
}
public enum ServiceError: Error {
case urlCreationError(url: String)
case cantConvertToUUID(id: String)
case missingUserName
case missingUserId
case responseError(response: String)
}
public enum UUIDError: Error {
case cantConvertString(string: String)
}

Loading…
Cancel
Save