Removed the StoreIdentifier concept to just use a String and a default parameter named store_id to send to the server

sync2
Laurent 1 year ago
parent 7059cc913b
commit 8b7c39c0de
  1. 9
      LeStorage/Services.swift
  2. 2
      LeStorage/Storable.swift
  3. 84
      LeStorage/Store.swift
  4. 24
      LeStorage/StoreCenter.swift
  5. 2
      LeStorage/StoredCollection.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<T: SyncedStorable>(type: T.Type, identifier: StoreIdentifier?)
fileprivate func _getRequest<T: SyncedStorable>(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<T: SyncedStorable>(identifier: StoreIdentifier? = nil) async throws -> [T] {
public func get<T: SyncedStorable>(identifier: String? = nil) async throws -> [T] {
let getRequest = try _getRequest(type: T.self, identifier: identifier)
return try await self._runRequest(getRequest)
}

@ -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)
}

@ -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<T>(_ type: T.Type) -> StoredCollection<T> {
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<T : Storable>(_ collection: StoredCollection<T>, identifier: StoreIdentifier, type: T.Type) {
//
// self._validIds.append(identifier.value)
//
// let oldCollection: StoredCollection<T> = StoredCollection<T>(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
// }
//
//}

@ -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<T: 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<T: SyncedStorable>(identifier: StoreIdentifier? = nil) async throws -> [T] {
func getItems<T: SyncedStorable>(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)
}

@ -238,7 +238,7 @@ public class StoredCollection<T: Storable>: 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 {

Loading…
Cancel
Save