docs: ajoute index+ancres et capitalise app-alexandrie

This commit is contained in:
MaksTinyWorkshop
2026-03-09 10:28:02 +01:00
parent 0ea345b1ae
commit a5ce37a3eb
12 changed files with 383 additions and 49 deletions

View File

@@ -8,7 +8,22 @@ Ce fichier contient **uniquement** des patterns back-end :
Objectif : éviter de réinventer la roue et réduire le temps de debug.
Dernière mise à jour : 25-01-2026
Dernière mise à jour : 09-03-2026
---
## Index
- [Format derreur API standardisé](#pattern-format-derreur-api-standardise)
- [Middleware de corrélation (requestId / traceId)](#pattern-middleware-correlation-requestid-traceid)
- [Idempotency key pour opérations sensibles](#pattern-idempotency-key-operations-sensibles)
- [Pagination robuste (cursor-based) pour les listings](#pattern-pagination-robuste-cursor-based)
- [Exécution asynchrone des tâches longues (queue + outbox light)](#pattern-execution-asynchrone-taches-longues)
- [Soft delete et archivage explicite](#pattern-soft-delete-archivage-explicite)
- [Webhooks sortants robustes et idempotents](#pattern-webhooks-sortants-robustes-idempotents)
- [Contracts-First / Zod-Infer / No-DTO (monorepo TypeScript fullstack)](#pattern-contracts-first-zod-infer-no-dto)
- [Guard global NestJS — ordre denregistrement et décorateurs de bypass](#pattern-guard-global-nestjs)
- [Provider-Strategy pour intégrations tierces — périmètre complet](#pattern-provider-strategy-integrations-tierces)
---
@@ -65,6 +80,7 @@ Si ce nest pas confirmé comme fonctionnel et utile, **ça na rien à fair
---
<a id="pattern-format-derreur-api-standardise"></a>
## Pattern : Format derreur API standardisé
- Objectif : fournir des erreurs prévisibles, exploitables et cohérentes pour tous les clients.
@@ -101,6 +117,7 @@ Si ce nest pas confirmé comme fonctionnel et utile, **ça na rien à fair
---
<a id="pattern-middleware-correlation-requestid-traceid"></a>
## Pattern : Middleware de corrélation (requestId / traceId)
- Objectif : relier chaque requête aux logs et erreurs associées.
@@ -131,6 +148,7 @@ Si ce nest pas confirmé comme fonctionnel et utile, **ça na rien à fair
---
<a id="pattern-idempotency-key-operations-sensibles"></a>
## Pattern : Idempotency key pour opérations sensibles
- Objectif : empêcher les doublons lors de retries ou timeouts.
@@ -161,6 +179,7 @@ Si ce nest pas confirmé comme fonctionnel et utile, **ça na rien à fair
---
<a id="pattern-pagination-robuste-cursor-based"></a>
## Pattern : Pagination robuste (cursor-based) pour les listings
- Objectif : fournir des listings stables et performants sans incohérences entre pages.
@@ -195,6 +214,7 @@ Si ce nest pas confirmé comme fonctionnel et utile, **ça na rien à fair
---
<a id="pattern-execution-asynchrone-taches-longues"></a>
## Pattern : Exécution asynchrone des tâches longues (queue + outbox light)
- Objectif : sortir les opérations longues ou fragiles du chemin request/response.
@@ -231,6 +251,7 @@ Si ce nest pas confirmé comme fonctionnel et utile, **ça na rien à fair
---
<a id="pattern-soft-delete-archivage-explicite"></a>
## Pattern : Soft delete et archivage explicite
- Objectif : permettre la suppression logique sans perte immédiate de données.
@@ -266,6 +287,7 @@ Si ce nest pas confirmé comme fonctionnel et utile, **ça na rien à fair
---
<a id="pattern-webhooks-sortants-robustes-idempotents"></a>
## Pattern : Webhooks sortants robustes et idempotents
- Objectif : garantir des intégrations fiables avec des systèmes externes.
@@ -302,6 +324,7 @@ Si ce nest pas confirmé comme fonctionnel et utile, **ça na rien à fair
---
<a id="pattern-contracts-first-zod-infer-no-dto"></a>
## Pattern : Contracts-First / Zod-Infer / No-DTO (monorepo TypeScript fullstack)
- Objectif : avoir une seule source de vérité pour les contrats dinterface entre API et client, sans redéfinition manuelle de types.
@@ -376,6 +399,7 @@ packages/contracts/src/
---
<a id="pattern-guard-global-nestjs"></a>
## Pattern : Guard global NestJS — ordre denregistrement et décorateurs de bypass
- Objectif : protéger tous les endpoints par défaut, avec un mécanisme explicite pour les exceptions.
@@ -423,19 +447,52 @@ if (skip) return true;
---
### Index (à remplir au fil des validations)
<a id="pattern-provider-strategy-integrations-tierces"></a>
## Pattern : Provider-Strategy pour intégrations tierces — périmètre complet
- Format derreur API standardisé
- Middleware de corrélation (requestId / traceId)
- Idempotency key pour opérations sensibles
- Pagination robuste (cursor-based) pour les listings
- Exécution asynchrone des tâches longues (queue + outbox light)
- Soft delete et archivage explicite
- Webhooks sortants robustes et idempotents
- Contracts-First / Zod-Infer / No-DTO (monorepo TypeScript fullstack)
- Guard global NestJS — ordre denregistrement et décorateurs de bypass
- Objectif : isoler intégralement la logique propre à un prestataire (Stripe, Brevo, Firebase…) derrière une interface stable, pour éviter la contamination du domaine par le SDK tiers.
- Contexte : backend NestJS/TypeScript avec 1+ prestataires externes (paiement, email, storage…).
- Quand lutiliser : dès quun service applicatif dépend dun SDK tiers (et plus encore sil y a des webhooks).
- Quand léviter : intégration ponctuelle non critique sans effet de bord (rare) — sinon on perd vite le contrôle.
- Avantage :
- Testabilité : mock du provider, pas du SDK
- Remplacement du prestataire sans refactor “en cascade”
- Responsabilités claires : provider = “parle Stripe”, service = “parle domaine”
- Limites / vigilance :
- Linterface doit exposer des **types normalisés** (pas de types Stripe)
- Le provider gère aussi les webhooks : validation signature, parsing event, mapping
- Validé le : 09-03-2026
- Contexte technique : NestJS v10+ / intégration Stripe (webhooks) — pattern généralisable
### Implémentation (exemple minimal)
```typescript
// billing-provider.interface.ts (pas d'import Stripe)
export type BillingPlan = 'MONTHLY' | 'ANNUAL';
export type BillingWebhookResult = {
userId: string;
externalId: string;
plan: BillingPlan;
status: 'ACTIVE' | 'INACTIVE' | 'CANCELLED';
currentPeriodEnd: Date | null;
};
export interface BillingProvider {
createCheckoutSession(userId: string, plan: BillingPlan): Promise<{ checkoutUrl: string }>;
cancelSubscription(externalId: string): Promise<void>;
handleWebhook(rawBody: Buffer, signature: string): Promise<BillingWebhookResult | null>;
}
// billing.service.ts (domaine uniquement)
async handleWebhook(rawBody: Buffer, signature: string): Promise<void> {
const result = await this.billingProvider.handleWebhook(rawBody, signature);
if (!result) return;
await this.prisma.subscription.upsert({ /* données normalisées */ });
}
```
---
### Notes importantes