nestcraftx 0.2.6 → 0.4.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 +259 -0
- package/commands/demo.js +2 -42
- package/commands/generate.js +5 -4
- package/commands/help.js +29 -2
- package/commands/new.js +6 -49
- package/package.json +1 -1
- package/utils/app-module.updater.js +102 -0
- package/utils/cliParser.js +0 -45
- package/utils/configs/setupCleanArchitecture.js +2 -2
- package/utils/envGenerator.js +6 -0
- package/utils/file-system.js +90 -0
- package/utils/file-utils/packageJsonUtils.js +6 -0
- package/utils/file-utils/saveProjectConfig.js +6 -0
- package/utils/fullModeInput.js +8 -229
- package/utils/generators/application/dtoGenerator.js +252 -0
- package/utils/generators/application/dtoUpdater.js +5 -0
- package/utils/generators/database/setupDatabase.js +32 -14
- package/utils/generators/domain/entityGenerator.js +126 -0
- package/utils/generators/domain/entityUpdater.js +5 -0
- package/utils/generators/infrastructure/mapperGenerator.js +114 -0
- package/utils/generators/infrastructure/mapperUpdater.js +5 -0
- package/utils/generators/infrastructure/middlewareGenerator.js +645 -0
- package/utils/generators/infrastructure/mongooseSchemaGenerator.js +229 -0
- package/utils/generators/infrastructure/repositoryGenerator.js +334 -0
- package/utils/generators/presentation/controllerGenerator.js +142 -0
- package/utils/helpers.js +115 -0
- package/utils/interactive/askEntityInputs.js +5 -68
- package/utils/interactive/entityBuilder.js +400 -0
- package/utils/lightModeInput.js +13 -246
- package/utils/setups/orms/typeOrmSetup.js +31 -4
- package/utils/setups/projectSetup.js +78 -8
- package/utils/setups/setupAuth.js +6 -7
- package/utils/setups/setupDatabase.js +2 -1
- package/utils/setups/setupMongoose.js +96 -30
- package/utils/setups/setupPrisma.js +118 -134
- package/utils/setups/setupSwagger.js +12 -8
- package/utils/shell.js +125 -10
- 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,259 @@
|
|
|
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) | ✅ Terminé | 18 | 18 | 100% |
|
|
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** | **35** | **39%** |
|
|
19
|
+
|
|
20
|
+
> Mis à jour : 2026-06-16
|
|
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` | ✅ Terminé | 2026-06-14 |
|
|
83
|
+
| PROD-05 | Écran de révision d'entité (modifier, supprimer, renommer) | `utils/fullModeInput.js`, `utils/lightModeInput.js` | ✅ Terminé | 2026-06-14 |
|
|
84
|
+
| PROD-04b | Refonte state-based : `EntityBuilder` navigable | `utils/fullModeInput.js` | ✅ Terminé | 2026-06-14 |
|
|
85
|
+
| MP-02 | Dédupliquer `addCustomEntities` et `addRelations` | `utils/fullModeInput.js`, `utils/lightModeInput.js` | ✅ Terminé | 2026-06-14 |
|
|
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` | ✅ Terminé | 2026-06-16 |
|
|
92
|
+
| MP-04 | Remplacer `execSync` par `execa` avec timeout | `utils/shell.js` | ✅ Terminé | 2026-06-16 |
|
|
93
|
+
| MA-01 | Mécanisme de rapport final (accumuler warnings, afficher en bloc) | `utils/shell.js`, `commands/new.js` | ✅ Terminé | 2026-06-16 |
|
|
94
|
+
| MA-02 | Isoler `process.chdir` — vérifier CWD avant chaque I/O | `utils/setups/projectSetup.js` | ✅ Terminé | 2026-06-16 |
|
|
95
|
+
| DRY-01 | Ajouter `--dry-run` flag (simuler sans écrire) | `bin/nestcraft.js`, `commands/new.js` | ✅ Terminé | 2026-06-16 |
|
|
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
|
+
| 2026-06-14 | 0.3.0-wip | PROD-04a, PROD-04b, PROD-05, MP-02 | Refonte state-based interactive de la saisie d'entités avec EntityBuilder. Support des contraintes unique, nullable et valeurs par défaut. Alignement et déduplication des générateurs (Prisma, TypeORM, Mongoose, DTOs, et Domain Entities). |
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## 🔑 Légende des statuts
|
|
247
|
+
|
|
248
|
+
| Icône | Signification |
|
|
249
|
+
|---|---|
|
|
250
|
+
| ⬜ À faire | Ticket non démarré |
|
|
251
|
+
| 🔵 En cours | Travail en cours |
|
|
252
|
+
| ✅ Terminé | Ticket complété et validé |
|
|
253
|
+
| ❌ Annulé | Ticket annulé (avec raison dans Notes) |
|
|
254
|
+
| ⏸️ Bloqué | En attente d'un autre ticket |
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
*Ce fichier est mis à jour manuellement à chaque session de travail.*
|
|
259
|
+
*Pour le détail technique de chaque ticket, voir [AUDIT_ROADMAP.md](./AUDIT_ROADMAP.md)*
|
package/commands/demo.js
CHANGED
|
@@ -1,20 +1,7 @@
|
|
|
1
1
|
const inquirer = require("inquirer");
|
|
2
2
|
const { logInfo } = require("../utils/loggers/logInfo");
|
|
3
3
|
const { logSuccess } = require("../utils/loggers/logSuccess");
|
|
4
|
-
const {
|
|
5
|
-
const {
|
|
6
|
-
setupCleanArchitecture,
|
|
7
|
-
} = require("../utils/configs/setupCleanArchitecture");
|
|
8
|
-
const {
|
|
9
|
-
setupLightArchitecture,
|
|
10
|
-
} = require("../utils/configs/setupLightArchitecture");
|
|
11
|
-
const { setupAuth } = require("../utils/setups/setupAuth");
|
|
12
|
-
const { setupSwagger } = require("../utils/setups/setupSwagger");
|
|
13
|
-
const { setupDatabase } = require("../utils/setups/setupDatabase");
|
|
14
|
-
const { configureDocker } = require("../utils/configs/configureDocker");
|
|
15
|
-
const { generateEnvFile, writeEnvFile } = require("../utils/envGenerator");
|
|
16
|
-
const { setupBootstrapLogger } = require("../utils/setups/setupLogger");
|
|
17
|
-
const { saveProjectConfig } = require("../utils/file-utils/saveProjectConfig");
|
|
4
|
+
const { runProjectSetupPipeline } = require("../utils/setups/projectSetup");
|
|
18
5
|
const actualInquirer = inquirer.default || inquirer;
|
|
19
6
|
|
|
20
7
|
async function demoCommand(flags = {}) {
|
|
@@ -209,34 +196,7 @@ async function demoCommand(flags = {}) {
|
|
|
209
196
|
dbConfig,
|
|
210
197
|
};
|
|
211
198
|
|
|
212
|
-
await
|
|
213
|
-
|
|
214
|
-
if (isLight) {
|
|
215
|
-
await setupLightArchitecture(demoInputs);
|
|
216
|
-
} else {
|
|
217
|
-
await setupCleanArchitecture(demoInputs);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
if (useAuth) {
|
|
221
|
-
await setupAuth(demoInputs);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
if (useSwagger) {
|
|
225
|
-
await setupSwagger(demoInputs.swaggerInputs);
|
|
226
|
-
} else {
|
|
227
|
-
await setupBootstrapLogger();
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
if (useDocker) {
|
|
231
|
-
await configureDocker(demoInputs);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
await setupDatabase(demoInputs);
|
|
235
|
-
|
|
236
|
-
const envContent = await generateEnvFile(demoInputs);
|
|
237
|
-
writeEnvFile(envContent);
|
|
238
|
-
|
|
239
|
-
await saveProjectConfig(demoInputs);
|
|
199
|
+
await runProjectSetupPipeline(demoInputs);
|
|
240
200
|
|
|
241
201
|
console.log("\n" + "=".repeat(60));
|
|
242
202
|
logSuccess("Demonstration project created successfully!");
|
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
|
@@ -1,25 +1,12 @@
|
|
|
1
1
|
const { getFullModeInputs } = require("../utils/fullModeInput");
|
|
2
2
|
const { getLightModeInputs } = require("../utils/lightModeInput");
|
|
3
|
-
const {
|
|
4
|
-
const {
|
|
5
|
-
setupCleanArchitecture,
|
|
6
|
-
} = require("../utils/configs/setupCleanArchitecture");
|
|
7
|
-
const {
|
|
8
|
-
setupLightArchitecture,
|
|
9
|
-
} = require("../utils/configs/setupLightArchitecture");
|
|
10
|
-
const { setupAuth } = require("../utils/setups/setupAuth");
|
|
11
|
-
const { setupSwagger } = require("../utils/setups/setupSwagger");
|
|
12
|
-
const { setupDatabase } = require("../utils/setups/setupDatabase");
|
|
13
|
-
const { configureDocker } = require("../utils/configs/configureDocker");
|
|
14
|
-
const { setupBootstrapLogger } = require("../utils/setups/setupLogger");
|
|
3
|
+
const { runProjectSetupPipeline } = require("../utils/setups/projectSetup");
|
|
15
4
|
const { logSuccess } = require("../utils/loggers/logSuccess");
|
|
16
5
|
const { logInfo } = require("../utils/loggers/logInfo");
|
|
17
6
|
const { logError } = require("../utils/loggers/logError");
|
|
18
|
-
const { generateEnvFile, writeEnvFile } = require("../utils/envGenerator");
|
|
19
7
|
const readline = require("readline-sync");
|
|
20
8
|
const { info, warning } = require("../utils/colors");
|
|
21
9
|
const { logWarning } = require("../utils/loggers/logWarning");
|
|
22
|
-
const { saveProjectConfig } = require("../utils/file-utils/saveProjectConfig");
|
|
23
10
|
|
|
24
11
|
async function newCommand(projectName, flags = {}) {
|
|
25
12
|
if (!projectName) {
|
|
@@ -96,11 +83,10 @@ async function buildFullModeInputs(projectName, flags) {
|
|
|
96
83
|
}
|
|
97
84
|
|
|
98
85
|
function hasAllLightModeFlags(flags) {
|
|
99
|
-
|
|
100
|
-
if (!flags.interactive || flags.interactive === false) {
|
|
86
|
+
if (flags.interactive === true) {
|
|
101
87
|
return false;
|
|
102
88
|
}
|
|
103
|
-
return
|
|
89
|
+
return flags.orm !== undefined;
|
|
104
90
|
}
|
|
105
91
|
|
|
106
92
|
function buildLightModeFromFlags(projectName, flags) {
|
|
@@ -166,11 +152,10 @@ function buildLightModeFromFlags(projectName, flags) {
|
|
|
166
152
|
}
|
|
167
153
|
|
|
168
154
|
function hasAllFullModeFlags(flags) {
|
|
169
|
-
|
|
170
|
-
if (!flags.interactive || flags.interactive === false) {
|
|
155
|
+
if (flags.interactive === true) {
|
|
171
156
|
return false;
|
|
172
157
|
}
|
|
173
|
-
return
|
|
158
|
+
return flags.orm !== undefined;
|
|
174
159
|
}
|
|
175
160
|
|
|
176
161
|
function buildFullModeFromFlags(projectName, flags) {
|
|
@@ -241,37 +226,9 @@ function buildFullModeFromFlags(projectName, flags) {
|
|
|
241
226
|
|
|
242
227
|
async function executeProjectSetup(inputs) {
|
|
243
228
|
try {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
await createProject(inputs);
|
|
247
|
-
|
|
248
|
-
if (inputs.mode === "light") {
|
|
249
|
-
await setupLightArchitecture(inputs);
|
|
250
|
-
} else {
|
|
251
|
-
await setupCleanArchitecture(inputs);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
if (inputs.useAuth) await setupAuth(inputs);
|
|
255
|
-
|
|
256
|
-
if (inputs.useSwagger) {
|
|
257
|
-
await setupSwagger(inputs.swaggerInputs);
|
|
258
|
-
} else {
|
|
259
|
-
setupBootstrapLogger();
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
if (inputs.useDocker) await configureDocker(inputs);
|
|
263
|
-
|
|
264
|
-
await setupDatabase(inputs);
|
|
265
|
-
|
|
266
|
-
const envContent = await generateEnvFile(inputs);
|
|
267
|
-
writeEnvFile(envContent);
|
|
268
|
-
|
|
269
|
-
await saveProjectConfig(inputs);
|
|
270
|
-
|
|
229
|
+
await runProjectSetupPipeline(inputs);
|
|
271
230
|
printSuccessSummary(inputs);
|
|
272
231
|
} catch (error) {
|
|
273
|
-
// Erreur lors de la creation du projet: ${error.message}
|
|
274
|
-
logError(`Error during project creation: ${error.message}`);
|
|
275
232
|
throw error;
|
|
276
233
|
}
|
|
277
234
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nestcraftx",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.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,102 @@
|
|
|
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 isDryRun = process.argv.includes("--dry-run");
|
|
28
|
+
if (isDryRun) {
|
|
29
|
+
console.log(`[DRY-RUN] Simulated: safe update app.module.ts with ${capitalize(entity)}Module`);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const filePath = "src/app.module.ts";
|
|
34
|
+
const moduleName = `${capitalize(entity)}Module`;
|
|
35
|
+
const importLine = `import { ${moduleName} } from 'src/${entity}/${entity}.module';`;
|
|
36
|
+
|
|
37
|
+
let content = fs.readFileSync(filePath, "utf-8");
|
|
38
|
+
|
|
39
|
+
// Étape 1 : Ajout de l'import en haut du fichier si nécessaire
|
|
40
|
+
if (!content.includes(importLine)) {
|
|
41
|
+
const importMarker = `import { ConfigModule } from '@nestjs/config';`;
|
|
42
|
+
|
|
43
|
+
if (content.includes(importMarker)) {
|
|
44
|
+
await updateFile({
|
|
45
|
+
path: filePath,
|
|
46
|
+
pattern: importMarker,
|
|
47
|
+
replacement: `${importMarker}\n${importLine}`,
|
|
48
|
+
});
|
|
49
|
+
content = fs.readFileSync(filePath, "utf-8");
|
|
50
|
+
} else {
|
|
51
|
+
logInfo(
|
|
52
|
+
" Impossible de trouver le point d'insertion de l'import (ConfigModule manquant)",
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Étape 2 : Vérifier le bloc des imports du @Module avec gestion des crochets imbriqués
|
|
58
|
+
const importsHeaderMatch = content.match(/imports:\s*\[/);
|
|
59
|
+
if (!importsHeaderMatch) {
|
|
60
|
+
logInfo(" Impossible de trouver le bloc 'imports' dans AppModule.");
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const startIndex =
|
|
65
|
+
importsHeaderMatch.index + importsHeaderMatch[0].length - 1; // index du '['
|
|
66
|
+
let depth = 1;
|
|
67
|
+
let endIndex = -1;
|
|
68
|
+
for (let i = startIndex + 1; i < content.length; i++) {
|
|
69
|
+
if (content[i] === "[") {
|
|
70
|
+
depth++;
|
|
71
|
+
} else if (content[i] === "]") {
|
|
72
|
+
depth--;
|
|
73
|
+
if (depth === 0) {
|
|
74
|
+
endIndex = i;
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (endIndex === -1) {
|
|
81
|
+
logInfo(
|
|
82
|
+
" Impossible de trouver le crochet de fermeture du bloc 'imports' dans AppModule.",
|
|
83
|
+
);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const currentImportsBlock = content.substring(startIndex + 1, endIndex);
|
|
88
|
+
const isAlreadyImportedInModule = currentImportsBlock.includes(moduleName);
|
|
89
|
+
|
|
90
|
+
if (!isAlreadyImportedInModule) {
|
|
91
|
+
const updatedBlock = currentImportsBlock.trim().endsWith(",")
|
|
92
|
+
? `${currentImportsBlock.trim()} ${moduleName},`
|
|
93
|
+
: `${currentImportsBlock.trim()}, ${moduleName},`;
|
|
94
|
+
|
|
95
|
+
const beforeBlock = content.substring(0, startIndex + 1);
|
|
96
|
+
const afterBlock = content.substring(endIndex);
|
|
97
|
+
const newContent = beforeBlock + updatedBlock + afterBlock;
|
|
98
|
+
fs.writeFileSync(filePath, newContent, "utf-8");
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
module.exports = { safeUpdateAppModule };
|