import Foundation import Combine /// A "Store Store," which holds a list of type-erased stores. public final class SecretStoreList: ObservableObject { /// The Stores managed by the SecretStoreList. @Published public var stores: [AnySecretStore] = [] /// A modifiable store, if one is available. @Published public var modifiableStore: AnySecretStoreModifiable? private var cancellables: Set = [] /// Initializes a SecretStoreList. public init() { } /// Adds a non-type-erased SecretStore to the list. public func add(store: SecretStoreType) { addInternal(store: AnySecretStore(store)) } /// Adds a non-type-erased modifiable SecretStore. public func add(store: SecretStoreType) { let modifiable = AnySecretStoreModifiable(modifiable: store) modifiableStore = modifiable addInternal(store: modifiable) } /// A boolean describing whether there are any Stores available. public var anyAvailable: Bool { stores.reduce(false, { $0 || $1.isAvailable }) } public var allSecrets: [AnySecret] { stores.flatMap(\.secrets) } } extension SecretStoreList { private func addInternal(store: AnySecretStore) { stores.append(store) store.objectWillChange.sink { self.objectWillChange.send() }.store(in: &cancellables) } }