nestcraftx 0.2.4 → 0.2.6
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/.gitattributes +6 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +33 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +19 -0
- package/.github/ISSUE_TEMPLATE/pull_request_template.md +24 -0
- package/CHANGELOG.fr.md +97 -97
- package/CHANGELOG.md +98 -98
- package/CLI_USAGE.fr.md +331 -331
- package/CLI_USAGE.md +364 -364
- package/DEMO.fr.md +292 -292
- package/DEMO.md +294 -294
- package/LICENSE +21 -21
- package/MIGRATION_GUIDE.fr.md +127 -127
- package/MIGRATION_GUIDE.md +124 -124
- package/QUICK_START.fr.md +152 -152
- package/QUICK_START.md +169 -169
- package/README.fr.md +653 -659
- package/SECURITY.md +10 -0
- package/bin/nestcraft.js +84 -64
- package/commands/demo.js +333 -330
- package/commands/generate.js +93 -0
- package/commands/generateConf.js +91 -0
- package/commands/help.js +78 -78
- package/commands/info.js +48 -48
- package/commands/new.js +338 -335
- package/commands/start.js +19 -19
- package/commands/test.js +7 -7
- package/package.json +41 -41
- package/readme.md +638 -643
- package/utils/cliParser.js +133 -76
- package/utils/colors.js +62 -62
- package/utils/configs/configureDocker.js +120 -120
- package/utils/configs/setupCleanArchitecture.js +563 -557
- package/utils/configs/setupLightArchitecture.js +701 -660
- package/utils/envGenerator.js +122 -122
- package/utils/file-utils/packageJsonUtils.js +49 -55
- package/utils/file-utils/saveProjectConfig.js +36 -0
- package/utils/fullModeInput.js +607 -607
- package/utils/generators/application/dtoUpdater.js +54 -0
- package/utils/generators/cleanModuleGenerator.js +475 -0
- package/utils/generators/database/setupDatabase.js +31 -0
- package/utils/generators/domain/entityUpdater.js +78 -0
- package/utils/generators/infrastructure/mapperUpdater.js +65 -0
- package/utils/generators/lightModuleGenerator.js +131 -0
- package/utils/generators/relation/relation.engine.js +64 -0
- package/utils/interactive/askEntityInputs.js +165 -0
- package/utils/lightModeInput.js +460 -460
- package/utils/loggers/logError.js +7 -7
- package/utils/loggers/logInfo.js +7 -7
- package/utils/loggers/logSuccess.js +7 -7
- package/utils/loggers/logWarning.js +7 -7
- package/utils/setups/orms/typeOrmSetup.js +630 -630
- package/utils/setups/projectSetup.js +46 -46
- package/utils/setups/setupAuth.js +973 -926
- package/utils/setups/setupDatabase.js +75 -75
- package/utils/setups/setupLogger.js +69 -59
- package/utils/setups/setupMongoose.js +377 -432
- package/utils/setups/setupPrisma.js +802 -630
- package/utils/setups/setupSwagger.js +97 -88
- package/utils/shell.js +32 -32
- package/utils/spinner.js +57 -57
- package/utils/systemCheck.js +124 -124
- package/utils/userInput.js +421 -421
- package/utils/utils.js +2197 -1762
package/utils/envGenerator.js
CHANGED
|
@@ -1,122 +1,122 @@
|
|
|
1
|
-
const crypto = require("crypto");
|
|
2
|
-
const fs = require("fs");
|
|
3
|
-
const path = require("path");
|
|
4
|
-
|
|
5
|
-
function generateSecret(length = 64) {
|
|
6
|
-
return crypto.randomBytes(length).toString("base64url");
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
async function generateEnvFile(inputs) {
|
|
10
|
-
const jwtSecret = generateSecret(64);
|
|
11
|
-
const jwtRefreshSecret = generateSecret(64);
|
|
12
|
-
|
|
13
|
-
// --- SECTION
|
|
14
|
-
let content = `# ==============================================================================
|
|
15
|
-
# APPLICATION CONFIGURATION
|
|
16
|
-
# ==============================================================================
|
|
17
|
-
# development | production | test
|
|
18
|
-
NODE_ENV=development
|
|
19
|
-
PORT=3000
|
|
20
|
-
|
|
21
|
-
`;
|
|
22
|
-
|
|
23
|
-
// --- SECTION
|
|
24
|
-
content += `# ------------------------------------------------------------------------------
|
|
25
|
-
# AUTHENTICATION (JWT)
|
|
26
|
-
# ------------------------------------------------------------------------------
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
JWT_SECRET=${jwtSecret}
|
|
30
|
-
JWT_REFRESH_SECRET=${jwtRefreshSecret}
|
|
31
|
-
|
|
32
|
-
#
|
|
33
|
-
JWT_EXPIRES_IN=15m
|
|
34
|
-
JWT_REFRESH_EXPIRES_IN=7d
|
|
35
|
-
|
|
36
|
-
`;
|
|
37
|
-
|
|
38
|
-
// --- SECTION
|
|
39
|
-
content += `# ------------------------------------------------------------------------------
|
|
40
|
-
# DATABASE CONFIGURATION (${inputs.dbConfig.orm.toUpperCase()})
|
|
41
|
-
# ------------------------------------------------------------------------------
|
|
42
|
-
`;
|
|
43
|
-
|
|
44
|
-
if (inputs.dbConfig.orm === "mongoose") {
|
|
45
|
-
const mongoUri = inputs.dbConfig.MONGO_URI || "mongodb://localhost:27017";
|
|
46
|
-
const mongoDb = inputs.dbConfig.MONGO_DB || inputs.projectName;
|
|
47
|
-
content += `#
|
|
48
|
-
MONGO_URI=${mongoUri}
|
|
49
|
-
MONGO_DB=${mongoDb}
|
|
50
|
-
`;
|
|
51
|
-
} else {
|
|
52
|
-
const user = inputs.dbConfig.POSTGRES_USER || "postgres";
|
|
53
|
-
const pass = inputs.dbConfig.POSTGRES_PASSWORD || "postgres";
|
|
54
|
-
const db = inputs.dbConfig.POSTGRES_DB || inputs.projectName;
|
|
55
|
-
const host = inputs.dbConfig.POSTGRES_HOST || "localhost";
|
|
56
|
-
const port = inputs.dbConfig.POSTGRES_PORT || "5432";
|
|
57
|
-
|
|
58
|
-
const dbUrl = buildDatabaseUrl(
|
|
59
|
-
user,
|
|
60
|
-
pass,
|
|
61
|
-
host,
|
|
62
|
-
port,
|
|
63
|
-
db,
|
|
64
|
-
inputs.dbConfig.orm
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
content += `#
|
|
68
|
-
POSTGRES_USER=${user}
|
|
69
|
-
POSTGRES_PASSWORD=${pass}
|
|
70
|
-
POSTGRES_DB=${db}
|
|
71
|
-
POSTGRES_HOST=${host}
|
|
72
|
-
POSTGRES_PORT=${port}
|
|
73
|
-
|
|
74
|
-
#
|
|
75
|
-
DATABASE_URL=${dbUrl}
|
|
76
|
-
`;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return content;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function buildDatabaseUrl(user, password, host, port, database, orm) {
|
|
83
|
-
const baseUrl = `postgresql://${user}:${password}@${host}:${port}/${database}`;
|
|
84
|
-
return orm === "prisma" ? `${baseUrl}?schema=public` : baseUrl;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function writeEnvFile(envContent, projectPath = ".") {
|
|
88
|
-
// Écriture du .env (avec secrets)
|
|
89
|
-
const envPath = path.join(projectPath, ".env");
|
|
90
|
-
fs.writeFileSync(envPath, envContent, "utf8");
|
|
91
|
-
|
|
92
|
-
// Génération du .env.example (sans secrets pour le Git)
|
|
93
|
-
const envExample = envContent
|
|
94
|
-
.split("\n")
|
|
95
|
-
.map((line) => {
|
|
96
|
-
if (
|
|
97
|
-
line.includes("JWT_SECRET=") ||
|
|
98
|
-
line.includes("JWT_REFRESH_SECRET=")
|
|
99
|
-
) {
|
|
100
|
-
return line.split("=")[0] + "=votre_cle_secrete_ici";
|
|
101
|
-
}
|
|
102
|
-
if (line.includes("POSTGRES_PASSWORD=")) {
|
|
103
|
-
return "POSTGRES_PASSWORD=votre_mot_de_passe";
|
|
104
|
-
}
|
|
105
|
-
if (line.includes("DATABASE_URL=")) {
|
|
106
|
-
// Masquer le mot de passe dans l'URL d'exemple
|
|
107
|
-
return "DATABASE_URL=postgresql://user:password@localhost:5432/db_name?schema=public";
|
|
108
|
-
}
|
|
109
|
-
return line;
|
|
110
|
-
})
|
|
111
|
-
.join("\n");
|
|
112
|
-
|
|
113
|
-
const envExamplePath = path.join(projectPath, ".env.example");
|
|
114
|
-
fs.writeFileSync(envExamplePath, envExample, "utf8");
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
module.exports = {
|
|
118
|
-
generateSecret,
|
|
119
|
-
generateEnvFile,
|
|
120
|
-
writeEnvFile,
|
|
121
|
-
buildDatabaseUrl,
|
|
122
|
-
};
|
|
1
|
+
const crypto = require("crypto");
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
|
|
5
|
+
function generateSecret(length = 64) {
|
|
6
|
+
return crypto.randomBytes(length).toString("base64url");
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
async function generateEnvFile(inputs) {
|
|
10
|
+
const jwtSecret = generateSecret(64);
|
|
11
|
+
const jwtRefreshSecret = generateSecret(64);
|
|
12
|
+
|
|
13
|
+
// --- APPLICATION SECTION ---
|
|
14
|
+
let content = `# ==============================================================================
|
|
15
|
+
# APPLICATION CONFIGURATION
|
|
16
|
+
# ==============================================================================
|
|
17
|
+
# development | production | test
|
|
18
|
+
NODE_ENV=development
|
|
19
|
+
PORT=3000
|
|
20
|
+
|
|
21
|
+
`;
|
|
22
|
+
|
|
23
|
+
// --- AUTHENTICATION SECTION ---
|
|
24
|
+
content += `# ------------------------------------------------------------------------------
|
|
25
|
+
# AUTHENTICATION (JWT)
|
|
26
|
+
# ------------------------------------------------------------------------------
|
|
27
|
+
# Auto-generated secrets to secure tokens.
|
|
28
|
+
# Never share these keys in production.
|
|
29
|
+
JWT_SECRET=${jwtSecret}
|
|
30
|
+
JWT_REFRESH_SECRET=${jwtRefreshSecret}
|
|
31
|
+
|
|
32
|
+
# Accepted formats: 15m (minutes), 1h (hours), 7d (days)
|
|
33
|
+
JWT_EXPIRES_IN=15m
|
|
34
|
+
JWT_REFRESH_EXPIRES_IN=7d
|
|
35
|
+
|
|
36
|
+
`;
|
|
37
|
+
|
|
38
|
+
// --- DATABASE SECTION ---
|
|
39
|
+
content += `# ------------------------------------------------------------------------------
|
|
40
|
+
# DATABASE CONFIGURATION (${inputs.dbConfig.orm.toUpperCase()})
|
|
41
|
+
# ------------------------------------------------------------------------------
|
|
42
|
+
`;
|
|
43
|
+
|
|
44
|
+
if (inputs.dbConfig.orm === "mongoose") {
|
|
45
|
+
const mongoUri = inputs.dbConfig.MONGO_URI || "mongodb://localhost:27017";
|
|
46
|
+
const mongoDb = inputs.dbConfig.MONGO_DB || inputs.projectName;
|
|
47
|
+
content += `# MongoDB connection URI
|
|
48
|
+
MONGO_URI=${mongoUri}
|
|
49
|
+
MONGO_DB=${mongoDb}
|
|
50
|
+
`;
|
|
51
|
+
} else {
|
|
52
|
+
const user = inputs.dbConfig.POSTGRES_USER || "postgres";
|
|
53
|
+
const pass = inputs.dbConfig.POSTGRES_PASSWORD || "postgres";
|
|
54
|
+
const db = inputs.dbConfig.POSTGRES_DB || inputs.projectName;
|
|
55
|
+
const host = inputs.dbConfig.POSTGRES_HOST || "localhost";
|
|
56
|
+
const port = inputs.dbConfig.POSTGRES_PORT || "5432";
|
|
57
|
+
|
|
58
|
+
const dbUrl = buildDatabaseUrl(
|
|
59
|
+
user,
|
|
60
|
+
pass,
|
|
61
|
+
host,
|
|
62
|
+
port,
|
|
63
|
+
db,
|
|
64
|
+
inputs.dbConfig.orm
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
content += `# Individual variables (useful for Docker or third-party scripts)
|
|
68
|
+
POSTGRES_USER=${user}
|
|
69
|
+
POSTGRES_PASSWORD=${pass}
|
|
70
|
+
POSTGRES_DB=${db}
|
|
71
|
+
POSTGRES_HOST=${host}
|
|
72
|
+
POSTGRES_PORT=${port}
|
|
73
|
+
|
|
74
|
+
# Full connection URL used by ${inputs.dbConfig.orm.toUpperCase()}
|
|
75
|
+
DATABASE_URL=${dbUrl}
|
|
76
|
+
`;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return content;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function buildDatabaseUrl(user, password, host, port, database, orm) {
|
|
83
|
+
const baseUrl = `postgresql://${user}:${password}@${host}:${port}/${database}`;
|
|
84
|
+
return orm === "prisma" ? `${baseUrl}?schema=public` : baseUrl;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function writeEnvFile(envContent, projectPath = ".") {
|
|
88
|
+
// Écriture du .env (avec secrets)
|
|
89
|
+
const envPath = path.join(projectPath, ".env");
|
|
90
|
+
fs.writeFileSync(envPath, envContent, "utf8");
|
|
91
|
+
|
|
92
|
+
// Génération du .env.example (sans secrets pour le Git)
|
|
93
|
+
const envExample = envContent
|
|
94
|
+
.split("\n")
|
|
95
|
+
.map((line) => {
|
|
96
|
+
if (
|
|
97
|
+
line.includes("JWT_SECRET=") ||
|
|
98
|
+
line.includes("JWT_REFRESH_SECRET=")
|
|
99
|
+
) {
|
|
100
|
+
return line.split("=")[0] + "=votre_cle_secrete_ici";
|
|
101
|
+
}
|
|
102
|
+
if (line.includes("POSTGRES_PASSWORD=")) {
|
|
103
|
+
return "POSTGRES_PASSWORD=votre_mot_de_passe";
|
|
104
|
+
}
|
|
105
|
+
if (line.includes("DATABASE_URL=")) {
|
|
106
|
+
// Masquer le mot de passe dans l'URL d'exemple
|
|
107
|
+
return "DATABASE_URL=postgresql://user:password@localhost:5432/db_name?schema=public";
|
|
108
|
+
}
|
|
109
|
+
return line;
|
|
110
|
+
})
|
|
111
|
+
.join("\n");
|
|
112
|
+
|
|
113
|
+
const envExamplePath = path.join(projectPath, ".env.example");
|
|
114
|
+
fs.writeFileSync(envExamplePath, envExample, "utf8");
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
module.exports = {
|
|
118
|
+
generateSecret,
|
|
119
|
+
generateEnvFile,
|
|
120
|
+
writeEnvFile,
|
|
121
|
+
buildDatabaseUrl,
|
|
122
|
+
};
|
|
@@ -1,55 +1,49 @@
|
|
|
1
|
-
const fs = require("fs");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
const { logError } = require("../loggers/logError");
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Lit le package.json, fusionne les scripts et les dépendances, et réécrit le fichier.
|
|
7
|
-
*
|
|
8
|
-
* @param {object} inputs Les inputs du CLI (pour le chemin du projet et le nom)
|
|
9
|
-
* @param {object} scripts Les scripts à ajouter/mettre à jour (ex: { "seed": "npm run prisma:seed" })
|
|
10
|
-
* @param {object} [devDependencies={}] Les dépendances de développement à ajouter/mettre à jour
|
|
11
|
-
*/
|
|
12
|
-
async function updatePackageJson(inputs, scripts, devDependencies = {}) {
|
|
13
|
-
const projectPath = process.cwd();
|
|
14
|
-
const packageJsonPath = path.join(projectPath, "package.json");
|
|
15
|
-
|
|
16
|
-
try {
|
|
17
|
-
// 1. Lire le contenu actuel
|
|
18
|
-
const fileContent = fs.readFileSync(packageJsonPath, "utf8");
|
|
19
|
-
const packageJson = JSON.parse(fileContent);
|
|
20
|
-
|
|
21
|
-
// 2. Fusionner les scripts
|
|
22
|
-
packageJson.scripts = {
|
|
23
|
-
...packageJson.scripts,
|
|
24
|
-
...scripts,
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
// 3. Fusionner les dépendances de développement (si fournies)
|
|
28
|
-
packageJson.devDependencies = {
|
|
29
|
-
...packageJson.devDependencies,
|
|
30
|
-
...devDependencies,
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
`Échec de la mise à jour du fichier package.json., ${error.message}`
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
module.exports = { updatePackageJson };
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const { logError } = require("../loggers/logError");
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Lit le package.json, fusionne les scripts et les dépendances, et réécrit le fichier.
|
|
7
|
+
*
|
|
8
|
+
* @param {object} inputs Les inputs du CLI (pour le chemin du projet et le nom)
|
|
9
|
+
* @param {object} scripts Les scripts à ajouter/mettre à jour (ex: { "seed": "npm run prisma:seed" })
|
|
10
|
+
* @param {object} [devDependencies={}] Les dépendances de développement à ajouter/mettre à jour
|
|
11
|
+
*/
|
|
12
|
+
async function updatePackageJson(inputs, scripts, devDependencies = {}) {
|
|
13
|
+
const projectPath = process.cwd();
|
|
14
|
+
const packageJsonPath = path.join(projectPath, "package.json");
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
// 1. Lire le contenu actuel
|
|
18
|
+
const fileContent = fs.readFileSync(packageJsonPath, "utf8");
|
|
19
|
+
const packageJson = JSON.parse(fileContent);
|
|
20
|
+
|
|
21
|
+
// 2. Fusionner les scripts
|
|
22
|
+
packageJson.scripts = {
|
|
23
|
+
...packageJson.scripts,
|
|
24
|
+
...scripts,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// 3. Fusionner les dépendances de développement (si fournies)
|
|
28
|
+
packageJson.devDependencies = {
|
|
29
|
+
...packageJson.devDependencies,
|
|
30
|
+
...devDependencies,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// 4. Réécrire le fichier (avec une indentation de 2 espaces pour la lisibilité)
|
|
34
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
35
|
+
|
|
36
|
+
// Note: Les dépendances installées via runCommand (npm install X) sont déjà dans package.json,
|
|
37
|
+
// cette fonction est surtout utile pour les scripts personnalisés ou les dépendances manquantes.
|
|
38
|
+
} catch (error) {
|
|
39
|
+
logError(
|
|
40
|
+
`❌ Erreur lors de la mise à jour de package.json pour ${inputs.projectName}:`,
|
|
41
|
+
error.message
|
|
42
|
+
);
|
|
43
|
+
throw new Error(
|
|
44
|
+
`Échec de la mise à jour du fichier package.json., ${error.message}`
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
module.exports = { updatePackageJson };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Lit le package.json, fusionne les scripts et les dépendances, et réécrit le fichier.
|
|
6
|
+
*
|
|
7
|
+
* @param {object} inputs Les inputs du CLI (pour le chemin du projet et le nom)
|
|
8
|
+
*
|
|
9
|
+
*/
|
|
10
|
+
async function saveProjectConfig(inputs) {
|
|
11
|
+
const configDir = path.join(process.cwd(), ".nestcraftx");
|
|
12
|
+
const configFile = path.join(configDir, ".nestcraftxrc");
|
|
13
|
+
|
|
14
|
+
const configData = {
|
|
15
|
+
name: inputs.projectName,
|
|
16
|
+
mode: inputs.mode,
|
|
17
|
+
orm: inputs.dbConfig.orm,
|
|
18
|
+
database: inputs.selectedDB,
|
|
19
|
+
auth: inputs.useAuth,
|
|
20
|
+
swagger: inputs.useSwagger,
|
|
21
|
+
packageManager: inputs.packageManager,
|
|
22
|
+
docker: inputs.useDocker,
|
|
23
|
+
generatedAt: new Date().toISOString(),
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
if (!fs.existsSync(configDir)) {
|
|
28
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
29
|
+
}
|
|
30
|
+
fs.writeFileSync(configFile, JSON.stringify(configData, null, 2));
|
|
31
|
+
} catch (error) {
|
|
32
|
+
logWarning("Could not save project configuration file.");
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
module.exports = { saveProjectConfig };
|