From a78a7b18b5db8db2aae5ce080f7bdb1d202f8af7 Mon Sep 17 00:00:00 2001 From: Davide De Rosa Date: Sat, 27 May 2023 12:32:53 +0200 Subject: [PATCH] Encapsulate *Persistence responsibilities (#305) Do not leave the choice of a repository context up to the library consumer. Instead, provide a specific factory (*Persistence) for each module. --- .../AppShared/Context/CoreContext.swift | 20 ++++++++-------- .../Context/PersistenceManager.swift | 8 +++---- .../PassepartoutCore/Passepartout.swift | 3 --- ...tence.swift => ProvidersPersistence.swift} | 24 +++++++++++-------- ...Persistence.swift => VPNPersistence.swift} | 23 +++++++++++------- .../ProvidersTests.swift | 8 +++---- 6 files changed, 46 insertions(+), 40 deletions(-) rename PassepartoutLibrary/Sources/PassepartoutProvidersImpl/Data/{Persistence.swift => ProvidersPersistence.swift} (71%) rename PassepartoutLibrary/Sources/PassepartoutVPNImpl/Data/{Persistence.swift => VPNPersistence.swift} (74%) diff --git a/Passepartout/AppShared/Context/CoreContext.swift b/Passepartout/AppShared/Context/CoreContext.swift index cf3022e0..5ba9d5ad 100644 --- a/Passepartout/AppShared/Context/CoreContext.swift +++ b/Passepartout/AppShared/Context/CoreContext.swift @@ -33,18 +33,18 @@ import TunnelKitManager final class CoreContext { let store: KeyValueStore - private let profilesPersistence: CoreDataPersistentStore + private let providersPersistence: ProvidersPersistence - private let providersPersistence: CoreDataPersistentStore - - var urlsForProfiles: [URL]? { - profilesPersistence.containerURLs - } + private let vpnPersistence: VPNPersistence var urlsForProviders: [URL]? { providersPersistence.containerURLs } + var urlsForProfiles: [URL]? { + vpnPersistence.containerURLs + } + let upgradeManager: UpgradeManager let providerManager: ProviderManager @@ -67,7 +67,7 @@ final class CoreContext { pp_log.info("Logging to: \(logger.logFile!)") let persistenceManager = PersistenceManager(store: store) - profilesPersistence = persistenceManager.profilesPersistence( + vpnPersistence = persistenceManager.vpnPersistence( withName: Constants.Persistence.profilesContainerName ) providersPersistence = persistenceManager.providersPersistence( @@ -89,17 +89,17 @@ final class CoreContext { Constants.Repos.api, timeout: Constants.Services.connectivityTimeout ), - webServicesRepository: PassepartoutPersistence.webServicesRepository(providersPersistence) + webServicesRepository: providersPersistence.webServicesRepository() ) providerManager = ProviderManager( - localProvidersRepository: PassepartoutPersistence.localProvidersRepository(providersPersistence), + localProvidersRepository: providersPersistence.localProvidersRepository(), remoteProvidersStrategy: remoteProvidersStrategy ) profileManager = ProfileManager( store: store, providerManager: providerManager, - profileRepository: PassepartoutPersistence.profileRepository(profilesPersistence), + profileRepository: vpnPersistence.profileRepository(), keychain: KeychainSecretRepository(appGroup: Constants.App.appGroupId), keychainEntry: Unlocalized.Keychain.passwordEntry, keychainLabel: Unlocalized.Keychain.passwordLabel diff --git a/Passepartout/AppShared/Context/PersistenceManager.swift b/Passepartout/AppShared/Context/PersistenceManager.swift index 605cf1bb..6f03a804 100644 --- a/Passepartout/AppShared/Context/PersistenceManager.swift +++ b/Passepartout/AppShared/Context/PersistenceManager.swift @@ -39,12 +39,12 @@ final class PersistenceManager { } } - func profilesPersistence(withName containerName: String) -> CoreDataPersistentStore { - PassepartoutPersistence.profilesStore(withName: containerName, cloudKit: true, author: persistenceAuthor) + func vpnPersistence(withName containerName: String) -> VPNPersistence { + VPNPersistence(withName: containerName, cloudKit: true, author: persistenceAuthor) } - func providersPersistence(withName containerName: String) -> CoreDataPersistentStore { - PassepartoutPersistence.providersStore(withName: containerName, cloudKit: false, author: persistenceAuthor) + func providersPersistence(withName containerName: String) -> ProvidersPersistence { + ProvidersPersistence(withName: containerName, cloudKit: false, author: persistenceAuthor) } } diff --git a/PassepartoutLibrary/Sources/PassepartoutCore/Passepartout.swift b/PassepartoutLibrary/Sources/PassepartoutCore/Passepartout.swift index 0776b22e..111b662a 100644 --- a/PassepartoutLibrary/Sources/PassepartoutCore/Passepartout.swift +++ b/PassepartoutLibrary/Sources/PassepartoutCore/Passepartout.swift @@ -35,9 +35,6 @@ public class Passepartout { public var logger: Logger = DefaultLogger() } -public enum PassepartoutPersistence { -} - public struct PassepartoutError: Error, Equatable { private let string: String diff --git a/PassepartoutLibrary/Sources/PassepartoutProvidersImpl/Data/Persistence.swift b/PassepartoutLibrary/Sources/PassepartoutProvidersImpl/Data/ProvidersPersistence.swift similarity index 71% rename from PassepartoutLibrary/Sources/PassepartoutProvidersImpl/Data/Persistence.swift rename to PassepartoutLibrary/Sources/PassepartoutProvidersImpl/Data/ProvidersPersistence.swift index f3283982..8a22c292 100644 --- a/PassepartoutLibrary/Sources/PassepartoutProvidersImpl/Data/Persistence.swift +++ b/PassepartoutLibrary/Sources/PassepartoutProvidersImpl/Data/ProvidersPersistence.swift @@ -1,5 +1,5 @@ // -// Persistence.swift +// ProvidersPersistence.swift // Passepartout // // Created by Davide De Rosa on 4/7/22. @@ -29,30 +29,34 @@ import PassepartoutCore import PassepartoutProviders import PassepartoutServices -extension PassepartoutPersistence { - private static let providersDataModel: NSManagedObjectModel = { +public final class ProvidersPersistence { + private static let dataModel: NSManagedObjectModel = { guard let model = NSManagedObjectModel.mergedModel(from: [.module]) else { fatalError("Could not load PassepartoutProviders model") } return model }() - public static func providersStore(withName containerName: String, cloudKit: Bool, author: String?) -> CoreDataPersistentStore { - .init( + private let store: CoreDataPersistentStore + + public var containerURLs: [URL]? { + store.containerURLs + } + + public init(withName containerName: String, cloudKit: Bool, author: String?) { + store = .init( withName: containerName, - model: providersDataModel, + model: Self.dataModel, cloudKit: cloudKit, author: author ) } -} -extension PassepartoutPersistence { - public static func webServicesRepository(_ store: CoreDataPersistentStore) -> WebServicesRepository { + public func webServicesRepository() -> WebServicesRepository { CDWebServicesRepository(store.context) } - public static func localProvidersRepository(_ store: CoreDataPersistentStore) -> LocalProvidersRepository { + public func localProvidersRepository() -> LocalProvidersRepository { CDLocalProvidersRepository(store.context) } } diff --git a/PassepartoutLibrary/Sources/PassepartoutVPNImpl/Data/Persistence.swift b/PassepartoutLibrary/Sources/PassepartoutVPNImpl/Data/VPNPersistence.swift similarity index 74% rename from PassepartoutLibrary/Sources/PassepartoutVPNImpl/Data/Persistence.swift rename to PassepartoutLibrary/Sources/PassepartoutVPNImpl/Data/VPNPersistence.swift index 132876fa..89eeb61c 100644 --- a/PassepartoutLibrary/Sources/PassepartoutVPNImpl/Data/Persistence.swift +++ b/PassepartoutLibrary/Sources/PassepartoutVPNImpl/Data/VPNPersistence.swift @@ -1,5 +1,5 @@ // -// Persistence.swift +// VPNPersistence.swift // Passepartout // // Created by Davide De Rosa on 4/7/22. @@ -28,25 +28,30 @@ import Foundation import PassepartoutCore import PassepartoutVPN -extension PassepartoutPersistence { - private static let profilesDataModel: NSManagedObjectModel = { +public final class VPNPersistence { + private static let dataModel: NSManagedObjectModel = { guard let model = NSManagedObjectModel.mergedModel(from: [.module]) else { fatalError("Could not load PassepartoutProfiles model") } return model }() - public static func profilesStore(withName containerName: String, cloudKit: Bool, author: String?) -> CoreDataPersistentStore { - .init( + private let store: CoreDataPersistentStore + + public var containerURLs: [URL]? { + store.containerURLs + } + + public init(withName containerName: String, cloudKit: Bool, author: String?) { + store = .init( withName: containerName, - model: profilesDataModel, + model: Self.dataModel, cloudKit: cloudKit, author: author ) } -} -extension PassepartoutPersistence { - public static func profileRepository(_ store: CoreDataPersistentStore) -> ProfileRepository { + + public func profileRepository() -> ProfileRepository { CDProfileRepository(store.context) } } diff --git a/PassepartoutLibrary/Tests/PassepartoutProvidersTests/ProvidersTests.swift b/PassepartoutLibrary/Tests/PassepartoutProvidersTests/ProvidersTests.swift index 00e949c0..0a1df4d9 100644 --- a/PassepartoutLibrary/Tests/PassepartoutProvidersTests/ProvidersTests.swift +++ b/PassepartoutLibrary/Tests/PassepartoutProvidersTests/ProvidersTests.swift @@ -31,7 +31,7 @@ import PassepartoutProviders import XCTest final class ProvidersTests: XCTestCase { - private var persistence: CoreDataPersistentStore! + private var persistence: ProvidersPersistence! private var manager: ProviderManager! @@ -39,16 +39,16 @@ final class ProvidersTests: XCTestCase { override func setUp() { let model = NSManagedObjectModel.mergedModel(from: [.module])! - persistence = CoreDataPersistentStore(withName: "ProvidersTests", model: model, cloudKit: false, author: nil) + persistence = ProvidersPersistence(withName: "ProvidersTests", cloudKit: false, author: nil) let remoteStrategy = APIRemoteProvidersStrategy( appBuild: 10000, bundleServices: APIWebServices.bundledServices(withVersion: "v5"), remoteServices: APIWebServices("v5", URL(string: "https://passepartoutvpn.app/api/")!, timeout: nil), - webServicesRepository: PassepartoutPersistence.webServicesRepository(persistence) + webServicesRepository: persistence.webServicesRepository() ) manager = ProviderManager( - localProvidersRepository: PassepartoutPersistence.localProvidersRepository(persistence), + localProvidersRepository: persistence.localProvidersRepository(), remoteProvidersStrategy: remoteStrategy ) // persistence.truncate()