From 81a215080070d419140cc55bd478f2177176623c Mon Sep 17 00:00:00 2001 From: Andi Date: Fri, 27 Oct 2023 14:13:27 -0700 Subject: [PATCH] Make the StandardBacked protocol visible to the outside (#31) # Make the StandardBacked protocol visible to the outside ## :recycle: Current situation & Problem We currently don't expose the `StandardBacked` protocol to the outside. The protocol can be helpful do more clearly inspect the type of an account service. Therefore, we expose the protocol with an underscore. ## :gear: Release Notes * Made `_StandardBacked` public. ## :books: Documentation * Documentation was added. ## :white_check_mark: Testing -- ## :pencil: Code of Conduct & Contributing Guidelines By submitting creating this pull request, you agree to follow our [Code of Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md): - [x] I agree to follow the [Code of Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md). --- Sources/SpeziAccount/Account.swift | 6 +-- .../NotifyStandardBackedAccountService.swift | 2 +- .../StorageStandardBackedAccountService.swift | 2 +- ...dardBacked.swift => _StandardBacked.swift} | 39 +++++++++++-------- 4 files changed, 28 insertions(+), 21 deletions(-) rename Sources/SpeziAccount/AccountService/Wrapper/{StandardBacked.swift => _StandardBacked.swift} (64%) diff --git a/Sources/SpeziAccount/Account.swift b/Sources/SpeziAccount/Account.swift index 3889e51f..97141102 100644 --- a/Sources/SpeziAccount/Account.swift +++ b/Sources/SpeziAccount/Account.swift @@ -210,7 +210,7 @@ public class Account: ObservableObject, Sendable { // Account details will always get built by the respective Account Service. Therefore, we need to patch it // if they are wrapped into a StandardBacked one such that the `AccountDetails` carry the correct reference. for service in registeredAccountServices { - if let standardBacked = service as? any StandardBacked, + if let standardBacked = service as? any _StandardBacked, standardBacked.isBacking(service: details.accountService) { details.patchAccountService(service) break @@ -224,7 +224,7 @@ public class Account: ObservableObject, Sendable { ) } - if let standardBacked = details.accountService as? any StandardBacked, + if let standardBacked = details.accountService as? any _StandardBacked, let storageStandard = standardBacked.standard as? any AccountStorageStandard { let recordId = AdditionalRecordId(serviceId: standardBacked.backedId, accountId: details.accountId) @@ -252,7 +252,7 @@ public class Account: ObservableObject, Sendable { /// signed in user and notify others that the user logged out (or the account was removed). public func removeUserDetails() async { if let details, - let standardBacked = details.accountService as? any StandardBacked, + let standardBacked = details.accountService as? any _StandardBacked, let storageStandard = standardBacked.standard as? any AccountStorageStandard { let recordId = AdditionalRecordId(serviceId: standardBacked.backedId, accountId: details.accountId) diff --git a/Sources/SpeziAccount/AccountService/Wrapper/NotifyStandardBackedAccountService.swift b/Sources/SpeziAccount/AccountService/Wrapper/NotifyStandardBackedAccountService.swift index 9208b523..26910bdf 100644 --- a/Sources/SpeziAccount/AccountService/Wrapper/NotifyStandardBackedAccountService.swift +++ b/Sources/SpeziAccount/AccountService/Wrapper/NotifyStandardBackedAccountService.swift @@ -9,7 +9,7 @@ import Spezi -actor NotifyStandardBackedAccountService: AccountService, StandardBacked { +actor NotifyStandardBackedAccountService: AccountService, _StandardBacked { @AccountReference private var account let accountService: Service diff --git a/Sources/SpeziAccount/AccountService/Wrapper/StorageStandardBackedAccountService.swift b/Sources/SpeziAccount/AccountService/Wrapper/StorageStandardBackedAccountService.swift index ded588b0..9364e43f 100644 --- a/Sources/SpeziAccount/AccountService/Wrapper/StorageStandardBackedAccountService.swift +++ b/Sources/SpeziAccount/AccountService/Wrapper/StorageStandardBackedAccountService.swift @@ -11,7 +11,7 @@ import Spezi /// An ``AccountService`` implementation for account services with ``SupportedAccountKeys/exactly(_:)`` configuration /// to forward unsupported account values to a ``AccountStorageStandard`` implementation. -actor StorageStandardBackedAccountService: AccountService, StandardBacked { +actor StorageStandardBackedAccountService: AccountService, _StandardBacked { @AccountReference private var account let accountService: Service diff --git a/Sources/SpeziAccount/AccountService/Wrapper/StandardBacked.swift b/Sources/SpeziAccount/AccountService/Wrapper/_StandardBacked.swift similarity index 64% rename from Sources/SpeziAccount/AccountService/Wrapper/StandardBacked.swift rename to Sources/SpeziAccount/AccountService/Wrapper/_StandardBacked.swift index adfa12b4..c315d411 100644 --- a/Sources/SpeziAccount/AccountService/Wrapper/StandardBacked.swift +++ b/Sources/SpeziAccount/AccountService/Wrapper/_StandardBacked.swift @@ -10,43 +10,50 @@ import Spezi /// Internal marker protocol to determine what ``AccountService`` require assistance by a ``AccountStorageStandard``. -protocol StandardBacked: AccountService { +public protocol _StandardBacked: AccountService { // swiftlint:disable:this type_name associatedtype Service: AccountService associatedtype AccountStandard: Standard var accountService: Service { get } var standard: AccountStandard { get } + /// Retrieves the underlying account service, resolving multiple levels of nesting. + var underlyingService: any AccountService { get } + init(service: Service, standard: AccountStandard) + /// ObjectIdentifier-based check if they underlying account service equals the provided one. func isBacking(service accountService: any AccountService) -> Bool func preUserDetailsSupply(recordId: AdditionalRecordId) async throws } -extension StandardBacked { - var backedId: String { - if let nestedBacked = accountService as? any StandardBacked { - return nestedBacked.backedId - } - - return accountService.id +extension _StandardBacked { + /// The account service id of the underlying account service + public var backedId: String { + underlyingService.id } - - func isBacking(service: any AccountService) -> Bool { - if let nestedBacked = self.accountService as? any StandardBacked { - return nestedBacked.isBacking(service: service) + /// Recursively retrieves the innermost account service. + public var underlyingService: any AccountService { + if let nestedBacked = accountService as? any _StandardBacked { + return nestedBacked.underlyingService } - return self.accountService.objId == service.objId + return accountService + } + + /// An ObjectIdentifier-based check if they underlying account service equals the provided one. + public func isBacking(service: any AccountService) -> Bool { + underlyingService.objId == service.objId } - func preUserDetailsSupply(recordId: AdditionalRecordId) async throws {} + /// Default implementation. + public func preUserDetailsSupply(recordId: AdditionalRecordId) async throws {} } -extension StandardBacked { +extension _StandardBacked { func signUp(signupDetails: SignupDetails) async throws { try await accountService.signUp(signupDetails: signupDetails) } @@ -65,7 +72,7 @@ extension StandardBacked { } -extension StandardBacked where Self: UserIdPasswordAccountService, Service: UserIdPasswordAccountService { +extension _StandardBacked where Self: UserIdPasswordAccountService, Service: UserIdPasswordAccountService { func login(userId: String, password: String) async throws { try await accountService.login(userId: userId, password: password) }