refactor: strengthen upload boundary types

This commit is contained in:
Tom Boullay
2026-04-27 17:21:44 +02:00
parent d049318a73
commit fd586f4185
7 changed files with 96 additions and 39 deletions
+35 -13
View File
@@ -16,6 +16,20 @@ export interface StageResult {
filesCount: number
}
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === 'object' && value !== null
}
function getApiError(data: unknown, fallback: string) {
return isRecord(data) && typeof data.error === 'string' ? data.error : fallback
}
function isFileDiff(value: unknown): value is FileDiff {
return isRecord(value)
&& typeof value.name === 'string'
&& (value.status === 'new' || value.status === 'changed' || value.status === 'deleted')
}
// ---------------------------------------------------------------------------
// Shared FormData builder
// ---------------------------------------------------------------------------
@@ -69,18 +83,20 @@ export async function checkFolderDiffs(
signal,
})
const data = await res.json()
const data: unknown = await res.json()
// Surface auth/server errors to the caller
if (!res.ok) {
throw new Error(data.error || `Erreur serveur (${res.status})`)
throw new Error(getApiError(data, `Erreur serveur (${res.status})`))
}
if (!data.success || !data.exists) {
if (!isRecord(data) || data.success !== true || data.exists !== true) {
return { exists: false, diffs: [] }
}
return { exists: true, diffs: (data.diffs || []) as FileDiff[] }
const diffs = Array.isArray(data.diffs) ? data.diffs.filter(isFileDiff) : []
return { exists: true, diffs }
}
export async function stageUpload(
@@ -96,10 +112,14 @@ export async function stageUpload(
signal,
})
const data = await res.json()
const data: unknown = await res.json()
if (!res.ok || !data.success) {
throw new Error(data.error || `Erreur serveur (${res.status})`)
if (!res.ok || !isRecord(data) || data.success !== true) {
throw new Error(getApiError(data, `Erreur serveur (${res.status})`))
}
if (typeof data.stagingId !== 'string' || typeof data.folderName !== 'string' || typeof data.filesCount !== 'number') {
throw new Error('Reponse serveur invalide')
}
return {
@@ -130,8 +150,10 @@ export async function uploadDrive(
body: JSON.stringify({ stagingId, action }),
signal,
})
const data = await res.json()
if (!data.success) return { success: false, error: data.error }
const data: unknown = await res.json()
if (!res.ok || !isRecord(data) || data.success !== true) {
return { success: false, error: getApiError(data, `Erreur serveur (${res.status})`) }
}
return { success: true }
} catch (err) {
if (err instanceof DOMException && err.name === 'AbortError') {
@@ -166,14 +188,14 @@ export async function uploadGit(
})
onProgress(80)
const data = await res.json()
const data: unknown = await res.json()
if (!data.success) {
return { success: false, error: data.error }
if (!res.ok || !isRecord(data) || data.success !== true) {
return { success: false, error: getApiError(data, `Erreur serveur (${res.status})`) }
}
onProgress(100)
return { success: true, filename: data.folderName }
return { success: true, filename: typeof data.folderName === 'string' ? data.folderName : undefined }
} catch (err) {
if (err instanceof DOMException && err.name === 'AbortError') {
return { success: false, error: 'Upload annule' }