From 22753ae2308d72cbb33ccdb9bafbd58f879193d6 Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 16 Sep 2024 10:31:56 +0200 Subject: [PATCH] first draft --- LeStorage/Services.swift | 86 ++++++++++++++++++++++++++++++++++-- LeStorage/Utils/Errors.swift | 8 ---- 2 files changed, 82 insertions(+), 12 deletions(-) diff --git a/LeStorage/Services.swift b/LeStorage/Services.swift index 84b9c50..60caa94 100644 --- a/LeStorage/Services.swift +++ b/LeStorage/Services.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(_ 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(_ apiCall: ApiCall) 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(from apiCall: ApiCall) 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: Encodable { + var operation: String + var modelName: String + var data: T +} + struct ErrorMessage { let error: String let domain: String diff --git a/LeStorage/Utils/Errors.swift b/LeStorage/Utils/Errors.swift index 2eb0d9f..474a97b 100644 --- a/LeStorage/Utils/Errors.swift +++ b/LeStorage/Utils/Errors.swift @@ -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) }