import Foundation /// The only type in the app that knows the on-disk directory layout. public struct AppSupportPaths: Sendable { public let root: URL public let spool: URL public let archive: URL public let outbox: URL public let watchFolder: URL /// Production paths. public static func standard() throws -> AppSupportPaths { let fileManager = FileManager.default let appSupportParent = try fileManager.url( for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true ) let desktop = try fileManager.url( for: .desktopDirectory, in: .userDomainMask, appropriateFor: nil, create: true ) let downloads = try fileManager.url( for: .downloadsDirectory, in: .userDomainMask, appropriateFor: nil, create: true ) let root = appSupportParent.appendingPathComponent("Shotdeck", isDirectory: true) return try AppSupportPaths(root: root, outbox: desktop, watchFolder: downloads) } /// Test paths rooted anywhere. Every directory is created if missing. public init(root: URL, outbox: URL, watchFolder: URL) throws { self.root = root self.spool = root.appendingPathComponent("spool", isDirectory: true) self.archive = root.appendingPathComponent("archive", isDirectory: true) self.outbox = outbox self.watchFolder = watchFolder try Self.createDirectory(self.root) try Self.createDirectory(self.spool) try Self.createDirectory(self.archive) try Self.createDirectory(self.outbox) try Self.createDirectory(self.watchFolder) } public func sessionDirectory(_ id: UUID) -> URL { spool.appendingPathComponent(id.uuidString, isDirectory: true) } public func archiveDirectory(_ id: UUID) -> URL { archive.appendingPathComponent(id.uuidString, isDirectory: true) } private static func createDirectory(_ url: URL) throws { try FileManager.default.createDirectory( at: url, withIntermediateDirectories: true ) } }