import { config } from "../config"; import { UploadVersionResult, VersionRecord } from "../models/versionRecord"; import { apiFetch, apiGetJson, apiSendExpectJson, ApiError, readErrorMessage } from "./apiClient"; import { generateGuid } from "./metadataService"; /** * เรียก version API ของ backend (FR-5/6/7 ฝั่ง client) * `fields` = map จาก `readContentControlFields()` ตาม FR-11 */ /** FR-5 — อัปโหลดไฟล์ปัจจุบันเป็น version ใหม่ (แนบ fields map ถ้ามี) * + FR-13: แนบ commit message ทางเลือกของผู้ใช้ * + FR-16: แนบ templateId เฉพาะตอน Start Versioning ของไฟล์ร่าง (backend ใช้ตอน auto-create Document) */ export async function uploadVersion( documentId: string, file: Blob, clientVersionId: string, fields?: Record, fileName?: string, message?: string, pdf?: Blob, templateId?: string ): Promise { const form = new FormData(); form.append("file", file, fileName || `${documentId}.docx`); form.append("clientVersionId", clientVersionId); if (pdf) form.append("pdf", pdf, `${documentId}.pdf`); if (fields && Object.keys(fields).length > 0) { form.append("fields", JSON.stringify(fields)); } const trimmedMessage = message?.trim(); if (trimmedMessage) { form.append("message", trimmedMessage); } if (templateId) { form.append("templateId", templateId); } return apiSendExpectJson( `/api/documents/${documentId}/versions`, { method: "POST", body: form }, "อัปโหลด version ไม่สำเร็จ" ); } /** FR-6 — version history เรียงใหม่ → เก่า */ export async function getVersions(documentId: string): Promise { return apiGetJson( `/api/documents/${documentId}/versions`, "โหลด version history ไม่สำเร็จ" ); } /** FR-7 — URL ของ download endpoint (ผ่าน backend proxy เท่านั้น — MinIO ไม่ถูก expose) */ export function buildDownloadUrl( documentId: string, versionId: string, format?: "docx" | "pdf" ): string { return `${config.apiBaseUrl}/api/documents/${documentId}/versions/${versionId}/download${format === "pdf" ? "?format=pdf" : ""}`; } export interface VersionDownloadLink { url: string; /** ISO-8601 เวลาที่ URL หมดอายุ */ expiresAt: string; } /** * FR-7 — ขอ presigned URL อายุสั้นของ version หนึ่ง เพื่อเปิดในเบราว์เซอร์ของผู้ใช้ * (webview ของ Word ทิ้ง blob download เงียบๆ — ให้เบราว์เซอร์จริงจัดการแทน) */ export async function getDownloadLink( documentId: string, versionId: string, format?: "docx" | "pdf" ): Promise { return apiGetJson( `/api/documents/${documentId}/versions/${versionId}/download-link${format === "pdf" ? "?format=pdf" : ""}`, "ขอลิงก์ดาวน์โหลดไม่สำเร็จ" ); } /** FR-7 — ดาวน์โหลดไฟล์ของ version หนึ่งเป็น Blob (ต้องแนบ Bearer จึงต้อง fetch แทน link ตรง) */ export async function downloadVersion( documentId: string, versionId: string, format?: "docx" | "pdf" ): Promise { const response = await apiFetch(buildDownloadUrl(documentId, versionId, format)); if (!response.ok) { throw new ApiError( response.status, await readErrorMessage(response, `ดาวน์โหลด version ไม่สำเร็จ (${response.status})`) ); } return response.blob(); } /** สร้าง clientVersionId ใหม่สำหรับ upload ครั้งถัดไป */ export function newClientVersionId(): string { return generateGuid(); }