nestcraftx 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Augustin Selete
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+
3
+ const [, , command] = process.argv;
4
+
5
+ switch (command) {
6
+ case "start":
7
+ require("../commands/start")();
8
+ break;
9
+ case "--help":
10
+ case "-h":
11
+ default:
12
+ console.log(`
13
+ 🌟 Bienvenue sur NestCraftX CLI 🌟
14
+
15
+ Usage :
16
+ npx nestcraftx start Génère une structure NestJS Clean Architecture
17
+
18
+ Exemples :
19
+ npx nestcraftx start
20
+
21
+ 📘 Plus de commandes à venir...
22
+ `);
23
+ break;
24
+ }
@@ -0,0 +1,8 @@
1
+ const path = require("path");
2
+
3
+ module.exports = function () {
4
+ console.log("🚀 Lancement de la génération NestJS...");
5
+
6
+ const setupPath = path.join(__dirname, "..", "setup.js");
7
+ require(setupPath);
8
+ };
Binary file
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "nestcraftx",
3
+ "version": "0.1.0",
4
+ "description": "CLI to generate scalable NestJS projects with Clean Architecture and Clean Code",
5
+ "main": "bin/nestcraft.js",
6
+ "bin": {
7
+ "nestcraftx": "./bin/nestcraft.js"
8
+ },
9
+ "scripts": {
10
+ "test": "nestcraftx test"
11
+ },
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/august-dev-pro/NestCraftX"
15
+ },
16
+ "keywords": [
17
+ "nestjs",
18
+ "cli",
19
+ "starter",
20
+ "generator",
21
+ "clean architecture",
22
+ "ddd",
23
+ "scaffold"
24
+ ],
25
+ "author": "Ablanhou Augustin Selete",
26
+ "license": "MIT",
27
+ "engines": {
28
+ "node": ">=14.0.0"
29
+ },
30
+ "dependencies": {}
31
+ }
package/readme ADDED
@@ -0,0 +1,181 @@
1
+ ## 🛠️ NestCraft — Générateur de projet backend NestJS
2
+
3
+ ![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)
4
+ ![Node.js](https://img.shields.io/badge/node-%3E=16.0.0-green.svg)
5
+
6
+ Bienvenue dans **NestCraft**, un CLI Node.js puissant pour générer automatiquement une structure de projet backend modulaire, professionnelle et maintenable. Il s’appuie sur les meilleures pratiques modernes : **Clean Architecture**, **Domain-Driven Design (DDD)**, **Prisma**, **TypeORM**, **JWT Auth**, **Swagger**, **Docker**, etc.
7
+
8
+ > 🧠 L’objectif ? Ne plus jamais repartir de zéro pour créer une base de projet solide, évolutive et prête pour la production.
9
+
10
+ ---
11
+
12
+ ## 📑 Sommaire
13
+
14
+ - [✨ Objectif du projet](#-objectif-du-projet)
15
+ - [📦 Prérequis](#-prérequis)
16
+ - [🚀 Installation et utilisation](#-installation-et-utilisation)
17
+ - [🧰 Ce que la commande configure automatiquement](#-Ce-que-la-commande-configure-automatiquement)
18
+ - [📁 Exemple d’architecture générée](#-exemple-darchitecture-générée)
19
+ - [📌 À venir](#-à-venir)
20
+ - [❤️ Contribuer](#️-contribuer)
21
+ - [📜 Licence](#-licence)
22
+
23
+ ---
24
+
25
+ ## ✨ Objectif du projet
26
+
27
+ L’idée est simple : au lieu de réinventer la roue à chaque projet, ce CLI vous génère une base de code solide, bien organisée et évolutive en quelques minutes. Cela vous permet de :
28
+
29
+ - Démarrer un nouveau projet rapidement
30
+ - Avoir une structure claire dès le départ
31
+ - Uniformiser vos projets
32
+ - Se concentrer sur la logique métier sans perdre de temps sur la configuration
33
+
34
+ ---
35
+
36
+ ## 📦 Prérequis
37
+
38
+ Assurez-vous d’avoir :
39
+
40
+ - **Node.js** v16 ou supérieur
41
+ - **npm** ou **yarn**
42
+ - **Docker** (pour l intégration avec la base de données)
43
+ - **Git** (optionnel pour init un repo)
44
+
45
+
46
+ ---```bash
47
+
48
+ ## 🚀 Installation et utilisation
49
+
50
+ 💻 Installation locale (développement ou usage temporaire)
51
+
52
+ git clone https://github.com/august-dev-pro/nestcraft
53
+ cd nestcraft
54
+ npm install
55
+ node setup.js
56
+ ---
57
+
58
+ ## 🧰 Ce que la commande configure automatiquement :
59
+
60
+ ✅ Structure Clean Architecture (domain/usecases/infra)
61
+
62
+ ✅ Swagger (documentation automatique)
63
+
64
+ ✅ Authentification JWT (optionnelle)
65
+
66
+ ✅ Prisma ou TypeORM
67
+
68
+ ✅ Docker + docker-compose
69
+
70
+ ✅ Logger personnalisés (logSuccess, logError, etc.)
71
+
72
+ ✅ Setup .env, Prisma schema, et plus encore...
73
+
74
+ ---
75
+
76
+ ## 📁 Exemple d’architecture générée
77
+ my-app/
78
+ ├── src/
79
+ │ ├── auth/
80
+ │ │ ├── auth.module.ts
81
+ │ │ ├── controllers/
82
+ │ │ │ └── auth.controller.ts
83
+ │ │ ├── guards/
84
+ │ │ │ ├── auth.guard.ts
85
+ │ │ │ ├── jwt-auth.guard.ts
86
+ │ │ │ └── role.guard.ts
87
+ │ │ ├── services/
88
+ │ │ │ └── auth.service.ts
89
+ │ │ └── strategy/
90
+ │ │ └── jwt.strategy.ts
91
+ │ │
92
+ │ ├── common/
93
+ │ │ ├── decorators/
94
+ │ │ │ ├── public.decorator.ts
95
+ │ │ │ └── role.decorator.ts
96
+ │ │ ├── filters/
97
+ │ │ │ └── all-exceptions.filter.ts
98
+ │ │ ├── interceptors/
99
+ │ │ │ └── response.interceptor.ts
100
+ │ │ └── middlewares/
101
+ │ │ └── logger.middleware.ts
102
+ │ │
103
+ │ ├── user/
104
+ │ │ ├── user.module.ts
105
+ │ │ ├── application/
106
+ │ │ │ ├── dtos/
107
+ │ │ │ │ └── user.dto.ts
108
+ │ │ │ ├── interfaces/
109
+ │ │ │ │ └── user.repository.interface.ts
110
+ │ │ │ └── use-cases/
111
+ │ │ │ ├── create-user.use-case.ts
112
+ │ │ │ ├── delete-user.use-case.ts
113
+ │ │ │ ├── getAll-user.use-case.ts
114
+ │ │ │ ├── getById-user.use-case.ts
115
+ │ │ │ └── update-user.use-case.ts
116
+ │ │ │
117
+ │ │ ├── domain/
118
+ │ │ │ ├── entities/
119
+ │ │ │ │ └── user.entity.ts
120
+ │ │ │ ├── enums/
121
+ │ │ │ │ ├── role.enum.ts
122
+ │ │ │ │ └── user.enum.ts
123
+ │ │ │ └── mappers/
124
+ │ │ │ └── user.mapper.ts
125
+ │ │ │
126
+ │ │ ├── infrastructure/
127
+ │ │ │ ├── adapters/
128
+ │ │ │ │ └── user.adapter.ts
129
+ │ │ │ ├── repositories/
130
+ │ │ │ │ └── user.repository.ts
131
+ │ │ │ └── services/
132
+ │ │ │ └── user.service.ts
133
+ │ │ │
134
+ │ │ └── presentation/
135
+ │ │ └── controllers/
136
+ │ │ └── user.controller.ts
137
+ │ │
138
+ │ ├── entities/
139
+ │ │ └── User.entity.ts
140
+ │ │
141
+ │ ├── app.module.ts
142
+ │ └── main.ts
143
+
144
+ ├── .env
145
+ ├── .gitignore
146
+ ├── Dockerfile
147
+ ├── docker-compose.yml
148
+ ├── package.json
149
+ └── README.md
150
+
151
+
152
+ ---
153
+
154
+ ## 📌 À venir
155
+
156
+ npx nestcraft generate [nom de l'entité] → Génère un module complet automatiquement
157
+
158
+ npx nestcraft add:auth → Intègre le système d'auth JWT
159
+
160
+ Menu CLI interactif intelligent (choix d'ORM, de Bases de données ( mysql/mariaBD,firebase,mongodb...), modules, options avancées)
161
+
162
+ Génération de tests unitaires
163
+
164
+ Déploiement Docker simplifié
165
+
166
+ 🧪 Intégration CI/CD de base
167
+
168
+ 🌐 Site de documentation officiel
169
+ ---
170
+
171
+ ##❤️ Contribuer
172
+
173
+ Tu veux améliorer NestCraft ?
174
+ Fork le repo, ajoute tes idées, propose une Pull Request ou ouvre une issue pour en discuter !
175
+ ---
176
+
177
+ ## 📜 Licence
178
+
179
+ MIT © [Augustin_Selete] — libre d’usage, mais le mérite te revient 😉
180
+
181
+ ---
package/setup.js ADDED
@@ -0,0 +1,33 @@
1
+ const { getUserInputs, getUserInputs2 } = require("./utils/userInput");
2
+ const { configureDocker } = require("./utils/configs/configureDocker");
3
+ const {
4
+ setupCleanArchitecture,
5
+ } = require("./utils/configs/setupCleanArchitecture");
6
+ const { logSuccess } = require("./utils/loggers/logSuccess");
7
+ const { createProject } = require("./utils/setups/projectSetup");
8
+ // const { setupPrisma } = require("./utils/setups/setupPrisma");
9
+ const { setupAuth } = require("./utils/setups/setupAuth");
10
+ const { setupSwagger } = require("./utils/setups/setupSwagger");
11
+ const { setupDatabase } = require("./utils/setups/setupDatabase");
12
+
13
+ async function main() {
14
+ const inputs = await getUserInputs2();
15
+
16
+ await createProject(inputs);
17
+ await setupCleanArchitecture(inputs);
18
+
19
+ if (inputs.useAuth) await setupAuth();
20
+ if (inputs.useSwagger) await setupSwagger(inputs.swaggerInputs);
21
+ if (inputs.useDocker) await configureDocker(inputs);
22
+
23
+ // await setupPrisma(inputs);
24
+
25
+ // Sélection dynamique du script de configuration BDD
26
+ await setupDatabase(inputs);
27
+ logSuccess(`Projet ${inputs.projectName} configuré avec succès!`);
28
+ console.log(
29
+ `\n🚀 Pour commencer :\n cd ${inputs.projectName}\n ${inputs.packageManager} run start:dev`
30
+ );
31
+ }
32
+
33
+ main();
package/unutils.txt ADDED
@@ -0,0 +1,173 @@
1
+ `import { Injectable } from '@nestjs/common';
2
+ import { ${capitalize(
3
+ entity
4
+ )}Entity } from '${entityPath}/domain/entities/${entity}.entity';
5
+ /* a decommenter apres migration des schema prisma */
6
+ /* import { ${capitalize(entity)} as Prisma${capitalize(
7
+ entity
8
+ )} } from '@prisma/client'; */
9
+ import { Create${capitalize(entity)}Dto,Update${capitalize(
10
+ entity
11
+ )}Dto } from 'src/${entity}/application/dtos/${entity}.dto';
12
+
13
+ @Injectable()
14
+ export class ${capitalize(entity)}Mapper {
15
+ toDomain(data: any/* Prisma${capitalize(entity)} */): ${capitalize(
16
+ entity
17
+ )}Entity {
18
+ return new ${capitalize(entity)}Entity(
19
+ data.id,
20
+ // ajoute ici tous les autres champs selon l'ordre de l'entité
21
+ // exemple:
22
+ // data.name,
23
+ // data.description,
24
+ // ...
25
+ data.createdAt,
26
+ data.updatedAt,
27
+ );
28
+ }
29
+
30
+ toPersistence(dto: Create${capitalize(entity)}Dto): any {
31
+ return {
32
+ // ajoute ici les champs correspondants au DTO de création
33
+ // exemple:
34
+ // name: dto.name,
35
+ // description: dto.description,
36
+ // ...
37
+ };
38
+ }
39
+
40
+ toUpdatePersistence(dto: Update${capitalize(entity)}Dto): any {
41
+ const data: any = {};
42
+ // Logique conditionnelle pour ne mettre que les champs fournis
43
+ // exemple:
44
+ // if (dto.name) data.name = dto.name;
45
+ // if (dto.description) data.description = dto.description;
46
+ return data;
47
+ }
48
+ }
49
+ `
50
+
51
+ // 📌 5. DTOs
52
+ const DtoFileContent = generateDto(entity);
53
+ await createFile({
54
+ path: `${entityPath}/application/dtos/${entity}.dto.ts`,
55
+ contente: `
56
+ // Importer les décorateurs nécessaires pour la validation et la documentation (Swagger)
57
+ // import { ApiProperty } from '@nestjs/swagger';
58
+ // import { IsString, IsOptional, IsInt, IsDate } from 'class-validator'; // Dépendances pour la validation
59
+
60
+ // Classe DTO pour la création de l'entité ${capitalize(entity)}
61
+ export class Create${capitalize(entity)}Dto {
62
+ // Exemple de propriété pour une chaîne de caractères
63
+ /* @ApiProperty({
64
+ description: 'Le nom complet de l\'utilisateur',
65
+ example: 'John Doe', // Exemple d'un nom complet
66
+ })
67
+ @IsString()
68
+ name: string; // Le nom de l'utilisateur, représenté par une chaîne de caractères */
69
+
70
+ // Exemple de propriété pour un nombre entier
71
+ /* @ApiProperty({
72
+ description: 'L\'âge de l\'utilisateur',
73
+ example: 25, // Exemple d'âge
74
+ })
75
+ @IsInt()
76
+ @IsOptional() // L'âge est optionnel lors de la création
77
+ age?: number; // Âge de l'utilisateur, un nombre entier */
78
+
79
+ // Exemple de propriété pour une date
80
+ /* @ApiProperty({
81
+ description: 'Date de naissance de l\'utilisateur',
82
+ example: '1996-05-20', // Exemple de date au format ISO
83
+ })
84
+ @IsDate()
85
+ birthdate: Date; // Date de naissance de l'utilisateur */
86
+ }
87
+
88
+ // Classe DTO pour la mise à jour de l'entité ${capitalize(entity)}
89
+ export class Update${capitalize(entity)}Dto {
90
+ // Exemple de propriété optionnelle pour un changement de nom
91
+ /* @ApiProperty({
92
+ description: 'Nom mis à jour de l\'utilisateur',
93
+ example: 'Jane Smith', // Exemple de nouveau nom
94
+ })
95
+ @IsString()
96
+ @IsOptional()
97
+ name?: string; // Nom mis à jour, chaîne de caractères optionnelle */
98
+
99
+ // Exemple de propriété optionnelle pour une mise à jour d'âge
100
+ /* @ApiProperty({
101
+ description: 'Âge mis à jour de l\'utilisateur',
102
+ example: 26, // Exemple d'âge mis à jour
103
+ })
104
+ @IsInt()
105
+ @IsOptional()
106
+ age?: number; // Âge mis à jour, nombre entier optionnel */
107
+ }
108
+ `,
109
+ });
110
+
111
+
112
+
113
+
114
+
115
+ `import { Injectable, NotFoundException } from '@nestjs/common';
116
+ import { PrismaService } from 'src/prisma/prisma.service';
117
+ import { Create${entityNameCapitalized}Dto,Update${entityNameCapitalized}Dto } from 'src/${entityNameLower}/application/dtos/${entityNameLower}.dto';
118
+ import { I${entityNameCapitalized}Repository } from 'src/${entityNameLower}/application/interfaces/${entityNameLower}.repository.interface';
119
+ import { ${entityNameCapitalized}Entity } from 'src/${entityNameLower}/domain/entities/${entityNameLower}.entity';
120
+ import { ${entityNameCapitalized}Mapper } from 'src/${entityNameLower}/domain/mappers/${entityNameLower}.mapper';
121
+
122
+ @Injectable()
123
+ export class ${entityNameCapitalized}Repository implements I${entityNameCapitalized}Repository {
124
+ constructor(
125
+ private readonly prisma: PrismaService,
126
+ private readonly mapper: ${entityNameCapitalized}Mapper,
127
+ ) {}
128
+
129
+ // create
130
+ async create(data: Create${entityNameCapitalized}Dto): Promise<${entityNameCapitalized}Entity> {
131
+ const toPersist = this.mapper.toPersistence(data);
132
+ const created = await this.prisma.${entityNameLower}.create({ data: toPersist });
133
+ return this.mapper.toDomain(created);
134
+ }
135
+
136
+ // find by id
137
+ async findById(id: string): Promise<${entityNameCapitalized}Entity> {
138
+ const record = await this.prisma.${entityNameLower}.findUnique({
139
+ where: { id },
140
+ });
141
+
142
+ if (!record) {
143
+ throw new NotFoundException(\`${entityNameCapitalized}Entity with id \${id} not found\`);
144
+ }
145
+
146
+ return this.mapper.toDomain(record);
147
+ }
148
+
149
+ // update
150
+ async update(id: string, data: Update${entityNameCapitalized}Dto): Promise<${entityNameCapitalized}Entity> {
151
+ const toUpdate = this.mapper.toUpdatePersistence(data);
152
+ const updated = await this.prisma.${entityNameLower}.update({
153
+ where: { id },
154
+ data: toUpdate,
155
+ });
156
+
157
+ return this.mapper.toDomain(updated);
158
+ }
159
+
160
+ // find all
161
+ async findAll(): Promise<${entityNameCapitalized}Entity[]> {
162
+ const records = await this.prisma.${entityNameLower}.findMany();
163
+ return records.map(record => this.mapper.toDomain(record));
164
+ }
165
+
166
+ // delete
167
+ async delete(id: string): Promise<void> {
168
+ await this.prisma.${entityNameLower}.delete({
169
+ where: { id },
170
+ });
171
+ }
172
+ }
173
+ `
@@ -0,0 +1,16 @@
1
+ const fs = require("fs");
2
+ const { logInfo } = require("../loggers/logInfo");
3
+ const { logSuccess } = require("../loggers/logSuccess");
4
+
5
+ async function configureDocker(inputs) {
6
+ logInfo("Génération des fichiers Docker...");
7
+
8
+ const dockerfileContent = `FROM node:18\nWORKDIR /app\nCOPY . .\nRUN ${inputs.packageManager} install\nCMD ["${inputs.packageManager}", "run", "start"]`;
9
+ fs.writeFileSync("Dockerfile", dockerfileContent);
10
+
11
+ const dockerComposeContent = `version: '3'\nservices:\n db:\n image: postgres\n restart: always\n environment:\n POSTGRES_USER: ${inputs.dbUser}\n POSTGRES_PASSWORD: ${inputs.dbPassword}\n POSTGRES_DB: ${inputs.databaseName}\n ports:\n - "5432:5432"`;
12
+ fs.writeFileSync("docker-compose.yml", dockerComposeContent);
13
+
14
+ logSuccess("Docker Configuré avec succès");
15
+ }
16
+ module.exports = { configureDocker };