mirror of
https://github.com/MaksTinyWorkshop/_Assistant_Lead_Tech
synced 2026-04-06 13:31:43 +02:00
ajout patterns
This commit is contained in:
@@ -55,17 +55,13 @@ FILE_UPDATE_PROPOSAL
|
||||
Fichier cible : 10_backend_patterns_valides.md
|
||||
|
||||
Pourquoi :
|
||||
Ordre d'enregistrement des Guards NestJS causant un bug
|
||||
`request.user undefined` observé à plusieurs reprises.
|
||||
Pattern réutilisable validé sur un projet réel.
|
||||
|
||||
Proposition :
|
||||
|
||||
## Ordre des Guards NestJS
|
||||
## Nom du pattern
|
||||
|
||||
Toujours enregistrer `AuthGuard` avant les Guards dépendants
|
||||
(`EmailVerifiedGuard`, `RoleGuard`, etc.).
|
||||
|
||||
Sinon `request.user` peut être undefined dans les guards suivants.
|
||||
Description courte, factuelle, orientée réutilisation.
|
||||
```
|
||||
|
||||
---
|
||||
@@ -104,129 +100,8 @@ Pour une feature de progression minimum viable :
|
||||
FILE_UPDATE_PROPOSAL
|
||||
Fichier cible : 10_frontend_patterns_valides.md
|
||||
|
||||
Pourquoi :
|
||||
Pattern frontend/mobile utile pour brancher un écran récapitulatif serveur sans dupliquer la logique réseau dans l'écran et sans navigation impérative via `store.getState()`.
|
||||
|
||||
Proposition :
|
||||
|
||||
## Écran récapitulatif branché sur store de domaine existant
|
||||
|
||||
Quand une vue récapitulative dépend d'un domaine déjà présent :
|
||||
- étendre le `service` et le `store` existants au lieu de créer un nouveau domaine artificiel
|
||||
- laisser l'écran purement déclaratif avec états `loading / error / empty / nominal`
|
||||
- déclencher le chargement via `useEffect` et actions du store
|
||||
- réserver `refresh` à une action idempotente du store
|
||||
- ajouter le point d'entrée depuis l'écran parent naturel (`library`, `profile`, etc.) au lieu de refondre la navigation globale
|
||||
|
||||
Réduit les régressions et garde le comportement async testable.
|
||||
|
||||
---
|
||||
|
||||
2026-03-10 — app-alexandrie
|
||||
|
||||
FILE_UPDATE_PROPOSAL
|
||||
Fichier cible : 10_frontend_patterns_valides.md
|
||||
|
||||
Pourquoi :
|
||||
Le pull-to-refresh mobile sur listes paginées a besoin d’une vraie idempotence côté store, sinon on crée des doublons et des courses réseau invisibles. Le pattern a été validé ici avec Zustand sans introduire de lib de cache serveur.
|
||||
|
||||
Proposition :
|
||||
Pattern "Refresh idempotent sur store de liste paginée" : conserver une promesse de refresh en vol partagée, refuser les refresh concurrents, remplacer atomiquement la liste à la fin du refresh, et dédupliquer les items par identifiant au merge des pages suivantes.
|
||||
|
||||
---
|
||||
|
||||
2026-03-10 — app-alexandrie
|
||||
|
||||
FILE_UPDATE_PROPOSAL
|
||||
Fichier cible : 10_frontend_risques_et_vigilance.md
|
||||
|
||||
Pourquoi :
|
||||
Un écran gated par des droits distants peut tomber dans un faux état `loading` infini si l’erreur de chargement des entitlements laisse les données à `null` et relance automatiquement l’effet. Le défaut a été détecté en review sur la Bibliothèque mobile.
|
||||
|
||||
Proposition :
|
||||
Risque "Loading infini sur écran gated" : si un écran dépend d’un store d’entitlements ou d’autorisations, distinguer explicitement `loading`, `error`, `ready`, et bloquer les retries automatiques en boucle après erreur tant qu’un retry utilisateur ou une nouvelle condition d’entrée n’a pas eu lieu.
|
||||
|
||||
# Rôle dans l'architecture
|
||||
|
||||
```
|
||||
Projet
|
||||
↓
|
||||
Proposition
|
||||
↓
|
||||
95_a_capitaliser.md
|
||||
↓
|
||||
Validation humaine
|
||||
↓
|
||||
Lead_tech
|
||||
```
|
||||
|
||||
Ce mécanisme permet :
|
||||
|
||||
- d'éviter la pollution de la base de connaissance
|
||||
- de capitaliser progressivement l'expérience des projets
|
||||
- de garder `Lead_tech` cohérent et fiable.
|
||||
|
||||
---
|
||||
|
||||
2026-03-10 — app-alexandrie
|
||||
|
||||
FILE_UPDATE_PROPOSAL
|
||||
Fichier cible : 10_backend_patterns_valides.md
|
||||
|
||||
Pourquoi :
|
||||
Quand une story métier demande un pouvoir interne limité, ajouter un rôle minimal persistant + un guard dédié permet de sécuriser l’authz sans ouvrir prématurément un RBAC complet. Le pattern a été validé ici pour la publication admin de contenus.
|
||||
|
||||
Proposition :
|
||||
Pattern "Autorisation interne minimale sans RBAC complet" : introduire un enum de rôle simple côté source de vérité backend (ex. `USER | ADMIN`), le propager dans la session/auth, puis créer un décorateur + guard dédiés à la capacité sensible. Éviter les booléens front, les emails hardcodés et les `if` dispersés dans les contrôleurs.
|
||||
|
||||
---
|
||||
|
||||
2026-03-10 — app-alexandrie
|
||||
|
||||
FILE_UPDATE_PROPOSAL
|
||||
Fichier cible : 10_frontend_patterns_valides.md
|
||||
|
||||
Pourquoi :
|
||||
Pour une capacité admin mince sur mobile, une route dédiée légère branchée sur le domaine existant et un refresh explicite du store après mutation permettent de rester testable et robuste sans lancer un back-office séparé.
|
||||
|
||||
Proposition :
|
||||
Pattern "UI admin légère sur domaine existant" : pour une action interne simple (publication, activation, modération légère), ajouter une route dédiée minimale qui réutilise le service/store métier existant, afficher le statut courant, bloquer les actions concurrentes avec un flag `isUpdating*`, et déclencher un refresh explicite des vues impactées après succès au lieu d’un `fire-and-forget`.
|
||||
|
||||
---
|
||||
2026-03-10 — app-alexandrie
|
||||
|
||||
FILE_UPDATE_PROPOSAL
|
||||
Fichier cible : 90_debug_et_postmortem.md
|
||||
|
||||
Pourquoi :
|
||||
`tsx` (esbuild) ignore `emitDecoratorMetadata` — l'injection par type NestJS est silencieusement `undefined` au runtime, même avec `emitDecoratorMetadata: true` dans tsconfig.json. Bug difficile à diagnostiquer car aucune erreur de compilation.
|
||||
|
||||
Proposition :
|
||||
|
||||
## tsx + NestJS : injection par type cassée silencieusement
|
||||
|
||||
**Contexte :** app-alexandrie, Epic 3, 2026-03-10
|
||||
|
||||
**Symptôme :** `TypeError: Cannot read properties of undefined (reading 'get')` dans le constructeur d'un service NestJS. `this.config` (de type `ConfigService`) est `undefined` malgré `@Injectable()` et `ConfigModule` correctement configuré.
|
||||
|
||||
**Cause racine :** `tsx` utilise esbuild pour transpiler TypeScript. esbuild ignore `emitDecoratorMetadata` même si activé dans tsconfig. NestJS ne peut donc pas résoudre les types pour l'injection de dépendances par type (`constructor(private config: ConfigService)`).
|
||||
|
||||
**Conditions :** runner = `tsx watch`, `module: nodenext` dans tsconfig (requis pour Prisma v7 ESM), `emitDecoratorMetadata: true` présent mais ignoré.
|
||||
|
||||
**Fix :** Remplacer l'injection `ConfigService` par `process.env['VAR']` directement dans le constructeur. `ConfigModule.forRoot` avec `isGlobal: true` charge dotenv en amont → `process.env` est peuplé avant l'instanciation des services.
|
||||
|
||||
```typescript
|
||||
// AVANT (cassé avec tsx)
|
||||
constructor(private readonly config: ConfigService) {
|
||||
const host = this.config.get('REDIS_HOST');
|
||||
}
|
||||
|
||||
// APRÈS (compatible tsx)
|
||||
constructor() {
|
||||
const host = process.env['REDIS_HOST'] ?? 'localhost';
|
||||
}
|
||||
```
|
||||
|
||||
**Alternative non retenue :** `nest start --watch` → conflits ESM/CJS avec Prisma v7 + `module: nodenext` (exports is not defined).
|
||||
|
||||
**Règle :** Dans un projet NestJS avec `tsx` comme runner, ne jamais injecter `ConfigService` par type. Toujours utiliser `process.env` directement dans les services d'infra (Redis, DB pools, etc.).
|
||||
|
||||
Reference in New Issue
Block a user