- ExceptionHandler : convertit les violations de contrainte unique PG (23505) en réponse `{ errors: [{ code: 'duplicate', field, message }] }` 422 au lieu d'un 500 avec stack pg-protocol. Extrait le nom de colonne via regex sur le `detail` PG.
- InvoicesController.store + ImportBatchesController.validateDraft : wrap les appels schedulers (Redis side-effect, hors tx) dans try/catch + logger.warn. Si Redis flanche, l'invoice est créée et la requête HTTP retourne 201 normalement — l'utilisateur peut re-déclencher la programmation plus tard. Évite qu'une panne Redis casse le path de saisie.
43 lines
1.3 KiB
TypeScript
43 lines
1.3 KiB
TypeScript
import app from '@adonisjs/core/services/app'
|
|
import { type HttpContext, ExceptionHandler } from '@adonisjs/core/http'
|
|
|
|
/**
|
|
* Exception handler API JSON-only. On normalise les erreurs DB / Vine
|
|
* en réponse `{ errors: [...] }` (cf. backend.md §6 pour le contrat).
|
|
*/
|
|
export default class HttpExceptionHandler extends ExceptionHandler {
|
|
protected debug = !app.inProduction
|
|
|
|
async handle(error: unknown, ctx: HttpContext) {
|
|
// Postgres unique violation → 422 avec field/code stables, pas un
|
|
// 500 avec stack pg-protocol.
|
|
if (
|
|
error &&
|
|
typeof error === 'object' &&
|
|
'code' in error &&
|
|
(error as { code: unknown }).code === '23505'
|
|
) {
|
|
const detail = String((error as { detail?: unknown }).detail ?? '')
|
|
// Tente d'extraire le nom de colonne du message PG ("Key (numero, ...)").
|
|
const fieldMatch = detail.match(/Key \(([^)]+)\)=/)
|
|
const field = fieldMatch?.[1]?.split(',')[0]?.trim()
|
|
ctx.response.status(422)
|
|
return ctx.response.json({
|
|
errors: [
|
|
{
|
|
code: 'duplicate',
|
|
message: 'Cette valeur existe déjà.',
|
|
field: field ?? undefined,
|
|
},
|
|
],
|
|
})
|
|
}
|
|
|
|
return super.handle(error, ctx)
|
|
}
|
|
|
|
async report(error: unknown, ctx: HttpContext) {
|
|
return super.report(error, ctx)
|
|
}
|
|
}
|