Files
luma/Sources/LumaCore/LumaDocument.swift
Ole André Vadla Ravnås c9fc806c10 Persist event log as a single file
events/ → events.log; EventStore takes a file URL directly. Open
copies follow the new name.
2026-05-20 19:16:41 +02:00

104 lines
3.3 KiB
Swift

import Foundation
public struct LumaDocument: Sendable, Equatable {
public enum Storage: Sendable, Equatable {
case file(URL)
case untitled(URL)
}
public var storage: Storage
public var url: URL {
switch storage {
case .file(let u), .untitled(let u):
return u
}
}
public var displayName: String {
switch storage {
case .file(let u):
let name = u.deletingPathExtension().lastPathComponent
return name.isEmpty ? "Untitled" : name
case .untitled:
return "Untitled"
}
}
public var isUntitled: Bool {
if case .untitled = storage { return true }
return false
}
public var sqliteURL: URL { url.appendingPathComponent("db.sqlite") }
public var sqlitePath: String { sqliteURL.path }
public var tracesDirectory: URL { url.appendingPathComponent("traces", isDirectory: true) }
public var eventsLogURL: URL { url.appendingPathComponent("events.log") }
public init(storage: Storage) {
self.storage = storage
}
}
public enum LumaDocumentError: Error {
case invalidPath(URL)
case copyFailed(URL, URL, Error)
}
public enum LumaDocumentLoader {
public static let fileExtension = "luma"
public static func open(at url: URL) throws -> LumaDocument {
guard FileManager.default.fileExists(atPath: url.path) else {
throw LumaDocumentError.invalidPath(url)
}
return LumaDocument(storage: .file(url))
}
/// Reopen a document that was previously auto-saved at `url` inside
/// the untitled directory. Keeps the `.untitled` storage kind so
/// the title bar still shows "Untitled" and Save As prompts for a
/// new location instead of overwriting the auto-save file.
public static func openUntitled(at url: URL) throws -> LumaDocument {
guard FileManager.default.fileExists(atPath: url.path) else {
throw LumaDocumentError.invalidPath(url)
}
return LumaDocument(storage: .untitled(url))
}
public static func makeUntitled(in directory: URL) throws -> LumaDocument {
let fm = FileManager.default
try fm.createDirectory(at: directory, withIntermediateDirectories: true)
let url: URL = {
for index in 0..<4096 {
let name = index == 0 ? "Untitled.luma" : "Untitled \(index).luma"
let candidate = directory.appendingPathComponent(name)
if !fm.fileExists(atPath: candidate.path) {
return candidate
}
}
return directory.appendingPathComponent("Untitled-\(UUID().uuidString).luma")
}()
try fm.createDirectory(at: url, withIntermediateDirectories: true)
return LumaDocument(storage: .untitled(url))
}
public static func saveAs(
_ document: LumaDocument,
to destination: URL
) throws -> LumaDocument {
let fm = FileManager.default
if fm.fileExists(atPath: destination.path) {
try fm.removeItem(at: destination)
}
do {
try fm.copyItem(at: document.url, to: destination)
} catch {
throw LumaDocumentError.copyFailed(document.url, destination, error)
}
return LumaDocument(storage: .file(destination))
}
}