From 8b7c39c0de20e85a6ae42961da69fd5fa81ba804 Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 11 Nov 2024 17:40:34 +0100 Subject: [PATCH] Removed the StoreIdentifier concept to just use a String and a default parameter named store_id to send to the server --- LeStorage/Services.swift | 9 ++-- LeStorage/Storable.swift | 2 - LeStorage/Store.swift | 84 +++++++++++--------------------- LeStorage/StoreCenter.swift | 24 +++++---- LeStorage/StoredCollection.swift | 2 +- 5 files changed, 49 insertions(+), 72 deletions(-) diff --git a/LeStorage/Services.swift b/LeStorage/Services.swift index 26a6d18..ede9d9c 100644 --- a/LeStorage/Services.swift +++ b/LeStorage/Services.swift @@ -188,7 +188,7 @@ public class Services { /// Returns a GET request for the resource /// - Parameters: /// - type: the type of the request resource - fileprivate func _getRequest(type: T.Type, identifier: StoreIdentifier?) + fileprivate func _getRequest(type: T.Type, identifier: String?) throws -> URLRequest { @@ -243,11 +243,12 @@ public class Services { /// - identifier: an optional StoreIdentifier that allows to filter GET requests with the StoreIdentifier values fileprivate func _baseRequest( servicePath: String, method: HTTPMethod, requiresToken: Bool? = nil, - identifier: StoreIdentifier? = nil + identifier: String? = nil ) throws -> URLRequest { var urlString = baseURL + servicePath if let identifier { - urlString.append(identifier.urlComponent) + let component = "?store_id=\(identifier)" + urlString.append(component) } guard let url = URL(string: urlString) else { throw ServiceError.urlCreationError(url: urlString) @@ -403,7 +404,7 @@ public class Services { // MARK: - Services /// Executes a GET request - public func get(identifier: StoreIdentifier? = nil) async throws -> [T] { + public func get(identifier: String? = nil) async throws -> [T] { let getRequest = try _getRequest(type: T.self, identifier: identifier) return try await self._runRequest(getRequest) } diff --git a/LeStorage/Storable.swift b/LeStorage/Storable.swift index d13cb37..1b30afc 100644 --- a/LeStorage/Storable.swift +++ b/LeStorage/Storable.swift @@ -28,8 +28,6 @@ public protocol Storable: Codable, Identifiable, NSObjectProtocol { /// so when we do that on the server, we also need to do it locally func deleteDependencies() -// static var relationshipNames: [String] { get } - func copy(from other: any Storable) } diff --git a/LeStorage/Store.swift b/LeStorage/Store.swift index df9a8cf..cb29b78 100644 --- a/LeStorage/Store.swift +++ b/LeStorage/Store.swift @@ -17,21 +17,21 @@ public enum StoreError: Error { case cannotSyncCollection(name: String) } -public struct StoreIdentifier { - var value: String - var parameterName: String - - public init(value: String, parameterName: String) { - self.value = value - self.parameterName = parameterName - } - - var urlComponent: String { - return "?\(self.parameterName)=\(self.value)" - } -} +//public struct StoreIdentifier { +// var value: String +// var parameterName: String +// +// public init(value: String, parameterName: String) { +// self.value = value +// self.parameterName = parameterName +// } +// +// var urlComponent: String { +// return "?\(self.parameterName)=\(self.value)" +// } +//} -open class Store { +final public class Store { /// The Store singleton public static let main = Store() @@ -43,7 +43,7 @@ open class Store { static let storageDirectory = "storage" /// The store identifier, used to name the store directory, and to perform filtering requests to the server - fileprivate(set) var identifier: StoreIdentifier? = nil + fileprivate(set) var identifier: String? = nil /// Indicates whether the store directory has been created at the init fileprivate var _created: Bool = false @@ -52,8 +52,8 @@ open class Store { self._createDirectory(directory: Store.storageDirectory) } - public required init(identifier: String, parameter: String) { - self.identifier = StoreIdentifier(value: identifier, parameterName: parameter) + public required init(identifier: String) { + self.identifier = identifier let directory = "\(Store.storageDirectory)/\(identifier)" self._createDirectory(directory: directory) } @@ -145,6 +145,16 @@ open class Store { throw StoreError.collectionNotRegistered(type: T.resourceName()) } + subscript(_ type: T.Type) -> StoredCollection { + get { + do { + return try self.collection() + } catch { + fatalError(error.localizedDescription) + } + } + } + /// Loads all collection with the data from the server public func loadCollectionsFromServer() { for collection in self._syncedCollections() { @@ -216,7 +226,7 @@ open class Store { /// Returns the directory URL of the store fileprivate func _directoryPath() throws -> URL { var url = try FileUtils.pathForDirectoryInDocuments(directory: Store.storageDirectory) - if let identifier = self.identifier?.value { + if let identifier { url.append(component: identifier) } return url @@ -289,42 +299,4 @@ open class Store { return self._collections.values.allSatisfy { $0.hasLoaded } } - // fileprivate var _validIds: [String] = [] - // - // fileprivate func _migrate(_ collection: StoredCollection, identifier: StoreIdentifier, type: T.Type) { - // - // self._validIds.append(identifier.value) - // - // let oldCollection: StoredCollection = StoredCollection(synchronized: false, store: Store.main, asynchronousIO: false) - // - // let filtered: [T] = oldCollection.items.filter { item in - // var propertyValue: String? = item.stringForPropertyName(identifier.parameterName) - // if propertyValue == nil { - // let values = T.relationshipNames.map { item.stringForPropertyName($0) } - // propertyValue = values.compactMap { $0 }.first - // } - // return self._validIds.first(where: { $0 == propertyValue }) != nil - // } - // - // if filtered.count > 0 { - // self._validIds.append(contentsOf: filtered.map { $0.stringId }) - // try? collection.addOrUpdateNoSync(contentOfs: filtered) - // Logger.log("Migrated \(filtered.count) \(T.resourceName())") - // } - // } - } - -//fileprivate extension Storable { -// -// func stringForPropertyName(_ propertyName: String) -> String? { -// let mirror = Mirror(reflecting: self) -// for child in mirror.children { -// if let label = child.label, label == "_\(propertyName)" { -// return child.value as? String -// } -// } -// return nil -// } -// -//} diff --git a/LeStorage/StoreCenter.swift b/LeStorage/StoreCenter.swift index 6e4b77a..6bac901 100644 --- a/LeStorage/StoreCenter.swift +++ b/LeStorage/StoreCenter.swift @@ -105,7 +105,7 @@ public class StoreCenter { /// - Parameters: /// - store: A store to save fileprivate func _registerStore(store: Store) { - guard let identifier = store.identifier?.value else { + guard let identifier = store.identifier else { fatalError("The store has no identifier") } if self._stores[identifier] != nil { @@ -118,11 +118,11 @@ public class StoreCenter { /// - Parameters: /// - identifier: The store identifer /// - parameter: The parameter name used to filter data on the server - public func store(identifier: String, parameter: String) -> T { - if let store = self._stores[identifier] as? T { + public func store(identifier: String) -> Store { + if let store = self._stores[identifier] { return store } else { - let store = T(identifier: identifier, parameter: parameter) + let store = Store(identifier: identifier) self._registerStore(store: store) return store } @@ -350,7 +350,7 @@ public class StoreCenter { } /// Retrieves all the items on the server - func getItems(identifier: StoreIdentifier? = nil) async throws -> [T] { + func getItems(identifier: String? = nil) async throws -> [T] { return try await self.service().get(identifier: identifier) } @@ -483,9 +483,15 @@ public class StoreCenter { } - fileprivate func _store(id: String?) -> Store? { + fileprivate func _store(id: String?) -> Store { if let storeId = id { - return self._stores[storeId] + if let store = self._stores[storeId] { + return store + } else { + let store = Store(identifier: storeId) + self._registerStore(store: store) + return store + } } else { return Store.main } @@ -501,7 +507,7 @@ public class StoreCenter { let hasAlreadyBeenDeleted: Bool = self._hasAlreadyBeenDeleted(instance) if !hasAlreadyBeenDeleted { DispatchQueue.main.asyncAfter(deadline: .now() + 1) { - self._store(id: storeId)?.addOrUpdateIfNewer(instance) + self._store(id: storeId).addOrUpdateIfNewer(instance) } } } @@ -511,7 +517,7 @@ public class StoreCenter { DispatchQueue.main.async { do { let type = try StoreCenter.classFromName(model) - try self._store(id: storeId)?.deleteNoSync(type: type, id: id) + try self._store(id: storeId).deleteNoSync(type: type, id: id) } catch { Logger.error(error) } diff --git a/LeStorage/StoredCollection.swift b/LeStorage/StoredCollection.swift index 45e80fa..5d0c5b6 100644 --- a/LeStorage/StoredCollection.swift +++ b/LeStorage/StoredCollection.swift @@ -238,7 +238,7 @@ public class StoredCollection: RandomAccessCollection, SomeCollecti } fileprivate func _affectStoreIdIfNecessary(instance: T) { - if let storeId = self.store.identifier?.value { + if let storeId = self.store.identifier { if var altStorable = instance as? SideStorable { altStorable.storeId = storeId } else {