/** * เปลี่ยน snapshot fields ของ version (จาก GET .../versions) ให้เป็น list ที่ UI ใช้แสดงได้ * snapshot มี 2 รูปตามที่ backend เก็บ (phase 3): * - เอกสารผูก template: { key: { value: string, missing: boolean } } * - เอกสารไม่ผูก template: map ดิบ { key: value } * pure function — แยกไว้ให้ unit test ได้ (Phase 7) */ export interface SnapshotEntry { key: string value: string missing: boolean } export function normalizeSnapshot(fields: unknown, orderKeys?: string[]): SnapshotEntry[] { if (fields === null || fields === undefined || typeof fields !== 'object') return [] const entries = new Map() for (const [key, raw] of Object.entries(fields as Record)) { if (raw !== null && typeof raw === 'object' && 'value' in raw) { const obj = raw as { value?: unknown; missing?: unknown } entries.set(key, { key, value: obj.value === null || obj.value === undefined ? '' : String(obj.value), missing: obj.missing === true, }) } else { entries.set(key, { key, value: raw === null || raw === undefined ? '' : String(raw), missing: false }) } } const list = [...entries.values()] if (orderKeys?.length) { // เรียงตามลำดับ field defs ของ template — key ที่ไม่มีใน defs ต่อท้ายตามตัวอักษร const rank = new Map(orderKeys.map((k, i) => [k, i])) list.sort((a, b) => { const ra = rank.get(a.key) ?? orderKeys.length const rb = rank.get(b.key) ?? orderKeys.length return ra === rb ? a.key.localeCompare(b.key) : ra - rb }) } return list }