nestcraftx 0.1.6 → 0.1.8
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/package.json +1 -1
- package/setup.js +7 -2
- package/unutils.txt +401 -143
- package/utils/configs/configureDocker.js +1 -1
- package/utils/configs/setupCleanArchitecture.js +204 -242
- package/utils/setups/orms/typeOrmSetup.js +1 -1
- package/utils/setups/setupAuth.js +211 -83
- package/utils/setups/setupDatabase.js +2 -2
- package/utils/setups/setupLogger.js +53 -0
- package/utils/setups/setupMongoose.js +45 -0
- package/utils/setups/setupPrisma.js +5 -1
- package/utils/setups/setupSwagger.js +6 -5
- package/utils/userInput.js +101 -225
- package/utils/utils.js +204 -43
|
@@ -3,9 +3,14 @@ const { logInfo } = require("../loggers/logInfo");
|
|
|
3
3
|
const { runCommand } = require("../shell");
|
|
4
4
|
const { createDirectory, createFile, updateFile } = require("../userInput");
|
|
5
5
|
const { logSuccess } = require("../loggers/logSuccess");
|
|
6
|
+
const { generateDto } = require("../utils");
|
|
6
7
|
|
|
7
|
-
async function setupAuth() {
|
|
8
|
+
async function setupAuth(inputs) {
|
|
8
9
|
logInfo("Ajout de l'authentification avec JWT et Passport...");
|
|
10
|
+
|
|
11
|
+
const dbConfig = inputs.dbConfig;
|
|
12
|
+
const useSwagger = inputs.useSwagger;
|
|
13
|
+
|
|
9
14
|
await runCommand(
|
|
10
15
|
`npm install @nestjs/jwt @nestjs/passport passport passport-jwt bcrypt`,
|
|
11
16
|
"Échec de l'installation des dépendances d'authentification"
|
|
@@ -29,26 +34,64 @@ async function setupAuth() {
|
|
|
29
34
|
await createDirectory(path);
|
|
30
35
|
});
|
|
31
36
|
|
|
32
|
-
|
|
37
|
+
let ormImports = "";
|
|
38
|
+
let ormModuleImport = "";
|
|
39
|
+
let prismaProvider = ""; // Pour n'ajouter PrismaService que si besoin
|
|
40
|
+
|
|
41
|
+
if (dbConfig.orm === "typeorm") {
|
|
42
|
+
ormImports = `import { TypeOrmModule } from '@nestjs/typeorm';
|
|
43
|
+
import { User } from 'src/entities/User.entity';`;
|
|
44
|
+
ormModuleImport = `TypeOrmModule.forFeature([User]),`;
|
|
45
|
+
prismaProvider = "PrismaService,";
|
|
46
|
+
} else if (dbConfig.orm === "mongoose") {
|
|
47
|
+
ormImports = `import { MongooseModule } from '@nestjs/mongoose';
|
|
48
|
+
import { User, UserSchema } from 'src/user/domain/entities/user.schema';`;
|
|
49
|
+
ormModuleImport = `MongooseModule.forFeature([{ name: User.name, schema: UserSchema }]),`;
|
|
50
|
+
prismaProvider = ""; // Ne pas ajouter PrismaService
|
|
51
|
+
} else if (dbConfig.orm === "prisma") {
|
|
52
|
+
ormImports = "";
|
|
53
|
+
ormModuleImport = "";
|
|
54
|
+
prismaProvider = "PrismaService,";
|
|
55
|
+
}
|
|
56
|
+
|
|
33
57
|
await createFile({
|
|
34
58
|
path: `${authPath}/auth.module.ts`,
|
|
35
|
-
contente: `
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
59
|
+
contente: `
|
|
60
|
+
import { Module } from '@nestjs/common';
|
|
61
|
+
import { JwtModule } from '@nestjs/jwt';
|
|
62
|
+
import { PassportModule } from '@nestjs/passport';
|
|
63
|
+
import { UserMapper } from 'src/user/domain/mappers/user.mapper';
|
|
64
|
+
${ormImports}
|
|
65
|
+
import { AuthService } from '${authPaths.authServicesPath}/auth.service';
|
|
66
|
+
${
|
|
67
|
+
dbConfig.orm === "prisma"
|
|
68
|
+
? "import { PrismaService } from 'src/prisma/prisma.service';"
|
|
69
|
+
: ""
|
|
70
|
+
}
|
|
71
|
+
import { AuthController } from '${
|
|
72
|
+
authPaths.authControllersPath
|
|
73
|
+
}/auth.controller';
|
|
74
|
+
import { JwtStrategy } from '${authPaths.authStrategyPath}/jwt.strategy';
|
|
75
|
+
import { AuthGuard } from '${authPaths.authGuardsPath}/auth.guard';
|
|
76
|
+
import { UserRepository } from 'src/user/infrastructure/repositories/user.repository';
|
|
77
|
+
|
|
78
|
+
@Module({
|
|
79
|
+
imports: [
|
|
80
|
+
${ormModuleImport}
|
|
81
|
+
PassportModule,
|
|
82
|
+
JwtModule.register({ secret: 'your-secret-key', signOptions: { expiresIn: '1h' } }),
|
|
83
|
+
],
|
|
84
|
+
controllers: [AuthController],
|
|
85
|
+
providers: [
|
|
86
|
+
${prismaProvider}
|
|
87
|
+
AuthService,
|
|
88
|
+
JwtStrategy,
|
|
89
|
+
AuthGuard
|
|
90
|
+
],
|
|
91
|
+
exports: [AuthService],
|
|
92
|
+
})
|
|
93
|
+
export class AuthModule {}
|
|
94
|
+
`.trim(),
|
|
52
95
|
});
|
|
53
96
|
|
|
54
97
|
// 📌 Auth Service
|
|
@@ -63,11 +106,17 @@ async function setupAuth() {
|
|
|
63
106
|
} from '@nestjs/common';
|
|
64
107
|
import { JwtService } from '@nestjs/jwt';
|
|
65
108
|
import * as bcrypt from 'bcrypt';
|
|
66
|
-
import { CreateUserDto } from 'src/user/application/dtos/user.dto';
|
|
67
|
-
import { IUserRepository } from 'src/user/application/interfaces/user.repository.interface';
|
|
68
|
-
import { UserEntity } from 'src/user/domain/entities/user.entity';
|
|
69
109
|
import { v4 as uuidv4 } from 'uuid';
|
|
70
110
|
|
|
111
|
+
import { IUserRepository } from 'src/user/application/interfaces/user.repository.interface';
|
|
112
|
+
import { CreateUserDto } from 'src/user/application/dtos/user.dto';
|
|
113
|
+
import { LoginCredentialDto } from 'src/user/application/dtos/loginCredential.dto';
|
|
114
|
+
import { RefreshTokenDto } from 'src/user/application/dtos/refreshToken.dto';
|
|
115
|
+
import { SendOtpDto } from 'src/user/application/dtos/sendOtp.dto';
|
|
116
|
+
import { VerifyOtpDto } from 'src/user/application/dtos/verifyOtp.dto';
|
|
117
|
+
import { ForgotPasswordDto } from 'src/user/application/dtos/forgotPassword.dto';
|
|
118
|
+
import { ResetPasswordDto } from 'src/user/application/dtos/resetPassword.dto';
|
|
119
|
+
|
|
71
120
|
@Injectable()
|
|
72
121
|
export class AuthService {
|
|
73
122
|
private refreshTokens = new Map<string, string>();
|
|
@@ -75,19 +124,21 @@ export class AuthService {
|
|
|
75
124
|
|
|
76
125
|
constructor(
|
|
77
126
|
private readonly jwtService: JwtService,
|
|
78
|
-
@Inject('
|
|
127
|
+
@Inject('IUserRepository')
|
|
128
|
+
private readonly userRepository: IUserRepository,
|
|
79
129
|
) {}
|
|
80
130
|
|
|
81
|
-
//
|
|
131
|
+
// 🔒 Hasher le mot de passe utilisateur
|
|
82
132
|
async hashPassword(password: string): Promise<string> {
|
|
83
133
|
return bcrypt.hash(password, 10);
|
|
84
134
|
}
|
|
85
135
|
|
|
136
|
+
// 🧪 Comparer un mot de passe en clair avec un hash
|
|
86
137
|
async comparePassword(password: string, hash: string): Promise<boolean> {
|
|
87
138
|
return bcrypt.compare(password, hash);
|
|
88
139
|
}
|
|
89
140
|
|
|
90
|
-
// 🧾
|
|
141
|
+
// 🧾 Inscription (register)
|
|
91
142
|
async register(dto: CreateUserDto): Promise<{ message: string }> {
|
|
92
143
|
const existing = await this.userRepository.findAll();
|
|
93
144
|
if (existing.find((user) => user.getEmail() === dto.email)) {
|
|
@@ -100,11 +151,11 @@ export class AuthService {
|
|
|
100
151
|
return { message: 'Registration successful' };
|
|
101
152
|
}
|
|
102
153
|
|
|
103
|
-
// 🔑
|
|
104
|
-
async login(
|
|
154
|
+
// 🔑 Connexion (login)
|
|
155
|
+
async login(dto: LoginCredentialDto) {
|
|
105
156
|
const users = await this.userRepository.findAll();
|
|
106
|
-
const user = users.find((u) => u.getEmail() === email);
|
|
107
|
-
if (!user || !(await this.comparePassword(password, user.getPassword()))) {
|
|
157
|
+
const user = users.find((u) => u.getEmail() === dto.email);
|
|
158
|
+
if (!user || !(await this.comparePassword(dto.password, user.getPassword()))) {
|
|
108
159
|
throw new UnauthorizedException('Invalid credentials');
|
|
109
160
|
}
|
|
110
161
|
|
|
@@ -117,12 +168,12 @@ export class AuthService {
|
|
|
117
168
|
return { accessToken, refreshToken };
|
|
118
169
|
}
|
|
119
170
|
|
|
120
|
-
// 🔁
|
|
121
|
-
async refreshToken(
|
|
171
|
+
// 🔁 Rafraîchir un token d'accès
|
|
172
|
+
async refreshToken(dto: RefreshTokenDto) {
|
|
122
173
|
try {
|
|
123
|
-
const payload = this.jwtService.verify(refreshToken);
|
|
174
|
+
const payload = this.jwtService.verify(dto.refreshToken);
|
|
124
175
|
const stored = this.refreshTokens.get(payload.sub);
|
|
125
|
-
if (stored !== refreshToken) throw new UnauthorizedException();
|
|
176
|
+
if (stored !== dto.refreshToken) throw new UnauthorizedException();
|
|
126
177
|
|
|
127
178
|
const accessToken = this.jwtService.sign(
|
|
128
179
|
{ sub: payload.sub, email: payload.email },
|
|
@@ -134,135 +185,146 @@ export class AuthService {
|
|
|
134
185
|
}
|
|
135
186
|
}
|
|
136
187
|
|
|
137
|
-
// 🚪
|
|
138
|
-
async logout(
|
|
139
|
-
const payload = this.jwtService.verify(refreshToken);
|
|
188
|
+
// 🚪 Déconnexion
|
|
189
|
+
async logout(dto: RefreshTokenDto) {
|
|
190
|
+
const payload = this.jwtService.verify(dto.refreshToken);
|
|
140
191
|
this.refreshTokens.delete(payload.sub);
|
|
141
192
|
return { message: 'Logged out successfully' };
|
|
142
193
|
}
|
|
143
194
|
|
|
144
|
-
// 📲
|
|
145
|
-
async sendOtp(
|
|
195
|
+
// 📲 Envoyer un OTP
|
|
196
|
+
async sendOtp(dto: SendOtpDto) {
|
|
146
197
|
const otp = Math.floor(100000 + Math.random() * 900000).toString();
|
|
147
|
-
this.otps.set(email, otp);
|
|
148
|
-
console.log(\`[OTP] for \${email} is \${otp}\`);
|
|
198
|
+
this.otps.set(dto.email, otp);
|
|
199
|
+
console.log(\`[OTP] for \${dto.email} is \${otp}\`);
|
|
149
200
|
return { message: 'OTP sent' };
|
|
150
201
|
}
|
|
151
202
|
|
|
152
|
-
// ✅
|
|
153
|
-
async verifyOtp(
|
|
154
|
-
const valid = this.otps.get(email);
|
|
155
|
-
if (valid === otp) {
|
|
156
|
-
this.otps.delete(email);
|
|
203
|
+
// ✅ Vérifier un OTP
|
|
204
|
+
async verifyOtp(dto: VerifyOtpDto) {
|
|
205
|
+
const valid = this.otps.get(dto.email);
|
|
206
|
+
if (valid === dto.otp) {
|
|
207
|
+
this.otps.delete(dto.email);
|
|
157
208
|
return { message: 'OTP verified' };
|
|
158
209
|
}
|
|
159
210
|
throw new UnauthorizedException('Invalid OTP');
|
|
160
211
|
}
|
|
161
212
|
|
|
162
|
-
//
|
|
163
|
-
async forgotPassword(
|
|
213
|
+
// 📬 Mot de passe oublié
|
|
214
|
+
async forgotPassword(dto: ForgotPasswordDto) {
|
|
164
215
|
const users = await this.userRepository.findAll();
|
|
165
|
-
const user = users.find((u) => u.getEmail() === email);
|
|
216
|
+
const user = users.find((u) => u.getEmail() === dto.email);
|
|
166
217
|
if (!user) throw new NotFoundException('User not found');
|
|
167
218
|
|
|
168
219
|
const token = uuidv4();
|
|
169
|
-
|
|
170
|
-
console.log(\`[ResetToken] for ${email} is ${token}\`);
|
|
171
|
-
|
|
220
|
+
console.log(\`[ResetToken] for \${dto.email} is \${token}\`);
|
|
172
221
|
return { message: 'Reset token sent' };
|
|
173
222
|
}
|
|
174
223
|
|
|
175
|
-
//
|
|
176
|
-
async resetPassword({
|
|
177
|
-
email,
|
|
178
|
-
newPassword,
|
|
179
|
-
}: {
|
|
180
|
-
email: string;
|
|
181
|
-
newPassword: string;
|
|
182
|
-
}) {
|
|
224
|
+
// 🔄 Réinitialiser le mot de passe
|
|
225
|
+
async resetPassword(dto: ResetPasswordDto) {
|
|
183
226
|
const users = await this.userRepository.findAll();
|
|
184
|
-
const user = users.find((u) => u.getEmail() === email);
|
|
227
|
+
const user = users.find((u) => u.getEmail() === dto.email);
|
|
185
228
|
if (!user) throw new UnauthorizedException('Invalid reset token');
|
|
186
229
|
|
|
187
|
-
const password = await this.hashPassword(newPassword);
|
|
230
|
+
const password = await this.hashPassword(dto.newPassword);
|
|
188
231
|
await this.userRepository.update(user.getId(), { password });
|
|
189
232
|
|
|
190
233
|
return { message: 'Password reset successful' };
|
|
191
234
|
}
|
|
192
235
|
|
|
193
|
-
|
|
194
|
-
async getProfile(user:
|
|
195
|
-
const found = await this.userRepository.findById(user.
|
|
236
|
+
// 👤 Obtenir le profil
|
|
237
|
+
async getProfile(user: any) {
|
|
238
|
+
const found = await this.userRepository.findById(user.userId);
|
|
196
239
|
if (!found) throw new NotFoundException('User not found');
|
|
197
|
-
|
|
240
|
+
const email = found.getEmail();
|
|
241
|
+
return { email: email };
|
|
198
242
|
}
|
|
199
243
|
|
|
200
|
-
//
|
|
244
|
+
// 🔧 Générer un token manuellement
|
|
201
245
|
generateToken(payload: any) {
|
|
202
246
|
return this.jwtService.sign(payload);
|
|
203
247
|
}
|
|
204
248
|
}
|
|
205
249
|
`,
|
|
206
250
|
});
|
|
207
|
-
|
|
208
251
|
// 📌 Auth Controller
|
|
209
252
|
await createFile({
|
|
210
253
|
path: `${authPaths.authControllersPath}/auth.controller.ts`,
|
|
211
254
|
contente: `import { Controller, Post, Body, UseGuards, Get, Req } from '@nestjs/common';
|
|
212
255
|
import { Request } from 'express';
|
|
213
|
-
import { AuthService } from
|
|
214
|
-
import { JwtAuthGuard } from
|
|
256
|
+
import { AuthService } from "${authPaths.authServicesPath}/auth.service";
|
|
257
|
+
import { JwtAuthGuard } from "${authPaths.authGuardsPath}/jwt-auth.guard";
|
|
258
|
+
import { CreateUserDto } from 'src/user/application/dtos/user.dto';
|
|
259
|
+
import { LoginCredentialDto } from 'src/user/application/dtos/loginCredential.dto';
|
|
260
|
+
import { RefreshTokenDto } from 'src/user/application/dtos/refreshToken.dto';
|
|
261
|
+
import { SendOtpDto } from 'src/user/application/dtos/sendOtp.dto';
|
|
262
|
+
import { VerifyOtpDto } from 'src/user/application/dtos/verifyOtp.dto';
|
|
263
|
+
import { ForgotPasswordDto } from 'src/user/application/dtos/forgotPassword.dto';
|
|
264
|
+
import { ResetPasswordDto } from 'src/user/application/dtos/resetPassword.dto';
|
|
265
|
+
${useSwagger ? "import { ApiBearerAuth } from '@nestjs/swagger';" : ""}
|
|
215
266
|
|
|
216
267
|
@Controller('auth')
|
|
217
268
|
export class AuthController {
|
|
218
269
|
constructor(private readonly authService: AuthService) {}
|
|
219
270
|
|
|
271
|
+
// 📝 Créer un compte utilisateur (👤)
|
|
220
272
|
@Post('register')
|
|
221
|
-
async register(@Body() body:
|
|
273
|
+
async register(@Body() body: CreateUserDto) {
|
|
222
274
|
return this.authService.register(body);
|
|
223
275
|
}
|
|
224
276
|
|
|
277
|
+
// 🔐 Connexion utilisateur (🔑)
|
|
225
278
|
@Post('login')
|
|
226
|
-
async login(@Body() body:
|
|
279
|
+
async login(@Body() body: LoginCredentialDto) {
|
|
227
280
|
return this.authService.login(body);
|
|
228
281
|
}
|
|
229
282
|
|
|
283
|
+
// ♻️ Rafraîchir le token d'accès (🔁)
|
|
230
284
|
@Post('refresh')
|
|
231
|
-
async refreshToken(@Body() body:
|
|
232
|
-
return this.authService.refreshToken(body
|
|
285
|
+
async refreshToken(@Body() body: RefreshTokenDto) {
|
|
286
|
+
return this.authService.refreshToken(body);
|
|
233
287
|
}
|
|
234
288
|
|
|
289
|
+
// 🚪 Déconnexion utilisateur (🚫)
|
|
235
290
|
@Post('logout')
|
|
236
|
-
async logout(@Body() body:
|
|
237
|
-
return this.authService.logout(body
|
|
291
|
+
async logout(@Body() body: RefreshTokenDto) {
|
|
292
|
+
return this.authService.logout(body);
|
|
238
293
|
}
|
|
239
294
|
|
|
295
|
+
// 📤 Envoyer un OTP au mail (📧)
|
|
240
296
|
@Post('send-otp')
|
|
241
|
-
async sendOtp(@Body() body:
|
|
297
|
+
async sendOtp(@Body() body: SendOtpDto) {
|
|
242
298
|
return this.authService.sendOtp(body);
|
|
243
299
|
}
|
|
244
300
|
|
|
301
|
+
// ✅ Vérifier l'OTP envoyé (✔️)
|
|
245
302
|
@Post('verify-otp')
|
|
246
|
-
async verifyOtp(@Body() body:
|
|
247
|
-
return this.authService.verifyOtp(body
|
|
303
|
+
async verifyOtp(@Body() body: VerifyOtpDto) {
|
|
304
|
+
return this.authService.verifyOtp(body);
|
|
248
305
|
}
|
|
249
306
|
|
|
307
|
+
// 🔁 Mot de passe oublié (📨)
|
|
250
308
|
@Post('forgot-password')
|
|
251
|
-
async forgotPassword(@Body() body:
|
|
252
|
-
return this.authService.forgotPassword(body
|
|
309
|
+
async forgotPassword(@Body() body: ForgotPasswordDto) {
|
|
310
|
+
return this.authService.forgotPassword(body);
|
|
253
311
|
}
|
|
254
312
|
|
|
313
|
+
// 🔄 Réinitialiser le mot de passe (🔓)
|
|
255
314
|
@Post('reset-password')
|
|
256
|
-
async resetPassword(@Body() body:
|
|
315
|
+
async resetPassword(@Body() body: ResetPasswordDto) {
|
|
257
316
|
return this.authService.resetPassword(body);
|
|
258
317
|
}
|
|
259
318
|
|
|
319
|
+
// 👤 Obtenir le profil utilisateur connecté (🧑💼)
|
|
320
|
+
${useSwagger ? "@ApiBearerAuth()" : ""}
|
|
260
321
|
@UseGuards(JwtAuthGuard)
|
|
261
322
|
@Get('me')
|
|
262
323
|
async getProfile(@Req() req: Request) {
|
|
263
324
|
if (req.user) return this.authService.getProfile(req.user);
|
|
264
325
|
}
|
|
265
326
|
}
|
|
327
|
+
|
|
266
328
|
`,
|
|
267
329
|
});
|
|
268
330
|
|
|
@@ -282,8 +344,10 @@ export class AuthController {
|
|
|
282
344
|
});
|
|
283
345
|
}
|
|
284
346
|
async validate(payload: any) {
|
|
285
|
-
return {
|
|
286
|
-
|
|
347
|
+
return {
|
|
348
|
+
userId: payload.sub,
|
|
349
|
+
email: payload.email,
|
|
350
|
+
}; }
|
|
287
351
|
}`,
|
|
288
352
|
});
|
|
289
353
|
|
|
@@ -400,6 +464,70 @@ export class JwtAuthGuard extends AuthGuard('jwt') {
|
|
|
400
464
|
`,
|
|
401
465
|
});
|
|
402
466
|
|
|
467
|
+
// 📌 auth DTOs in user entity
|
|
468
|
+
const dtos = [
|
|
469
|
+
{
|
|
470
|
+
name: "loginCredential",
|
|
471
|
+
fields: [
|
|
472
|
+
{ name: "email", type: "string", swaggerExample: "user@example.com" },
|
|
473
|
+
{
|
|
474
|
+
name: "password",
|
|
475
|
+
type: "string",
|
|
476
|
+
swaggerExample: "StrongPassword123!",
|
|
477
|
+
},
|
|
478
|
+
],
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
name: "refreshToken",
|
|
482
|
+
fields: [
|
|
483
|
+
{
|
|
484
|
+
name: "refreshToken",
|
|
485
|
+
type: "string",
|
|
486
|
+
swaggerExample: "eyJhbGciOiJIUzI1NiIsInR5cCI6...",
|
|
487
|
+
},
|
|
488
|
+
],
|
|
489
|
+
},
|
|
490
|
+
{
|
|
491
|
+
name: "sendOtp",
|
|
492
|
+
fields: [
|
|
493
|
+
{ name: "email", type: "string", swaggerExample: "user@example.com" },
|
|
494
|
+
],
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
name: "verifyOtp",
|
|
498
|
+
fields: [
|
|
499
|
+
{ name: "email", type: "string", swaggerExample: "user@example.com" },
|
|
500
|
+
{ name: "otp", type: "string", swaggerExample: "123456" },
|
|
501
|
+
],
|
|
502
|
+
},
|
|
503
|
+
{
|
|
504
|
+
name: "forgotPassword",
|
|
505
|
+
fields: [
|
|
506
|
+
{ name: "email", type: "string", swaggerExample: "user@example.com" },
|
|
507
|
+
],
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
name: "resetPassword",
|
|
511
|
+
fields: [
|
|
512
|
+
{ name: "email", type: "string", swaggerExample: "user@example.com" },
|
|
513
|
+
{
|
|
514
|
+
name: "newPassword",
|
|
515
|
+
type: "string",
|
|
516
|
+
swaggerExample: "NewStrongPass123!",
|
|
517
|
+
},
|
|
518
|
+
],
|
|
519
|
+
},
|
|
520
|
+
];
|
|
521
|
+
|
|
522
|
+
// ✅ Génération de chaque DTO
|
|
523
|
+
for (const dto of dtos) {
|
|
524
|
+
const DtoFileContent = await generateDto(dto, useSwagger, true); // tu dois adapter ta fonction generateDto pour recevoir un dto avec `name` et `fields`
|
|
525
|
+
await createFile({
|
|
526
|
+
path: `src/user/application/dtos/${dto.name}.dto.ts`,
|
|
527
|
+
contente: DtoFileContent,
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
|
|
403
531
|
// modification de AppModule
|
|
404
532
|
const appModulePath = "src/app.module.ts";
|
|
405
533
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const { logInfo } = require("../loggers/logInfo");
|
|
2
2
|
const { runCommand } = require("../shell");
|
|
3
3
|
const { setupTypeORM } = require("./orms/typeOrmSetup");
|
|
4
|
+
const { setupMongoose } = require("./setupMongoose");
|
|
4
5
|
const { setupPrisma } = require("./setupPrisma");
|
|
5
6
|
|
|
6
7
|
async function setupDatabase(inputs) {
|
|
@@ -36,8 +37,7 @@ async function setupDatabase(inputs) {
|
|
|
36
37
|
}
|
|
37
38
|
async function setupMongoDB(inputs) {
|
|
38
39
|
logInfo("Configuration de MongoDB...");
|
|
39
|
-
|
|
40
|
-
await setupMongoDBConfig(inputs);
|
|
40
|
+
await setupMongoose(inputs);
|
|
41
41
|
}
|
|
42
42
|
async function setupSQLite(inputs) {
|
|
43
43
|
logInfo("Configuration de SQLite...");
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
|
|
3
|
+
async function setupBootstrapLogger() {
|
|
4
|
+
// Modification de main.ts pour intégrer Swagger
|
|
5
|
+
const mainTsPath = "src/main.ts";
|
|
6
|
+
let mainTs = fs.readFileSync(mainTsPath, "utf8");
|
|
7
|
+
|
|
8
|
+
if (!mainTs.includes("await app.listen")) return mainTs;
|
|
9
|
+
|
|
10
|
+
// Injecte les imports si non présents
|
|
11
|
+
if (!mainTs.includes("Logger")) {
|
|
12
|
+
mainTs = mainTs.replace(
|
|
13
|
+
"import { NestFactory",
|
|
14
|
+
"import { Logger } from '@nestjs/common';\nimport { NestFactory"
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
if (!mainTs.includes("ConfigService")) {
|
|
18
|
+
mainTs = mainTs.replace(
|
|
19
|
+
"import { NestFactory",
|
|
20
|
+
"import { ConfigService } from '@nestjs/config';\nimport { NestFactory"
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Injecte la récupération des variables
|
|
25
|
+
if (!mainTs.includes("const host = configService.get<string>('HOST'")) {
|
|
26
|
+
mainTs = mainTs.replace(
|
|
27
|
+
"const app = await NestFactory.create(AppModule);",
|
|
28
|
+
`const app = await NestFactory.create(AppModule);
|
|
29
|
+
|
|
30
|
+
const configService = app.get(ConfigService);
|
|
31
|
+
const port = configService.get<number>('PORT', 3000);
|
|
32
|
+
const host = configService.get<string>('HOST', '0.0.0.0');`
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Remplace le démarrage de l'app par le bloc stylisé
|
|
37
|
+
return mainTs.replace(
|
|
38
|
+
"await app.listen(process.env.PORT ?? 3000);",
|
|
39
|
+
`try {
|
|
40
|
+
await app.listen(port, host);
|
|
41
|
+
|
|
42
|
+
const logger = new Logger('Bootstrap');
|
|
43
|
+
logger.log(\`🚀 Application running on: \${await app.getUrl()}\`);
|
|
44
|
+
logger.log(\`🌐 Environment: \${process.env.NODE_ENV || 'development'}\`);
|
|
45
|
+
logger.log(\`📡 Listening on \${host}:\${port}\`);
|
|
46
|
+
} catch (error) {
|
|
47
|
+
const logger = new Logger('Bootstrap');
|
|
48
|
+
logger.error('❌ Failed to start the server', error);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
module.exports = { setupBootstrapLogger };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const { execSync } = require("child_process");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const { createFile, updateFile } = require("../userInput");
|
|
4
|
+
const { logSuccess } = require("../loggers/logSuccess");
|
|
5
|
+
const { logInfo } = require("../loggers/logInfo");
|
|
6
|
+
|
|
7
|
+
async function setupMongoose(inputs) {
|
|
8
|
+
logInfo("📦 Installation de Mongoose et @nestjs/mongoose...");
|
|
9
|
+
execSync("npm install @nestjs/mongoose mongoose", { stdio: "inherit" });
|
|
10
|
+
|
|
11
|
+
// Génération du fichier .env
|
|
12
|
+
const envContent = `
|
|
13
|
+
MONGO_URI=${inputs.dbConfig.MONGO_URI}
|
|
14
|
+
MONGO_DB=${inputs.dbConfig.MONGO_DB}
|
|
15
|
+
`.trim();
|
|
16
|
+
await createFile({ path: ".env", contente: envContent });
|
|
17
|
+
|
|
18
|
+
// Ajout de l'import et de la configuration Mongoose dans app.module.ts
|
|
19
|
+
const appModulePath = path.join("src", "app.module.ts");
|
|
20
|
+
const mongooseImport = `import { MongooseModule } from '@nestjs/mongoose';`;
|
|
21
|
+
|
|
22
|
+
// Ajoute l'import si absent
|
|
23
|
+
await updateFile({
|
|
24
|
+
path: appModulePath,
|
|
25
|
+
pattern: /import {[\s\S]*?} from '@nestjs\/config';/,
|
|
26
|
+
replacement: (match) => `${match}\n${mongooseImport}`,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// Ajoute la configuration MongooseModule dans les imports
|
|
30
|
+
const importsPattern =
|
|
31
|
+
/imports:\s*\[[\s\S]*?ConfigModule\.forRoot\([\s\S]*?\),/;
|
|
32
|
+
await updateFile({
|
|
33
|
+
path: appModulePath,
|
|
34
|
+
pattern: importsPattern,
|
|
35
|
+
replacement: (match) =>
|
|
36
|
+
`${match}
|
|
37
|
+
MongooseModule.forRoot(process.env.MONGO_URI, {
|
|
38
|
+
dbName: process.env.MONGO_DB,
|
|
39
|
+
}),`,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
logSuccess("Mongoose configuré et injecté dans app.module.ts !");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
module.exports = { setupMongoose };
|
|
@@ -210,8 +210,12 @@ function mapTypeToPrisma(type) {
|
|
|
210
210
|
switch (type.toLowerCase()) {
|
|
211
211
|
case "string":
|
|
212
212
|
return "String";
|
|
213
|
+
case "int":
|
|
214
|
+
return "Int";
|
|
215
|
+
case "float":
|
|
216
|
+
return "Float";
|
|
213
217
|
case "number":
|
|
214
|
-
return "Float"; //
|
|
218
|
+
return "Float"; // ou "Int" selon le besoin
|
|
215
219
|
case "boolean":
|
|
216
220
|
return "Boolean";
|
|
217
221
|
case "date":
|
|
@@ -45,14 +45,15 @@ async function setupSwagger(inputs) {
|
|
|
45
45
|
.setTitle('${inputs.title}')
|
|
46
46
|
.setDescription('${inputs.description}')
|
|
47
47
|
.setVersion('${inputs.version}')
|
|
48
|
-
.addBearerAuth(
|
|
49
|
-
{ type: 'http', scheme: 'bearer', bearerFormat: 'JWT', in: 'header' },
|
|
50
|
-
'access-token'
|
|
51
|
-
)
|
|
48
|
+
.addBearerAuth()
|
|
52
49
|
.build();
|
|
53
50
|
|
|
54
51
|
const document = SwaggerModule.createDocument(app, config);
|
|
55
|
-
SwaggerModule.setup('${inputs.endpoint}', app, document
|
|
52
|
+
SwaggerModule.setup('${inputs.endpoint}', app, document,{
|
|
53
|
+
swaggerOptions: {
|
|
54
|
+
persistAuthorization: true,
|
|
55
|
+
},
|
|
56
|
+
});
|
|
56
57
|
|
|
57
58
|
const configService = app.get(ConfigService);
|
|
58
59
|
const port = configService.get<number>('PORT', 3000);
|