From d019e491af52f99ad2edf8683eb5682fa82cc319 Mon Sep 17 00:00:00 2001 From: Laurent Date: Wed, 5 Nov 2025 10:34:40 +0100 Subject: [PATCH] improvements and cleanup --- LeStorage/Codables/Log.swift | 11 +++-- LeStorage/Storable.swift | 2 + LeStorage/Store.swift | 53 +--------------------- LeStorage/StoreCenter.swift | 12 +---- LeStorage/StoredCollection.swift | 15 ++---- LeStorage/SyncedCollection.swift | 78 +------------------------------- 6 files changed, 17 insertions(+), 154 deletions(-) diff --git a/LeStorage/Codables/Log.swift b/LeStorage/Codables/Log.swift index eecb5de..bd01f25 100644 --- a/LeStorage/Codables/Log.swift +++ b/LeStorage/Codables/Log.swift @@ -23,13 +23,13 @@ class Log: SyncedModelObject, SyncedStorable { } var id: String = Store.randomId() - var date: Date = Date() - + var user: String? = nil var message: String = "" - init(message: String) { + init(message: String, user: String?) { self.message = message + self.user = user super.init() } @@ -38,6 +38,7 @@ class Log: SyncedModelObject, SyncedStorable { enum CodingKeys: String, CodingKey { case id case date + case user case message } @@ -45,6 +46,7 @@ class Log: SyncedModelObject, SyncedStorable { let container = try decoder.container(keyedBy: CodingKeys.self) id = try container.decode(String.self, forKey: .id) date = try container.decode(Date.self, forKey: .date) + user = try container.decodeIfPresent(String.self, forKey: .user) message = try container.decode(String.self, forKey: .message) try super.init(from: decoder) } @@ -53,16 +55,17 @@ class Log: SyncedModelObject, SyncedStorable { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(id, forKey: .id) try container.encode(date, forKey: .date) + try container.encodeIfPresent(user, forKey: .user) try container.encode(message, forKey: .message) try super.encode(to: encoder) } func copy(from other: any Storable) { guard let log = other as? Log else { return } - self.date = log.date self.message = log.message } + public func copyForUpdate(from other: any Storable) { fatalError("should not happen") } diff --git a/LeStorage/Storable.swift b/LeStorage/Storable.swift index 73f5f16..1a3eb55 100644 --- a/LeStorage/Storable.swift +++ b/LeStorage/Storable.swift @@ -37,6 +37,8 @@ public protocol Storable: Codable, Identifiable, NSObjectProtocol { static func parentRelationships() -> [Relationship] static func childrenRelationships() -> [Relationship] + /// Denotes a data that own its own store + /// Effectively used to trigger directory creation when adding an item to the collection static func storeParent() -> Bool } diff --git a/LeStorage/Store.swift b/LeStorage/Store.swift index 08ae90b..8c02089 100644 --- a/LeStorage/Store.swift +++ b/LeStorage/Store.swift @@ -142,13 +142,13 @@ final public class Store { /// - Parameters: /// - indexed: Creates an index to quickly access the data /// - inMemory: Indicates if the collection should only live in memory, and not write into a file - public func registerSynchronizedCollection(indexed: Bool = false, inMemory: Bool = false, limit: Int? = nil, synchronousLoading: Bool = false, noLoad: Bool = false) -> SyncedCollection { + public func registerSynchronizedCollection(indexed: Bool = false, inMemory: Bool = false, limit: Int? = nil, noLoad: Bool = false) -> SyncedCollection { if let collection: SyncedCollection = try? self.syncedCollection() { return collection } - let collection = SyncedCollection(store: self, indexed: indexed, inMemory: inMemory, limit: limit, synchronousLoading: synchronousLoading, noLoad: noLoad) + let collection = SyncedCollection(store: self, indexed: indexed, inMemory: inMemory, limit: limit, noLoad: noLoad) self._collections[T.resourceName()] = collection self._baseCollections[T.resourceName()] = collection.collection @@ -225,14 +225,6 @@ final public class Store { throw StoreError.collectionNotRegistered(type: T.resourceName()) } - /// Returns a collection by type -// func collection() throws -> BaseCollection { -// if let collection = self._collections[T.resourceName()] as? BaseCollection { -// return collection -// } -// throw StoreError.collectionNotRegistered(type: T.resourceName()) -// } - func registerOrGetSyncedCollection(_ type: T.Type) -> SyncedCollection { do { return try self.syncedCollection() @@ -331,16 +323,6 @@ final public class Store { } self._requestWrite(type: T.self) - -// for identifier in identifiers { -// do { -// try self.deleteNoSyncNoCascade(type: type, id: identifier.modelId) -// } catch { -// Logger.error(error) -// } -// self.storeCenter.cleanupDataLog(dataId: identifier.modelId) -// } -// self._requestWrite(type: T.self) } fileprivate func _instance(id: String, type: T.Type) -> T? { @@ -348,31 +330,12 @@ final public class Store { return self.findById(realId) } - /// Calls deleteById from the collection corresponding to the instance -// func deleteNoSync(instance: T) { -// do { -// let collection: BaseCollection = try self.collection() -// collection.delete(instance: instance) -// } catch { -// Logger.error(error) -// } -// } - /// Calls deleteById from the collection corresponding to the instance func deleteNoSyncNoCascadeNoWrite(type: T.Type, id: String) throws { let collection: SyncedCollection = try self.syncedCollection() collection.deleteByStringId(id, actionOption: .noCascadeNoWrite) } - /// Calls deleteById from the collection corresponding to the instance -// func referenceCount(type: T.Type, id: String) -> Int { -// var count: Int = 0 -// for collection in self._collections.values { -// count += collection.referenceCount(type: type, id: id) -// } -// return count -// } - func isReferenced(collectionType: S.Type, type: T.Type, id: String) -> Bool { if let collection = self._baseCollections[S.resourceName()] { return collection.hasParentReferences(type: type, id: id) @@ -462,18 +425,6 @@ final public class Store { } } -// public func deleteDependencies(type: T.Type, actionOption: ActionOption, _ isIncluded: (T) -> Bool) { -// -// do { -// let collection: any SomeCollection = try self.someCollection(type: type) -// if let syncCollection = collection as? SyncedCollection { -// collection.deleteDependencies(actionOption: actionOption, isIncluded) -// } catch { -// Logger.error(error) -// } -// -// } - // MARK: - Write /// Returns the directory URL of the store diff --git a/LeStorage/StoreCenter.swift b/LeStorage/StoreCenter.swift index ef22f1c..bd67435 100644 --- a/LeStorage/StoreCenter.swift +++ b/LeStorage/StoreCenter.swift @@ -1197,21 +1197,11 @@ public class StoreCenter { /// Logs a message in the logs collection public func log(message: String) { DispatchQueue.main.async { - let log = Log(message: message) + let log = Log(message: message, user: self.userId) self._logsCollection().addOrUpdate(instance: log) } } - // MARK: - Migration - - /// Migrates the token from the provided service to the main Services instance -// public func migrateToken(_ services: Services) throws { -// guard let userName = self.userName() else { -// return -// } -// try self.service().migrateToken(services, userName: userName) -// } - deinit { NotificationCenter.default.removeObserver(self) } diff --git a/LeStorage/StoredCollection.swift b/LeStorage/StoredCollection.swift index cf95ea3..577d075 100644 --- a/LeStorage/StoredCollection.swift +++ b/LeStorage/StoredCollection.swift @@ -100,8 +100,6 @@ public class StoredCollection: SomeCollection { /// Sets a max number of items inside the collection fileprivate(set) var limit: Int? = nil - fileprivate var _delegate: (any CollectionDelegate)? = nil - init(store: Store, inMemory: Bool = false) async { self.store = store if self.inMemory == false { @@ -109,24 +107,19 @@ public class StoredCollection: SomeCollection { } } - init(store: Store, indexed: Bool = false, inMemory: Bool = false, limit: Int? = nil, synchronousLoading: Bool = false, noLoad: Bool = false, delegate: (any CollectionDelegate)? = nil) { + init(store: Store, indexed: Bool = false, inMemory: Bool = false, limit: Int? = nil, noLoad: Bool = false) { if indexed { self._indexes = [:] } self.inMemory = inMemory self.store = store self.limit = limit - self._delegate = delegate if noLoad { self.hasLoaded = true } else { Task { - if synchronousLoading { - await self.loadFromFile() - } else { - await self.load() - } + await self.load() } } @@ -159,14 +152,13 @@ public class StoredCollection: SomeCollection { if !self.inMemory { await self.loadFromFile() } else { - await self._delegate?.loadingForMemoryCollection() await MainActor.run { self.setAsLoaded() } } } - /// Starts the JSON file decoding synchronously or asynchronously + /// Starts the JSON file decoding asynchronously func loadFromFile() async { do { try await self._decodeJSONFile() @@ -503,7 +495,6 @@ public class StoredCollection: SomeCollection { self.deleteUnusedShared(data, actionOption: item.actionOption) } - self._delegate?.itemMerged(item) } manager.reset() diff --git a/LeStorage/SyncedCollection.swift b/LeStorage/SyncedCollection.swift index 2b8475f..4b07c4a 100644 --- a/LeStorage/SyncedCollection.swift +++ b/LeStorage/SyncedCollection.swift @@ -19,10 +19,10 @@ public class SyncedCollection: SomeSyncedCollection, Collect let store: Store let collection: StoredCollection - init(store: Store, indexed: Bool = false, inMemory: Bool = false, limit: Int? = nil, synchronousLoading: Bool = false, noLoad: Bool = false) { + init(store: Store, indexed: Bool = false, inMemory: Bool = false, limit: Int? = nil, noLoad: Bool = false) { self.store = store - self.collection = StoredCollection(store: store, indexed: indexed, inMemory: inMemory, limit: limit, synchronousLoading: synchronousLoading, noLoad: noLoad) + self.collection = StoredCollection(store: store, indexed: indexed, inMemory: inMemory, limit: limit, noLoad: noLoad) } @@ -42,19 +42,6 @@ public class SyncedCollection: SomeSyncedCollection, Collect return SyncedCollection(store: Store(storeCenter: StoreCenter.main)) } - /// Migrates if necessary and asynchronously decodes the json file -// override func load() async { -// do { -// if self.inMemory { -// try await self.loadDataFromServerIfAllowed() -// } else { -// await self.loadFromFile() -// } -// } catch { -// Logger.error(error) -// } -// } - /// Loads the collection using the server data only if the collection file doesn't exists func loadCollectionsFromServerIfNoFile() async throws { let fileURL: URL = try self.store.fileURL(type: T.self) @@ -190,41 +177,6 @@ public class SyncedCollection: SomeSyncedCollection, Collect return batch } - /// Deletes an instance without writing, logs the operation and sends an API call -// fileprivate func _deleteNoWrite(instance: T) { -// self.deleteItem(instance, shouldBeSynchronized: true) -// self.storeCenter.createDeleteLog(instance) -//// await self._sendDeletion(instance) -// } - -// public func deleteDependencies(_ items: any RandomAccessCollection, actionOption: ActionOption) { -// guard items.isNotEmpty else { return } -// if actionOption.synchronize { -// self.delete(contentOfs: items) -// } else { -// self.deleteNoSync(contentOfs: items) -// } -// } - -// public func deleteDependencies(_ items: any Sequence) { -// -// self.collection.deleteDependencies(items) -// -//// super.deleteDependencies(items) -// -// let batch = OperationBatch() -// batch.deletes = Array(items) -// Task { await self._sendOperationBatch(batch) } -// } - -// public func deleteDependenciesAsync(_ items: any Sequence) async { -// super.deleteDependencies(items) -// -// let batch = OperationBatch() -// batch.deletes = Array(items) -// await self._sendOperationBatch(batch) -// } - fileprivate func _cleanUpSharedDependencies() { for relationship in T.relationships() { if let syncedType = relationship.type as? (any SyncedStorable.Type) { @@ -246,11 +198,6 @@ public class SyncedCollection: SomeSyncedCollection, Collect case .child: throw StoreError.invalidStoreLookup(from: type, to: relationship.type) } -// if relationship.storeLookup { -// store = self.store.storeCenter.mainStore -// } else { -// store = self.store -// } let collection: SyncedCollection = try store.syncedCollection() collection._deleteUnusedGrantedInstances(originStoreId: originStoreId) @@ -326,11 +273,6 @@ public class SyncedCollection: SomeSyncedCollection, Collect self.collection.addOrUpdate(contentOfs: sequence) } - /// Deletes the instance in the collection without synchronization -// func deleteNoSync(instance: T) { -// self.collection.delete(instance: instance) -// } - public func deleteNoSync(contentOfs sequence: any RandomAccessCollection) { self.collection.delete(contentOfs: sequence) } @@ -346,16 +288,6 @@ public class SyncedCollection: SomeSyncedCollection, Collect instance.deleteUnusedSharedDependencies(store: self.store) } - /// Deletes the instance in the collection without synchronization -// func deleteNoSyncNoCascade(id: String) { -// self.collection.deleteByStringId(id, actionOption: .standard) -// } -// -// /// Deletes the instance in the collection without synchronization -// func deleteNoSyncNoCascadeNoWrite(id: String) { -// self.collection.deleteByStringId(id, actionOption: .noCascadeNoWrite) -// } - func deleteByStringId(_ id: String, actionOption: ActionOption = .standard) { self.collection.deleteByStringId(id, actionOption: actionOption) } @@ -431,10 +363,6 @@ public class SyncedCollection: SomeSyncedCollection, Collect /// Adds or update an instance if it is newer than the local instance func addOrUpdateIfNewer(_ instance: T, shared: SharingStatus?) { - -// defer { -// self.triggerWrite() -// } if let index = self.collection.items.firstIndex(where: { $0.id == instance.id }) { let localInstance = self.collection.items[index] @@ -536,8 +464,6 @@ extension SyncedCollection: RandomAccessCollection { } set(newValue) { self.collection.update(newValue, index: index, actionOption: .standard) -// self.collection.items[index] = newValue -// self._triggerWrite = true } } }