import Foundation struct ContentItem: Codable, Identifiable, Hashable { var id: String { slug.isEmpty ? title : slug } var slug: String var title: String var type: String var status: String var date: String var modified: String var category: String var tags: [String] var summary: String var author: String var cover: String var allowComments: Bool var menuOrder: Int var url: String var excerpt: String var markdown: String init( slug: String = "", title: String = "Untitled", type: String = "post", status: String = "draft", date: String = ISO8601DateFormatter().string(from: Date()), modified: String = "", category: String = "Notes", tags: [String] = [], summary: String = "", author: String = "Editor", cover: String = "", allowComments: Bool = true, menuOrder: Int = 0, url: String = "", excerpt: String = "", markdown: String = "# Untitled\n\nStart writing here." ) { self.slug = slug self.title = title self.type = type self.status = status self.date = date self.modified = modified self.category = category self.tags = tags self.summary = summary self.author = author self.cover = cover self.allowComments = allowComments self.menuOrder = menuOrder self.url = url self.excerpt = excerpt self.markdown = markdown } enum CodingKeys: String, CodingKey { case slug, title, type, status, date, modified, category, tags, summary, author, cover, url, excerpt, markdown case allowComments = "allow_comments" case menuOrder = "menu_order" } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) slug = try container.decodeIfPresent(String.self, forKey: .slug) ?? "" title = try container.decodeIfPresent(String.self, forKey: .title) ?? "Untitled" type = try container.decodeIfPresent(String.self, forKey: .type) ?? "post" status = try container.decodeIfPresent(String.self, forKey: .status) ?? "draft" date = try container.decodeIfPresent(String.self, forKey: .date) ?? "" modified = try container.decodeIfPresent(String.self, forKey: .modified) ?? "" category = try container.decodeIfPresent(String.self, forKey: .category) ?? "Notes" tags = try container.decodeIfPresent([String].self, forKey: .tags) ?? [] summary = try container.decodeIfPresent(String.self, forKey: .summary) ?? "" author = try container.decodeIfPresent(String.self, forKey: .author) ?? "Editor" cover = try container.decodeIfPresent(String.self, forKey: .cover) ?? "" allowComments = try container.decodeIfPresent(Bool.self, forKey: .allowComments) ?? true menuOrder = try container.decodeIfPresent(Int.self, forKey: .menuOrder) ?? 0 url = try container.decodeIfPresent(String.self, forKey: .url) ?? "" excerpt = try container.decodeIfPresent(String.self, forKey: .excerpt) ?? "" markdown = try container.decodeIfPresent(String.self, forKey: .markdown) ?? "" } } struct ContentMetadata: Codable { var title: String var slug: String var type: String var status: String var date: String var category: String var tags: [String] var summary: String var author: String var cover: String var allowComments: Bool var menuOrder: Int init(item: ContentItem) { title = item.title slug = item.slug type = item.type status = item.status date = item.date category = item.category tags = item.tags summary = item.summary author = item.author cover = item.cover allowComments = item.allowComments menuOrder = item.menuOrder } enum CodingKeys: String, CodingKey { case title, slug, type, status, date, category, tags, summary, author, cover case allowComments = "allow_comments" case menuOrder = "menu_order" } } struct MediaItem: Codable, Identifiable, Hashable { var id: String { path } var name: String var path: String var url: String var size: Int var modified: String var mime: String } struct CommentItem: Codable, Identifiable, Hashable { var id: Int var slug: String var author: String var email: String var website: String var body: String var status: String var createdAt: String var updatedAt: String enum CodingKeys: String, CodingKey { case id, slug, author, email, website, body, status case createdAt = "created_at" case updatedAt = "updated_at" } } struct PingResponse: Codable { var ok: Bool var name: String var authenticated: Bool var tokenConfigured: Bool enum CodingKeys: String, CodingKey { case ok, name, authenticated case tokenConfigured = "token_configured" } } struct ContentListResponse: Codable { var ok: Bool var items: [ContentItem] } struct ContentItemResponse: Codable { var ok: Bool var item: ContentItem } struct MediaListResponse: Codable { var ok: Bool var items: [MediaItem] } struct MediaItemResponse: Codable { var ok: Bool var item: MediaItem } struct CommentListResponse: Codable { var ok: Bool var items: [CommentItem] } struct BasicResponse: Codable { var ok: Bool var error: String? } struct APIErrorResponse: Codable { var ok: Bool? var error: String? }