// // DailyNotificationModel.xcdatamodeld // DailyNotificationPlugin // // Created by Matthew Raymer on 2025-09-22 // Copyright © 2025 TimeSafari. All rights reserved. // import Foundation import CoreData /** * Core Data model for Daily Notification Plugin * Mirrors Android SQLite schema for cross-platform consistency * * @author Matthew Raymer * @version 1.1.0 * @created 2025-09-22 09:22:32 UTC */ // MARK: - ContentCache Entity @objc(ContentCache) public class ContentCache: NSManagedObject { } extension ContentCache { @nonobjc public class func fetchRequest() -> NSFetchRequest { return NSFetchRequest(entityName: "ContentCache") } @NSManaged public var id: String? @NSManaged public var fetchedAt: Date? @NSManaged public var ttlSeconds: Int32 @NSManaged public var payload: Data? @NSManaged public var meta: String? } extension ContentCache: Identifiable { } // MARK: - Schedule Entity @objc(Schedule) public class Schedule: NSManagedObject { } extension Schedule { @nonobjc public class func fetchRequest() -> NSFetchRequest { return NSFetchRequest(entityName: "Schedule") } @NSManaged public var id: String? @NSManaged public var kind: String? @NSManaged public var cron: String? @NSManaged public var clockTime: String? @NSManaged public var enabled: Bool @NSManaged public var lastRunAt: Date? @NSManaged public var nextRunAt: Date? @NSManaged public var jitterMs: Int32 @NSManaged public var backoffPolicy: String? @NSManaged public var stateJson: String? } extension Schedule: Identifiable { } // MARK: - Callback Entity @objc(Callback) public class Callback: NSManagedObject { } extension Callback { @nonobjc public class func fetchRequest() -> NSFetchRequest { return NSFetchRequest(entityName: "Callback") } @NSManaged public var id: String? @NSManaged public var kind: String? @NSManaged public var target: String? @NSManaged public var headersJson: String? @NSManaged public var enabled: Bool @NSManaged public var createdAt: Date? } extension Callback: Identifiable { } // MARK: - History Entity @objc(History) public class History: NSManagedObject { } extension History { @nonobjc public class func fetchRequest() -> NSFetchRequest { return NSFetchRequest(entityName: "History") } @NSManaged public var id: String? @NSManaged public var refId: String? @NSManaged public var kind: String? @NSManaged public var occurredAt: Date? @NSManaged public var durationMs: Int32 @NSManaged public var outcome: String? @NSManaged public var diagJson: String? } extension History: Identifiable { } // MARK: - Persistence Controller // Phase 2: CoreData integration for advanced features // Phase 1: Stubbed out - CoreData model not yet created class PersistenceController { // Lazy initialization to prevent Phase 1 errors private static var _shared: PersistenceController? static var shared: PersistenceController { if _shared == nil { _shared = PersistenceController() } return _shared! } let container: NSPersistentContainer? private var initializationError: Error? init(inMemory: Bool = false) { // Phase 1: CoreData model doesn't exist yet, so we'll handle gracefully // Phase 2: Will create DailyNotificationModel.xcdatamodeld var tempContainer: NSPersistentContainer? = nil do { tempContainer = NSPersistentContainer(name: "DailyNotificationModel") if inMemory { tempContainer?.persistentStoreDescriptions.first?.url = URL(fileURLWithPath: "/dev/null") } var loadError: Error? = nil tempContainer?.loadPersistentStores { _, error in if let error = error as NSError? { loadError = error print("DNP-PLUGIN: CoreData model not found (Phase 1 - expected). Error: \(error.localizedDescription)") print("DNP-PLUGIN: CoreData features will be available in Phase 2") } } if let error = loadError { self.initializationError = error self.container = nil } else { tempContainer?.viewContext.automaticallyMergesChangesFromParent = true self.container = tempContainer } } catch { print("DNP-PLUGIN: Failed to initialize CoreData container: \(error.localizedDescription)") self.initializationError = error self.container = nil } } /** * Check if CoreData is available (Phase 2+) */ var isAvailable: Bool { return container != nil && initializationError == nil } }