From 2b116c10bcdc2c3ef53e10912fc93e573f07e90a Mon Sep 17 00:00:00 2001 From: Jason R Tibbetts Date: Sat, 30 Jul 2022 22:59:26 -0400 Subject: [PATCH] #51 [refactor] Replaced Promises in Discogs & DiscogsClient with Swift 5.5 async/await. --- Source/Discogs.swift | 45 ++--- Source/DiscogsClient.swift | 104 +++++----- SwiftDiscogs.xcodeproj/project.pbxproj | 4 +- .../xcshareddata/swiftpm/Package.resolved | 186 +++++++++--------- 4 files changed, 168 insertions(+), 171 deletions(-) diff --git a/Source/Discogs.swift b/Source/Discogs.swift index d658b2e..8e73f46 100644 --- a/Source/Discogs.swift +++ b/Source/Discogs.swift @@ -29,14 +29,11 @@ public protocol Discogs { var isSignedIn: Bool { get } - func authorize(presentingViewController: UIViewController, - callbackUrlString: String) async -> OAuthSwiftCredential - func signOut() - func userIdentity() async -> UserIdentity + func userIdentity() async throws -> UserIdentity - func userProfile(userName: String) async -> UserProfile + func userProfile(userName: String) async throws -> UserProfile // MARK: - Database @@ -46,35 +43,35 @@ public protocol Discogs { /// - parameter identifier: The numeric ID of the artist. /// - parameter completion: The completion block that will be applied to /// the artist, if found, or the error, if one was thrown. - func artist(identifier: Int) async -> Artist + func artist(identifier: Int) async throws -> Artist /// Look up the releases by the specified artist's ID. /// /// - parameter artistId: The numeric ID of the artist. /// - parameter completion: The completion block that will be applied to /// all of the artist's releases, or to the error, if one was thrown. - func releases(forArtist artistId: Int) async -> ReleaseSummaries + func releases(forArtist artistId: Int) async throws -> ReleaseSummaries /// Look up the record label by its ID. /// /// - parameter identifier: The label's unique ID. /// - parameter completion: The completion block that will be applied to /// the label, or to the error, if one was thrown. - func label(identifier: Int) async -> RecordLabel + func label(identifier: Int) async throws -> RecordLabel /// Look up the record label's releases by the label's name. /// /// - parameter labelId: The label's unique ID. /// - parameter completion: The completion block that will be applied to /// all of the label's releases, or to the error, if one was thrown. - func releases(forLabel labelId: Int) async -> ReleaseSummaries + func releases(forLabel labelId: Int) async throws -> ReleaseSummaries /// Process a master release with a specified ID. /// /// - parameter identifier: The unique ID of the master release. /// - parameter completion: The completion block that will be applied to /// the master release, or to the error, if one was thrown. - func masterRelease(identifier: Int) async -> MasterRelease + func masterRelease(identifier: Int) async throws -> MasterRelease /// Process all of the release versions that belong to a master release. /// @@ -82,40 +79,40 @@ public protocol Discogs { /// - parameter pageNumber: The number of the page (i.e. batch). func releasesForMasterRelease(_ identifier: Int, pageNumber: Int, - resultsPerPage: Int) async -> MasterReleaseVersions + resultsPerPage: Int) async throws -> MasterReleaseVersions /// Process a release with a specified ID. /// /// - parameter identifier: The unique ID of the release. /// - parameter completion: The completion block that will be applied to /// the release, or to the error, if one was thrown. - func release(identifier: Int) async -> Release + func release(identifier: Int) async throws -> Release // MARK: - Collections - func customCollectionFields(forUserName: String) async -> CollectionCustomFields - func collectionValue(forUserName: String) async -> CollectionValue - func collectionFolders(forUserName: String) async -> CollectionFolders + func customCollectionFields(forUserName: String) async throws -> CollectionCustomFields + func collectionValue(forUserName: String) async throws -> CollectionValue + func collectionFolders(forUserName: String) async throws -> CollectionFolders func collectionFolderInfo(forFolderID: Int, - userName: String) async -> CollectionFolder + userName: String) async throws -> CollectionFolder func createFolder(named: String, - forUserName: String) async -> CollectionFolder + forUserName: String) async throws -> CollectionFolder func edit(_ folder: CollectionFolder, - forUserName: String) async -> CollectionFolder + forUserName: String) async throws -> CollectionFolder func collectionItems(inFolderID: Int, userName: String, pageNumber: Int, - resultsPerPage: Int) async -> CollectionFolderItems + resultsPerPage: Int) async throws -> CollectionFolderItems func addItem(_ itemId: Int, toFolderID: Int, - userName: String) async -> CollectionItemInfo + userName: String) async throws -> CollectionItemInfo // MARK: - Search func search(for queryString: String, - type: String) async -> SearchResults + type: String) async throws -> SearchResults - func search(forArtist artistName: String) async -> SearchResults + func search(forArtist artistName: String) async throws -> SearchResults } public enum DiscogsSearchType: String { @@ -126,8 +123,8 @@ public enum DiscogsSearchType: String { public extension Discogs { - func search(forArtist artistName: String) async -> SearchResults { - return await search(for: artistName, type: DiscogsSearchType.artist.rawValue) + func search(forArtist artistName: String) async throws -> SearchResults { + return try await search(for: artistName, type: DiscogsSearchType.artist.rawValue) } } diff --git a/Source/DiscogsClient.swift b/Source/DiscogsClient.swift index c4e4e75..f9a5569 100644 --- a/Source/DiscogsClient.swift +++ b/Source/DiscogsClient.swift @@ -40,125 +40,127 @@ open class DiscogsClient: OAuth1JSONClient, Discogs { // MARK: - JSONClient - open override func get(path: String, - headers: JSONClient.Headers = Headers(), - parameters: JSONClient.Parameters = Parameters()) - async -> T where T: Decodable, T: Encodable { + open override func get(path: String, + headers: JSONClient.Headers = Headers(), + parameters: JSONClient.Parameters = Parameters()) async throws -> T { print("GET for \(path); headers: \(headers); params: \(parameters)") debugPrint(path, headers, parameters) - return super.get(path: path, headers: headers, parameters: parameters) + + return try await super.get(path: path, headers: headers, parameters: parameters) } // MARK: - AuthorizedJSONClient - open override func authorizedGet(path: String, - headers: AuthorizedJSONClient.Headers = Headers(), - parameters: AuthorizedJSONClient.Parameters = Parameters()) - async -> T where T: Decodable, T: Encodable { + open override func authorizedGet(path: String, + headers: AuthorizedJSONClient.Headers = Headers(), + parameters: AuthorizedJSONClient.Parameters = Parameters()) async throws -> T { print("Authorized GET for \(path); headers: \(headers); params: \(parameters)") debugPrint(path, headers, parameters) - return super.authorizedGet(path: path, headers: headers, parameters: parameters) + + return try await super.authorizedGet(path: path, headers: headers, parameters: parameters) } // MARK: - Authorization & User Identity - public func userIdentity() async -> UserIdentity { - return await authorizedGet(path: "/oauth/identity", headers: headers) + public func userIdentity() async throws -> UserIdentity { + return try await authorizedGet(path: "/oauth/identity", headers: headers) } - public func userProfile(userName: String) async -> UserProfile { - return await authorizedGet(path: "/users/\(userName)", headers: headers) + public func userProfile(userName: String) async throws -> UserProfile { + return try await authorizedGet(path: "/users/\(userName)", headers: headers) } // MARK: - Database - public func artist(identifier: Int) async -> Artist { - return await get(path: "/artists/\(identifier)", headers: headers) + public func artist(identifier: Int) async throws -> Artist { + return try await get(path: "/artists/\(identifier)", headers: headers) } - public func label(identifier: Int) async -> RecordLabel { - return await get(path: "/labels/\(identifier)", headers: headers) + public func label(identifier: Int) async throws -> RecordLabel { + return try await get(path: "/labels/\(identifier)", headers: headers) } - public func masterRelease(identifier: Int) async -> MasterRelease { - return await get(path: "/masters/\(identifier)", headers: headers) + public func masterRelease(identifier: Int) async throws -> MasterRelease { + return try await get(path: "/masters/\(identifier)", headers: headers) } - public func release(identifier: Int) async -> Release { - return await get(path: "/releases/\(identifier)", headers: headers) + public func release(identifier: Int) async throws -> Release { + return try await get(path: "/releases/\(identifier)", headers: headers) } - public func releases(forArtist artistId: Int) async -> ReleaseSummaries { - return await get(path: "/artists/\(artistId)/releases", headers: headers) + public func releases(forArtist artistId: Int) async throws -> ReleaseSummaries { + return try await get(path: "/artists/\(artistId)/releases", headers: headers) } - public func releases(forLabel labelId: Int) async -> ReleaseSummaries { - return await get(path: "/labels/\(labelId)/releases", headers: headers) + public func releases(forLabel labelId: Int) async throws -> ReleaseSummaries { + return try await get(path: "/labels/\(labelId)/releases", headers: headers) } public func releasesForMasterRelease(_ identifier: Int, pageNumber: Int = 1, - resultsPerPage: Int = 50) async -> MasterReleaseVersions { + resultsPerPage: Int = 50) async throws -> MasterReleaseVersions { // turn the pageNumber and resultsPerPage into query parameters - return await get(path: "/masters/\(identifier)/versions", - headers: headers, - parameters: ["per_page": "\(resultsPerPage)", "page": "\(pageNumber)"]) + return try await get(path: "/masters/\(identifier)/versions", + headers: headers, + parameters: ["per_page": "\(resultsPerPage)", "page": "\(pageNumber)"]) } // MARK: - Collections - public func customCollectionFields(forUserName userName: String) async -> CollectionCustomFields { - return await authorizedGet(path: "/users/\(userName)/collection/fields", headers: headers) + public func customCollectionFields(forUserName userName: String) async throws -> CollectionCustomFields { + return try await authorizedGet(path: "/users/\(userName)/collection/fields", headers: headers) } - public func collectionValue(forUserName userName: String) async -> CollectionValue { - return await authorizedGet(path: "/users/\(userName)/collection/value", headers: headers) + public func collectionValue(forUserName userName: String) async throws -> CollectionValue { + return try await authorizedGet(path: "/users/\(userName)/collection/value", headers: headers) } - public func collectionFolders(forUserName userName: String) async -> CollectionFolders { - return await authorizedGet(path: "/users/\(userName)/collection/folders", headers: headers) + public func collectionFolders(forUserName userName: String) async throws -> CollectionFolders { + return try await authorizedGet(path: "/users/\(userName)/collection/folders", headers: headers) } public func collectionFolderInfo(forFolderID folderID: Int, - userName: String) async -> CollectionFolder { - return await authorizedGet(path: "/users/\(userName)/collection/folders/\(folderID)", headers: headers) + userName: String) async throws -> CollectionFolder { + return try await authorizedGet(path: "/users/\(userName)/collection/folders/\(folderID)", headers: headers) } public func createFolder(named folderName: String, - forUserName userName: String) async -> CollectionFolder { - return authorizedPost(path: "/users/\(userName)/collection/folders/\(folderName)", headers: headers) + forUserName userName: String) async throws -> CollectionFolder { + return try await authorizedPost(path: "/users/\(userName)/collection/folders/\(folderName)", headers: headers) } public func edit(_ folder: CollectionFolder, - forUserName userName: String) async -> CollectionFolder { - return Promise { _ in - } + forUserName userName: String) async throws -> CollectionFolder { + throw DiscogsError.unknown(nil) } public func collectionItems(inFolderID folderID: Int, userName: String, pageNumber: Int = 1, - resultsPerPage: Int = 50) async -> CollectionFolderItems { - return await authorizedGet(path: "/users/\(userName)/collection/folders/\(folderID)/releases", + resultsPerPage: Int = 50) async throws -> CollectionFolderItems { + return try await authorizedGet( + path: "/users/\(userName)/collection/folders/\(folderID)/releases", headers: headers, - parameters: ["per_page": "\(resultsPerPage)", "page": "\(pageNumber)"]) + parameters: ["per_page": "\(resultsPerPage)", "page": "\(pageNumber)"] + ) } public func addItem(_ itemID: Int, toFolderID folderID: Int, - userName: String) async -> CollectionItemInfo { - return authorizedPost( + userName: String) async throws -> CollectionItemInfo { + return try await authorizedPost( path: "/users/\(userName)/collection/folders/\(folderID)/releases/{itemId}", - headers: headers) + headers: headers + ) } // MARK: - Search public func search(for queryString: String, - type: String) async -> SearchResults { + type: String) async throws -> SearchResults { let params = ["q": queryString] - return await authorizedGet(path: "/database/search", headers: headers, parameters: params) + return try await authorizedGet(path: "/database/search", headers: headers, parameters: params) } } diff --git a/SwiftDiscogs.xcodeproj/project.pbxproj b/SwiftDiscogs.xcodeproj/project.pbxproj index 8e7b8cd..b5cb716 100644 --- a/SwiftDiscogs.xcodeproj/project.pbxproj +++ b/SwiftDiscogs.xcodeproj/project.pbxproj @@ -2413,8 +2413,8 @@ isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/jrtibbetts/JSONClient"; requirement = { - branch = main; - kind = branch; + kind = upToNextMinorVersion; + minimumVersion = 3.0.0; }; }; /* End XCRemoteSwiftPackageReference section */ diff --git a/SwiftDiscogs.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/SwiftDiscogs.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 3ff1f35..89c6da7 100644 --- a/SwiftDiscogs.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/SwiftDiscogs.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,97 +1,95 @@ { - "object": { - "pins": [ - { - "package": "BrightFutures", - "repositoryURL": "https://github.com/Thomvis/BrightFutures.git", - "state": { - "branch": null, - "revision": "9279defa6bdc21501ce740266e5a14d0119ddc63", - "version": "8.0.1" - } - }, - { - "package": "Erik", - "repositoryURL": "https://github.com/phimage/Erik.git", - "state": { - "branch": null, - "revision": "109a130e9cdb00789a43a7a625293eeb12d22989", - "version": "5.1.0" - } - }, - { - "package": "FileKit", - "repositoryURL": "https://github.com/nvzqz/FileKit.git", - "state": { - "branch": null, - "revision": "826d9161b184509f80d85c28cd612d630646de98", - "version": "6.0.0" - } - }, - { - "package": "JSONClient", - "repositoryURL": "https://github.com/jrtibbetts/JSONClient", - "state": { - "branch": "main", - "revision": "d51d5f3e172b56004fdae1b17ad612fbad193e92", - "version": null - } - }, - { - "package": "Kanna", - "repositoryURL": "https://github.com/tid-kijyun/Kanna.git", - "state": { - "branch": null, - "revision": "c657fb9f5827ef138068215c76ad0bb62bbc92da", - "version": "5.2.4" - } - }, - { - "package": "Medi8", - "repositoryURL": "https://github.com/jrtibbetts/Medi8", - "state": { - "branch": "main", - "revision": "3f42fb801a4a7da4bcbb55032d0ef59e20379c57", - "version": null - } - }, - { - "package": "OAuthSwift", - "repositoryURL": "https://github.com/OAuthSwift/OAuthSwift.git", - "state": { - "branch": null, - "revision": "fde77955e6983fbfaabd491709d52b8a82fda4d0", - "version": "2.1.2" - } - }, - { - "package": "PromiseKit", - "repositoryURL": "https://github.com/mxcl/PromiseKit.git", - "state": { - "branch": null, - "revision": "aea48ea1855f5d82e2dffa6027afce3aab8f3dd7", - "version": "6.13.3" - } - }, - { - "package": "Stylobate", - "repositoryURL": "https://github.com/jrtibbetts/Stylobate.git", - "state": { - "branch": "main", - "revision": "1102510b399a9662045d73a367b6419676ec9f75", - "version": null - } - }, - { - "package": "Swifter", - "repositoryURL": "https://github.com/httpswift/swifter.git", - "state": { - "branch": null, - "revision": "9483a5d459b45c3ffd059f7b55f9638e268632fd", - "version": "1.5.0" - } + "pins" : [ + { + "identity" : "brightfutures", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Thomvis/BrightFutures.git", + "state" : { + "revision" : "9279defa6bdc21501ce740266e5a14d0119ddc63", + "version" : "8.0.1" } - ] - }, - "version": 1 + }, + { + "identity" : "erik", + "kind" : "remoteSourceControl", + "location" : "https://github.com/phimage/Erik.git", + "state" : { + "revision" : "109a130e9cdb00789a43a7a625293eeb12d22989", + "version" : "5.1.0" + } + }, + { + "identity" : "filekit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/nvzqz/FileKit.git", + "state" : { + "revision" : "826d9161b184509f80d85c28cd612d630646de98", + "version" : "6.0.0" + } + }, + { + "identity" : "jsonclient", + "kind" : "remoteSourceControl", + "location" : "https://github.com/jrtibbetts/JSONClient", + "state" : { + "branch" : "28-replace-promisekit-with-async-await", + "revision" : "111fa2050dc17cec670445389c728183ca336f41" + } + }, + { + "identity" : "kanna", + "kind" : "remoteSourceControl", + "location" : "https://github.com/tid-kijyun/Kanna.git", + "state" : { + "revision" : "c657fb9f5827ef138068215c76ad0bb62bbc92da", + "version" : "5.2.4" + } + }, + { + "identity" : "medi8", + "kind" : "remoteSourceControl", + "location" : "https://github.com/jrtibbetts/Medi8", + "state" : { + "branch" : "main", + "revision" : "3f42fb801a4a7da4bcbb55032d0ef59e20379c57" + } + }, + { + "identity" : "oauthswift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/OAuthSwift/OAuthSwift", + "state" : { + "branch" : "master", + "revision" : "73f97878d988e33cc0d5482c18db6264c37ffbcd" + } + }, + { + "identity" : "oauthswiftauthenticationservices", + "kind" : "remoteSourceControl", + "location" : "https://github.com/raxityo/OAuthSwiftAuthenticationServices", + "state" : { + "branch" : "master", + "revision" : "84bc8a1215550347372e4cb0356fa91fec4a3ea4" + } + }, + { + "identity" : "stylobate", + "kind" : "remoteSourceControl", + "location" : "https://github.com/jrtibbetts/Stylobate.git", + "state" : { + "branch" : "main", + "revision" : "1102510b399a9662045d73a367b6419676ec9f75" + } + }, + { + "identity" : "swifter", + "kind" : "remoteSourceControl", + "location" : "https://github.com/httpswift/swifter.git", + "state" : { + "revision" : "9483a5d459b45c3ffd059f7b55f9638e268632fd", + "version" : "1.5.0" + } + } + ], + "version" : 2 }