You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
LeStorage/LeStorage/Storable.swift

84 lines
2.8 KiB

//
// Storable.swift
// LeStorage
//
// Created by Laurent Morvillier on 03/02/2024.
//
import Foundation
/// A protocol describing classes that can be stored locally in JSON and synchronized on our django server
public protocol Storable: Codable, Identifiable, NSObjectProtocol {
/// The store containing a reference to the instance
var store: Store? { get set }
/// The resource name corresponding to the resource path on the API
/// Also used as the name of the local file
static func resourceName() -> String
/// A method that deletes the local dependencies of the resource
/// Mimics the behavior of the cascading delete on the django server
/// Typically when we delete a resource, we automatically delete items that depends on it,
/// so when we do that on the server, we also need to do it locally
func deleteDependencies(store: Store, actionOption: ActionOption)
/// A method that deletes dependencies of shared resources, but only if they are themselves shared
/// and not referenced by other objects in the store
/// This is used when cleaning up shared objects that are no longer in use
func deleteUnusedSharedDependencies(store: Store)
/// Copies the content of another item into the instance
/// This behavior has been made to get live updates when looking at properties in SwiftUI screens
func copy(from other: any Storable)
/// This method returns RelationShips objects of the type
static func relationships() -> [Relationship]
static func parentRelationships() -> [Relationship]
static func childrenRelationships() -> [Relationship]
static func storeParent() -> Bool
}
extension Storable {
/// Returns a filename for the class type
static func fileName() -> String {
return self.resourceName() + ".json"
}
/// Returns a string id for the instance
public var stringId: String {
switch self.id {
case let sp as any StringProtocol:
return String(sp)
case let intLitteral as any ExpressibleByIntegerLiteral:
return "\(intLitteral)"
default:
fatalError("id not convertible to string")
}
}
/// Returns the relative path of the instance for the django server
static func path(id: String? = nil) -> String {
var path = self.resourceName() + "/"
if let id {
path.append(id)
path.append("/")
}
return path
}
static func buildRealId(id: String) -> ID {
switch ID.self {
case is String.Type:
return id as! ID
case is Int64.Type:
return Formatter.number.number(from: id)?.int64Value as! ID
default:
fatalError("ID \(type(of: ID.self)) is neither String nor Int, can't parse \(id)")
}
}
}