Files
hyungi_document_server/Sources/DSKit/Models/Memo.swift
T
Hyungi 0becf7829e feat(s3): SwiftPM scaffold + DSKit data layer + 14-fixture acceptance
- Package.swift: AI (S2-owned) + DSKit (models/client/fixtures) + DSKitTests, tools 6.2, .swiftLanguageMode(.v6), .macOS(.v26)
- JSONValue (Sendable AnyCodable), DSDate (value-type ISO8601FormatStyle cascade, date-only UTC), explicit-CodingKeys decoder
- Models: Auth/Document(+Detail flat-compose, MD-first)/Catalog/Search+Ask/Memo/Digest; non-optional limited to id/file_type/created+updated_at/total
- DSClient protocol + FixtureDSClient (Bundle.module, zero backend) + DSError + DSConfig + DownloadURL (?token= query)
- Tests: 14-fixture contract acceptance (value asserts) + JSONValue number trap + Ask round-trip + AI router fallback/explicit-unavailable

swift build + swift test green (19 tests). Sources/AI untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 17:16:55 +09:00

72 lines
2.4 KiB
Swift

import Foundation
public struct MemoResponse: Codable, Sendable, Identifiable {
public let id: Int
public let title: String?
public let content: String?
public let fileFormat: String?
public let fileType: String?
public let filePath: String?
public let userTags: [String]?
public let aiTags: [String]?
public let aiDomain: String?
public let aiSubGroup: String?
public let aiSummary: String?
public let pinned: Bool?
public let archived: Bool?
public let askIncludable: Bool?
public let memoTaskState: JSONValue?
public let aiEventKind: String?
public let aiEventConfidence: Double?
public let sourceChannel: String?
public let sourceMetadata: JSONValue?
public let createdAtRaw: String?
public let updatedAtRaw: String?
public var createdAt: Date? { DSDate.parse(createdAtRaw) }
public var updatedAt: Date? { DSDate.parse(updatedAtRaw) }
public var isPinned: Bool { pinned ?? false }
public var isArchived: Bool { archived ?? false }
public var isAudio: Bool { fileType == "audio" }
/// Checked task indices derived from memo_task_state keys (index-keyed object).
public var checkedTaskIndices: Set<Int> {
guard let o = memoTaskState?.objectValue else { return [] }
var s = Set<Int>()
for k in o.keys { if let i = Int(k) { s.insert(i) } }
return s
}
enum CodingKeys: String, CodingKey {
case id, title, content, pinned, archived
case fileFormat = "file_format"
case fileType = "file_type"
case filePath = "file_path"
case userTags = "user_tags"
case aiTags = "ai_tags"
case aiDomain = "ai_domain"
case aiSubGroup = "ai_sub_group"
case aiSummary = "ai_summary"
case askIncludable = "ask_includable"
case memoTaskState = "memo_task_state"
case aiEventKind = "ai_event_kind"
case aiEventConfidence = "ai_event_confidence"
case sourceChannel = "source_channel"
case sourceMetadata = "source_metadata"
case createdAtRaw = "created_at"
case updatedAtRaw = "updated_at"
}
}
public struct MemoListResponse: Codable, Sendable {
public let items: [MemoResponse]
public let total: Int
public let page: Int
public let pageSize: Int
enum CodingKeys: String, CodingKey {
case items, total, page
case pageSize = "page_size"
}
}