Refonte qualité (shared / back / front) #1

Open
z3n wants to merge 14 commits from chore/quality-refonte into main
Owner

Refonte qualité (shared / back / front)

Tour de l'app suivi d'une refonte qualité. 14 commits, chacun vérifié (typecheck, tests, build, runtime). Aucun changement fonctionnel régressif.

shared

  • Source de vérité unique des énums d'API ; fix API_STATUSES (NO_YAML manquant) ; types dérivés des constantes ; dédup de la validation ; dépendance front déclarée + exports map.

back (NestJS)

  • Validation d'environnement typée (refus de démarrer si var manquante).
  • Transaction sur setCurrent, fix N+1 sur le comptage des catégories.
  • console.*Logger ; I/O upload en async.
  • DTO validé sur l'upload (+ contraintes de longueur ; emails via @ValidateIf).
  • Coverage Vitest + infra migrations TypeORM (migration initiale vérifiée sur base vierge ; corrige le trou prod synchronize:false sans migrations). Dev inchangé (synchronize:true).
  • Tests : 48 → 59.

front (Angular 19)

  • Fuites de souscriptions RxJS éliminées (takeUntilDestroyed) sur tous les composants.
  • Config d'environnement + ErrorService + interceptor HTTP fonctionnel ; withInterceptors.
  • @gouvfr/dsfr en dependencies ; correction d'un build cassé préexistant (formValues privé utilisé en template).
  • ESLint 9 (flat config + angular-eslint) ; Vitest + 1er spec.
  • Composant <app-breadcrumb> mutualisé ; templates inline géants extraits en .html (upload 900→427 l., api-detail 700→330 l.) ; garde-fou de taille de fichier à l'upload.

Reste hors périmètre (volontairement)

Décomposition profonde de upload/api-detail en sous-composants, styles inline → SCSS, relations/cascade + bascule dev synchronize:false (stateful), durcissement sécurité (déprioritisé, interne/dev).

🤖 Generated with Claude Code

## Refonte qualité (shared / back / front) Tour de l'app suivi d'une refonte qualité. **14 commits**, chacun vérifié (typecheck, tests, build, runtime). Aucun changement fonctionnel régressif. ### shared - Source de vérité unique des énums d'API ; fix `API_STATUSES` (`NO_YAML` manquant) ; types dérivés des constantes ; dédup de la validation ; dépendance front déclarée + `exports` map. ### back (NestJS) - Validation d'environnement typée (refus de démarrer si var manquante). - Transaction sur `setCurrent`, fix N+1 sur le comptage des catégories. - `console.*` → `Logger` ; I/O upload en async. - **DTO validé sur l'upload** (+ contraintes de longueur ; emails via `@ValidateIf`). - Coverage Vitest + **infra migrations TypeORM** (migration initiale vérifiée sur base vierge ; corrige le trou prod `synchronize:false` sans migrations). Dev inchangé (`synchronize:true`). - Tests : **48 → 59**. ### front (Angular 19) - **Fuites de souscriptions RxJS éliminées** (`takeUntilDestroyed`) sur tous les composants. - Config d'environnement + `ErrorService` + interceptor HTTP fonctionnel ; `withInterceptors`. - `@gouvfr/dsfr` en `dependencies` ; correction d'un build cassé préexistant (`formValues` privé utilisé en template). - **ESLint 9** (flat config + angular-eslint) ; **Vitest** + 1er spec. - Composant `<app-breadcrumb>` mutualisé ; templates inline géants extraits en `.html` (`upload` 900→427 l., `api-detail` 700→330 l.) ; garde-fou de taille de fichier à l'upload. ### Reste hors périmètre (volontairement) Décomposition profonde de `upload`/`api-detail` en sous-composants, styles inline → SCSS, relations/cascade + bascule dev `synchronize:false` (stateful), durcissement sécurité (déprioritisé, interne/dev). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
z3n added 14 commits 2026-06-28 21:24:49 +00:00
- API_STATUSES inclut 'NO_YAML' (était manquant alors que le type et le
  code l'utilisent)
- ApiType/ApiStatus/ApiConvention dérivés des constantes (typeof X[number])
  -> plus de double maintenance type <-> tableau
- DTO back réutilisent API_CONVENTIONS/API_TYPES dans @IsIn (fin de la
  triple duplication des valeurs)
- front: déclare la dépendance @datacat/shared (workspace:*)
- shared: exports map + métadonnées + README (double build front/back)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- ConfigModule.forRoot({ validate }) : schéma class-validator des variables
  d'env, l'app refuse de démarrer si une var manque/mal typée ; suppression
  des fallbacks de credentials DB (getOrThrow)
- setCurrent() enveloppé dans une transaction (plus de fenêtre incohérente
  sur isCurrent entre les 2 updates)
- browse() : compteurs de toutes les catégories en 2 requêtes + calcul en
  mémoire au lieu d'un N+1 récursif par enfant
- console.* -> Logger Nest partout (apis, uploads, seeder, bootstrap) ;
  .catch(console.error) -> logger.error avec contexte

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
readFileSync/existsSync/mkdirSync -> fs/promises (readFile, mkdir recursive
idempotent). detectMainFile devient async. Retire l'import fs sync inutilisé.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- src/environments/{environment,environment.prod}.ts + fileReplacements :
  baseUrl API configurable au lieu de '/api' hardcodé dans les services
- ErrorService + errorInterceptor (HttpInterceptorFn) ; app.config passe à
  withInterceptors([...]) (remplace withInterceptorsFromDi legacy)
- @gouvfr/dsfr déplacé en dependencies (chargé au runtime)
- api.service: extrait ValidateResponse (dédup du type inline)
- fix: formValues passe en protected (utilisé dans le template -> build NG1
  cassé, le conteneur servait un ancien bundle)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Toutes les souscriptions des composants passent par
takeUntilDestroyed(this.destroyRef) : browse, catalog, api-detail, upload,
category-form-modal, category-delete-modal. api-detail abandonne le pattern
manuel Subscription/ngOnDestroy au profit de DestroyRef (ngOnDestroy ne garde
que le clearPoll du setInterval).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- CreateApiUploadDto : valide le multipart POST /uploads via ValidationPipe
  (types, @IsIn énums partagés, @IsUUID, @MaxLength(255)). Emails validés
  seulement si renseignés (@ValidateIf) -> n'casse pas les contacts vides.
  Remplace le body inline + les checks manuels du contrôleur.
- create-api-entry.dto: @MaxLength(255) sur name/provider/contacts (matche les
  colonnes entité) + @MaxLength sur emails.

Vérifié: email invalide -> 400 message clair, contacts vides -> 201 OK.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ajoute le provider de coverage + section coverage dans vitest.config (reporter
text/html/lcov, exclusions modules/entities/dto/main) et un script test:cov.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- eslint.config.js (flat) : recommended TS + angular-eslint (ts + templates
  a11y), règles selectors app + no-unused-vars (^_ ignoré)
- script lint -> 'eslint .' (+ lint:fix), évite la résolution du builder
  Angular sous pnpm
- fix de la seule violation (variable _ inutilisée dans l'effect catalog)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Vitest (cohérent avec le back) pour les tests de logique/services purs ;
  vitest-setup charge @angular/compiler (fallback JIT requis pour importer
  les symboles @angular/* partiellement compilés)
- error.service.spec.ts : 6 cas couvrant toMessage()
- script test -> vitest run (+ test:watch). Tests de composants TestBed =
  plugin Angular dédié, hors périmètre pour l'instant.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- data-source.ts (CLI) + scripts migration:generate/run/revert/show
- migration InitialSchema : schéma complet (categories, api_entries),
  vérifiée en l'appliquant sur une base vierge (crée aussi l'ext uuid-ossp)
- app.module: charge les migrations et migrationsRun en prod uniquement.
  Corrige un trou : la prod avait synchronize:false SANS migrations
  (schéma vide au déploiement). Dev inchangé (synchronize:true).

Bascule de dev vers migrations-only (synchronize:false + baseline de la base
dev existante) = étape ultérieure à faire en supervisé.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rejette les fichiers trop volumineux à la sélection avec un message clair,
avant lecture FileReader/envoi serveur.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extrait le fil d'Ariane DSFR dupliqué dans browse/api-detail/upload vers un
composant présentationnel piloté par une liste d'items. Chaque page construit
ses items (computed pour browse/api-detail, statique pour upload).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
upload (900->427 l.) et api-detail (700->330 l.) : le template inline géant
passe en templateUrl. Aucun changement de comportement (build + eslint a11y
+ runtime OK). Composants bien plus navigables ; les .html sont désormais
lintés par angular-eslint (a11y).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- env.validation.spec : config valide/coercion/défauts + rejets (var manquante,
  port hors plage, NODE_ENV inconnu)
- create-api-upload.dto.spec : name requis, emails @ValidateIf (vides OK,
  invalides rejetés), énum convention, MaxLength
- vitest-setup charge reflect-metadata (décorateurs class-validator en test)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin chore/quality-refonte:chore/quality-refonte
git checkout chore/quality-refonte
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: z3n/datacat#1