From 48f6b508a82ae2c06f3ed1b90412941bb17d9a64 Mon Sep 17 00:00:00 2001 From: Rudrank Date: Sun, 31 Oct 2021 20:41:44 +0530 Subject: [PATCH] Update for backwards async/await --- Sources/QuoteKit/APIs/AuthorAPIs.swift | 4 +-- Sources/QuoteKit/APIs/QuoteAPIs.swift | 20 +++++------ Sources/QuoteKit/APIs/SearchAPIs.swift | 36 ++++++++----------- Sources/QuoteKit/APIs/TagAPIs.swift | 6 ++-- .../QuoteKit/Endpoint/QuotableURLHost.swift | 2 ++ .../QuoteKit/Extension/QuoteFetchError.swift | 13 +++++++ Sources/QuoteKit/Extension/URLSession.swift | 33 +++++++++++++++++ Sources/QuoteKit/QuoteKit.swift | 6 ---- .../Authors/AuthorsDataTests.swift | 6 ++-- .../Quotes/QuotesDataTests.swift | 6 ++-- .../Tags/QuoteKitTagsDataTests.swift | 2 +- 11 files changed, 85 insertions(+), 49 deletions(-) create mode 100644 Sources/QuoteKit/Extension/QuoteFetchError.swift create mode 100644 Sources/QuoteKit/Extension/URLSession.swift diff --git a/Sources/QuoteKit/APIs/AuthorAPIs.swift b/Sources/QuoteKit/APIs/AuthorAPIs.swift index a6fb1ca..503b90e 100644 --- a/Sources/QuoteKit/APIs/AuthorAPIs.swift +++ b/Sources/QuoteKit/APIs/AuthorAPIs.swift @@ -12,7 +12,7 @@ public extension QuoteKit { QuotableEndpoint(.authorProfile(size, slug), host: .images).url } - @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) + static func author(id: String) async throws -> Author? { try await execute(with: QuotableEndpoint(.author(id))) } @@ -21,7 +21,7 @@ public extension QuoteKit { execute(with: QuotableEndpoint(.author(id)), completion: completion) } - @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) + static func authors(slugs: [String]? = nil, sortBy: AuthorsAndTagsSortType? = nil, order: QuotableListOrder? = nil, diff --git a/Sources/QuoteKit/APIs/QuoteAPIs.swift b/Sources/QuoteKit/APIs/QuoteAPIs.swift index 590ca4d..f733a07 100644 --- a/Sources/QuoteKit/APIs/QuoteAPIs.swift +++ b/Sources/QuoteKit/APIs/QuoteAPIs.swift @@ -8,17 +8,17 @@ import Foundation public extension QuoteKit { - @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) + static func quote(id: String) async throws -> Quote? { try await execute(with: QuotableEndpoint(.quote(id))) } - @available(iOS 13.0, macOS 11.0, tvOS 13.0, watchOS 6.0, *) + static func quote(id: String, completion: @escaping (Result) -> ()) { execute(with: QuotableEndpoint(.quote(id)), completion: completion) } - @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) + static func quotes(minLength: Int? = nil, maxLength: Int? = nil, tags: [String]? = nil, @@ -42,7 +42,7 @@ public extension QuoteKit { return try await execute(with: QuotableEndpoint(.quotes, queryItems: queryItems)) } - @available(iOS 13.0, macOS 11.0, tvOS 13.0, watchOS 6.0, *) + static func quotes(minLength: Int? = nil, maxLength: Int? = nil, tags: [String]? = nil, @@ -67,7 +67,7 @@ public extension QuoteKit { return execute(with: QuotableEndpoint(.quotes, queryItems: queryItems), completion: completion) } - @available(iOS 13.0, macOS 11.0, tvOS 13.0, watchOS 6.0, *) + static private func quotesParameter(minLength: Int? = nil, maxLength: Int? = nil, tags: [String]? = nil, @@ -110,17 +110,17 @@ public extension QuoteKit { return queryItems } - @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) + static func quotes() async throws -> Quotes? { try await execute(with: QuotableEndpoint(.quotes)) } - @available(iOS 13.0, macOS 11.0, tvOS 13.0, watchOS 6.0, *) + static func quotes(completion: @escaping (Result) -> ()) { execute(with: QuotableEndpoint(.quotes), completion: completion) } - @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) + static func randomQuote(minLength: Int? = nil, maxLength: Int? = nil, tags: [String]? = nil, @@ -136,7 +136,7 @@ public extension QuoteKit { return try await execute(with: QuotableEndpoint(.randomQuote, queryItems: queryItems)) } - @available(iOS 13.0, macOS 11.0, tvOS 13.0, watchOS 6.0, *) + static func randomQuote(minLength: Int? = nil, maxLength: Int? = nil, tags: [String]? = nil, @@ -153,7 +153,7 @@ public extension QuoteKit { return execute(with: QuotableEndpoint(.randomQuote, queryItems: queryItems), completion: completion) } - @available(iOS 13.0, macOS 11.0, tvOS 13.0, watchOS 6.0, *) + static private func randomQuoteParameters(minLength: Int? = nil, maxLength: Int? = nil, tags: [String]? = nil, diff --git a/Sources/QuoteKit/APIs/SearchAPIs.swift b/Sources/QuoteKit/APIs/SearchAPIs.swift index 6bf8f9b..f10d21a 100644 --- a/Sources/QuoteKit/APIs/SearchAPIs.swift +++ b/Sources/QuoteKit/APIs/SearchAPIs.swift @@ -8,37 +8,18 @@ import Foundation public extension QuoteKit { - @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) static func searchQuotes(for query: String, limit: Int = 20, page: Int = 1) async throws -> Quotes? { try await search(path: .searchQuotes, query: query, limit: limit, page: page) } - @available(iOS 13.0, macOS 11.0, tvOS 13.0, watchOS 6.0, *) - static func searchQuotes(for query: String, - limit: Int = 20, - page: Int = 1, - completion: @escaping (Result) -> ()) { - search(path: .searchQuotes, query: query, completion: completion) - } - - @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) static func searchAuthors(for query: String, limit: Int = 20, page: Int = 1) async throws -> Authors? { try await search(path: .searchAuthors, query: query, limit: limit, page: page) } - @available(iOS 13.0, macOS 11.0, tvOS 13.0, watchOS 6.0, *) - static func searchAuthors(for query: String, - limit: Int = 20, - page: Int = 1, - completion: @escaping (Result) -> ()) { - search(path: .searchAuthors, query: query, completion: completion) - } - - @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) private static func search(path: QuotableEndpointPath, query: String, limit: Int = 20, @@ -49,7 +30,20 @@ public extension QuoteKit { return try await execute(with: QuotableEndpoint(path, queryItems: queryItems)) } - @available(iOS 13.0, macOS 11.0, tvOS 13.0, watchOS 6.0, *) + static func searchQuotes(for query: String, + limit: Int = 20, + page: Int = 1, + completion: @escaping (Result) -> ()) { + search(path: .searchQuotes, query: query, completion: completion) + } + + static func searchAuthors(for query: String, + limit: Int = 20, + page: Int = 1, + completion: @escaping (Result) -> ()) { + search(path: .searchAuthors, query: query, completion: completion) + } + private static func search(path: QuotableEndpointPath, query: String, limit: Int = 20, @@ -61,7 +55,7 @@ public extension QuoteKit { return execute(with: QuotableEndpoint(path, queryItems: queryItems), completion: completion) } - @available(iOS 13.0, macOS 11.0, tvOS 13.0, watchOS 6.0, *) + private static func searchParameters(query: String, limit: Int = 20, page: Int = 1) -> [URLQueryItem] { diff --git a/Sources/QuoteKit/APIs/TagAPIs.swift b/Sources/QuoteKit/APIs/TagAPIs.swift index 71e8a25..180bd2e 100644 --- a/Sources/QuoteKit/APIs/TagAPIs.swift +++ b/Sources/QuoteKit/APIs/TagAPIs.swift @@ -8,7 +8,7 @@ import Foundation public extension QuoteKit { - @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) + static func tags(sortBy: AuthorsAndTagsSortType? = nil, order: QuotableListOrder? = nil) async throws -> Tags? { @@ -17,7 +17,7 @@ public extension QuoteKit { return try await execute(with: QuotableEndpoint(.tags, queryItems: queryItems)) } - @available(iOS 13.0, macOS 11.0, tvOS 13.0, watchOS 6.0, *) + static func tags(sortBy: AuthorsAndTagsSortType? = nil, order: QuotableListOrder? = nil, completion: @escaping (Result) -> ()) { @@ -27,7 +27,7 @@ public extension QuoteKit { return execute(with: QuotableEndpoint(.tags, queryItems: queryItems), completion: completion) } - @available(iOS 13.0, macOS 11.0, tvOS 13.0, watchOS 6.0, *) + private static func tagsParameters(sortBy: AuthorsAndTagsSortType? = nil, order: QuotableListOrder? = nil) -> [URLQueryItem] { diff --git a/Sources/QuoteKit/Endpoint/QuotableURLHost.swift b/Sources/QuoteKit/Endpoint/QuotableURLHost.swift index ac23937..5852e57 100644 --- a/Sources/QuoteKit/Endpoint/QuotableURLHost.swift +++ b/Sources/QuoteKit/Endpoint/QuotableURLHost.swift @@ -7,6 +7,8 @@ import Foundation +/// Learnt this way of creating a URLHost from this article - https://www.swiftbysundell.com/articles/testing-networking-logic-in-swift/ + struct QuotableURLHost: RawRepresentable { var rawValue: String } diff --git a/Sources/QuoteKit/Extension/QuoteFetchError.swift b/Sources/QuoteKit/Extension/QuoteFetchError.swift new file mode 100644 index 0000000..79c06d6 --- /dev/null +++ b/Sources/QuoteKit/Extension/QuoteFetchError.swift @@ -0,0 +1,13 @@ +// +// QuoteFetchError.swift +// +// +// Created by Rudrank Riyam on 31/10/21. +// + +import Foundation + +enum QuoteFetchError: Error { + case invalidURL + case missingData +} diff --git a/Sources/QuoteKit/Extension/URLSession.swift b/Sources/QuoteKit/Extension/URLSession.swift new file mode 100644 index 0000000..ca3a35c --- /dev/null +++ b/Sources/QuoteKit/Extension/URLSession.swift @@ -0,0 +1,33 @@ +// +// URLSession.swift +// +// +// Created by Rudrank Riyam on 31/10/21. +// + +import Foundation + +// Taken from Swift by Sundell - +// (Making async system APIs backward compatible)[https://www.swiftbysundell.com/articles/making-async-system-apis-backward-compatible/] +@available(iOS, deprecated: 15.0, message: "Use the built-in API instead") +extension URLSession { + func data(from url: URL) async throws -> (Data, URLResponse) { + try await withCheckedThrowingContinuation { continuation in + let task = self.dataTask(with: url) { data, response, error in + if let error = error { + return continuation.resume(throwing: error) + } + + guard let response = response else { + return continuation.resume(throwing: URLError(.badServerResponse)) + } + + guard let data = data else { + return continuation.resume(throwing: QuoteFetchError.missingData) + } + continuation.resume(returning: (data, response)) + } + task.resume() + } + } +} diff --git a/Sources/QuoteKit/QuoteKit.swift b/Sources/QuoteKit/QuoteKit.swift index ba729a2..698eff6 100644 --- a/Sources/QuoteKit/QuoteKit.swift +++ b/Sources/QuoteKit/QuoteKit.swift @@ -7,13 +7,7 @@ import Foundation -enum QuoteFetchError: Error { - case invalidURL - case missingData -} - public struct QuoteKit { - @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) static func execute(with endpoint: QuotableEndpoint) async throws -> Model { let url = endpoint.url diff --git a/Tests/QuoteKitTests/Authors/AuthorsDataTests.swift b/Tests/QuoteKitTests/Authors/AuthorsDataTests.swift index d6739c6..4bea02a 100644 --- a/Tests/QuoteKitTests/Authors/AuthorsDataTests.swift +++ b/Tests/QuoteKitTests/Authors/AuthorsDataTests.swift @@ -9,7 +9,7 @@ import XCTest @testable import QuoteKit final class AuthorsDataTests: XCTestCase { - @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) + func testAuthorMatchesParticularID() async throws { do { let author = try await QuoteKit.author(id: "XYxYtSeixS-o") @@ -26,7 +26,7 @@ final class AuthorsDataTests: XCTestCase { } } - @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) + func testAuthorsReturnsManyAuthors() async throws { do { let authors = try await QuoteKit.authors() @@ -38,7 +38,7 @@ final class AuthorsDataTests: XCTestCase { } } - @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) + func testAuthorsSearchForParticularQuery() async throws { do { let authors = try await QuoteKit.searchAuthors(for: "aesop") diff --git a/Tests/QuoteKitTests/Quotes/QuotesDataTests.swift b/Tests/QuoteKitTests/Quotes/QuotesDataTests.swift index e6493e2..c1396c3 100644 --- a/Tests/QuoteKitTests/Quotes/QuotesDataTests.swift +++ b/Tests/QuoteKitTests/Quotes/QuotesDataTests.swift @@ -9,7 +9,7 @@ import XCTest @testable import QuoteKit final class QuotesDataTests: XCTestCase { - @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) + func testQuoteForParticularIDAsync() async throws { do { let quote = try await QuoteKit.quote(id: "2xpHvSOQMD") @@ -59,7 +59,7 @@ final class QuotesDataTests: XCTestCase { XCTAssertEqual(unwrappedQuote.dateModified, "2021-06-18") } - @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) + func testQuotesReturnsManyQuotesAsync() async throws { do { let quotes = try await QuoteKit.quotes() @@ -95,7 +95,7 @@ final class QuotesDataTests: XCTestCase { XCTAssertGreaterThan(unwrappedQuotes.count, 1) } - @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) + func testQuotesSearchForParticularQueryAsync() async throws { do { let quotes = try await QuoteKit.searchQuotes(for: "biggest room") diff --git a/Tests/QuoteKitTests/Tags/QuoteKitTagsDataTests.swift b/Tests/QuoteKitTests/Tags/QuoteKitTagsDataTests.swift index 32207cd..83e322a 100644 --- a/Tests/QuoteKitTests/Tags/QuoteKitTagsDataTests.swift +++ b/Tests/QuoteKitTests/Tags/QuoteKitTagsDataTests.swift @@ -9,7 +9,7 @@ import XCTest @testable import QuoteKit final class QuoteKitTagsDataTests: XCTestCase { - @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) + func testTagsReturnsManyTags() async throws { do { let tags = try await QuoteKit.tags()