nestcraftx 0.2.5 → 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.
Files changed (56) hide show
  1. package/AUDIT_ROADMAP.md +798 -0
  2. package/CHANGELOG.fr.md +22 -0
  3. package/CHANGELOG.md +22 -0
  4. package/CLI_USAGE.fr.md +331 -331
  5. package/CLI_USAGE.md +364 -364
  6. package/LICENSE +21 -21
  7. package/PROGRESS.md +258 -0
  8. package/bin/nestcraft.js +84 -64
  9. package/commands/demo.js +337 -330
  10. package/commands/generate.js +94 -0
  11. package/commands/generateConf.js +91 -0
  12. package/commands/help.js +29 -2
  13. package/commands/info.js +48 -48
  14. package/commands/new.js +340 -335
  15. package/commands/start.js +19 -19
  16. package/commands/test.js +7 -7
  17. package/package.json +1 -1
  18. package/utils/app-module.updater.js +96 -0
  19. package/utils/cliParser.js +88 -76
  20. package/utils/colors.js +62 -62
  21. package/utils/configs/configureDocker.js +120 -120
  22. package/utils/configs/setupCleanArchitecture.js +17 -15
  23. package/utils/configs/setupLightArchitecture.js +15 -9
  24. package/utils/file-system.js +75 -0
  25. package/utils/file-utils/saveProjectConfig.js +36 -0
  26. package/utils/fullModeInput.js +607 -607
  27. package/utils/generators/application/dtoGenerator.js +251 -0
  28. package/utils/generators/application/dtoUpdater.js +54 -0
  29. package/utils/generators/cleanModuleGenerator.js +475 -0
  30. package/utils/generators/database/setupDatabase.js +49 -0
  31. package/utils/generators/domain/entityGenerator.js +126 -0
  32. package/utils/generators/domain/entityUpdater.js +78 -0
  33. package/utils/generators/infrastructure/mapperGenerator.js +114 -0
  34. package/utils/generators/infrastructure/mapperUpdater.js +65 -0
  35. package/utils/generators/infrastructure/middlewareGenerator.js +645 -0
  36. package/utils/generators/infrastructure/mongooseSchemaGenerator.js +196 -0
  37. package/utils/generators/infrastructure/repositoryGenerator.js +334 -0
  38. package/utils/generators/lightModuleGenerator.js +131 -0
  39. package/utils/generators/presentation/controllerGenerator.js +142 -0
  40. package/utils/generators/relation/relation.engine.js +64 -0
  41. package/utils/helpers.js +109 -0
  42. package/utils/interactive/askEntityInputs.js +165 -0
  43. package/utils/loggers/logError.js +7 -7
  44. package/utils/loggers/logInfo.js +7 -7
  45. package/utils/loggers/logSuccess.js +7 -7
  46. package/utils/loggers/logWarning.js +7 -7
  47. package/utils/setups/orms/typeOrmSetup.js +630 -630
  48. package/utils/setups/setupAuth.js +33 -20
  49. package/utils/setups/setupDatabase.js +76 -75
  50. package/utils/setups/setupMongoose.js +22 -5
  51. package/utils/setups/setupPrisma.js +748 -630
  52. package/utils/shell.js +112 -32
  53. package/utils/spinner.js +57 -57
  54. package/utils/systemCheck.js +124 -124
  55. package/utils/userInput.js +357 -421
  56. package/utils/utils.js +29 -2164
package/utils/shell.js CHANGED
@@ -1,32 +1,112 @@
1
- const { execSync } = require("child_process");
2
- const fs = require("fs");
3
- const { logError } = require("./loggers/logError");
4
- const { spinner } = require("./spinner");
5
-
6
- async function runCommand(command, errorMessage, spinnerText = null) {
7
- const spin = spinnerText ? spinner(spinnerText) : null;
8
-
9
- try {
10
- if (spin) spin.start();
11
- execSync(command, { stdio: spinnerText ? "pipe" : "inherit" });
12
- if (spin) spin.succeed(spinnerText);
13
- } catch (error) {
14
- if (spin) spin.fail(errorMessage);
15
- logError(errorMessage);
16
- fs.appendFileSync(
17
- "setup.log",
18
- `[Erreur] ${errorMessage}: ${error.message}\n`
19
- );
20
- process.exit(1);
21
- }
22
- }
23
-
24
- async function runCommandSilent(command) {
25
- try {
26
- return execSync(command, { stdio: "pipe" }).toString();
27
- } catch (error) {
28
- return null;
29
- }
30
- }
31
-
32
- module.exports = { runCommand, runCommandSilent };
1
+ const { execSync } = require("child_process");
2
+ const fs = require("fs");
3
+ const { logError } = require("./loggers/logError");
4
+ const { logWarning } = require("./loggers/logWarning");
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
+ }
38
+
39
+ const spin = spinnerText ? spinner(spinnerText) : null;
40
+
41
+ try {
42
+ if (spin) spin.start();
43
+ execSync(command, { stdio: spinnerText ? "pipe" : "inherit" });
44
+ if (spin) spin.succeed(spinnerText);
45
+ return true;
46
+ } catch (error) {
47
+ if (spin) spin.fail(errorMessage);
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
+ }
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Silent command — returns stdout string or null on failure. Never exits.
70
+ * @param {string} command
71
+ * @returns {string|null}
72
+ */
73
+ async function runCommandSilent(command) {
74
+ try {
75
+ return execSync(command, { stdio: "pipe" }).toString();
76
+ } catch (error) {
77
+ return null;
78
+ }
79
+ }
80
+
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/spinner.js CHANGED
@@ -1,57 +1,57 @@
1
- const { info, success, error: errorColor } = require('./colors');
2
-
3
- class Spinner {
4
- constructor(text = 'Loading...') {
5
- this.text = text;
6
- this.frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
7
- this.currentFrame = 0;
8
- this.intervalId = null;
9
- this.isSpinning = false;
10
- }
11
-
12
- start() {
13
- if (this.isSpinning) return;
14
-
15
- this.isSpinning = true;
16
- this.currentFrame = 0;
17
-
18
- process.stdout.write('\n');
19
-
20
- this.intervalId = setInterval(() => {
21
- const frame = this.frames[this.currentFrame];
22
- process.stdout.write(`\r${info(frame)} ${this.text}`);
23
- this.currentFrame = (this.currentFrame + 1) % this.frames.length;
24
- }, 80);
25
- }
26
-
27
- stop() {
28
- if (!this.isSpinning) return;
29
-
30
- this.isSpinning = false;
31
- if (this.intervalId) {
32
- clearInterval(this.intervalId);
33
- this.intervalId = null;
34
- }
35
- process.stdout.write('\r' + ' '.repeat(this.text.length + 10) + '\r');
36
- }
37
-
38
- succeed(text) {
39
- this.stop();
40
- console.log(success('✓') + ` ${text || this.text}`);
41
- }
42
-
43
- fail(text) {
44
- this.stop();
45
- console.log(errorColor('✗') + ` ${text || this.text}`);
46
- }
47
-
48
- update(text) {
49
- this.text = text;
50
- }
51
- }
52
-
53
- function spinner(text) {
54
- return new Spinner(text);
55
- }
56
-
57
- module.exports = { Spinner, spinner };
1
+ const { info, success, error: errorColor } = require('./colors');
2
+
3
+ class Spinner {
4
+ constructor(text = 'Loading...') {
5
+ this.text = text;
6
+ this.frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
7
+ this.currentFrame = 0;
8
+ this.intervalId = null;
9
+ this.isSpinning = false;
10
+ }
11
+
12
+ start() {
13
+ if (this.isSpinning) return;
14
+
15
+ this.isSpinning = true;
16
+ this.currentFrame = 0;
17
+
18
+ process.stdout.write('\n');
19
+
20
+ this.intervalId = setInterval(() => {
21
+ const frame = this.frames[this.currentFrame];
22
+ process.stdout.write(`\r${info(frame)} ${this.text}`);
23
+ this.currentFrame = (this.currentFrame + 1) % this.frames.length;
24
+ }, 80);
25
+ }
26
+
27
+ stop() {
28
+ if (!this.isSpinning) return;
29
+
30
+ this.isSpinning = false;
31
+ if (this.intervalId) {
32
+ clearInterval(this.intervalId);
33
+ this.intervalId = null;
34
+ }
35
+ process.stdout.write('\r' + ' '.repeat(this.text.length + 10) + '\r');
36
+ }
37
+
38
+ succeed(text) {
39
+ this.stop();
40
+ console.log(success('✓') + ` ${text || this.text}`);
41
+ }
42
+
43
+ fail(text) {
44
+ this.stop();
45
+ console.log(errorColor('✗') + ` ${text || this.text}`);
46
+ }
47
+
48
+ update(text) {
49
+ this.text = text;
50
+ }
51
+ }
52
+
53
+ function spinner(text) {
54
+ return new Spinner(text);
55
+ }
56
+
57
+ module.exports = { Spinner, spinner };
@@ -1,124 +1,124 @@
1
- const { execSync } = require("child_process");
2
- const fs = require("fs");
3
-
4
- function checkCommand(cmd) {
5
- try {
6
- execSync(`${cmd} --version`, { stdio: "pipe" });
7
- return true;
8
- } catch {
9
- return false;
10
- }
11
- }
12
-
13
- function getVersion(cmd) {
14
- try {
15
- const output = execSync(`${cmd} --version`, {
16
- encoding: "utf8",
17
- stdio: "pipe",
18
- });
19
- return output.trim().split("\n")[0];
20
- } catch {
21
- return "not installed";
22
- }
23
- }
24
-
25
- function checkSystemRequirements() {
26
- const checks = {
27
- node: {
28
- installed: checkCommand("node"),
29
- version: getVersion("node"),
30
- },
31
- npm: {
32
- installed: checkCommand("npm"),
33
- version: getVersion("npm"),
34
- },
35
- nestCli: {
36
- installed: checkCommand("nest"),
37
- version: getVersion("nest"),
38
- },
39
- git: {
40
- installed: checkCommand("git"),
41
- version: getVersion("git"),
42
- },
43
- docker: {
44
- installed: checkCommand("docker"),
45
- version: getVersion("docker"),
46
- },
47
- npx: {
48
- installed: checkCommand("npx"),
49
- version: "npx available",
50
- },
51
- };
52
-
53
- const envExists = fs.existsSync(".env");
54
-
55
- let postgresStatus = "not detected locally";
56
- if (envExists) {
57
- try {
58
- const envContent = fs.readFileSync(".env", "utf8");
59
- if (
60
- envContent.includes("POSTGRES_") ||
61
- envContent.includes("DATABASE_URL")
62
- ) {
63
- postgresStatus = "configured in .env";
64
- }
65
- } catch {}
66
- }
67
-
68
- checks.postgres = {
69
- installed: false,
70
- version: postgresStatus,
71
- };
72
-
73
- return checks;
74
- }
75
-
76
- function displaySystemCheck() {
77
- console.log("\n🔍 NestCraftX System Check");
78
- console.log("--------------------------------");
79
-
80
- const checks = checkSystemRequirements();
81
- let successCount = 0;
82
- let totalCount = 0;
83
-
84
- Object.entries(checks).forEach(([name, info]) => {
85
- totalCount++;
86
- const displayName =
87
- name.charAt(0).toUpperCase() + name.slice(1).replace(/([A-Z])/g, " $1");
88
-
89
- if (info.installed || info.version.includes("configured")) {
90
- console.log(`✅ ${displayName}: ${info.version}`);
91
- successCount++;
92
- } else {
93
- console.log(`⚠️ ${displayName}: ${info.version}`);
94
- }
95
- });
96
-
97
- console.log("--------------------------------");
98
-
99
- const status =
100
- successCount === totalCount
101
- ? "✅ Ready"
102
- : successCount >= totalCount - 2
103
- ? "⚠️ Almost Ready"
104
- : "❌ Missing Requirements";
105
-
106
- console.log(`System status: ${status} (${successCount}/${totalCount} OK)`);
107
-
108
- if (successCount < totalCount) {
109
- console.log("\n💡 Tips:");
110
- if (!checks.nestCli.installed) {
111
- console.log(" - Install Nest CLI: npm install -g @nestjs/cli");
112
- }
113
- if (!checks.docker.installed) {
114
- console.log(" - Install Docker: https://docs.docker.com/get-docker/");
115
- }
116
- if (!checks.git.installed) {
117
- console.log(" - Install Git: https://git-scm.com/downloads");
118
- }
119
- }
120
-
121
- console.log("");
122
- }
123
-
124
- module.exports = { checkSystemRequirements, displaySystemCheck };
1
+ const { execSync } = require("child_process");
2
+ const fs = require("fs");
3
+
4
+ function checkCommand(cmd) {
5
+ try {
6
+ execSync(`${cmd} --version`, { stdio: "pipe" });
7
+ return true;
8
+ } catch {
9
+ return false;
10
+ }
11
+ }
12
+
13
+ function getVersion(cmd) {
14
+ try {
15
+ const output = execSync(`${cmd} --version`, {
16
+ encoding: "utf8",
17
+ stdio: "pipe",
18
+ });
19
+ return output.trim().split("\n")[0];
20
+ } catch {
21
+ return "not installed";
22
+ }
23
+ }
24
+
25
+ function checkSystemRequirements() {
26
+ const checks = {
27
+ node: {
28
+ installed: checkCommand("node"),
29
+ version: getVersion("node"),
30
+ },
31
+ npm: {
32
+ installed: checkCommand("npm"),
33
+ version: getVersion("npm"),
34
+ },
35
+ nestCli: {
36
+ installed: checkCommand("nest"),
37
+ version: getVersion("nest"),
38
+ },
39
+ git: {
40
+ installed: checkCommand("git"),
41
+ version: getVersion("git"),
42
+ },
43
+ docker: {
44
+ installed: checkCommand("docker"),
45
+ version: getVersion("docker"),
46
+ },
47
+ npx: {
48
+ installed: checkCommand("npx"),
49
+ version: "npx available",
50
+ },
51
+ };
52
+
53
+ const envExists = fs.existsSync(".env");
54
+
55
+ let postgresStatus = "not detected locally";
56
+ if (envExists) {
57
+ try {
58
+ const envContent = fs.readFileSync(".env", "utf8");
59
+ if (
60
+ envContent.includes("POSTGRES_") ||
61
+ envContent.includes("DATABASE_URL")
62
+ ) {
63
+ postgresStatus = "configured in .env";
64
+ }
65
+ } catch {}
66
+ }
67
+
68
+ checks.postgres = {
69
+ installed: false,
70
+ version: postgresStatus,
71
+ };
72
+
73
+ return checks;
74
+ }
75
+
76
+ function displaySystemCheck() {
77
+ console.log("\n🔍 NestCraftX System Check");
78
+ console.log("--------------------------------");
79
+
80
+ const checks = checkSystemRequirements();
81
+ let successCount = 0;
82
+ let totalCount = 0;
83
+
84
+ Object.entries(checks).forEach(([name, info]) => {
85
+ totalCount++;
86
+ const displayName =
87
+ name.charAt(0).toUpperCase() + name.slice(1).replace(/([A-Z])/g, " $1");
88
+
89
+ if (info.installed || info.version.includes("configured")) {
90
+ console.log(`✅ ${displayName}: ${info.version}`);
91
+ successCount++;
92
+ } else {
93
+ console.log(`⚠️ ${displayName}: ${info.version}`);
94
+ }
95
+ });
96
+
97
+ console.log("--------------------------------");
98
+
99
+ const status =
100
+ successCount === totalCount
101
+ ? "✅ Ready"
102
+ : successCount >= totalCount - 2
103
+ ? "⚠️ Almost Ready"
104
+ : "❌ Missing Requirements";
105
+
106
+ console.log(`System status: ${status} (${successCount}/${totalCount} OK)`);
107
+
108
+ if (successCount < totalCount) {
109
+ console.log("\n💡 Tips:");
110
+ if (!checks.nestCli.installed) {
111
+ console.log(" - Install Nest CLI: npm install -g @nestjs/cli");
112
+ }
113
+ if (!checks.docker.installed) {
114
+ console.log(" - Install Docker: https://docs.docker.com/get-docker/");
115
+ }
116
+ if (!checks.git.installed) {
117
+ console.log(" - Install Git: https://git-scm.com/downloads");
118
+ }
119
+ }
120
+
121
+ console.log("");
122
+ }
123
+
124
+ module.exports = { checkSystemRequirements, displaySystemCheck };