@abuhannaa/create-apptemplate 1.0.8 → 1.0.10
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/dist/index.js +817 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4,11 +4,669 @@
|
|
|
4
4
|
import { intro, outro, isCancel as isCancel2 } from "@clack/prompts";
|
|
5
5
|
import pc3 from "picocolors";
|
|
6
6
|
|
|
7
|
+
// src/types.ts
|
|
8
|
+
var ALL_FEATURES = [
|
|
9
|
+
"auth",
|
|
10
|
+
"userManagement",
|
|
11
|
+
"departments",
|
|
12
|
+
"fileUpload",
|
|
13
|
+
"auditLogs",
|
|
14
|
+
"notifications",
|
|
15
|
+
"dataExport",
|
|
16
|
+
"dashboard"
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
// src/features.ts
|
|
20
|
+
var FEATURE_OPTIONS = [
|
|
21
|
+
{
|
|
22
|
+
value: "auth",
|
|
23
|
+
label: "Authentication (Login, JWT, Guards)",
|
|
24
|
+
hint: "Login/logout pages, JWT middleware, auth guards, profile"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
value: "userManagement",
|
|
28
|
+
label: "User Management",
|
|
29
|
+
hint: "User CRUD, roles, permissions"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
value: "departments",
|
|
33
|
+
label: "Departments",
|
|
34
|
+
hint: "Department CRUD module"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
value: "fileUpload",
|
|
38
|
+
label: "File Management",
|
|
39
|
+
hint: "File upload, download, preview"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
value: "auditLogs",
|
|
43
|
+
label: "Audit Logging",
|
|
44
|
+
hint: "Track all data changes with audit trail"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
value: "notifications",
|
|
48
|
+
label: "Notifications",
|
|
49
|
+
hint: "Real-time notification system (WebSocket)"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
value: "dataExport",
|
|
53
|
+
label: "Data Export",
|
|
54
|
+
hint: "CSV, Excel, PDF export"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
value: "dashboard",
|
|
58
|
+
label: "Dashboard",
|
|
59
|
+
hint: "Dashboard page with statistics (Requires Users, Depts, Notifications)"
|
|
60
|
+
}
|
|
61
|
+
];
|
|
62
|
+
function applyFeatureDependencies(selected) {
|
|
63
|
+
let result = [...selected];
|
|
64
|
+
if (!result.includes("auth")) {
|
|
65
|
+
result = result.filter((f) => f !== "userManagement" && f !== "departments");
|
|
66
|
+
}
|
|
67
|
+
if (!result.includes("userManagement")) {
|
|
68
|
+
result = result.filter((f) => f !== "departments");
|
|
69
|
+
}
|
|
70
|
+
if (!result.includes("userManagement") || !result.includes("departments") || !result.includes("notifications")) {
|
|
71
|
+
result = result.filter((f) => f !== "dashboard");
|
|
72
|
+
}
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
var DOTNET_CLEAN_MAP = {
|
|
76
|
+
auth: {
|
|
77
|
+
backend: [
|
|
78
|
+
// Application layer
|
|
79
|
+
"src/Core/App.Template.Application/Features/Authentication",
|
|
80
|
+
"src/Core/App.Template.Application/DTOs/Auth",
|
|
81
|
+
"src/Core/App.Template.Application/Interfaces/IJwtTokenService.cs",
|
|
82
|
+
"src/Core/App.Template.Application/Interfaces/IPasswordHashService.cs",
|
|
83
|
+
"src/Core/App.Template.Application/Interfaces/ISsoAuthService.cs",
|
|
84
|
+
"src/Core/App.Template.Application/Interfaces/IEmailService.cs",
|
|
85
|
+
// Infrastructure layer
|
|
86
|
+
"src/Infrastructure/App.Template.Infrastructure/Services/JwtTokenService.cs",
|
|
87
|
+
"src/Infrastructure/App.Template.Infrastructure/Services/PasswordHashService.cs",
|
|
88
|
+
"src/Infrastructure/App.Template.Infrastructure/Services/SsoAuthService.cs",
|
|
89
|
+
"src/Infrastructure/App.Template.Infrastructure/Services/SsoApiModels.cs",
|
|
90
|
+
"src/Infrastructure/App.Template.Infrastructure/Services/EmailService.cs",
|
|
91
|
+
// Presentation layer
|
|
92
|
+
"src/Presentation/App.Template.WebAPI/Controllers/AuthController.cs"
|
|
93
|
+
],
|
|
94
|
+
frontend: []
|
|
95
|
+
// Frontend auth files handled by pattern below
|
|
96
|
+
},
|
|
97
|
+
userManagement: {
|
|
98
|
+
backend: [
|
|
99
|
+
"src/Core/App.Template.Application/Features/UserManagement",
|
|
100
|
+
"src/Core/App.Template.Application/DTOs/UserDto.cs",
|
|
101
|
+
"src/Presentation/App.Template.WebAPI/Controllers/UsersController.cs"
|
|
102
|
+
],
|
|
103
|
+
frontend: []
|
|
104
|
+
},
|
|
105
|
+
departments: {
|
|
106
|
+
backend: [
|
|
107
|
+
"src/Core/App.Template.Application/Features/DepartmentManagement",
|
|
108
|
+
"src/Core/App.Template.Application/DTOs/DepartmentDto.cs",
|
|
109
|
+
"src/Core/App.Template.Application/Interfaces/IOrganizationService.cs",
|
|
110
|
+
"src/Infrastructure/App.Template.Infrastructure/Services/OrganizationService.cs",
|
|
111
|
+
"src/Presentation/App.Template.WebAPI/Controllers/DepartmentsController.cs"
|
|
112
|
+
],
|
|
113
|
+
frontend: []
|
|
114
|
+
},
|
|
115
|
+
fileUpload: {
|
|
116
|
+
backend: [
|
|
117
|
+
"src/Core/App.Template.Application/Features/FileManagement",
|
|
118
|
+
"src/Core/App.Template.Application/DTOs/UploadedFileDto.cs",
|
|
119
|
+
"src/Core/App.Template.Application/Interfaces/IFileStorageService.cs",
|
|
120
|
+
"src/Infrastructure/App.Template.Infrastructure/Services/FileStorageService.cs",
|
|
121
|
+
"src/Presentation/App.Template.WebAPI/Controllers/FilesController.cs"
|
|
122
|
+
],
|
|
123
|
+
frontend: []
|
|
124
|
+
},
|
|
125
|
+
auditLogs: {
|
|
126
|
+
backend: [
|
|
127
|
+
"src/Core/App.Template.Application/Features/AuditLogManagement",
|
|
128
|
+
"src/Core/App.Template.Application/DTOs/AuditLogDto.cs",
|
|
129
|
+
"src/Infrastructure/App.Template.Infrastructure/Persistence/AuditEntry.cs",
|
|
130
|
+
"src/Presentation/App.Template.WebAPI/Controllers/AuditLogsController.cs"
|
|
131
|
+
],
|
|
132
|
+
frontend: []
|
|
133
|
+
},
|
|
134
|
+
notifications: {
|
|
135
|
+
backend: [
|
|
136
|
+
"src/Core/App.Template.Application/Features/NotificationManagement",
|
|
137
|
+
"src/Core/App.Template.Application/DTOs/NotificationDto.cs",
|
|
138
|
+
"src/Core/App.Template.Application/Interfaces/INotificationService.cs",
|
|
139
|
+
"src/Infrastructure/App.Template.Infrastructure/Services/NotificationService.cs",
|
|
140
|
+
"src/Infrastructure/App.Template.Infrastructure/Hubs",
|
|
141
|
+
"src/Infrastructure/App.Template.Infrastructure/SignalR",
|
|
142
|
+
"src/Presentation/App.Template.WebAPI/Controllers/NotificationsController.cs"
|
|
143
|
+
],
|
|
144
|
+
frontend: []
|
|
145
|
+
},
|
|
146
|
+
dataExport: {
|
|
147
|
+
backend: [
|
|
148
|
+
"src/Core/App.Template.Application/Interfaces/IExportService.cs",
|
|
149
|
+
"src/Infrastructure/App.Template.Infrastructure/Services/ExportService.cs",
|
|
150
|
+
"src/Presentation/App.Template.WebAPI/Controllers/ExportController.cs"
|
|
151
|
+
],
|
|
152
|
+
frontend: []
|
|
153
|
+
},
|
|
154
|
+
dashboard: {
|
|
155
|
+
backend: [],
|
|
156
|
+
frontend: []
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
var DOTNET_NLAYER_MAP = {
|
|
160
|
+
auth: {
|
|
161
|
+
backend: [
|
|
162
|
+
"src/App.Template.Api/Controllers/AuthController.cs",
|
|
163
|
+
"src/App.Template.Api/Services/AuthService.cs",
|
|
164
|
+
"src/App.Template.Api/Services/JwtTokenGenerator.cs",
|
|
165
|
+
"src/App.Template.Api/Models/Dtos/AuthDtos.cs"
|
|
166
|
+
],
|
|
167
|
+
frontend: []
|
|
168
|
+
},
|
|
169
|
+
userManagement: {
|
|
170
|
+
backend: [
|
|
171
|
+
"src/App.Template.Api/Controllers/UsersController.cs",
|
|
172
|
+
"src/App.Template.Api/Services/UserService.cs",
|
|
173
|
+
"src/App.Template.Api/Services/IUserService.cs",
|
|
174
|
+
"src/App.Template.Api/Repositories/UserRepository.cs",
|
|
175
|
+
"src/App.Template.Api/Repositories/IUserRepository.cs",
|
|
176
|
+
"src/App.Template.Api/Models/Dtos/UserDtos.cs"
|
|
177
|
+
],
|
|
178
|
+
frontend: []
|
|
179
|
+
},
|
|
180
|
+
departments: {
|
|
181
|
+
backend: [
|
|
182
|
+
"src/App.Template.Api/Controllers/DepartmentsController.cs",
|
|
183
|
+
"src/App.Template.Api/Models/Dtos/DepartmentDtos.cs"
|
|
184
|
+
],
|
|
185
|
+
frontend: []
|
|
186
|
+
},
|
|
187
|
+
fileUpload: {
|
|
188
|
+
backend: [
|
|
189
|
+
"src/App.Template.Api/Controllers/FilesController.cs"
|
|
190
|
+
],
|
|
191
|
+
frontend: []
|
|
192
|
+
},
|
|
193
|
+
auditLogs: {
|
|
194
|
+
backend: [],
|
|
195
|
+
frontend: []
|
|
196
|
+
},
|
|
197
|
+
notifications: {
|
|
198
|
+
backend: [
|
|
199
|
+
"src/App.Template.Api/Controllers/NotificationsController.cs",
|
|
200
|
+
"src/App.Template.Api/Infrastructure/Hubs"
|
|
201
|
+
],
|
|
202
|
+
frontend: []
|
|
203
|
+
},
|
|
204
|
+
dataExport: {
|
|
205
|
+
backend: [
|
|
206
|
+
"src/App.Template.Api/Controllers/ExportController.cs"
|
|
207
|
+
],
|
|
208
|
+
frontend: []
|
|
209
|
+
},
|
|
210
|
+
dashboard: {
|
|
211
|
+
backend: [],
|
|
212
|
+
frontend: []
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
var DOTNET_FEATURE_MAP = {
|
|
216
|
+
auth: {
|
|
217
|
+
backend: [
|
|
218
|
+
"src/App.Template.Api/Features/Auth"
|
|
219
|
+
],
|
|
220
|
+
frontend: []
|
|
221
|
+
},
|
|
222
|
+
userManagement: {
|
|
223
|
+
backend: [
|
|
224
|
+
"src/App.Template.Api/Features/Users"
|
|
225
|
+
],
|
|
226
|
+
frontend: []
|
|
227
|
+
},
|
|
228
|
+
departments: {
|
|
229
|
+
backend: [
|
|
230
|
+
"src/App.Template.Api/Features/Departments"
|
|
231
|
+
],
|
|
232
|
+
frontend: []
|
|
233
|
+
},
|
|
234
|
+
fileUpload: {
|
|
235
|
+
backend: [
|
|
236
|
+
"src/App.Template.Api/Features/Files"
|
|
237
|
+
],
|
|
238
|
+
frontend: []
|
|
239
|
+
},
|
|
240
|
+
auditLogs: {
|
|
241
|
+
backend: [],
|
|
242
|
+
frontend: []
|
|
243
|
+
},
|
|
244
|
+
notifications: {
|
|
245
|
+
backend: [
|
|
246
|
+
"src/App.Template.Api/Features/Notifications"
|
|
247
|
+
],
|
|
248
|
+
frontend: []
|
|
249
|
+
},
|
|
250
|
+
dataExport: {
|
|
251
|
+
backend: [
|
|
252
|
+
"src/App.Template.Api/Features/Export"
|
|
253
|
+
],
|
|
254
|
+
frontend: []
|
|
255
|
+
},
|
|
256
|
+
dashboard: {
|
|
257
|
+
backend: [],
|
|
258
|
+
frontend: []
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
var SPRING_CLEAN_MAP = {
|
|
262
|
+
auth: {
|
|
263
|
+
backend: [
|
|
264
|
+
"api/src/main/java/apptemplate/api/controllers/AuthController.java"
|
|
265
|
+
],
|
|
266
|
+
frontend: []
|
|
267
|
+
},
|
|
268
|
+
userManagement: {
|
|
269
|
+
backend: [
|
|
270
|
+
"api/src/main/java/apptemplate/api/controllers/UsersController.java"
|
|
271
|
+
],
|
|
272
|
+
frontend: []
|
|
273
|
+
},
|
|
274
|
+
departments: {
|
|
275
|
+
backend: [
|
|
276
|
+
"api/src/main/java/apptemplate/api/controllers/DepartmentsController.java"
|
|
277
|
+
],
|
|
278
|
+
frontend: []
|
|
279
|
+
},
|
|
280
|
+
fileUpload: {
|
|
281
|
+
backend: [
|
|
282
|
+
"api/src/main/java/apptemplate/api/controllers/FilesController.java"
|
|
283
|
+
],
|
|
284
|
+
frontend: []
|
|
285
|
+
},
|
|
286
|
+
auditLogs: {
|
|
287
|
+
backend: [
|
|
288
|
+
"api/src/main/java/apptemplate/api/controllers/AuditLogsController.java"
|
|
289
|
+
],
|
|
290
|
+
frontend: []
|
|
291
|
+
},
|
|
292
|
+
notifications: {
|
|
293
|
+
backend: [
|
|
294
|
+
"api/src/main/java/apptemplate/api/controllers/NotificationsController.java"
|
|
295
|
+
],
|
|
296
|
+
frontend: []
|
|
297
|
+
},
|
|
298
|
+
dataExport: {
|
|
299
|
+
backend: [
|
|
300
|
+
"api/src/main/java/apptemplate/api/controllers/ExportController.java"
|
|
301
|
+
],
|
|
302
|
+
frontend: []
|
|
303
|
+
},
|
|
304
|
+
dashboard: {
|
|
305
|
+
backend: [],
|
|
306
|
+
frontend: []
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
var SPRING_NLAYER_MAP = {
|
|
310
|
+
auth: {
|
|
311
|
+
backend: [
|
|
312
|
+
"src/main/java/com/apptemplate/api/controller/AuthController.java"
|
|
313
|
+
],
|
|
314
|
+
frontend: []
|
|
315
|
+
},
|
|
316
|
+
userManagement: {
|
|
317
|
+
backend: [
|
|
318
|
+
"src/main/java/com/apptemplate/api/controller/UserController.java"
|
|
319
|
+
],
|
|
320
|
+
frontend: []
|
|
321
|
+
},
|
|
322
|
+
departments: {
|
|
323
|
+
backend: [
|
|
324
|
+
"src/main/java/com/apptemplate/api/controller/DepartmentController.java"
|
|
325
|
+
],
|
|
326
|
+
frontend: []
|
|
327
|
+
},
|
|
328
|
+
fileUpload: {
|
|
329
|
+
backend: [
|
|
330
|
+
"src/main/java/com/apptemplate/api/controller/FileController.java"
|
|
331
|
+
],
|
|
332
|
+
frontend: []
|
|
333
|
+
},
|
|
334
|
+
auditLogs: {
|
|
335
|
+
backend: [
|
|
336
|
+
"src/main/java/com/apptemplate/api/audit"
|
|
337
|
+
],
|
|
338
|
+
frontend: []
|
|
339
|
+
},
|
|
340
|
+
notifications: {
|
|
341
|
+
backend: [
|
|
342
|
+
"src/main/java/com/apptemplate/api/controller/NotificationController.java"
|
|
343
|
+
],
|
|
344
|
+
frontend: []
|
|
345
|
+
},
|
|
346
|
+
dataExport: {
|
|
347
|
+
backend: [
|
|
348
|
+
"src/main/java/com/apptemplate/api/controller/ExportController.java"
|
|
349
|
+
],
|
|
350
|
+
frontend: []
|
|
351
|
+
},
|
|
352
|
+
dashboard: {
|
|
353
|
+
backend: [],
|
|
354
|
+
frontend: []
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
var SPRING_FEATURE_MAP = {
|
|
358
|
+
auth: {
|
|
359
|
+
backend: [
|
|
360
|
+
"src/main/java/com/apptemplate/api/features/auth"
|
|
361
|
+
],
|
|
362
|
+
frontend: []
|
|
363
|
+
},
|
|
364
|
+
userManagement: {
|
|
365
|
+
backend: [
|
|
366
|
+
"src/main/java/com/apptemplate/api/features/users"
|
|
367
|
+
],
|
|
368
|
+
frontend: []
|
|
369
|
+
},
|
|
370
|
+
departments: {
|
|
371
|
+
backend: [
|
|
372
|
+
"src/main/java/com/apptemplate/api/features/departments"
|
|
373
|
+
],
|
|
374
|
+
frontend: []
|
|
375
|
+
},
|
|
376
|
+
fileUpload: {
|
|
377
|
+
backend: [
|
|
378
|
+
"src/main/java/com/apptemplate/api/features/files"
|
|
379
|
+
],
|
|
380
|
+
frontend: []
|
|
381
|
+
},
|
|
382
|
+
auditLogs: {
|
|
383
|
+
backend: [
|
|
384
|
+
"src/main/java/com/apptemplate/api/common/audit"
|
|
385
|
+
],
|
|
386
|
+
frontend: []
|
|
387
|
+
},
|
|
388
|
+
notifications: {
|
|
389
|
+
backend: [
|
|
390
|
+
"src/main/java/com/apptemplate/api/features/notifications"
|
|
391
|
+
],
|
|
392
|
+
frontend: []
|
|
393
|
+
},
|
|
394
|
+
dataExport: {
|
|
395
|
+
backend: [
|
|
396
|
+
"src/main/java/com/apptemplate/api/features/export"
|
|
397
|
+
],
|
|
398
|
+
frontend: []
|
|
399
|
+
},
|
|
400
|
+
dashboard: {
|
|
401
|
+
backend: [],
|
|
402
|
+
frontend: []
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
var NESTJS_CLEAN_MAP = {
|
|
406
|
+
auth: {
|
|
407
|
+
backend: [
|
|
408
|
+
"src/modules/auth"
|
|
409
|
+
],
|
|
410
|
+
frontend: []
|
|
411
|
+
},
|
|
412
|
+
userManagement: {
|
|
413
|
+
backend: [
|
|
414
|
+
"src/modules/user-management"
|
|
415
|
+
],
|
|
416
|
+
frontend: []
|
|
417
|
+
},
|
|
418
|
+
departments: {
|
|
419
|
+
backend: [
|
|
420
|
+
"src/modules/department-management"
|
|
421
|
+
],
|
|
422
|
+
frontend: []
|
|
423
|
+
},
|
|
424
|
+
fileUpload: {
|
|
425
|
+
backend: [
|
|
426
|
+
"src/modules/file-management"
|
|
427
|
+
],
|
|
428
|
+
frontend: []
|
|
429
|
+
},
|
|
430
|
+
auditLogs: {
|
|
431
|
+
backend: [
|
|
432
|
+
"src/modules/audit-log"
|
|
433
|
+
],
|
|
434
|
+
frontend: []
|
|
435
|
+
},
|
|
436
|
+
notifications: {
|
|
437
|
+
backend: [
|
|
438
|
+
"src/modules/notification"
|
|
439
|
+
],
|
|
440
|
+
frontend: []
|
|
441
|
+
},
|
|
442
|
+
dataExport: {
|
|
443
|
+
backend: [
|
|
444
|
+
"src/modules/export"
|
|
445
|
+
],
|
|
446
|
+
frontend: []
|
|
447
|
+
},
|
|
448
|
+
dashboard: {
|
|
449
|
+
backend: [],
|
|
450
|
+
frontend: []
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
var NESTJS_NLAYER_MAP = {
|
|
454
|
+
auth: {
|
|
455
|
+
backend: [
|
|
456
|
+
"src/auth"
|
|
457
|
+
],
|
|
458
|
+
frontend: []
|
|
459
|
+
},
|
|
460
|
+
userManagement: {
|
|
461
|
+
backend: [],
|
|
462
|
+
frontend: []
|
|
463
|
+
},
|
|
464
|
+
departments: {
|
|
465
|
+
backend: [
|
|
466
|
+
"src/modules/departments"
|
|
467
|
+
],
|
|
468
|
+
frontend: []
|
|
469
|
+
},
|
|
470
|
+
fileUpload: {
|
|
471
|
+
backend: [
|
|
472
|
+
"src/modules/files"
|
|
473
|
+
],
|
|
474
|
+
frontend: []
|
|
475
|
+
},
|
|
476
|
+
auditLogs: {
|
|
477
|
+
backend: [],
|
|
478
|
+
frontend: []
|
|
479
|
+
},
|
|
480
|
+
notifications: {
|
|
481
|
+
backend: [
|
|
482
|
+
"src/modules/notifications"
|
|
483
|
+
],
|
|
484
|
+
frontend: []
|
|
485
|
+
},
|
|
486
|
+
dataExport: {
|
|
487
|
+
backend: [
|
|
488
|
+
"src/modules/export"
|
|
489
|
+
],
|
|
490
|
+
frontend: []
|
|
491
|
+
},
|
|
492
|
+
dashboard: {
|
|
493
|
+
backend: [],
|
|
494
|
+
frontend: []
|
|
495
|
+
}
|
|
496
|
+
};
|
|
497
|
+
var NESTJS_FEATURE_MAP = {
|
|
498
|
+
auth: {
|
|
499
|
+
backend: [
|
|
500
|
+
"src/features/auth"
|
|
501
|
+
],
|
|
502
|
+
frontend: []
|
|
503
|
+
},
|
|
504
|
+
userManagement: {
|
|
505
|
+
backend: [
|
|
506
|
+
"src/features/users"
|
|
507
|
+
],
|
|
508
|
+
frontend: []
|
|
509
|
+
},
|
|
510
|
+
departments: {
|
|
511
|
+
backend: [
|
|
512
|
+
"src/features/departments"
|
|
513
|
+
],
|
|
514
|
+
frontend: []
|
|
515
|
+
},
|
|
516
|
+
fileUpload: {
|
|
517
|
+
backend: [
|
|
518
|
+
"src/features/files"
|
|
519
|
+
],
|
|
520
|
+
frontend: []
|
|
521
|
+
},
|
|
522
|
+
auditLogs: {
|
|
523
|
+
backend: [],
|
|
524
|
+
frontend: []
|
|
525
|
+
},
|
|
526
|
+
notifications: {
|
|
527
|
+
backend: [
|
|
528
|
+
"src/features/notifications"
|
|
529
|
+
],
|
|
530
|
+
frontend: []
|
|
531
|
+
},
|
|
532
|
+
dataExport: {
|
|
533
|
+
backend: [
|
|
534
|
+
"src/features/export"
|
|
535
|
+
],
|
|
536
|
+
frontend: []
|
|
537
|
+
},
|
|
538
|
+
dashboard: {
|
|
539
|
+
backend: [],
|
|
540
|
+
frontend: []
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
var VUE_FRONTEND_MAP = {
|
|
544
|
+
auth: [
|
|
545
|
+
"src/pages/login.vue",
|
|
546
|
+
"src/pages/forgot-password.vue",
|
|
547
|
+
"src/pages/reset-password.vue",
|
|
548
|
+
"src/pages/profile.vue",
|
|
549
|
+
"src/stores/auth.js",
|
|
550
|
+
"src/services/authApi.js"
|
|
551
|
+
],
|
|
552
|
+
userManagement: [
|
|
553
|
+
"src/pages/users",
|
|
554
|
+
"src/stores/user.js",
|
|
555
|
+
"src/services/userApi.js"
|
|
556
|
+
],
|
|
557
|
+
departments: [
|
|
558
|
+
"src/pages/departments",
|
|
559
|
+
"src/stores/department.js",
|
|
560
|
+
"src/services/departmentApi.js"
|
|
561
|
+
],
|
|
562
|
+
fileUpload: [
|
|
563
|
+
"src/pages/files",
|
|
564
|
+
"src/services/fileService.js"
|
|
565
|
+
],
|
|
566
|
+
auditLogs: [
|
|
567
|
+
"src/pages/audit-logs",
|
|
568
|
+
"src/services/auditLogService.js"
|
|
569
|
+
],
|
|
570
|
+
notifications: [
|
|
571
|
+
"src/pages/notifications",
|
|
572
|
+
"src/stores/notification.js",
|
|
573
|
+
"src/stores/persistentNotification.js",
|
|
574
|
+
"src/services/notificationApi.js"
|
|
575
|
+
],
|
|
576
|
+
dataExport: [
|
|
577
|
+
"src/services/exportService.js"
|
|
578
|
+
],
|
|
579
|
+
dashboard: [
|
|
580
|
+
"src/pages/dashboard.vue"
|
|
581
|
+
]
|
|
582
|
+
};
|
|
583
|
+
var REACT_FRONTEND_MAP = {
|
|
584
|
+
auth: [
|
|
585
|
+
"src/pages/Login.tsx",
|
|
586
|
+
"src/pages/ForgotPassword.tsx",
|
|
587
|
+
"src/pages/ResetPassword.tsx",
|
|
588
|
+
"src/pages/Profile.tsx",
|
|
589
|
+
"src/stores/authStore.ts",
|
|
590
|
+
"src/services/authApi.ts"
|
|
591
|
+
],
|
|
592
|
+
userManagement: [
|
|
593
|
+
"src/pages/Users.tsx",
|
|
594
|
+
"src/stores/userStore.ts",
|
|
595
|
+
"src/services/userApi.ts"
|
|
596
|
+
],
|
|
597
|
+
departments: [
|
|
598
|
+
"src/pages/Departments.tsx",
|
|
599
|
+
"src/stores/departmentStore.ts",
|
|
600
|
+
"src/services/departmentApi.ts"
|
|
601
|
+
],
|
|
602
|
+
fileUpload: [
|
|
603
|
+
"src/pages/FilesPage.tsx",
|
|
604
|
+
"src/services/fileService.ts"
|
|
605
|
+
],
|
|
606
|
+
auditLogs: [
|
|
607
|
+
"src/pages/AuditLogsPage.tsx",
|
|
608
|
+
"src/pages/AuditLogs.tsx",
|
|
609
|
+
"src/services/auditLogService.ts"
|
|
610
|
+
],
|
|
611
|
+
notifications: [
|
|
612
|
+
"src/pages/Notifications.tsx",
|
|
613
|
+
"src/stores/notificationStore.ts",
|
|
614
|
+
"src/stores/persistentNotificationStore.ts",
|
|
615
|
+
"src/services/notificationApi.ts"
|
|
616
|
+
],
|
|
617
|
+
dataExport: [
|
|
618
|
+
"src/services/exportService.ts"
|
|
619
|
+
],
|
|
620
|
+
dashboard: [
|
|
621
|
+
"src/pages/Dashboard.tsx",
|
|
622
|
+
"src/pages/Dashboard.scss"
|
|
623
|
+
]
|
|
624
|
+
};
|
|
625
|
+
function getBackendFileMap(backend, architecture) {
|
|
626
|
+
const key = `${backend}-${architecture}`;
|
|
627
|
+
switch (key) {
|
|
628
|
+
case "dotnet-clean":
|
|
629
|
+
return DOTNET_CLEAN_MAP;
|
|
630
|
+
case "dotnet-nlayer":
|
|
631
|
+
return DOTNET_NLAYER_MAP;
|
|
632
|
+
case "dotnet-feature":
|
|
633
|
+
return DOTNET_FEATURE_MAP;
|
|
634
|
+
case "spring-clean":
|
|
635
|
+
return SPRING_CLEAN_MAP;
|
|
636
|
+
case "spring-nlayer":
|
|
637
|
+
return SPRING_NLAYER_MAP;
|
|
638
|
+
case "spring-feature":
|
|
639
|
+
return SPRING_FEATURE_MAP;
|
|
640
|
+
case "nestjs-clean":
|
|
641
|
+
return NESTJS_CLEAN_MAP;
|
|
642
|
+
case "nestjs-nlayer":
|
|
643
|
+
return NESTJS_NLAYER_MAP;
|
|
644
|
+
case "nestjs-feature":
|
|
645
|
+
return NESTJS_FEATURE_MAP;
|
|
646
|
+
default:
|
|
647
|
+
return {};
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
function getFrontendFileMap(frontendFramework) {
|
|
651
|
+
return frontendFramework === "vue" ? VUE_FRONTEND_MAP : REACT_FRONTEND_MAP;
|
|
652
|
+
}
|
|
653
|
+
function getFeaturesLabel(features, allFeatures) {
|
|
654
|
+
if (features.length === allFeatures.length) {
|
|
655
|
+
return "All features";
|
|
656
|
+
}
|
|
657
|
+
if (features.length === 0) {
|
|
658
|
+
return "None (bare template)";
|
|
659
|
+
}
|
|
660
|
+
return features.map((f) => FEATURE_OPTIONS.find((o) => o.value === f)?.label || f).join(", ");
|
|
661
|
+
}
|
|
662
|
+
|
|
7
663
|
// src/cli.ts
|
|
8
664
|
var validProjectTypes = ["fullstack", "backend", "frontend"];
|
|
9
665
|
var validBackends = ["dotnet", "spring", "nestjs"];
|
|
666
|
+
var validArchitectures = ["clean", "nlayer", "feature"];
|
|
10
667
|
var validFrontendFrameworks = ["vue", "react"];
|
|
11
668
|
var validUILibraries = ["vuetify", "primevue", "primereact", "mui"];
|
|
669
|
+
var validFeatures = [...ALL_FEATURES];
|
|
12
670
|
function parseArgs() {
|
|
13
671
|
const args = process.argv.slice(2);
|
|
14
672
|
const result = {};
|
|
@@ -55,6 +713,16 @@ function parseArgs() {
|
|
|
55
713
|
i++;
|
|
56
714
|
continue;
|
|
57
715
|
}
|
|
716
|
+
if (arg === "-a" || arg === "--architecture") {
|
|
717
|
+
const value = args[++i];
|
|
718
|
+
if (isValidArchitecture(value)) {
|
|
719
|
+
result.architecture = value;
|
|
720
|
+
} else {
|
|
721
|
+
console.warn(`Warning: Invalid architecture "${value}". Valid options: ${validArchitectures.join(", ")}`);
|
|
722
|
+
}
|
|
723
|
+
i++;
|
|
724
|
+
continue;
|
|
725
|
+
}
|
|
58
726
|
if (arg === "-f" || arg === "--framework") {
|
|
59
727
|
const value = args[++i];
|
|
60
728
|
if (isValidFrontendFramework(value)) {
|
|
@@ -85,6 +753,24 @@ function parseArgs() {
|
|
|
85
753
|
i++;
|
|
86
754
|
continue;
|
|
87
755
|
}
|
|
756
|
+
if (arg === "--features" || arg === "--feat") {
|
|
757
|
+
const value = args[++i];
|
|
758
|
+
if (value) {
|
|
759
|
+
if (value === "all") {
|
|
760
|
+
result.features = [...ALL_FEATURES];
|
|
761
|
+
} else {
|
|
762
|
+
const requested = value.split(",").map((s) => s.trim());
|
|
763
|
+
const valid = requested.filter((f) => validFeatures.includes(f));
|
|
764
|
+
const invalid = requested.filter((f) => !validFeatures.includes(f));
|
|
765
|
+
if (invalid.length > 0) {
|
|
766
|
+
console.warn(`Warning: Invalid features "${invalid.join(", ")}". Valid options: ${validFeatures.join(", ")}`);
|
|
767
|
+
}
|
|
768
|
+
result.features = applyFeatureDependencies(valid);
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
i++;
|
|
772
|
+
continue;
|
|
773
|
+
}
|
|
88
774
|
if (!arg.startsWith("-") && !result.projectPath) {
|
|
89
775
|
result.projectPath = arg;
|
|
90
776
|
}
|
|
@@ -98,6 +784,9 @@ function isValidProjectType(value) {
|
|
|
98
784
|
function isValidBackend(value) {
|
|
99
785
|
return value !== void 0 && validBackends.includes(value);
|
|
100
786
|
}
|
|
787
|
+
function isValidArchitecture(value) {
|
|
788
|
+
return value !== void 0 && validArchitectures.includes(value);
|
|
789
|
+
}
|
|
101
790
|
function isValidFrontendFramework(value) {
|
|
102
791
|
return value !== void 0 && validFrontendFrameworks.includes(value);
|
|
103
792
|
}
|
|
@@ -184,6 +873,31 @@ async function runInteractivePrompts(cliArgs) {
|
|
|
184
873
|
if (p.isCancel(result)) return result;
|
|
185
874
|
backend = result;
|
|
186
875
|
}
|
|
876
|
+
let architecture = cliArgs.architecture || "clean";
|
|
877
|
+
if (projectType !== "frontend" && !cliArgs.architecture) {
|
|
878
|
+
const result = await p.select({
|
|
879
|
+
message: "Which architecture pattern would you like to use?",
|
|
880
|
+
options: [
|
|
881
|
+
{
|
|
882
|
+
value: "nlayer",
|
|
883
|
+
label: "N-Layer (3-Tier)",
|
|
884
|
+
hint: "Simple, traditional. Best for CRUD apps & prototypes"
|
|
885
|
+
},
|
|
886
|
+
{
|
|
887
|
+
value: "clean",
|
|
888
|
+
label: "Clean Architecture",
|
|
889
|
+
hint: "Enterprise-grade. Best for complex business domains"
|
|
890
|
+
},
|
|
891
|
+
{
|
|
892
|
+
value: "feature",
|
|
893
|
+
label: "Package by Feature",
|
|
894
|
+
hint: "Modular. Best for medium-large apps & team scalability"
|
|
895
|
+
}
|
|
896
|
+
]
|
|
897
|
+
});
|
|
898
|
+
if (p.isCancel(result)) return result;
|
|
899
|
+
architecture = result;
|
|
900
|
+
}
|
|
187
901
|
let frontendFramework = cliArgs.framework || "vue";
|
|
188
902
|
if (projectType !== "backend" && !cliArgs.framework) {
|
|
189
903
|
const result = await p.select({
|
|
@@ -237,6 +951,26 @@ async function runInteractivePrompts(cliArgs) {
|
|
|
237
951
|
if (p.isCancel(result)) return result;
|
|
238
952
|
ui = result;
|
|
239
953
|
}
|
|
954
|
+
let features = cliArgs.features || [...ALL_FEATURES];
|
|
955
|
+
if (!cliArgs.features) {
|
|
956
|
+
const result = await p.multiselect({
|
|
957
|
+
message: "Which features would you like to include?",
|
|
958
|
+
options: FEATURE_OPTIONS.map((opt) => ({
|
|
959
|
+
value: opt.value,
|
|
960
|
+
label: opt.label,
|
|
961
|
+
hint: opt.hint
|
|
962
|
+
})),
|
|
963
|
+
initialValues: [...ALL_FEATURES],
|
|
964
|
+
required: false
|
|
965
|
+
});
|
|
966
|
+
if (p.isCancel(result)) return result;
|
|
967
|
+
features = applyFeatureDependencies(result);
|
|
968
|
+
if (features.length < result.length) {
|
|
969
|
+
const removed = result.filter((f) => !features.includes(f));
|
|
970
|
+
const removedLabels = removed.map((f) => FEATURE_OPTIONS.find((o) => o.value === f)?.label || f);
|
|
971
|
+
console.log(pc.yellow(` \u26A0 Auto-removed due to dependencies: ${removedLabels.join(", ")}`));
|
|
972
|
+
}
|
|
973
|
+
}
|
|
240
974
|
let projectName = cliArgs.projectName;
|
|
241
975
|
const needsNamespace = projectType !== "frontend" && (backend === "dotnet" || backend === "spring");
|
|
242
976
|
if (needsNamespace && !projectName) {
|
|
@@ -283,11 +1017,13 @@ async function runInteractivePrompts(cliArgs) {
|
|
|
283
1017
|
];
|
|
284
1018
|
if (projectType !== "frontend") {
|
|
285
1019
|
summaryLines.push(`${pc.cyan("Backend:")} ${getBackendLabel(backend)}`);
|
|
1020
|
+
summaryLines.push(`${pc.cyan("Architecture:")} ${getArchitectureLabel(architecture)}`);
|
|
286
1021
|
}
|
|
287
1022
|
if (projectType !== "backend") {
|
|
288
1023
|
summaryLines.push(`${pc.cyan("Frontend:")} ${getFrontendLabel(frontendFramework)}`);
|
|
289
1024
|
summaryLines.push(`${pc.cyan("UI Library:")} ${getUILabel(ui)}`);
|
|
290
1025
|
}
|
|
1026
|
+
summaryLines.push(`${pc.cyan("Features:")} ${getFeaturesLabel(features, ALL_FEATURES)}`);
|
|
291
1027
|
if (needsNamespace && projectName) {
|
|
292
1028
|
summaryLines.push(`${pc.cyan("Namespace:")} ${projectName}`);
|
|
293
1029
|
}
|
|
@@ -307,11 +1043,13 @@ async function runInteractivePrompts(cliArgs) {
|
|
|
307
1043
|
projectPath,
|
|
308
1044
|
projectType,
|
|
309
1045
|
backend,
|
|
1046
|
+
architecture,
|
|
310
1047
|
frontendFramework,
|
|
311
1048
|
ui,
|
|
312
1049
|
projectName,
|
|
313
1050
|
installDeps,
|
|
314
|
-
placeInRoot
|
|
1051
|
+
placeInRoot,
|
|
1052
|
+
features
|
|
315
1053
|
};
|
|
316
1054
|
}
|
|
317
1055
|
function toPascalCase(str) {
|
|
@@ -325,6 +1063,14 @@ function getBackendLabel(backend) {
|
|
|
325
1063
|
};
|
|
326
1064
|
return labels[backend];
|
|
327
1065
|
}
|
|
1066
|
+
function getArchitectureLabel(architecture) {
|
|
1067
|
+
const labels = {
|
|
1068
|
+
clean: "Clean Architecture",
|
|
1069
|
+
nlayer: "N-Layer (3-Tier)",
|
|
1070
|
+
feature: "Package by Feature"
|
|
1071
|
+
};
|
|
1072
|
+
return labels[architecture];
|
|
1073
|
+
}
|
|
328
1074
|
function getFrontendLabel(framework) {
|
|
329
1075
|
const labels = {
|
|
330
1076
|
vue: "Vue 3",
|
|
@@ -680,7 +1426,8 @@ async function generateProject(config) {
|
|
|
680
1426
|
spinner2.start("Downloading templates...");
|
|
681
1427
|
try {
|
|
682
1428
|
if (config.projectType !== "frontend") {
|
|
683
|
-
const
|
|
1429
|
+
const archSuffix = config.architecture === "clean" ? "" : `-${config.architecture}`;
|
|
1430
|
+
const sourceFolder = `backend-${config.backend}${archSuffix}`;
|
|
684
1431
|
let destFolder;
|
|
685
1432
|
if (config.projectType === "fullstack") {
|
|
686
1433
|
destFolder = "backend";
|
|
@@ -710,6 +1457,16 @@ async function generateProject(config) {
|
|
|
710
1457
|
spinner2.stop("Download failed");
|
|
711
1458
|
throw error;
|
|
712
1459
|
}
|
|
1460
|
+
const deselectedFeatures = ALL_FEATURES.filter((f) => !config.features.includes(f));
|
|
1461
|
+
if (deselectedFeatures.length > 0) {
|
|
1462
|
+
spinner2.start("Removing deselected feature files...");
|
|
1463
|
+
try {
|
|
1464
|
+
await removeDeselectedFeatures(absolutePath, config, deselectedFeatures);
|
|
1465
|
+
spinner2.stop(`Removed ${deselectedFeatures.length} deselected feature(s)`);
|
|
1466
|
+
} catch (error) {
|
|
1467
|
+
spinner2.stop("Feature removal had warnings");
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
713
1470
|
spinner2.start("Updating configuration files...");
|
|
714
1471
|
try {
|
|
715
1472
|
await updateFolderReferences(absolutePath, config);
|
|
@@ -754,6 +1511,48 @@ async function generateProject(config) {
|
|
|
754
1511
|
await createAppSettingsFromExample(absolutePath, config);
|
|
755
1512
|
}
|
|
756
1513
|
}
|
|
1514
|
+
async function removeDeselectedFeatures(projectPath, config, deselectedFeatures) {
|
|
1515
|
+
if (config.projectType !== "frontend") {
|
|
1516
|
+
const backendMap = getBackendFileMap(config.backend, config.architecture);
|
|
1517
|
+
let backendDir;
|
|
1518
|
+
if (config.projectType === "fullstack") {
|
|
1519
|
+
backendDir = path5.join(projectPath, "backend");
|
|
1520
|
+
} else {
|
|
1521
|
+
backendDir = config.placeInRoot ? projectPath : path5.join(projectPath, "backend");
|
|
1522
|
+
}
|
|
1523
|
+
for (const feature of deselectedFeatures) {
|
|
1524
|
+
const featureMap = backendMap[feature];
|
|
1525
|
+
if (featureMap) {
|
|
1526
|
+
for (const filePath of featureMap.backend) {
|
|
1527
|
+
const fullPath = path5.join(backendDir, filePath);
|
|
1528
|
+
if (fs5.existsSync(fullPath)) {
|
|
1529
|
+
fs5.rmSync(fullPath, { recursive: true, force: true });
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
if (config.projectType !== "backend") {
|
|
1536
|
+
const frontendMap = getFrontendFileMap(config.frontendFramework);
|
|
1537
|
+
let frontendDir;
|
|
1538
|
+
if (config.projectType === "fullstack") {
|
|
1539
|
+
frontendDir = path5.join(projectPath, "frontend");
|
|
1540
|
+
} else {
|
|
1541
|
+
frontendDir = config.placeInRoot ? projectPath : path5.join(projectPath, "frontend");
|
|
1542
|
+
}
|
|
1543
|
+
for (const feature of deselectedFeatures) {
|
|
1544
|
+
const featurePaths = frontendMap[feature];
|
|
1545
|
+
if (featurePaths) {
|
|
1546
|
+
for (const filePath of featurePaths) {
|
|
1547
|
+
const fullPath = path5.join(frontendDir, filePath);
|
|
1548
|
+
if (fs5.existsSync(fullPath)) {
|
|
1549
|
+
fs5.rmSync(fullPath, { recursive: true, force: true });
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
757
1556
|
function cleanupFullstackDockerFiles(projectPath) {
|
|
758
1557
|
const filesToDelete = [
|
|
759
1558
|
"backend/Dockerfile",
|
|
@@ -907,15 +1706,18 @@ async function main() {
|
|
|
907
1706
|
const needsNamespace = projectType !== "frontend" && (backend === "dotnet" || backend === "spring");
|
|
908
1707
|
if (cliArgs.projectPath && cliArgs.backend && (!needsNamespace || cliArgs.projectName)) {
|
|
909
1708
|
const frontendFramework = cliArgs.framework || "vue";
|
|
1709
|
+
const architecture = cliArgs.architecture || "clean";
|
|
910
1710
|
config = {
|
|
911
1711
|
projectPath: cliArgs.projectPath,
|
|
912
1712
|
projectType,
|
|
913
1713
|
backend,
|
|
1714
|
+
architecture,
|
|
914
1715
|
frontendFramework,
|
|
915
1716
|
ui: cliArgs.ui || (frontendFramework === "vue" ? "vuetify" : "mui"),
|
|
916
1717
|
projectName: cliArgs.projectName,
|
|
917
1718
|
installDeps: cliArgs.install || false,
|
|
918
|
-
placeInRoot: cliArgs.root || false
|
|
1719
|
+
placeInRoot: cliArgs.root || false,
|
|
1720
|
+
features: cliArgs.features || [...ALL_FEATURES]
|
|
919
1721
|
};
|
|
920
1722
|
} else {
|
|
921
1723
|
const result = await runInteractivePrompts(cliArgs);
|
|
@@ -944,15 +1746,18 @@ ${pc3.bold("Usage:")}
|
|
|
944
1746
|
${pc3.cyan("npm create apptemplate@latest")} ${pc3.gray("[project-directory]")} ${pc3.gray("[options]")}
|
|
945
1747
|
|
|
946
1748
|
${pc3.bold("Options:")}
|
|
947
|
-
${pc3.yellow("-t, --type")}
|
|
948
|
-
${pc3.yellow("-b, --backend")}
|
|
949
|
-
${pc3.yellow("-
|
|
950
|
-
${pc3.yellow("-
|
|
951
|
-
${pc3.yellow("-
|
|
952
|
-
${pc3.yellow("-
|
|
953
|
-
${pc3.yellow("-
|
|
954
|
-
${pc3.yellow("
|
|
955
|
-
|
|
1749
|
+
${pc3.yellow("-t, --type")} Project type: fullstack, backend, frontend ${pc3.gray("(default: fullstack)")}
|
|
1750
|
+
${pc3.yellow("-b, --backend")} Backend framework: dotnet, spring, nestjs
|
|
1751
|
+
${pc3.yellow("-a, --architecture")} Architecture: clean, nlayer, feature ${pc3.gray("(default: clean)")}
|
|
1752
|
+
${pc3.yellow("-f, --framework")} Frontend framework: vue, react ${pc3.gray("(default: vue)")}
|
|
1753
|
+
${pc3.yellow("-u, --ui")} UI library: vuetify, primevue (Vue) | mui, primereact (React)
|
|
1754
|
+
${pc3.yellow("-n, --name")} Project namespace (Company.Project format, .NET/Spring only)
|
|
1755
|
+
${pc3.yellow("-r, --root")} Place files in project root ${pc3.gray("(backend/frontend-only)")}
|
|
1756
|
+
${pc3.yellow("--features")} Features to include (comma-separated or "all")
|
|
1757
|
+
Options: auth,userManagement,departments,fileUpload,auditLogs,notifications,dataExport,dashboard
|
|
1758
|
+
${pc3.yellow("-i, --install")} Install dependencies after creation
|
|
1759
|
+
${pc3.yellow("-h, --help")} Show this help message
|
|
1760
|
+
${pc3.yellow("-v, --version")} Show version number
|
|
956
1761
|
|
|
957
1762
|
${pc3.bold("Examples:")}
|
|
958
1763
|
${pc3.gray("# Interactive mode")}
|