feat(#251): expose backend error detail in apiFetch errors

Le wrapper apiFetch jetait `API error: 422` sans le body. Désormais lit
detail (string ou liste Pydantic) et le concatène au message :
`422: Neo4j config requires a non-empty 'index_name'`.

Permet aux pages StoreCreatePage / StoreEditPage de surfacer la cause
réelle du refus serveur dans l'errorMessage du form.
This commit is contained in:
Pier-Jean Malandrino 2026-05-04 13:55:57 +02:00
parent 3fe0d3daa5
commit 7873c6bd89

View file

@ -13,7 +13,31 @@ export async function apiFetch<T = unknown>(url: string, options: FetchOptions =
...options,
headers,
})
if (!response.ok) throw new Error(`API error: ${response.status}`)
if (!response.ok) {
const detail = await readErrorDetail(response)
throw new Error(detail ? `${response.status}: ${detail}` : `API error: ${response.status}`)
}
if (response.status === 204) return null as T
return response.json() as Promise<T>
}
async function readErrorDetail(response: Response): Promise<string | null> {
try {
const contentType = response.headers.get('content-type') ?? ''
if (!contentType.includes('application/json')) return null
const body = await response.json()
if (typeof body?.detail === 'string') return body.detail
if (Array.isArray(body?.detail)) {
return body.detail
.map((e: { loc?: unknown[]; msg?: string }) => {
const loc = Array.isArray(e.loc) ? e.loc.join('.') : ''
return loc ? `${loc}: ${e.msg ?? ''}` : (e.msg ?? '')
})
.filter(Boolean)
.join('; ')
}
return null
} catch {
return null
}
}