Files
upload-gltf/lib/upload-api.ts
T
2026-04-24 15:37:45 +02:00

153 lines
4.5 KiB
TypeScript

// ---------------------------------------------------------------------------
// Client-side API helpers for upload operations
// ---------------------------------------------------------------------------
import type { FolderEntry } from './client-types'
import type { FileDiff } from './types'
export interface CheckResult {
exists: boolean
diffs: FileDiff[]
}
// ---------------------------------------------------------------------------
// Shared FormData builder
// ---------------------------------------------------------------------------
function buildUploadFormData(
folder: FolderEntry,
destination: string,
extra?: Record<string, string>,
): FormData {
const formData = new FormData()
formData.append('folderName', folder.folderName)
formData.append('destination', destination)
if (extra) {
for (const [key, value] of Object.entries(extra)) {
formData.append(key, value)
}
}
formData.append('files', folder.modelFile)
formData.append('fileTypes', 'model')
formData.append('textureNames', '')
for (const tex of folder.textures) {
formData.append('files', tex.file)
formData.append('fileTypes', 'texture')
formData.append('textureNames', tex.name)
}
return formData
}
// ---------------------------------------------------------------------------
// Check folder diffs against remote (GitHub)
// ---------------------------------------------------------------------------
/**
* Check whether a folder already exists on the remote repo and compute diffs.
* Throws on auth/network errors so callers can surface them to the user.
*/
export async function checkFolderDiffs(
folder: FolderEntry,
destination: string,
secret: string,
signal?: AbortSignal,
): Promise<CheckResult> {
const formData = buildUploadFormData(folder, destination)
const res = await fetch('/api/upload/check', {
method: 'POST',
headers: { 'x-upload-secret': secret.trim() },
body: formData,
signal,
})
const data = await res.json()
// Surface auth/server errors to the caller
if (!res.ok) {
throw new Error(data.error || `Erreur serveur (${res.status})`)
}
if (!data.success || !data.exists) {
return { exists: false, diffs: [] }
}
return { exists: true, diffs: (data.diffs || []) as FileDiff[] }
}
// ---------------------------------------------------------------------------
// Upload original files to Nextcloud Drive
// ---------------------------------------------------------------------------
/** Upload original files to Nextcloud Drive (no Blender compression). */
export async function uploadDrive(
folder: FolderEntry,
secret: string,
destination: string,
action: 'new' | 'replace',
signal?: AbortSignal,
): Promise<{ success: boolean; error?: string }> {
const formData = buildUploadFormData(folder, destination, { action })
try {
const res = await fetch('/api/upload/drive', {
method: 'POST',
headers: { 'x-upload-secret': secret.trim() },
body: formData,
signal,
})
const data = await res.json()
if (!data.success) return { success: false, error: data.error }
return { success: true }
} catch (err) {
if (err instanceof DOMException && err.name === 'AbortError') {
return { success: false, error: 'Upload annule' }
}
return { success: false, error: 'Erreur reseau (Drive)' }
}
}
// ---------------------------------------------------------------------------
// Upload files to GitHub (with Blender compression)
// ---------------------------------------------------------------------------
/** Upload files to GitHub (with Blender compression). */
export async function uploadGit(
folder: FolderEntry,
secret: string,
destination: string,
onProgress: (pct: number) => void,
signal?: AbortSignal,
): Promise<{ success: boolean; filename?: string; error?: string }> {
const formData = buildUploadFormData(folder, destination)
onProgress(10)
try {
const res = await fetch('/api/upload/git', {
method: 'POST',
headers: { 'x-upload-secret': secret.trim() },
body: formData,
signal,
})
onProgress(80)
const data = await res.json()
if (!data.success) {
return { success: false, error: data.error }
}
onProgress(100)
return { success: true, filename: folder.folderName }
} catch (err) {
if (err instanceof DOMException && err.name === 'AbortError') {
return { success: false, error: 'Upload annule' }
}
return { success: false, error: 'Erreur reseau' }
}
}