From df7b1461a7e96fed0956e0c4fe98efb5bf3db6f3 Mon Sep 17 00:00:00 2001 From: Laurent Date: Fri, 24 May 2024 09:57:09 +0200 Subject: [PATCH] Adds documentation --- LeStorage/Store.swift | 21 ++++++++++++--------- LeStorage/StoredCollection.swift | 16 ++++++++++++++-- LeStorage/StoredSingleton.swift | 8 ++++---- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/LeStorage/Store.swift b/LeStorage/Store.swift index 44bf0b9..fbe9861 100644 --- a/LeStorage/Store.swift +++ b/LeStorage/Store.swift @@ -26,8 +26,6 @@ public class Store { /// The Store singleton public static let main = Store() -// public fileprivate(set) var currentUser: User? = nil - /// A method to provide ids corresponding to the django storage public static func randomId() -> String { return UUID().uuidString.lowercased() @@ -81,16 +79,10 @@ public class Store { let collection = StoredCollection(synchronized: synchronized, store: Store.main, indexed: indexed, inMemory: inMemory, sendsUpdate: sendsUpdate, loadCompletion: nil) self._collections[T.resourceName()] = collection -// if synchronized { // register additional collection for api calls -// let apiCallCollection = StoredCollection>(synchronized: false, store: Store.main, loadCompletion: { apiCallCollection in -// self._rescheduleCalls(collection: apiCallCollection) -// }) -// self._apiCallsCollections[T.resourceName()] = apiCallCollection -// } - return collection } + /// Registers a StoredSingleton instance public func registerObject(synchronized: Bool, inMemory: Bool = false, sendsUpdate: Bool = true) -> StoredSingleton { // register collection @@ -102,12 +94,14 @@ public class Store { // MARK: - Settings + /// Stores the user UUID func setUserUUID(uuidString: String) { self._settingsStorage.update { settings in settings.userId = uuidString } } + /// Returns the user's UUID public var currentUserUUID: UUID? { if let uuidString = self._settingsStorage.item.userId, let uuid = UUID(uuidString: uuidString) { @@ -116,6 +110,7 @@ public class Store { return nil } + /// Returns a UUID, using the user's if possible public func mandatoryUserUUID() -> UUID { if let uuid = self.currentUserUUID { return uuid @@ -128,16 +123,19 @@ public class Store { } } + /// Returns the username func userName() -> String? { return self._settingsStorage.item.username } + /// Sets the username func setUserName(_ username: String) { self._settingsStorage.update { settings in settings.username = username } } + /// Disconnect the user from the storage and resets collection public func disconnect(resetOption: ResetOption? = nil) { try? self.service().disconnect() self._settingsStorage.update { settings in @@ -162,6 +160,7 @@ public class Store { } + /// Returns whether the system has a user token public func hasToken() -> Bool { do { _ = try self.service().keychainStore.getToken() @@ -229,6 +228,7 @@ public class Store { return try await self.service().runApiCall(apiCall) } + /// Executes an API call func execute(apiCall: ApiCall) async throws -> T { return try await self._executeApiCall(apiCall) } @@ -240,12 +240,14 @@ public class Store { return try await self.service().get() } + /// Resets all registered collection public func reset() { for collection in self._collections.values { collection.reset() } } + /// Loads all collection with the data from the server public func loadCollectionFromServer() { for collection in self._collections.values { Task { @@ -254,6 +256,7 @@ public class Store { } } + /// Returns whether any collection has pending API calls public func hasPendingAPICalls() -> Bool { return self._collections.values.contains(where: { $0.hasPendingAPICalls() }) } diff --git a/LeStorage/StoredCollection.swift b/LeStorage/StoredCollection.swift index f7865cd..562f0d2 100644 --- a/LeStorage/StoredCollection.swift +++ b/LeStorage/StoredCollection.swift @@ -132,8 +132,8 @@ public class StoredCollection: RandomAccessCollection, SomeCollecti } + /// Starts the JSON file decoding synchronously or asynchronously fileprivate func _loadFromFile() throws { -// let url: URL = try self._urlForJSONFile() if self.asynchronousIO { Task(priority: .high) { @@ -214,6 +214,7 @@ public class StoredCollection: RandomAccessCollection, SomeCollecti } + /// A method the treat the collection as a single instance holder func setSingletonNoSync(instance: T) { defer { self._hasChanged = true @@ -251,6 +252,7 @@ public class StoredCollection: RandomAccessCollection, SomeCollecti } } + /// Adds or update a sequence of elements public func addOrUpdate(contentOfs sequence: any Sequence) throws { try self._addOrUpdate(contentOfs: sequence) } @@ -310,6 +312,7 @@ public class StoredCollection: RandomAccessCollection, SomeCollecti } + /// Proceeds to delete all instance of the collection, properly cleaning up dependencies and sending API calls public func deleteAll() throws { try self.delete(contentOfs: self.items) } @@ -350,10 +353,12 @@ public class StoredCollection: RandomAccessCollection, SomeCollecti Logger.log("End write") } + /// Simply clears the items of the collection func clear() { self.items.removeAll() } + /// Removes the items of the collection, deletes the corresponding file, and also reset the related API calls collection public func reset() { self.items.removeAll() @@ -373,6 +378,8 @@ public class StoredCollection: RandomAccessCollection, SomeCollecti // MARK: - Synchronization + /// Returns an APICall instance for the Storable [instance] and an HTTP [method] + /// The method updates existing calls or creates a new one fileprivate func _callForInstance(_ instance: T, method: HTTPMethod) throws -> ApiCall? { guard let apiCallCollection = self.apiCallsCollection else { throw StoredCollectionError.missingApiCallCollection @@ -395,6 +402,7 @@ public class StoredCollection: RandomAccessCollection, SomeCollecti } } + /// Creates an API call for the Storable [instance] and an HTTP [method] fileprivate func _createCall(_ instance: T, method: HTTPMethod) throws -> ApiCall { let baseURL = try _store.service().baseURL let jsonString = try instance.jsonString() @@ -410,6 +418,7 @@ public class StoredCollection: RandomAccessCollection, SomeCollecti return ApiCall(url: url, method: method.rawValue, dataId: String(instance.id), body: jsonString) } + /// Prepares a call for execution by updating its properties and adding it to its collection for storage fileprivate func _prepareCall(apiCall: ApiCall) throws { apiCall.lastAttemptDate = Date() apiCall.attemptsCount += 1 @@ -488,14 +497,15 @@ public class StoredCollection: RandomAccessCollection, SomeCollecti /// Indicates if the collection is currently retrying ApiCalls fileprivate var _isRetryingCalls: Bool = false + /// Reschedule API calls if necessary func rescheduleApiCallsIfNecessary() { if !self._isRetryingCalls { self._rescheduleApiCalls() } } + /// Reschedule API calls fileprivate func _rescheduleApiCalls() { -// return guard let apiCallsCollection, apiCallsCollection.isNotEmpty else { return @@ -532,6 +542,7 @@ public class StoredCollection: RandomAccessCollection, SomeCollecti } + /// Deletes an API call by [id] func deleteApiCallById(_ id: String) throws { guard let apiCallsCollection else { throw StoreError.apiCallCollectionNotRegistered(type: T.resourceName()) @@ -539,6 +550,7 @@ public class StoredCollection: RandomAccessCollection, SomeCollecti try apiCallsCollection.deleteById(id) } + /// Returns if the API call collection is not empty func hasPendingAPICalls() -> Bool { guard let apiCallsCollection else { return false } return apiCallsCollection.isNotEmpty diff --git a/LeStorage/StoredSingleton.swift b/LeStorage/StoredSingleton.swift index e656704..9fb2d70 100644 --- a/LeStorage/StoredSingleton.swift +++ b/LeStorage/StoredSingleton.swift @@ -7,28 +7,28 @@ import Foundation +/// A class extending the capabilities of StoredCollection but supposedly manages only one item public class StoredSingleton: StoredCollection { + /// Sets the singleton to the collection without synchronizing it public func setItemNoSync(_ instance: T) { self.setSingletonNoSync(instance: instance) } + /// updates the existing singleton public func update() throws { if let item = self.item() { try self.addOrUpdate(instance: item) } } + /// Returns the singleton public func item() -> T? { return self.items.first } // MARK: - Protects from use -// public override func addOrUpdate(instance: T) throws { -// fatalError("method unavailable for StoredSingleton") -// } - public override func addOrUpdate(contentOfs sequence: any Sequence) throws { fatalError("method unavailable for StoredSingleton, use update") }