nestcraftx 0.2.6 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AUDIT_ROADMAP.md +798 -0
- package/CHANGELOG.fr.md +22 -0
- package/CHANGELOG.md +22 -0
- package/PROGRESS.md +258 -0
- package/commands/demo.js +4 -0
- package/commands/generate.js +5 -4
- package/commands/help.js +29 -2
- package/commands/new.js +8 -6
- package/package.json +1 -1
- package/utils/app-module.updater.js +96 -0
- package/utils/cliParser.js +0 -45
- package/utils/configs/setupCleanArchitecture.js +2 -2
- package/utils/file-system.js +75 -0
- package/utils/generators/application/dtoGenerator.js +251 -0
- package/utils/generators/database/setupDatabase.js +32 -14
- package/utils/generators/domain/entityGenerator.js +126 -0
- package/utils/generators/infrastructure/mapperGenerator.js +114 -0
- package/utils/generators/infrastructure/middlewareGenerator.js +645 -0
- package/utils/generators/infrastructure/mongooseSchemaGenerator.js +196 -0
- package/utils/generators/infrastructure/repositoryGenerator.js +334 -0
- package/utils/generators/presentation/controllerGenerator.js +142 -0
- package/utils/helpers.js +109 -0
- package/utils/setups/setupAuth.js +5 -5
- package/utils/setups/setupDatabase.js +2 -1
- package/utils/setups/setupMongoose.js +22 -5
- package/utils/setups/setupPrisma.js +78 -132
- package/utils/shell.js +88 -8
- package/utils/userInput.js +37 -101
- package/utils/utils.js +29 -2164
package/CHANGELOG.fr.md
CHANGED
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
Toutes les modifications notables apportées à NestCraftX seront documentées dans ce fichier.
|
|
4
4
|
|
|
5
|
+
## [0.3.0] - 07-06-2026
|
|
6
|
+
|
|
7
|
+
### Ajouté
|
|
8
|
+
|
|
9
|
+
- **Version dynamique de l'aide** : Lecture dynamique de la version depuis le `package.json` dans la commande d'aide pour éviter les incohérences.
|
|
10
|
+
- **Validation interactive des flags** : Correction de la logique de vérification pour supporter correctement le mode non-interactif.
|
|
11
|
+
- **Package Manager dynamique** : Prise en compte dynamique du gestionnaire de paquets choisi au lieu de forcer `npm` dans le setup auth.
|
|
12
|
+
|
|
13
|
+
### Changé
|
|
14
|
+
|
|
15
|
+
- **Système de modules unifié** : Standardisation de tous les fichiers du projet en CommonJS afin d'éviter les crashs hybrides ESM/CJS au runtime.
|
|
16
|
+
- **Gestion gracieuse des erreurs** : Les échecs de commandes non critiques (comme `prisma format`) ne tuent plus l'ensemble du processus de génération.
|
|
17
|
+
|
|
18
|
+
### Corrigé
|
|
19
|
+
|
|
20
|
+
- **Capitalisation dans le générateur Prisma** : Capitalisation forcée des noms de modèles dans les relations du schéma pour respecter les contraintes Prisma.
|
|
21
|
+
- **Déduplication des clés étrangères (FK)** : Résolution de la duplication des clés étrangères lors de la génération des relations Prisma.
|
|
22
|
+
- **Boucles asynchrones Clean Architecture** : Remplacement des boucles `forEach` asynchrones par des boucles `for...of` séquentielles pour garantir l'ordre de création des fichiers.
|
|
23
|
+
- **Sauvegarde de l'environnement** : Modification de `setupMongoose` pour mettre à jour le fichier `.env` au lieu de l'écraser complètement.
|
|
24
|
+
- **Analyse robuste de AppModule** : Amélioration de la regex dans `safeUpdateAppModule` pour gérer en toute sécurité les crochets de tableaux imbriqués.
|
|
25
|
+
- **Nettoyages de code** : Suppression du code mort ou commenté et retrait des `console.log` de débogage dans les guards de sécurité générés.
|
|
26
|
+
|
|
5
27
|
## [0.2.5] - 10-01-2026
|
|
6
28
|
|
|
7
29
|
### Ajouté
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to NestCraftX will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.3.0] - 2026-06-07
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **Dynamic Help Version**: Read version dynamically from `package.json` in the help command to prevent version mismatches.
|
|
10
|
+
- **Interactive Flags Check**: Fixed flag check validations to support non-interactive execution modes properly.
|
|
11
|
+
- **Dynamic Package Manager**: Support package manager selection dynamically based on inputs rather than hardcoding `npm`.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- **Unified Module System**: Standardized all project files under CommonJS format to avoid hybrid ESM/CommonJS runtime crashes.
|
|
16
|
+
- **Graceful Error Handling**: Non-critical shell command failures (like `prisma format`) now log warnings rather than forcing process exit.
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- **Prisma Generator Capitalization**: Forced capitalization of model names in database relations to match Prisma schema constraints.
|
|
21
|
+
- **Foreign Key Duplication**: Fixed relation mappings to prevent duplicate foreign key definitions in generated Prisma schemas.
|
|
22
|
+
- **Clean Architecture Loops**: Replaced asynchronous `forEach` loops with sequential `for...of` to prevent files being written out-of-order.
|
|
23
|
+
- **Safe Environment Generation**: `setupMongoose` now updates the `.env` file instead of overwriting it completely.
|
|
24
|
+
- **Robust AppModule Parsing**: Upgraded regex pattern matching in `safeUpdateAppModule` to handle nested array brackets safely.
|
|
25
|
+
- **Cleanups**: Removed dead/commented-out code and removed active debug `console.log` statements in generated security guards.
|
|
26
|
+
|
|
5
27
|
## [0.2.5] - 2026-01-10
|
|
6
28
|
|
|
7
29
|
### Added
|
package/PROGRESS.md
ADDED
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
# ✅ NestCraftX — Suivi de Progression vers v1.0
|
|
2
|
+
> Fichier de check indépendant — le roadmap complet est dans `AUDIT_ROADMAP.md`
|
|
3
|
+
> **Ne jamais modifier `AUDIT_ROADMAP.md`** — il est la référence figée de l'audit.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 📊 Tableau de bord
|
|
8
|
+
|
|
9
|
+
| Phase | Statut | Tickets | Complétés | Progression |
|
|
10
|
+
|---|---|---|---|---|
|
|
11
|
+
| Phase 0 — Stabilisation (v0.3.0) | ✅ Terminé | 17 | 17 | 100% |
|
|
12
|
+
| Phase 1 — Refactorisation (v0.4.0) | 🔵 En cours | 18 | 9 | 50% |
|
|
13
|
+
| Phase 2 — Qualité & Sécurité (v0.5.0) | ⏸️ En attente | 10 | 0 | 0% |
|
|
14
|
+
| Phase 3 — Tests & CI/CD (v0.6.0) | ⏸️ En attente | 15 | 0 | 0% |
|
|
15
|
+
| Phase 4 — Features (v0.7–0.9) | ⏸️ En attente | 14 | 0 | 0% |
|
|
16
|
+
| Phase 5 — Documentation (v0.9.x) | ⏸️ En attente | 8 | 0 | 0% |
|
|
17
|
+
| Phase 6 — Release v1.0 | ⏸️ En attente | 7 | 0 | 0% |
|
|
18
|
+
| **TOTAL** | | **89** | **26** | **29%** |
|
|
19
|
+
|
|
20
|
+
> Mis à jour : 2026-06-07
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 🔴 PHASE 0 — Stabilisation d'urgence (v0.3.0)
|
|
25
|
+
> Objectif : Zéro crash, zéro bug bloquant
|
|
26
|
+
|
|
27
|
+
### 0A — Crash & Stabilité _(priorité maximale)_
|
|
28
|
+
|
|
29
|
+
| Ticket | Description | Fichier(s) | Statut | Date |
|
|
30
|
+
|---|---|---|---|---|
|
|
31
|
+
| PROD-03 | Refactoriser `runCommand` : ajouter `{ critical: boolean }` | `utils/shell.js` | ✅ Terminé | 2026-06-05 |
|
|
32
|
+
| PROD-01a | Dégradation gracieuse si `prisma format` échoue | `utils/setups/setupPrisma.js` | ✅ Terminé | 2026-06-05 |
|
|
33
|
+
| PROD-01b | Capitalisation modèles Prisma (`capitalize(from/to)`) | `utils/setups/setupPrisma.js` | ✅ Terminé | 2026-06-05 |
|
|
34
|
+
| PROD-01c | Déduplication FK dans le 2e pass des relations | `utils/setups/setupPrisma.js` | ✅ Terminé | 2026-06-05 |
|
|
35
|
+
| BUG-09 | `forEach async` → `for...of` dans setupCleanArchitecture | `utils/configs/setupCleanArchitecture.js` | ✅ Terminé | 2026-06-05 |
|
|
36
|
+
| BUG-01 | Unifier module system ESM/CJS (`utils.js` + `userInput.js`) | `utils/utils.js`, `utils/userInput.js` | ✅ Terminé | 2026-06-06 |
|
|
37
|
+
|
|
38
|
+
### 0B — Comportement incorrect
|
|
39
|
+
|
|
40
|
+
| Ticket | Description | Fichier(s) | Statut | Date |
|
|
41
|
+
|---|---|---|---|---|
|
|
42
|
+
| BUG-03 | Fixer logique `hasAllLightModeFlags` / `hasAllFullModeFlags` | `commands/new.js` | ✅ Terminé | 2026-06-06 |
|
|
43
|
+
| BUG-06 | `setupAuth` : utiliser `inputs.packageManager` (pas `npm` hardcodé) | `utils/setups/setupAuth.js` | ✅ Terminé | 2026-06-06 |
|
|
44
|
+
| BUG-07 | `setupMongoose` : ne plus écraser le `.env` complet | `utils/setups/setupMongoose.js` | ✅ Terminé | 2026-06-07 |
|
|
45
|
+
| BUG-04 | `createFile` : vraiment ne pas écraser quand `overwrite: false` | `utils/userInput.js` | ✅ Terminé | 2026-06-07 |
|
|
46
|
+
| BUG-08 | Corriger regex AppModule dans `safeUpdateAppModule` | `utils/userInput.js` | ✅ Terminé | 2026-06-07 |
|
|
47
|
+
|
|
48
|
+
### 0C — Nettoyage immédiat
|
|
49
|
+
|
|
50
|
+
| Ticket | Description | Fichier(s) | Statut | Date |
|
|
51
|
+
|---|---|---|---|---|
|
|
52
|
+
| BUG-12 | `help.js` : version dynamique depuis `package.json` | `commands/help.js` | ✅ Terminé | 2026-06-07 |
|
|
53
|
+
| MP-07a | Supprimer code mort dans `cliParser.js` (45 lignes) | `utils/cliParser.js` | ✅ Terminé | 2026-06-07 |
|
|
54
|
+
| MP-07b | Supprimer code mort dans `setupPrisma.js` (44 lignes) | `utils/setups/setupPrisma.js` | ✅ Terminé | 2026-06-07 |
|
|
55
|
+
| BUG-02 | `handleAuthGeneration` : implémenter ou message clair | `commands/generate.js` | ✅ Terminé | 2026-06-07 |
|
|
56
|
+
| BUG-11 | Retirer `console.log` debug du `RolesGuard` généré | `utils/setups/setupAuth.js` | ✅ Terminé | 2026-06-07 |
|
|
57
|
+
| BUG-12b | Corriger commentaire `PostMapper` hardcodé dans mapper généré | `utils/utils.js` | ✅ Terminé | 2026-06-07 |
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 🟠 PHASE 1 — Refactorisation Architecture (v0.4.0)
|
|
62
|
+
> Objectif : Code maintenable, testable, sans duplication
|
|
63
|
+
|
|
64
|
+
### 1A — Découpage des gros fichiers
|
|
65
|
+
|
|
66
|
+
| Ticket | Description | Fichier(s) | Statut | Date |
|
|
67
|
+
|---|---|---|---|---|
|
|
68
|
+
| MP-01a | Extraire `generators/entity.generator.js` depuis `utils.js` | `utils/utils.js` | ✅ Terminé | 2026-06-07 |
|
|
69
|
+
| MP-01b | Extraire `generators/dto.generator.js` depuis `utils.js` | `utils/utils.js` | ✅ Terminé | 2026-06-07 |
|
|
70
|
+
| MP-01c | Extraire `generators/controller.generator.js` depuis `utils.js` | `utils/utils.js` | ✅ Terminé | 2026-06-07 |
|
|
71
|
+
| MP-01d | Extraire `generators/mapper.generator.js` depuis `utils.js` | `utils/utils.js` | ✅ Terminé | 2026-06-07 |
|
|
72
|
+
| MP-01e | Extraire `generators/service.generator.js` depuis `utils.js` | `utils/utils.js` | ✅ Terminé | 2026-06-07 |
|
|
73
|
+
| MP-01f | Extraire `utils/helpers.js` (capitalize, decapitalize, pluralize) | `utils/utils.js` | ✅ Terminé | 2026-06-07 |
|
|
74
|
+
| MP-07c | Éclater `userInput.js` → `utils/file-system.js` | `utils/userInput.js` | ✅ Terminé | 2026-06-07 |
|
|
75
|
+
| MP-07d | Éclater `userInput.js` → `utils/app-module.updater.js` | `utils/userInput.js` | ✅ Terminé | 2026-06-07 |
|
|
76
|
+
| MP-03 | Supprimer `generateDtox` (doublon de `generateDto`) | `utils/utils.js` | ✅ Terminé | 2026-06-07 |
|
|
77
|
+
|
|
78
|
+
### 1B — Refonte du flow d'input entités (PROD-04 + PROD-05)
|
|
79
|
+
|
|
80
|
+
| Ticket | Description | Fichier(s) | Statut | Date |
|
|
81
|
+
|---|---|---|---|---|
|
|
82
|
+
| PROD-04a | Étendre modèle de champ : `unique`, `nullable`, `default` | `utils/fullModeInput.js`, `utils/lightModeInput.js` | ⬜ À faire | — |
|
|
83
|
+
| PROD-05 | Écran de révision d'entité (modifier, supprimer, renommer) | `utils/fullModeInput.js`, `utils/lightModeInput.js` | ⬜ À faire | — |
|
|
84
|
+
| PROD-04b | Refonte state-based : `EntityBuilder` navigable | `utils/fullModeInput.js` | ⬜ À faire | — |
|
|
85
|
+
| MP-02 | Dédupliquer `addCustomEntities` et `addRelations` | `utils/fullModeInput.js`, `utils/lightModeInput.js` | ⬜ À faire | — |
|
|
86
|
+
|
|
87
|
+
### 1C — Architecture générale
|
|
88
|
+
|
|
89
|
+
| Ticket | Description | Fichier(s) | Statut | Date |
|
|
90
|
+
|---|---|---|---|---|
|
|
91
|
+
| MA-05 | Extraire flow commun `demo.js` → partager avec `new.js` | `commands/demo.js`, `commands/new.js` | ⬜ À faire | — |
|
|
92
|
+
| MP-04 | Remplacer `execSync` par `execa` avec timeout | `utils/shell.js` | ⬜ À faire | — |
|
|
93
|
+
| MA-01 | Mécanisme de rapport final (accumuler warnings, afficher en bloc) | `utils/shell.js`, `commands/new.js` | ⬜ À faire | — |
|
|
94
|
+
| MA-02 | Isoler `process.chdir` — vérifier CWD avant chaque I/O | `utils/setups/projectSetup.js` | ⬜ À faire | — |
|
|
95
|
+
| DRY-01 | Ajouter `--dry-run` flag (simuler sans écrire) | `bin/nestcraft.js`, `commands/new.js` | ⬜ À faire | — |
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 🟠 PHASE 2 — Qualité & Sécurité (v0.5.0)
|
|
100
|
+
> Objectif : Code généré sécurisé et professionnel
|
|
101
|
+
|
|
102
|
+
### 2A — Sécurité du code généré
|
|
103
|
+
|
|
104
|
+
| Ticket | Description | Fichier(s) | Statut | Date |
|
|
105
|
+
|---|---|---|---|---|
|
|
106
|
+
| MP-17 | `resetPassword` : stocker et valider le token (table DB / Redis) | `utils/setups/setupAuth.js` | ⬜ À faire | — |
|
|
107
|
+
| MP-16 | OTPs : utiliser DB ou Redis au lieu de `Map` en mémoire | `utils/setups/setupAuth.js` | ⬜ À faire | — |
|
|
108
|
+
| MA-06 | Pinning versions dépendances générées (ranges semver stricts) | `utils/setups/*.js` | ⬜ À faire | — |
|
|
109
|
+
|
|
110
|
+
### 2B — Descriptions Swagger (PROD-02)
|
|
111
|
+
|
|
112
|
+
| Ticket | Description | Fichier(s) | Statut | Date |
|
|
113
|
+
|---|---|---|---|---|
|
|
114
|
+
| PROD-02a | Système de descriptions sémantiques par catégorie de champ | `utils/utils.js` (getFieldDescription) | ⬜ À faire | — |
|
|
115
|
+
| PROD-02b | Description manuelle optionnelle dans `getFullModeInputs` | `utils/fullModeInput.js` | ⬜ À faire | — |
|
|
116
|
+
| PROD-02c | Description contextuelle Create vs Update DTO | `utils/utils.js` (generateDto) | ⬜ À faire | — |
|
|
117
|
+
|
|
118
|
+
### 2C — Corrections qualité
|
|
119
|
+
|
|
120
|
+
| Ticket | Description | Fichier(s) | Statut | Date |
|
|
121
|
+
|---|---|---|---|---|
|
|
122
|
+
| BUG-18 | Corriger condition De Morgan dans `cleanModuleGenerator` | `utils/generators/cleanModuleGenerator.js` | ⬜ À faire | — |
|
|
123
|
+
| MP-09 | Corriger détection ORM dans `generateConf` (ordre priorité) | `commands/generateConf.js` | ⬜ À faire | — |
|
|
124
|
+
| MP-13 | JWT vars conditionnelles à `useAuth` dans `envGenerator` | `utils/envGenerator.js` | ⬜ À faire | — |
|
|
125
|
+
| MP-10 | Supporter mode LIGHT sans nom en argument dans `new.js` | `commands/new.js` | ⬜ À faire | — |
|
|
126
|
+
| MA-09 | Timeout 5 min sur `npm install` dans `runCommand` | `utils/shell.js` | ⬜ À faire | — |
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## 🟡 PHASE 3 — Tests & CI/CD (v0.6.0)
|
|
131
|
+
> Objectif : Zéro régression possible sur chaque PR
|
|
132
|
+
|
|
133
|
+
### 3A — Tests unitaires (Jest)
|
|
134
|
+
|
|
135
|
+
| Ticket | Description | Statut | Date |
|
|
136
|
+
|---|---|---|---|
|
|
137
|
+
| TEST-01 | `generateDto()` — output TypeScript valide pour chaque ORM | ⬜ À faire | — |
|
|
138
|
+
| TEST-02 | `generateEntityFileContent()` — structure domaine correcte | ⬜ À faire | — |
|
|
139
|
+
| TEST-03 | `generateController()` — routes, guards, decorators | ⬜ À faire | — |
|
|
140
|
+
| TEST-04 | `mapTypeToPrisma()` — tous les types | ⬜ À faire | — |
|
|
141
|
+
| TEST-05 | `mapTypeToMongoose()` — tous les types | ⬜ À faire | — |
|
|
142
|
+
| TEST-06 | Schema Prisma relations 1-n (FK, inverse, capitalisation) | ⬜ À faire | — |
|
|
143
|
+
| TEST-07 | Schema Prisma relations n-n et 1-1 | ⬜ À faire | — |
|
|
144
|
+
| TEST-08 | CLI Parser — tous les cas de flags | ⬜ À faire | — |
|
|
145
|
+
| TEST-09 | `safeUpdateAppModule` — différents états `app.module.ts` | ⬜ À faire | — |
|
|
146
|
+
|
|
147
|
+
### 3B — Tests d'intégration E2E
|
|
148
|
+
|
|
149
|
+
| Ticket | Description | Statut | Date |
|
|
150
|
+
|---|---|---|---|
|
|
151
|
+
| E2E-01 | Générer `test-full-prisma` → `tsc --noEmit` passe | ⬜ À faire | — |
|
|
152
|
+
| E2E-02 | Générer `test-full-typeorm` → `tsc --noEmit` passe | ⬜ À faire | — |
|
|
153
|
+
| E2E-03 | Générer `test-full-mongoose` → `tsc --noEmit` passe | ⬜ À faire | — |
|
|
154
|
+
| E2E-04 | Générer `test-light-prisma` → `tsc --noEmit` passe | ⬜ À faire | — |
|
|
155
|
+
| E2E-05 | Générer avec auth → `auth.module.ts` correctement câblé | ⬜ À faire | — |
|
|
156
|
+
| E2E-06 | Générer avec relations 1-n → schema Prisma valide | ⬜ À faire | — |
|
|
157
|
+
| E2E-07 | Test résilience PROD-03 : erreur migration → reste généré | ⬜ À faire | — |
|
|
158
|
+
|
|
159
|
+
### 3C — CI/CD
|
|
160
|
+
|
|
161
|
+
| Ticket | Description | Statut | Date |
|
|
162
|
+
|---|---|---|---|
|
|
163
|
+
| CI-01 | ESLint sur chaque PR | ⬜ À faire | — |
|
|
164
|
+
| CI-02 | Tests Node 18, 20, 22 LTS (matrix) | ⬜ À faire | — |
|
|
165
|
+
| CI-03 | Génération sur Ubuntu + Windows (matrix) | ⬜ À faire | — |
|
|
166
|
+
| CI-04 | Semantic Release automatique | ⬜ À faire | — |
|
|
167
|
+
| CI-05 | Publish automatique sur npm | ⬜ À faire | — |
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## 🟡 PHASE 4 — Features Manquantes (v0.7.0–v0.9.0)
|
|
172
|
+
> Objectif : Être feature-complete avant la v1.0
|
|
173
|
+
|
|
174
|
+
### 4A — Features CLI
|
|
175
|
+
|
|
176
|
+
| Ticket | Description | Statut | Date |
|
|
177
|
+
|---|---|---|---|
|
|
178
|
+
| FEAT-01 | `nestcraftx g auth` — implémenter complètement | ⬜ À faire | — |
|
|
179
|
+
| FEAT-02 | Mode non-interactif complet (tous les flags) | ⬜ À faire | — |
|
|
180
|
+
| FEAT-03 | `nestcraftx update` — auto-update de la CLI | ⬜ À faire | — |
|
|
181
|
+
| FEAT-04 | `nestcraftx list` — lister entités depuis `.nestcraftxrc` | ⬜ À faire | — |
|
|
182
|
+
| FEAT-05 | Support `pnpm` | ⬜ À faire | — |
|
|
183
|
+
|
|
184
|
+
### 4B — Qualité du code généré
|
|
185
|
+
|
|
186
|
+
| Ticket | Description | Statut | Date |
|
|
187
|
+
|---|---|---|---|
|
|
188
|
+
| FEAT-06 | Pagination GET all (`?page=1&limit=10`) | ⬜ À faire | — |
|
|
189
|
+
| FEAT-07 | Filtering & Sorting query params | ⬜ À faire | — |
|
|
190
|
+
| FEAT-08 | Rate limiting global (`@nestjs/throttler`) | ⬜ À faire | — |
|
|
191
|
+
| FEAT-09 | Health check endpoint (`/health`) | ⬜ À faire | — |
|
|
192
|
+
| FEAT-10 | Exception filter global typé | ⬜ À faire | — |
|
|
193
|
+
| FEAT-11 | Guards RBAC conditionnels sur endpoints | ⬜ À faire | — |
|
|
194
|
+
| FEAT-12 | Support MySQL/SQLite (Prisma/TypeORM) | ⬜ À faire | — |
|
|
195
|
+
|
|
196
|
+
### 4C — Expérience développeur
|
|
197
|
+
|
|
198
|
+
| Ticket | Description | Statut | Date |
|
|
199
|
+
|---|---|---|---|
|
|
200
|
+
| FEAT-13 | Templates personnalisés depuis GitHub | ⬜ À faire | — |
|
|
201
|
+
| FEAT-14 | `nestcraftx g relation` — relation entre modules existants | ⬜ À faire | — |
|
|
202
|
+
| FEAT-15 | Rapport de génération en fin de commande | ⬜ À faire | — |
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## 🟢 PHASE 5 — Documentation & Site Web (v0.9.x)
|
|
207
|
+
> Objectif : Site officiel avant la v1.0
|
|
208
|
+
|
|
209
|
+
| Ticket | Description | Statut | Date |
|
|
210
|
+
|---|---|---|---|
|
|
211
|
+
| DOC-01 | Créer site Docusaurus/VitePress (`nestcraftx.dev`) | ⬜ À faire | — |
|
|
212
|
+
| DOC-02 | Page Getting Started (5 minutes) | ⬜ À faire | — |
|
|
213
|
+
| DOC-03 | CLI Reference (toutes les commandes et flags) | ⬜ À faire | — |
|
|
214
|
+
| DOC-04 | Architecture Guide (Clean Arch générée) | ⬜ À faire | — |
|
|
215
|
+
| DOC-05 | ORM Guide (Prisma vs TypeORM vs Mongoose) | ⬜ À faire | — |
|
|
216
|
+
| DOC-06 | Auth Deep Dive (JWT, guards, roles) | ⬜ À faire | — |
|
|
217
|
+
| DOC-07 | Troubleshooting & Migration Guide (0.2.x → 1.0) | ⬜ À faire | — |
|
|
218
|
+
| DOC-08 | Playground interactif dans le navigateur | ⬜ À faire | — |
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## 🟢 PHASE 6 — Release v1.0 stable
|
|
223
|
+
|
|
224
|
+
| Ticket | Description | Statut | Date |
|
|
225
|
+
|---|---|---|---|
|
|
226
|
+
| REL-01 | Audit de sécurité final | ⬜ À faire | — |
|
|
227
|
+
| REL-02 | Test complet Windows + macOS + Linux | ⬜ À faire | — |
|
|
228
|
+
| REL-03 | Revue de toutes les sorties CLI | ⬜ À faire | — |
|
|
229
|
+
| REL-04 | README mis à jour avec badges CI | ⬜ À faire | — |
|
|
230
|
+
| REL-05 | CHANGELOG complet depuis v0.2.6 | ⬜ À faire | — |
|
|
231
|
+
| REL-06 | Publication npm avec tag `@stable` | ⬜ À faire | — |
|
|
232
|
+
| REL-07 | Annonce GitHub Release avec notes détaillées | ⬜ À faire | — |
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## 📝 Journal des changements
|
|
237
|
+
|
|
238
|
+
| 2026-06-05 | 0.2.6 | — | Audit initial + retours prod intégrés |
|
|
239
|
+
| 2026-06-05 | 0.3.0-wip | PROD-03, PROD-01a, PROD-01b, PROD-01c, BUG-09 | `runCommand` refactorisé (PROD-03). Prisma relations : capitalisation forcée des modèles et types, déduplication complète des clés étrangères (PROD-01a, b, c). Correction de la boucle asynchrone des use cases clean architecture (BUG-09). |
|
|
240
|
+
| 2026-06-06 | 0.3.0-wip | BUG-01, BUG-03, BUG-06 | Unification du module system en CommonJS (BUG-01). Validation non-interactive des flags (BUG-03). Utilisation de inputs.packageManager dynamique dans `setupAuth.js` au lieu de npm en dur (BUG-06). |
|
|
241
|
+
| 2026-06-07 | 0.3.0 | BUG-07, BUG-04, BUG-08, BUG-12, MP-07a, MP-07b, BUG-02, BUG-11, BUG-12b | Clôture de la Phase 0. Mongoose .env préservé. createFile supporte overwrite. safeUpdateAppModule robuste aux crochets imbriqués. help.js dynamic. Nettoyage de code mort et debug logs. |
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## 🔑 Légende des statuts
|
|
246
|
+
|
|
247
|
+
| Icône | Signification |
|
|
248
|
+
|---|---|
|
|
249
|
+
| ⬜ À faire | Ticket non démarré |
|
|
250
|
+
| 🔵 En cours | Travail en cours |
|
|
251
|
+
| ✅ Terminé | Ticket complété et validé |
|
|
252
|
+
| ❌ Annulé | Ticket annulé (avec raison dans Notes) |
|
|
253
|
+
| ⏸️ Bloqué | En attente d'un autre ticket |
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
*Ce fichier est mis à jour manuellement à chaque session de travail.*
|
|
258
|
+
*Pour le détail technique de chaque ticket, voir [AUDIT_ROADMAP.md](./AUDIT_ROADMAP.md)*
|
package/commands/demo.js
CHANGED
|
@@ -15,6 +15,7 @@ const { configureDocker } = require("../utils/configs/configureDocker");
|
|
|
15
15
|
const { generateEnvFile, writeEnvFile } = require("../utils/envGenerator");
|
|
16
16
|
const { setupBootstrapLogger } = require("../utils/setups/setupLogger");
|
|
17
17
|
const { saveProjectConfig } = require("../utils/file-utils/saveProjectConfig");
|
|
18
|
+
const { printSetupWarnings } = require("../utils/shell");
|
|
18
19
|
const actualInquirer = inquirer.default || inquirer;
|
|
19
20
|
|
|
20
21
|
async function demoCommand(flags = {}) {
|
|
@@ -238,6 +239,9 @@ async function demoCommand(flags = {}) {
|
|
|
238
239
|
|
|
239
240
|
await saveProjectConfig(demoInputs);
|
|
240
241
|
|
|
242
|
+
// Show any non-critical warnings accumulated during generation
|
|
243
|
+
printSetupWarnings();
|
|
244
|
+
|
|
241
245
|
console.log("\n" + "=".repeat(60));
|
|
242
246
|
logSuccess("Demonstration project created successfully!");
|
|
243
247
|
console.log("=".repeat(60));
|
package/commands/generate.js
CHANGED
|
@@ -6,8 +6,10 @@ const { logWarning } = require("../utils/loggers/logWarning");
|
|
|
6
6
|
const generateCleanModule = require("../utils/generators/cleanModuleGenerator");
|
|
7
7
|
const { askEntityInputs } = require("../utils/interactive/askEntityInputs");
|
|
8
8
|
const lightModuleGenerator = require("../utils/generators/lightModuleGenerator");
|
|
9
|
+
const { printSetupWarnings, clearSetupWarnings } = require("../utils/shell");
|
|
9
10
|
|
|
10
11
|
async function generate(subCommand, targetName, flags) {
|
|
12
|
+
clearSetupWarnings();
|
|
11
13
|
// 1. Localisation of config file
|
|
12
14
|
const configPath = path.join(process.cwd(), ".nestcraftx", ".nestcraftxrc");
|
|
13
15
|
|
|
@@ -81,13 +83,12 @@ async function handleModuleGeneration(name, config) {
|
|
|
81
83
|
} else {
|
|
82
84
|
await lightModuleGenerator(entityData, config);
|
|
83
85
|
}
|
|
86
|
+
|
|
87
|
+
printSetupWarnings();
|
|
84
88
|
}
|
|
85
89
|
|
|
86
90
|
async function handleAuthGeneration(config) {
|
|
87
|
-
|
|
88
|
-
// await require('../utils/setups/setupAuth')(config);
|
|
89
|
-
|
|
90
|
-
logInfo("🚀 Generating module auth...");
|
|
91
|
+
logWarning("nestcraftx g auth n'est pas encore disponible en v0.3 — prévu en v0.7");
|
|
91
92
|
}
|
|
92
93
|
|
|
93
94
|
module.exports = generate;
|
package/commands/help.js
CHANGED
|
@@ -1,9 +1,36 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
|
|
4
|
+
function getVersion() {
|
|
5
|
+
try {
|
|
6
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, "../package.json"), "utf8"));
|
|
7
|
+
return pkg.version;
|
|
8
|
+
} catch (err) {
|
|
9
|
+
return "0.2.6";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function centerText(text, width) {
|
|
14
|
+
const totalSpaces = width - text.length;
|
|
15
|
+
const leftSpaces = Math.max(0, Math.floor(totalSpaces / 2));
|
|
16
|
+
const rightSpaces = Math.max(0, totalSpaces - leftSpaces);
|
|
17
|
+
return " ".repeat(leftSpaces) + text + " ".repeat(rightSpaces);
|
|
18
|
+
}
|
|
19
|
+
|
|
1
20
|
async function helpCommand() {
|
|
21
|
+
const version = getVersion();
|
|
22
|
+
const versionLineText = `🌟 NestCraftX CLI v${version} 🌟`;
|
|
23
|
+
const descLineText = "Clean Architecture Generator for NestJS";
|
|
24
|
+
|
|
25
|
+
const innerWidth = 59; // 59 characters inside the border
|
|
26
|
+
const paddedVersionLine = centerText(versionLineText, innerWidth);
|
|
27
|
+
const paddedDescLine = centerText(descLineText, innerWidth);
|
|
28
|
+
|
|
2
29
|
console.log(`
|
|
3
30
|
╔═══════════════════════════════════════════════════════════╗
|
|
4
31
|
║ ║
|
|
5
|
-
║
|
|
6
|
-
║
|
|
32
|
+
║${paddedVersionLine}║
|
|
33
|
+
║${paddedDescLine}║
|
|
7
34
|
║ ║
|
|
8
35
|
╚═══════════════════════════════════════════════════════════╝
|
|
9
36
|
|
package/commands/new.js
CHANGED
|
@@ -20,6 +20,7 @@ const readline = require("readline-sync");
|
|
|
20
20
|
const { info, warning } = require("../utils/colors");
|
|
21
21
|
const { logWarning } = require("../utils/loggers/logWarning");
|
|
22
22
|
const { saveProjectConfig } = require("../utils/file-utils/saveProjectConfig");
|
|
23
|
+
const { printSetupWarnings } = require("../utils/shell");
|
|
23
24
|
|
|
24
25
|
async function newCommand(projectName, flags = {}) {
|
|
25
26
|
if (!projectName) {
|
|
@@ -96,11 +97,10 @@ async function buildFullModeInputs(projectName, flags) {
|
|
|
96
97
|
}
|
|
97
98
|
|
|
98
99
|
function hasAllLightModeFlags(flags) {
|
|
99
|
-
|
|
100
|
-
if (!flags.interactive || flags.interactive === false) {
|
|
100
|
+
if (flags.interactive === true) {
|
|
101
101
|
return false;
|
|
102
102
|
}
|
|
103
|
-
return
|
|
103
|
+
return flags.orm !== undefined;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
function buildLightModeFromFlags(projectName, flags) {
|
|
@@ -166,11 +166,10 @@ function buildLightModeFromFlags(projectName, flags) {
|
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
function hasAllFullModeFlags(flags) {
|
|
169
|
-
|
|
170
|
-
if (!flags.interactive || flags.interactive === false) {
|
|
169
|
+
if (flags.interactive === true) {
|
|
171
170
|
return false;
|
|
172
171
|
}
|
|
173
|
-
return
|
|
172
|
+
return flags.orm !== undefined;
|
|
174
173
|
}
|
|
175
174
|
|
|
176
175
|
function buildFullModeFromFlags(projectName, flags) {
|
|
@@ -268,6 +267,9 @@ async function executeProjectSetup(inputs) {
|
|
|
268
267
|
|
|
269
268
|
await saveProjectConfig(inputs);
|
|
270
269
|
|
|
270
|
+
// Show any non-critical warnings accumulated during generation
|
|
271
|
+
printSetupWarnings();
|
|
272
|
+
|
|
271
273
|
printSuccessSummary(inputs);
|
|
272
274
|
} catch (error) {
|
|
273
275
|
// Erreur lors de la creation du projet: ${error.message}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nestcraftx",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Modern CLI to generate scalable NestJS projects with Clean Architecture (FULL) and MVP mode (LIGHT) - Enhanced with auto-generated .env secrets, complete ORM support, and entity relations",
|
|
5
5
|
"main": "bin/nestcraft.js",
|
|
6
6
|
"bin": {
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* utils/app-module.updater.js
|
|
3
|
+
*
|
|
4
|
+
* Gestion de la mise à jour sécurisée du fichier app.module.ts.
|
|
5
|
+
* Extrait de userInput.js pour isoler cette responsabilité spécifique.
|
|
6
|
+
*
|
|
7
|
+
* Les fichiers qui importent `safeUpdateAppModule` depuis userInput.js
|
|
8
|
+
* continuent de fonctionner sans modification grâce aux ré-exports.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const fs = require("fs");
|
|
12
|
+
const { updateFile } = require("./file-system");
|
|
13
|
+
const { logInfo } = require("./loggers/logInfo");
|
|
14
|
+
const { capitalize } = require("./helpers");
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Ajoute un module NestJS dans le fichier `src/app.module.ts` de manière idempotente.
|
|
18
|
+
*
|
|
19
|
+
* - Ajoute la ligne `import { XModule } from 'src/x/x.module'` si absente
|
|
20
|
+
* - Ajoute `XModule` dans le tableau `imports: []` du décorateur @Module si absent
|
|
21
|
+
* - Utilise un parsing par comptage de crochets pour gérer les imports imbriqués
|
|
22
|
+
* (ex: ConfigModule.forRoot({ ... }))
|
|
23
|
+
*
|
|
24
|
+
* @param {string} entity - Le nom de l'entité en minuscule (ex: "user", "post")
|
|
25
|
+
*/
|
|
26
|
+
async function safeUpdateAppModule(entity) {
|
|
27
|
+
const filePath = "src/app.module.ts";
|
|
28
|
+
const moduleName = `${capitalize(entity)}Module`;
|
|
29
|
+
const importLine = `import { ${moduleName} } from 'src/${entity}/${entity}.module';`;
|
|
30
|
+
|
|
31
|
+
let content = fs.readFileSync(filePath, "utf-8");
|
|
32
|
+
|
|
33
|
+
// Étape 1 : Ajout de l'import en haut du fichier si nécessaire
|
|
34
|
+
if (!content.includes(importLine)) {
|
|
35
|
+
const importMarker = `import { ConfigModule } from '@nestjs/config';`;
|
|
36
|
+
|
|
37
|
+
if (content.includes(importMarker)) {
|
|
38
|
+
await updateFile({
|
|
39
|
+
path: filePath,
|
|
40
|
+
pattern: importMarker,
|
|
41
|
+
replacement: `${importMarker}\n${importLine}`,
|
|
42
|
+
});
|
|
43
|
+
content = fs.readFileSync(filePath, "utf-8");
|
|
44
|
+
} else {
|
|
45
|
+
logInfo(
|
|
46
|
+
" Impossible de trouver le point d'insertion de l'import (ConfigModule manquant)",
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Étape 2 : Vérifier le bloc des imports du @Module avec gestion des crochets imbriqués
|
|
52
|
+
const importsHeaderMatch = content.match(/imports:\s*\[/);
|
|
53
|
+
if (!importsHeaderMatch) {
|
|
54
|
+
logInfo(" Impossible de trouver le bloc 'imports' dans AppModule.");
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const startIndex =
|
|
59
|
+
importsHeaderMatch.index + importsHeaderMatch[0].length - 1; // index du '['
|
|
60
|
+
let depth = 1;
|
|
61
|
+
let endIndex = -1;
|
|
62
|
+
for (let i = startIndex + 1; i < content.length; i++) {
|
|
63
|
+
if (content[i] === "[") {
|
|
64
|
+
depth++;
|
|
65
|
+
} else if (content[i] === "]") {
|
|
66
|
+
depth--;
|
|
67
|
+
if (depth === 0) {
|
|
68
|
+
endIndex = i;
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (endIndex === -1) {
|
|
75
|
+
logInfo(
|
|
76
|
+
" Impossible de trouver le crochet de fermeture du bloc 'imports' dans AppModule.",
|
|
77
|
+
);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const currentImportsBlock = content.substring(startIndex + 1, endIndex);
|
|
82
|
+
const isAlreadyImportedInModule = currentImportsBlock.includes(moduleName);
|
|
83
|
+
|
|
84
|
+
if (!isAlreadyImportedInModule) {
|
|
85
|
+
const updatedBlock = currentImportsBlock.trim().endsWith(",")
|
|
86
|
+
? `${currentImportsBlock.trim()} ${moduleName},`
|
|
87
|
+
: `${currentImportsBlock.trim()}, ${moduleName},`;
|
|
88
|
+
|
|
89
|
+
const beforeBlock = content.substring(0, startIndex + 1);
|
|
90
|
+
const afterBlock = content.substring(endIndex);
|
|
91
|
+
const newContent = beforeBlock + updatedBlock + afterBlock;
|
|
92
|
+
fs.writeFileSync(filePath, newContent, "utf-8");
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
module.exports = { safeUpdateAppModule };
|
package/utils/cliParser.js
CHANGED
|
@@ -1,48 +1,3 @@
|
|
|
1
|
-
/* function parseCliArgs(args) {
|
|
2
|
-
const parsed = {
|
|
3
|
-
command: null,
|
|
4
|
-
projectName: null,
|
|
5
|
-
flags: {},
|
|
6
|
-
positional: [],
|
|
7
|
-
errors: []
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
for (let i = 2; i < args.length; i++) {
|
|
11
|
-
const arg = args[i];
|
|
12
|
-
|
|
13
|
-
if (i === 2 && !arg.startsWith('--')) {
|
|
14
|
-
parsed.command = arg;
|
|
15
|
-
continue;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
if (i === 3 && !arg.startsWith('--') && parsed.command === 'new') {
|
|
19
|
-
if (!isValidProjectName(arg)) {
|
|
20
|
-
parsed.errors.push(`Nom de projet invalide: "${arg}". Utilisez uniquement des lettres, chiffres, tirets et underscores.`);
|
|
21
|
-
}
|
|
22
|
-
parsed.projectName = arg;
|
|
23
|
-
continue;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (arg.startsWith('--')) {
|
|
27
|
-
const [key, value] = parseFlag(arg);
|
|
28
|
-
const nextArg = args[i + 1];
|
|
29
|
-
|
|
30
|
-
if (value !== null) {
|
|
31
|
-
parsed.flags[key] = value;
|
|
32
|
-
} else if (nextArg && !nextArg.startsWith('--')) {
|
|
33
|
-
parsed.flags[key] = nextArg;
|
|
34
|
-
i++;
|
|
35
|
-
} else {
|
|
36
|
-
parsed.flags[key] = true;
|
|
37
|
-
}
|
|
38
|
-
} else {
|
|
39
|
-
parsed.positional.push(arg);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
validateFlags(parsed);
|
|
44
|
-
return parsed;
|
|
45
|
-
} */
|
|
46
1
|
|
|
47
2
|
function parseCliArgs(args) {
|
|
48
3
|
const parsed = {
|
|
@@ -128,7 +128,7 @@ async function setupCleanArchitecture(inputs) {
|
|
|
128
128
|
|
|
129
129
|
// 4. Use Cases
|
|
130
130
|
const useCases = ["Create", "GetById", "GetAll", "Update", "Delete"];
|
|
131
|
-
|
|
131
|
+
for (const useCase of useCases) {
|
|
132
132
|
let content = "";
|
|
133
133
|
const entityName = capitalize(entity.name);
|
|
134
134
|
const entityNameLower = decapitalize(entity.name);
|
|
@@ -302,7 +302,7 @@ export class Delete${entityName}UseCase {
|
|
|
302
302
|
}.use-case.ts`,
|
|
303
303
|
contente: content.trim(),
|
|
304
304
|
});
|
|
305
|
-
}
|
|
305
|
+
}
|
|
306
306
|
|
|
307
307
|
// 5. DTOs
|
|
308
308
|
const DtoFileContent = await generateDto(entity, useSwagger);
|