From 4c415365a2ab6bfb10ca9ce00c0a3e9ed91ddab8 Mon Sep 17 00:00:00 2001 From: Victor Bodinaud Date: Fri, 12 Jan 2024 20:00:31 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20GET,=20POST=20&=20DELETE=20me?= =?UTF-8?q?thods?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 8 +++ Package.swift | 27 ++++++++ Sources/Hermes/Hermes.swift | 103 ++++++++++++++++++++++++++++ Tests/HermesTests/HermesTests.swift | 12 ++++ 4 files changed, 150 insertions(+) create mode 100644 .gitignore create mode 100644 Package.swift create mode 100644 Sources/Hermes/Hermes.swift create mode 100644 Tests/HermesTests/HermesTests.swift diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0023a53 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +/.build +/Packages +xcuserdata/ +DerivedData/ +.swiftpm/configuration/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..66cd907 --- /dev/null +++ b/Package.swift @@ -0,0 +1,27 @@ +// swift-tools-version: 5.9 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "Hermes", + platforms: [ + .macOS(.v13), + .iOS(.v15) + ], + products: [ + // Products define the executables and libraries a package produces, making them visible to other packages. + .library( + name: "Hermes", + targets: ["Hermes"]), + ], + targets: [ + // Targets are the basic building blocks of a package, defining a module or a test suite. + // Targets can depend on other targets in this package and products from dependencies. + .target( + name: "Hermes"), + .testTarget( + name: "HermesTests", + dependencies: ["Hermes"]), + ] +) diff --git a/Sources/Hermes/Hermes.swift b/Sources/Hermes/Hermes.swift new file mode 100644 index 0000000..eb99ccc --- /dev/null +++ b/Sources/Hermes/Hermes.swift @@ -0,0 +1,103 @@ +// +// hermes.swift +// +// Created by victor bodinaud on 11/01/2024. +// + +import Foundation + +public enum NetworkError: Error { + case badRequest + case serverError(String) + case decodingError + case invalidResponse +} + +extension NetworkError: LocalizedError { + public var errorDescription: String? { + switch self { + case .badRequest: + return NSLocalizedString("Unable to perform request", comment: "badRequestError") + case .serverError(let errorMessage): + print(errorMessage) + return NSLocalizedString(errorMessage, comment: "serverError") + case .decodingError: + return NSLocalizedString("Unable to decode successfully", comment: "decodingError") + case .invalidResponse: + return NSLocalizedString("Invalid response", comment: "invalidResponse") + } + } +} + +public enum HTTPMethod { + case get([URLQueryItem]) + case post(Data?) + case delete + + var name: String { + switch self { + case .get: + return "GET" + case .post: + return "POST" + case .delete: + return "DELETE" + } + } +} + +public struct Resource { + let url: URL + var method: HTTPMethod = .get([]) + var modelType: T.Type + + public init(url: URL, method: HTTPMethod, modelType: T.Type) { + self.url = url + self.method = method + self.modelType = modelType + } +} + +public struct Hermes { + + public init() { } + + public func load(_ resource: Resource) async throws -> T { + + var request = URLRequest(url: resource.url) + + switch resource.method { + case .get(let queryItems): + var components = URLComponents(url: resource.url, resolvingAgainstBaseURL: false) + components?.queryItems = queryItems + guard let url = components?.url else { + throw NetworkError.badRequest + } + + request = URLRequest(url: url) + + case .post(let data): + request.httpMethod = resource.method.name + request.httpBody = data + + case .delete: + request.httpMethod = resource.method.name + } + + let configuration = URLSessionConfiguration.default + configuration.httpAdditionalHeaders = ["Content-Type": "application/json"] + let session = URLSession(configuration: configuration) + + let (data, response) = try await session.data(for: request) + + guard let _ = response as? HTTPURLResponse else { + throw NetworkError.invalidResponse + } + + guard let result = try? JSONDecoder().decode(resource.modelType, from: data) else { + throw NetworkError.decodingError + } + + return result + } +} diff --git a/Tests/HermesTests/HermesTests.swift b/Tests/HermesTests/HermesTests.swift new file mode 100644 index 0000000..b1cef3e --- /dev/null +++ b/Tests/HermesTests/HermesTests.swift @@ -0,0 +1,12 @@ +import XCTest +@testable import Hermes + +final class HermesTests: XCTestCase { + func testExample() throws { + // XCTest Documentation + // https://developer.apple.com/documentation/xctest + + // Defining Test Cases and Test Methods + // https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods + } +}