Couverture du plan
Chaque point du plan d'origine (Plan d'apprentissage NestJS, profil Java/Spring) est relié ici à la section du site qui le traite. Si vous avez lu toutes les sections citées, vous avez couvert l'ensemble du plan.
Sections générales du plan
| Section du plan | Contenu | Traité dans |
|---|---|---|
| En-tête | Démarrage le 9/11/2026, 11 jours, prérequis, stack, fil rouge TaskFlow | Plan et méthode |
| 1. Principe de travail | Matin théorie (3 h), après-midi pratique (3 h), 30 min de LEARNINGS.md + tag jour-XX, 11/11 férié, un commit par jour | Méthode, journal |
| 2. Calendrier | Les 11 jours, thèmes et livrables | Calendrier |
| 3. Table Spring ↔ NestJS | Les 34 correspondances | Web, injection, données, pipeline, configuration, sécurité, asynchrone, tests, outillage |
| 4. Event loop vs thread-per-request | Un thread JS, await partout, pas de calcul lourd, promesse non attendue, Promise.all, WebFlux | Event loop, conséquences, calcul CPU, WebFlux |
| 4. Conteneur d'injection | Types effacés, emitDecoratorMetadata, tokens pour les interfaces, déclarer et exporter, forwardRef | Effacement des types, tokens, pas de scan, dépendances circulaires |
| 4. Écosystème | npm et lockfiles, pas de JVM, décorateurs = fonctions | Écosystème |
| 6. Modèle de domaine | USER, PROJECT, PROJECT_MEMBER, TASK ; statuts | Modèle, statuts |
| 7. Docker Compose | db, db-test (tmpfs), adminer, redis optionnel ; .env.example | docker-compose.yml, fichiers .env |
| 8. Structure du repo | Arborescence cible, conventions de nommage | Arborescence, conventions |
| 9. Suivi de progression | Cases J1 à J11 | Suivi |
| 10. Ressources | Doc officielle, TypeORM, cours Fundamentals, event loop Node | Ressources |
| 11. Pièges fréquents | Les 8 pièges | await oublié, synchronize, entités brutes, dépendance circulaire, état dans un singleton, validation, égalité et this, @Res() |
J1 · Fondations Node et Nest
| Point du plan | Traité dans |
|---|---|
| Node, event loop (phases, microtasks vs macrotasks) | Event loop |
Promise, async/await | Promise et async/await |
| Modules ES / CommonJS | Modules ES et CommonJS |
Structure Nest : main.ts, AppModule, AppController, AppService | Structure d'un projet Nest |
Nest CLI : nest new, nest g module/controller/service/resource | Nest CLI, aide-mémoire Nest CLI |
npm i -g @nestjs/cli puis nest new taskflow | Générer le projet |
docker-compose.yml (PostgreSQL + Adminer) | Docker Compose |
GET /health renvoyant { status: 'ok' } | GET /health |
Repo git, .gitignore, README.md, LEARNINGS.md | Dépôt git |
Exercice /block contre /ping, puis await sleep(5000) | Exercice event loop |
SpringApplication.run ↔ NestFactory.create | Structure d'un projet Nest |
J2 · Controllers, DTO, validation
| Point du plan | Traité dans |
|---|---|
| Décorateurs de routing | Routing |
Status codes (@HttpCode) | Codes de statut |
| Versioning d'API | Versioning |
DTO en classes, class-validator, class-transformer | DTO et validation |
ValidationPipe global (whitelist, transform, forbidNonWhitelisted) | ValidationPipe global |
@nestjs/mapped-types : PartialType, PickType, OmitType | Mapped types |
nest g resource projects | Générer la ressource |
CreateProjectDto, UpdateProjectDto avec validation | DTO |
| CRUD en mémoire | CRUD en mémoire |
Pagination et filtre via @Query() et un QueryDto | Pagination |
@Valid + Bean Validation ↔ ValidationPipe + class-validator | Spring → NestJS |
ResponseEntity ↔ objet + @HttpCode (ou @Res(), à éviter) | Codes de statut, pièges |
J3 · Injection de dépendances et modules
| Point du plan | Traité dans |
|---|---|
Providers : useClass, useValue, useFactory, useExisting | Providers |
Tokens personnalisés, @Inject, @Optional | Tokens |
| Scopes : default, request, transient (coût et limites) | Scopes |
Modules : imports, exports, @Global | Modules |
Modules dynamiques (forRoot, forRootAsync) | Modules dynamiques |
Logique isolée dans ProjectsService | ProjectsService |
Abstraction ProjectsStore (interface + token) en mémoire | ProjectsStore |
CommonModule pour les utilitaires partagés | CommonModule |
@Configuration + @Bean ↔ useFactory | Providers |
| Profil conditionnel ↔ provider choisi selon la configuration | ProjectsStore |
J4 · PostgreSQL et TypeORM
| Point du plan | Traité dans |
|---|---|
@nestjs/typeorm, forRoot / forRootAsync / forFeature | @nestjs/typeorm |
| Entités, colonnes | Entités |
Types PostgreSQL : uuid, timestamptz, jsonb, enums | Types PostgreSQL |
Repository : find, findOne, save, softDelete | Repository |
QueryBuilder | QueryBuilder |
synchronize: true en dev uniquement | synchronize |
Entité Project | L'entité Project |
| Remplacer la mémoire par TypeORM sans changer le contrôleur | TypeORM derrière ProjectsStore |
| Seed de données de dev | Seed |
JpaRepository ↔ Repository<T> ; pas de requêtes dérivées (ILike, QueryBuilder) ; pas de Page<T> (findAndCount + skip/take) | Spring → NestJS, recherche et pagination |
J5 · Relations, migrations, transactions
| Point du plan | Traité dans |
|---|---|
OneToMany, ManyToOne, ManyToMany | Relations |
Chargement eager, lazy, relations: [] | Chargement |
Problème N+1, leftJoinAndSelect | N+1 |
Migrations : generate, run, revert ; désactiver synchronize | Migrations |
Transactions : dataSource.transaction(), QueryRunner | Transactions, QueryRunner |
Entité Task liée à Project | L'entité Task |
POST /projects/:id/tasks, PATCH /tasks/:id/status | Endpoints |
| Archiver un projet et ses tâches (transaction) | Archiver |
| Première migration générée et versionnée | La première migration |
@Transactional ↔ pas d'équivalent déclaratif, manager propagé | Transactions |
J6 · Pipeline de requête
| Point du plan | Traité dans |
|---|---|
| Ordre d'exécution Middleware → … → Exception Filters | Ordre d'exécution |
| Exceptions HTTP intégrées | Exceptions HTTP |
ExceptionFilter, @Catch(), APP_FILTER | Filtre global |
Pipes : ParseUUIDPipe, ParseEnumPipe, pipes custom | Pipes |
| Interceptors : logging, timing, mapping de réponse, cache | Interceptors |
Middleware fonctionnel ou classe, configure(consumer) | Middleware |
AllExceptionsFilter global au format problem+json | AllExceptionsFilter |
| Erreurs TypeORM : unicité → 409, non trouvé → 404 | Erreurs TypeORM |
LoggingInterceptor (durée, méthode, route) | LoggingInterceptor |
CorrelationIdMiddleware | CorrelationIdMiddleware |
@ControllerAdvice ↔ APP_FILTER ; Filter ↔ middleware ; @Around ↔ interceptor | Spring → NestJS |
J7 · Configuration et logging
| Point du plan | Traité dans |
|---|---|
ConfigModule.forRoot({ isGlobal, validate }) | ConfigModule |
registerAs, config typée | Configuration typée |
Validation du schéma d'environnement (Joi ou class-validator) | Validation |
Logging : Logger Nest ou nestjs-pino | Logging |
OnModuleInit, OnApplicationShutdown, enableShutdownHooks() | Cycle de vie |
.env.development, .env.test, .env.example (seul versionné) | Fichiers .env |
| Config typée pour DB, JWT, port | Configuration typée |
Logs JSON avec correlationId via nestjs-pino | Logs JSON |
@ConfigurationProperties ↔ registerAs ; @PostConstruct ↔ OnModuleInit ; @PreDestroy ↔ OnModuleDestroy ; profils ↔ NODE_ENV | Spring → NestJS, profils |
J8 · Authentification et autorisation
| Point du plan | Traité dans |
|---|---|
@nestjs/passport + passport-jwt, @nestjs/jwt | Passport et JWT |
Hash : argon2 ou bcrypt | Hash de mot de passe |
AuthGuard, guard global, @Public() | Guard global, routes publiques |
Décorateurs de paramètre (@CurrentUser()) | @CurrentUser() |
RBAC : @Roles() + RolesGuard avec Reflector | RBAC |
Module users (User, rôles ADMIN / MEMBER) | Module users |
POST /auth/register, POST /auth/login (option refresh token) | Inscription et connexion, refresh token |
Guard JWT global, routes publiques @Public() | Guard JWT global |
| Un utilisateur ne voit que ses projets | Un utilisateur ne voit que ses projets |
SecurityFilterChain ↔ guards globaux ; @PreAuthorize ↔ @Roles ; SecurityContextHolder ↔ @CurrentUser() | Spring → NestJS |
J9 · Événements, cron, queues
| Point du plan | Traité dans |
|---|---|
@nestjs/event-emitter : emit, @OnEvent, listeners async | Événements applicatifs |
@nestjs/schedule : @Cron, @Interval, @Timeout | Tâches planifiées |
@nestjs/bullmq : processors, retries, backoff | Jobs Redis |
| Une exception de listener ne remonte pas à l'appelant | Erreurs asynchrones |
Événement task.status.changed → NotificationsListener | Événement |
Cron quotidien OVERDUE | Cron OVERDUE |
| Optionnel : Redis + BullMQ pour les notifications | File BullMQ |
ApplicationEventPublisher ↔ EventEmitter2 ; @EventListener ↔ @OnEvent ; @Scheduled ↔ @Cron ; JMS / Batch ↔ BullMQ | Spring → NestJS |
J10 · Tests
| Point du plan | Traité dans |
|---|---|
Jest : describe, it, jest.fn(), jest.mock(), beforeEach | Jest |
Test.createTestingModule avec providers mockés (useValue) | Testing module |
| e2e avec supertest et une base dédiée (Testcontainers ou Compose) | Tests e2e, base de test |
Mock de repositories : getRepositoryToken(Entity) | Mocker un repository |
Tests unitaires de ProjectsService et TasksService | Tests unitaires |
| e2e : register → login → projet → tâche → statut | Parcours e2e |
Seuil de couverture, npm run test:cov | Seuil de couverture |
Mockito ↔ jest.fn() / jest.Mocked<T> ; @SpringBootTest + MockMvc ↔ testing module + supertest ; @DataJpaTest ↔ vraie base | Spring → NestJS |
J11 · Finalisation et mise en production
| Point du plan | Traité dans |
|---|---|
@nestjs/swagger : plugin CLI, @ApiProperty, @ApiTags, @ApiBearerAuth | Swagger |
@nestjs/terminus : DB, mémoire, disque | Health checks |
helmet, CORS, @nestjs/throttler | Sécurité |
Dockerfile multi-stage, non root, npm ci --omit=dev | Dockerfile |
| CI GitLab : lint, tests, build de l'image | CI |
Swagger sur /docs | Swagger sur /docs |
/health Terminus (readiness et liveness) | /health |
Dockerfile et service app dans le Compose | Docker |
.gitlab-ci.yml : install, lint, test, build | Pipeline |
Revue finale : LEARNINGS.md, README | Revue finale |
Au-delà du plan
Ces sections ne figurent pas dans le plan ; elles viennent des problèmes rencontrés en construisant TaskFlow avec les versions actuelles (NestJS 12, TypeORM 1.1, BullMQ 6) :
- Métadonnées de type et
design:type reflect-metadatadans les tests qui ne démarrent pas NestConditionalModule.registerWhenavec une chaîne- BullMQ 6 sans
ioredis - Le jour calendaire du cron et le fuseau horaire
- L'aide-mémoire Nest CLI : commandes, alias et options vérifiés sur le CLI 12, et les commandes qui produisent le squelette de TaskFlow
- L'index des situations, pour retrouver un cas à partir d'une question concrète