/** * Batch operations (/api/batch/*). Used for multi-item copy — move and delete * already have per-item endpoints the files view loops over, but copy only * exists as a batch endpoint on the backend. */ import { apiFetch } from '$lib/api/client'; import { getCsrfHeaders } from '$lib/api/csrf'; const JSON_HEADERS = { 'Content-Type': 'application/json' }; async function post(url: string, body: unknown): Promise { const res = await apiFetch(url, { method: 'POST', credentials: 'same-origin', headers: { ...JSON_HEADERS, ...getCsrfHeaders() }, body: JSON.stringify(body) }); if (!res.ok) { const e = (await res.json().catch(() => ({}))) as { error?: string; message?: string }; throw new Error(e.error || e.message || `${url} failed: ${res.status}`); } } export function copyFiles(fileIds: string[], targetFolderId: string | null): Promise { if (fileIds.length === 0) return Promise.resolve(); return post('/api/batch/files/copy', { file_ids: fileIds, target_folder_id: targetFolderId }); } export function copyFolders(folderIds: string[], targetFolderId: string | null): Promise { if (folderIds.length === 0) return Promise.resolve(); return post('/api/batch/folders/copy', { folder_ids: folderIds, target_folder_id: targetFolderId }); } /** * Stream a multi-item selection as a server-built zip (`POST /api/batch/download` * — folders included, unlike the legacy per-item loop). The caller names and * saves the returned blob. */ export async function downloadBatch(fileIds: string[], folderIds: string[]): Promise { const res = await apiFetch('/api/batch/download', { method: 'POST', credentials: 'same-origin', headers: { ...JSON_HEADERS, ...getCsrfHeaders() }, body: JSON.stringify({ file_ids: fileIds, folder_ids: folderIds }) }); if (!res.ok) { const e = (await res.json().catch(() => ({}))) as { error?: string; message?: string }; throw new Error(e.error || e.message || `batch download failed: ${res.status}`); } return res.blob(); }