nestcraftx 0.2.6 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AUDIT_ROADMAP.md +798 -0
- package/CHANGELOG.fr.md +22 -0
- package/CHANGELOG.md +22 -0
- package/PROGRESS.md +258 -0
- package/commands/demo.js +4 -0
- package/commands/generate.js +5 -4
- package/commands/help.js +29 -2
- package/commands/new.js +8 -6
- package/package.json +1 -1
- package/utils/app-module.updater.js +96 -0
- package/utils/cliParser.js +0 -45
- package/utils/configs/setupCleanArchitecture.js +2 -2
- package/utils/file-system.js +75 -0
- package/utils/generators/application/dtoGenerator.js +251 -0
- package/utils/generators/database/setupDatabase.js +32 -14
- package/utils/generators/domain/entityGenerator.js +126 -0
- package/utils/generators/infrastructure/mapperGenerator.js +114 -0
- package/utils/generators/infrastructure/middlewareGenerator.js +645 -0
- package/utils/generators/infrastructure/mongooseSchemaGenerator.js +196 -0
- package/utils/generators/infrastructure/repositoryGenerator.js +334 -0
- package/utils/generators/presentation/controllerGenerator.js +142 -0
- package/utils/helpers.js +109 -0
- package/utils/setups/setupAuth.js +5 -5
- package/utils/setups/setupDatabase.js +2 -1
- package/utils/setups/setupMongoose.js +22 -5
- package/utils/setups/setupPrisma.js +78 -132
- package/utils/shell.js +88 -8
- package/utils/userInput.js +37 -101
- package/utils/utils.js +29 -2164
package/utils/shell.js
CHANGED
|
@@ -1,26 +1,75 @@
|
|
|
1
1
|
const { execSync } = require("child_process");
|
|
2
2
|
const fs = require("fs");
|
|
3
3
|
const { logError } = require("./loggers/logError");
|
|
4
|
+
const { logWarning } = require("./loggers/logWarning");
|
|
4
5
|
const { spinner } = require("./spinner");
|
|
6
|
+
const { warning, info } = require("./colors");
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Accumulated warnings collected during a generation session.
|
|
10
|
+
* Displayed as a summary at the end via printSetupWarnings().
|
|
11
|
+
*/
|
|
12
|
+
const _warnings = [];
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Runs a shell command synchronously.
|
|
16
|
+
*
|
|
17
|
+
* @param {string} command - The shell command to execute.
|
|
18
|
+
* @param {string} errorMessage - Human-readable error message shown on failure.
|
|
19
|
+
* @param {object} [options] - Optional configuration.
|
|
20
|
+
* @param {boolean} [options.critical=true] - If true (default), a failure calls process.exit(1).
|
|
21
|
+
* If false, the failure is logged as a warning and execution continues.
|
|
22
|
+
* @param {string|null} [options.spinner] - Optional spinner label shown during execution.
|
|
23
|
+
* @returns {Promise<boolean>} Resolves to true on success, false on non-critical failure.
|
|
24
|
+
*/
|
|
25
|
+
async function runCommand(command, errorMessage, options = {}) {
|
|
26
|
+
// Support old call signature: runCommand(cmd, msg, spinnerText)
|
|
27
|
+
// New signature: runCommand(cmd, msg, { critical, spinner })
|
|
28
|
+
let critical = true;
|
|
29
|
+
let spinnerText = null;
|
|
30
|
+
|
|
31
|
+
if (typeof options === "string") {
|
|
32
|
+
// Legacy: third arg was spinnerText string
|
|
33
|
+
spinnerText = options;
|
|
34
|
+
} else if (typeof options === "object" && options !== null) {
|
|
35
|
+
critical = options.critical !== false; // default true
|
|
36
|
+
spinnerText = options.spinner || null;
|
|
37
|
+
}
|
|
5
38
|
|
|
6
|
-
async function runCommand(command, errorMessage, spinnerText = null) {
|
|
7
39
|
const spin = spinnerText ? spinner(spinnerText) : null;
|
|
8
40
|
|
|
9
41
|
try {
|
|
10
42
|
if (spin) spin.start();
|
|
11
43
|
execSync(command, { stdio: spinnerText ? "pipe" : "inherit" });
|
|
12
44
|
if (spin) spin.succeed(spinnerText);
|
|
45
|
+
return true;
|
|
13
46
|
} catch (error) {
|
|
14
47
|
if (spin) spin.fail(errorMessage);
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
)
|
|
20
|
-
|
|
48
|
+
|
|
49
|
+
const logLine = `[${new Date().toISOString()}] ${errorMessage}: ${error.message}\n`;
|
|
50
|
+
fs.appendFileSync("setup.log", logLine);
|
|
51
|
+
|
|
52
|
+
if (critical) {
|
|
53
|
+
// Fatal — stop everything
|
|
54
|
+
logError(`${errorMessage}`);
|
|
55
|
+
logError(`Run: ${command}`);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
} else {
|
|
58
|
+
// Non-critical — warn and continue
|
|
59
|
+
logWarning(`${errorMessage} (non-fatal, continuing...)`);
|
|
60
|
+
logWarning(` Command: ${command}`);
|
|
61
|
+
logWarning(` See setup.log for details`);
|
|
62
|
+
_warnings.push({ command, errorMessage });
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
21
65
|
}
|
|
22
66
|
}
|
|
23
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Silent command — returns stdout string or null on failure. Never exits.
|
|
70
|
+
* @param {string} command
|
|
71
|
+
* @returns {string|null}
|
|
72
|
+
*/
|
|
24
73
|
async function runCommandSilent(command) {
|
|
25
74
|
try {
|
|
26
75
|
return execSync(command, { stdio: "pipe" }).toString();
|
|
@@ -29,4 +78,35 @@ async function runCommandSilent(command) {
|
|
|
29
78
|
}
|
|
30
79
|
}
|
|
31
80
|
|
|
32
|
-
|
|
81
|
+
/**
|
|
82
|
+
* Prints a summary of all non-critical warnings accumulated during the session.
|
|
83
|
+
* Call this at the very end of the generation pipeline.
|
|
84
|
+
*/
|
|
85
|
+
function printSetupWarnings() {
|
|
86
|
+
if (_warnings.length === 0) return;
|
|
87
|
+
|
|
88
|
+
console.log(
|
|
89
|
+
`\n${warning("⚠️ Setup completed with")} ${warning(String(_warnings.length))} ${warning("warning(s):")}`,
|
|
90
|
+
);
|
|
91
|
+
_warnings.forEach((w, i) => {
|
|
92
|
+
console.log(` ${info(`${i + 1}.`)} ${w.errorMessage}`);
|
|
93
|
+
console.log(` ${info("Command:")} ${w.command}`);
|
|
94
|
+
});
|
|
95
|
+
console.log(
|
|
96
|
+
`\n ${info("➜")} Full details in: ${info("setup.log")}\n`,
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Clears the warnings accumulator (useful between test runs).
|
|
102
|
+
*/
|
|
103
|
+
function clearSetupWarnings() {
|
|
104
|
+
_warnings.length = 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
module.exports = {
|
|
108
|
+
runCommand,
|
|
109
|
+
runCommandSilent,
|
|
110
|
+
printSetupWarnings,
|
|
111
|
+
clearSetupWarnings,
|
|
112
|
+
};
|
package/utils/userInput.js
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
const readline = require("readline-sync");
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
const { logInfo } = require("./loggers/logInfo");
|
|
4
|
+
|
|
5
|
+
// ── Modules extraits (Phase 1A) ────────────────────────────────────────────────
|
|
6
|
+
const {
|
|
7
|
+
createDirectory,
|
|
8
|
+
createFile,
|
|
9
|
+
updateFile,
|
|
10
|
+
} = require("./file-system");
|
|
11
|
+
const { safeUpdateAppModule } = require("./app-module.updater");
|
|
12
|
+
const { capitalize, decapitalize } = require("./helpers");
|
|
13
|
+
// ──────────────────────────────────────────────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
async function getUserInputs2() {
|
|
6
16
|
console.log("\n🔹🔹🔹 Configuration du projet 🔹🔹🔹\n");
|
|
7
17
|
|
|
8
18
|
const dataBases = [
|
|
@@ -299,7 +309,7 @@ export async function getUserInputs2() {
|
|
|
299
309
|
};
|
|
300
310
|
}
|
|
301
311
|
|
|
302
|
-
|
|
312
|
+
function getUserInputsSwagger() {
|
|
303
313
|
console.log("\n🔹 Configuration de Swagger 🔹");
|
|
304
314
|
|
|
305
315
|
const title = readline.question("Titre de l'API ? (ex: Mon API) ", {
|
|
@@ -324,98 +334,24 @@ export function getUserInputsSwagger() {
|
|
|
324
334
|
return { title, description, version, endpoint };
|
|
325
335
|
}
|
|
326
336
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
}
|
|
349
|
-
} catch (error) {
|
|
350
|
-
console.error(`Erreur creating file ${fileData.path}:`, error);
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
export async function updateFile({ path, pattern, replacement }) {
|
|
355
|
-
try {
|
|
356
|
-
let mainTs = fs.readFileSync(path, "utf8");
|
|
357
|
-
const updatedContent = mainTs.replace(pattern, replacement);
|
|
358
|
-
fs.writeFileSync(path, updatedContent, "utf-8");
|
|
359
|
-
// console.log(` Updated file: ${path}`);
|
|
360
|
-
} catch (error) {
|
|
361
|
-
console.error(` Error updating file ${path}:`, error);
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
export async function safeUpdateAppModule(entity) {
|
|
366
|
-
const filePath = "src/app.module.ts";
|
|
367
|
-
const moduleName = `${capitalize(entity)}Module`;
|
|
368
|
-
const importLine = `import { ${moduleName} } from 'src/${entity}/${entity}.module';`;
|
|
369
|
-
|
|
370
|
-
let content = fs.readFileSync(filePath, "utf-8");
|
|
371
|
-
|
|
372
|
-
// Étape 1 : Ajout de l'import si nécessaire
|
|
373
|
-
if (!content.includes(importLine)) {
|
|
374
|
-
const importMarker = `import { ConfigModule } from '@nestjs/config';`;
|
|
375
|
-
|
|
376
|
-
if (content.includes(importMarker)) {
|
|
377
|
-
await updateFile({
|
|
378
|
-
path: filePath,
|
|
379
|
-
pattern: importMarker,
|
|
380
|
-
replacement: `${importMarker}\n${importLine}`,
|
|
381
|
-
});
|
|
382
|
-
content = fs.readFileSync(filePath, "utf-8");
|
|
383
|
-
} else {
|
|
384
|
-
logInfo(
|
|
385
|
-
" Impossible de trouver le point d'insertion de l'import (ConfigModule manquant)",
|
|
386
|
-
);
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
// Étape 2 : Vérifier le bloc des imports du @Module
|
|
391
|
-
const importsBlockRegex = /imports:\s*\[((.|\n)*?)\]/m;
|
|
392
|
-
const match = content.match(importsBlockRegex);
|
|
393
|
-
|
|
394
|
-
if (!match) {
|
|
395
|
-
logInfo(" Impossible de trouver le bloc 'imports' dans AppModule.");
|
|
396
|
-
return;
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
const currentImportsBlock = match[1];
|
|
400
|
-
const isAlreadyImportedInModule = currentImportsBlock.includes(moduleName);
|
|
401
|
-
|
|
402
|
-
if (!isAlreadyImportedInModule) {
|
|
403
|
-
const updatedBlock = currentImportsBlock.trim().endsWith(",")
|
|
404
|
-
? `${currentImportsBlock.trim()} ${moduleName},`
|
|
405
|
-
: `${currentImportsBlock.trim()}, ${moduleName},`;
|
|
406
|
-
|
|
407
|
-
const newContent = content.replace(
|
|
408
|
-
importsBlockRegex,
|
|
409
|
-
`imports: [${updatedBlock}]`,
|
|
410
|
-
);
|
|
411
|
-
fs.writeFileSync(filePath, newContent, "utf-8");
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
export function capitalize(str) {
|
|
416
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
export function decapitalize(str) {
|
|
420
|
-
return str.charAt(0).toLowerCase() + str.slice(1);
|
|
421
|
-
}
|
|
337
|
+
// ── Fonctions déléguées aux modules extraits (Phase 1A) ───────────────────────
|
|
338
|
+
// createDirectory, createFile, updateFile → ./file-system.js
|
|
339
|
+
// safeUpdateAppModule → ./app-module.updater.js
|
|
340
|
+
// capitalize, decapitalize → ./helpers.js
|
|
341
|
+
//
|
|
342
|
+
// Les implémentations inline ont été supprimées. Toutes sont importées en haut
|
|
343
|
+
// du fichier et ré-exportées dans module.exports ci-dessous.
|
|
344
|
+
// ──────────────────────────────────────────────────────────────────────────────
|
|
345
|
+
|
|
346
|
+
module.exports = {
|
|
347
|
+
// Fonctions locales
|
|
348
|
+
getUserInputs2,
|
|
349
|
+
getUserInputsSwagger,
|
|
350
|
+
// Ré-exports des modules extraits (compatibilité ascendante 100%)
|
|
351
|
+
createDirectory,
|
|
352
|
+
createFile,
|
|
353
|
+
updateFile,
|
|
354
|
+
safeUpdateAppModule,
|
|
355
|
+
capitalize,
|
|
356
|
+
decapitalize,
|
|
357
|
+
};
|