diff --git a/.todo/tickets/95eb1fe7.yaml b/.todo/tickets/95eb1fe7.yaml index da4b1e3..ee3110d 100644 --- a/.todo/tickets/95eb1fe7.yaml +++ b/.todo/tickets/95eb1fe7.yaml @@ -1,4 +1,11 @@ id: 95eb1fe7 title: Define FileNode model (core-file-discovery TASK-02) -status: To Do +status: Done created_at: 2026-06-05T02:38:57.829857104Z +transitions: + - from: To Do + to: In Progress + at: 2026-06-06T17:54:43.8554997Z + - from: In Progress + to: Done + at: 2026-06-06T17:55:42.363318717Z diff --git a/.todo/tickets/ec0653c4.yaml b/.todo/tickets/ec0653c4.yaml index b40ca7a..085810c 100644 --- a/.todo/tickets/ec0653c4.yaml +++ b/.todo/tickets/ec0653c4.yaml @@ -1,4 +1,11 @@ id: ec0653c4 title: Implement recursive .md file discovery (core-file-discovery TASK-01) -status: To Do +status: Done created_at: 2026-06-05T02:38:57.826481921Z +transitions: + - from: To Do + to: In Progress + at: 2026-06-06T17:48:09.34035645Z + - from: In Progress + to: Done + at: 2026-06-06T17:49:37.974735989Z diff --git a/Sources/Core/FileDiscovery.swift b/Sources/Core/FileDiscovery.swift new file mode 100644 index 0000000..d74c2b4 --- /dev/null +++ b/Sources/Core/FileDiscovery.swift @@ -0,0 +1,29 @@ +import Foundation + +public enum DiscoveryError: Error { + case notADirectory(URL) +} + +public func discoverMarkdownFiles(in directoryURL: URL) throws -> [URL] { + var isDirectory: ObjCBool = false + guard FileManager.default.fileExists(atPath: directoryURL.path, isDirectory: &isDirectory), + isDirectory.boolValue else { + throw DiscoveryError.notADirectory(directoryURL) + } + + let enumerator = FileManager.default.enumerator( + at: directoryURL, + includingPropertiesForKeys: [.isDirectoryKey], + options: [.skipsHiddenFiles] + ) + + var results: [URL] = [] + while let url = enumerator?.nextObject() as? URL { + let values = try? url.resourceValues(forKeys: [.isDirectoryKey]) + if values?.isDirectory == false, url.pathExtension == "md" { + results.append(url) + } + } + + return results.sorted { $0.path < $1.path } +} diff --git a/Sources/Core/FileNode.swift b/Sources/Core/FileNode.swift new file mode 100644 index 0000000..5b749e2 --- /dev/null +++ b/Sources/Core/FileNode.swift @@ -0,0 +1,22 @@ +import Foundation + +public indirect enum FileNode: Equatable, Identifiable { + case file(name: String, path: URL) + case directory(name: String, path: URL, children: [FileNode]) + + public var id: URL { path } + + public var name: String { + switch self { + case .file(let name, _): return name + case .directory(let name, _, _): return name + } + } + + public var path: URL { + switch self { + case .file(_, let path): return path + case .directory(_, let path, _): return path + } + } +}