azotador-forge 1.0.3
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/nodeforge.js +351 -0
- package/package.json +12 -0
package/nodeforge.js
ADDED
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import { execSync } from "child_process";
|
|
6
|
+
import inquirer from "inquirer";
|
|
7
|
+
|
|
8
|
+
const CARPETAS_SRC = [
|
|
9
|
+
"config",
|
|
10
|
+
"controllers",
|
|
11
|
+
"dto",
|
|
12
|
+
"middlewares",
|
|
13
|
+
"models",
|
|
14
|
+
"routes",
|
|
15
|
+
"services",
|
|
16
|
+
"utils",
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
const MODULOS = [
|
|
20
|
+
{ name: "cookie-parser", value: { nombre: "cookie-parser", tipo: "prod" } },
|
|
21
|
+
{ name: "dotenv", value: { nombre: "dotenv", tipo: "prod" } },
|
|
22
|
+
{ name: "cors", value: { nombre: "cors", tipo: "prod" } },
|
|
23
|
+
{ name: "express", value: { nombre: "express", tipo: "prod" } },
|
|
24
|
+
{ name: "mysql2", value: { nombre: "mysql2", tipo: "prod" } },
|
|
25
|
+
{ name: "mongoose", value: { nombre: "mongoose", tipo: "prod" } },
|
|
26
|
+
{ name: "nodemon (dev)", value: { nombre: "nodemon", tipo: "dev" } },
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
function validarRuta(ruta) {
|
|
30
|
+
try {
|
|
31
|
+
return fs.existsSync(ruta);
|
|
32
|
+
} catch {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function crearEstructura(nodePath) {
|
|
38
|
+
fs.mkdirSync(nodePath, { recursive: true });
|
|
39
|
+
|
|
40
|
+
for (const carpeta of CARPETAS_SRC) {
|
|
41
|
+
fs.mkdirSync(path.join(nodePath, "src", carpeta), { recursive: true });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function generarContenidoAppJs(modulosSeleccionados) {
|
|
46
|
+
const nombres = modulosSeleccionados.map((m) => m.nombre);
|
|
47
|
+
|
|
48
|
+
const imports = [`import express from "express";`];
|
|
49
|
+
|
|
50
|
+
if (nombres.includes("cors")) {
|
|
51
|
+
imports.push(`import cors from "cors";`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (nombres.includes("cookie-parser")) {
|
|
55
|
+
imports.push(`import cookieParser from "cookie-parser";`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (nombres.includes("dotenv")) {
|
|
59
|
+
imports.push(`import dotenv from "dotenv";`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const lineas = [];
|
|
63
|
+
|
|
64
|
+
if (nombres.includes("dotenv")) {
|
|
65
|
+
lineas.push(`dotenv.config();`, ``);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
lineas.push(`const app = express();`);
|
|
69
|
+
lineas.push(``);
|
|
70
|
+
lineas.push(`app.use(express.json());`);
|
|
71
|
+
|
|
72
|
+
if (nombres.includes("cors")) {
|
|
73
|
+
lineas.push(`app.use(cors());`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (nombres.includes("cookie-parser")) {
|
|
77
|
+
lineas.push(`app.use(cookieParser());`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
lineas.push(``);
|
|
81
|
+
lineas.push(`app.get("/", (req, res) => {`);
|
|
82
|
+
lineas.push(` res.json({ mensaje: "Servidor funcionando 🚀" });`);
|
|
83
|
+
lineas.push(`});`);
|
|
84
|
+
lineas.push(``);
|
|
85
|
+
lineas.push(`export default app;`);
|
|
86
|
+
|
|
87
|
+
return `${imports.join("\n")}\n\n${lineas.join("\n")}\n`;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function generarContenidoServerJs() {
|
|
91
|
+
return `import app from "./app.js";
|
|
92
|
+
|
|
93
|
+
const PORT = process.env.PORT || 4000;
|
|
94
|
+
|
|
95
|
+
app.listen(PORT, () => {
|
|
96
|
+
console.log(\`Servidor corriendo en http://localhost:\${PORT}\`);
|
|
97
|
+
});
|
|
98
|
+
`;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function crearArchivosBase(nodePath, nombreProyecto, modulosSeleccionados) {
|
|
102
|
+
const packageJson = {
|
|
103
|
+
name: nombreProyecto.toLowerCase().replace(/\s+/g, "-"),
|
|
104
|
+
version: "1.0.0",
|
|
105
|
+
type: "module",
|
|
106
|
+
scripts: {
|
|
107
|
+
dev: "nodemon src/server.js",
|
|
108
|
+
start: "node src/server.js",
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
fs.writeFileSync(
|
|
113
|
+
path.join(nodePath, "package.json"),
|
|
114
|
+
JSON.stringify(packageJson, null, 2),
|
|
115
|
+
"utf-8"
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
fs.writeFileSync(
|
|
119
|
+
path.join(nodePath, ".gitignore"),
|
|
120
|
+
`node_modules
|
|
121
|
+
.env
|
|
122
|
+
`,
|
|
123
|
+
"utf-8"
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
fs.writeFileSync(
|
|
127
|
+
path.join(nodePath, ".env"),
|
|
128
|
+
`PORT=4000
|
|
129
|
+
`,
|
|
130
|
+
"utf-8"
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
fs.writeFileSync(
|
|
134
|
+
path.join(nodePath, "src", "app.js"),
|
|
135
|
+
generarContenidoAppJs(modulosSeleccionados),
|
|
136
|
+
"utf-8"
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
fs.writeFileSync(
|
|
140
|
+
path.join(nodePath, "src", "server.js"),
|
|
141
|
+
generarContenidoServerJs(),
|
|
142
|
+
"utf-8"
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function instalarDependencias(nodePath, modulosSeleccionados) {
|
|
147
|
+
const prod = modulosSeleccionados
|
|
148
|
+
.filter((m) => m.tipo === "prod")
|
|
149
|
+
.map((m) => m.nombre);
|
|
150
|
+
|
|
151
|
+
const dev = modulosSeleccionados
|
|
152
|
+
.filter((m) => m.tipo === "dev")
|
|
153
|
+
.map((m) => m.nombre);
|
|
154
|
+
|
|
155
|
+
process.chdir(nodePath);
|
|
156
|
+
|
|
157
|
+
if (prod.length) {
|
|
158
|
+
console.log(`\n📦 Instalando dependencias: ${prod.join(", ")}`);
|
|
159
|
+
execSync(`npm install ${prod.join(" ")}`, { stdio: "inherit" });
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (dev.length) {
|
|
163
|
+
console.log(`\n🛠 Instalando dependencias de desarrollo: ${dev.join(", ")}`);
|
|
164
|
+
execSync(`npm install -D ${dev.join(" ")}`, { stdio: "inherit" });
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async function preguntarModo() {
|
|
169
|
+
const { modo } = await inquirer.prompt([
|
|
170
|
+
{
|
|
171
|
+
type: "rawlist",
|
|
172
|
+
name: "modo",
|
|
173
|
+
message: "¿Qué querés hacer?",
|
|
174
|
+
choices: [
|
|
175
|
+
{
|
|
176
|
+
name: "Crear proyecto nuevo en la carpeta actual",
|
|
177
|
+
value: "proyecto_actual",
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
name: "Crear proyecto nuevo en una ruta personalizada",
|
|
181
|
+
value: "proyecto_ruta",
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
name: "Crear solo carpeta node en la carpeta actual",
|
|
185
|
+
value: "node_actual",
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
name: "Crear solo carpeta node en una ruta personalizada",
|
|
189
|
+
value: "node_ruta",
|
|
190
|
+
},
|
|
191
|
+
],
|
|
192
|
+
},
|
|
193
|
+
]);
|
|
194
|
+
|
|
195
|
+
return modo;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async function preguntarRutaPersonalizada() {
|
|
199
|
+
const { rutaPersonalizada } = await inquirer.prompt([
|
|
200
|
+
{
|
|
201
|
+
type: "input",
|
|
202
|
+
name: "rutaPersonalizada",
|
|
203
|
+
message: "Escribí la ruta completa donde querés crear el proyecto:",
|
|
204
|
+
validate: (input) => {
|
|
205
|
+
if (!input.trim()) {
|
|
206
|
+
return "Tenés que escribir una ruta.";
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (!validarRuta(input.trim())) {
|
|
210
|
+
return "La ruta no existe.";
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return true;
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
]);
|
|
217
|
+
|
|
218
|
+
return rutaPersonalizada.trim();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
async function preguntarNombreProyecto() {
|
|
222
|
+
const { nombreProyecto } = await inquirer.prompt([
|
|
223
|
+
{
|
|
224
|
+
type: "input",
|
|
225
|
+
name: "nombreProyecto",
|
|
226
|
+
message: "Nombre del proyecto:",
|
|
227
|
+
validate: (input) => {
|
|
228
|
+
if (!input.trim()) {
|
|
229
|
+
return "Tenés que escribir un nombre de proyecto.";
|
|
230
|
+
}
|
|
231
|
+
return true;
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
]);
|
|
235
|
+
|
|
236
|
+
return nombreProyecto.trim();
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
async function preguntarModulos() {
|
|
240
|
+
const { modulosSeleccionados } = await inquirer.prompt([
|
|
241
|
+
{
|
|
242
|
+
type: "checkbox",
|
|
243
|
+
name: "modulosSeleccionados",
|
|
244
|
+
message: "Seleccioná los módulos a instalar:",
|
|
245
|
+
choices: MODULOS,
|
|
246
|
+
pageSize: 10,
|
|
247
|
+
loop: false,
|
|
248
|
+
},
|
|
249
|
+
]);
|
|
250
|
+
|
|
251
|
+
return modulosSeleccionados;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
async function main() {
|
|
255
|
+
try {
|
|
256
|
+
console.log("\n🚀 Node Forge - Backend Generator\n");
|
|
257
|
+
|
|
258
|
+
const modo = await preguntarModo();
|
|
259
|
+
|
|
260
|
+
let basePath = "";
|
|
261
|
+
let proyectoPath = "";
|
|
262
|
+
let nodePath = "";
|
|
263
|
+
let nombreProyecto = "node-app";
|
|
264
|
+
|
|
265
|
+
if (modo === "proyecto_actual") {
|
|
266
|
+
nombreProyecto = await preguntarNombreProyecto();
|
|
267
|
+
basePath = process.cwd();
|
|
268
|
+
proyectoPath = path.join(basePath, nombreProyecto);
|
|
269
|
+
nodePath = path.join(proyectoPath, "node");
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (modo === "proyecto_ruta") {
|
|
273
|
+
nombreProyecto = await preguntarNombreProyecto();
|
|
274
|
+
basePath = await preguntarRutaPersonalizada();
|
|
275
|
+
proyectoPath = path.join(basePath, nombreProyecto);
|
|
276
|
+
nodePath = path.join(proyectoPath, "node");
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (modo === "node_actual") {
|
|
280
|
+
basePath = process.cwd();
|
|
281
|
+
proyectoPath = basePath;
|
|
282
|
+
nodePath = path.join(basePath, "node");
|
|
283
|
+
nombreProyecto = path.basename(basePath);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (modo === "node_ruta") {
|
|
287
|
+
basePath = await preguntarRutaPersonalizada();
|
|
288
|
+
proyectoPath = basePath;
|
|
289
|
+
nodePath = path.join(basePath, "node");
|
|
290
|
+
nombreProyecto = path.basename(basePath);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (fs.existsSync(nodePath)) {
|
|
294
|
+
console.log(`\n⚠ La carpeta ya existe:\n${nodePath}`);
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const modulosSeleccionados = await preguntarModulos();
|
|
299
|
+
|
|
300
|
+
const prod = modulosSeleccionados
|
|
301
|
+
.filter((m) => m.tipo === "prod")
|
|
302
|
+
.map((m) => m.nombre);
|
|
303
|
+
|
|
304
|
+
const dev = modulosSeleccionados
|
|
305
|
+
.filter((m) => m.tipo === "dev")
|
|
306
|
+
.map((m) => m.nombre);
|
|
307
|
+
|
|
308
|
+
console.log("\n📁 Se va a crear acá:");
|
|
309
|
+
console.log(proyectoPath);
|
|
310
|
+
|
|
311
|
+
console.log("\n📁 Carpeta backend:");
|
|
312
|
+
console.log(nodePath);
|
|
313
|
+
|
|
314
|
+
console.log("\n📦 Dependencias producción:");
|
|
315
|
+
console.log(prod.length ? prod.join(", ") : "Ninguna");
|
|
316
|
+
|
|
317
|
+
console.log("\n🛠 Dependencias desarrollo:");
|
|
318
|
+
console.log(dev.length ? dev.join(", ") : "Ninguna");
|
|
319
|
+
|
|
320
|
+
const { confirmar } = await inquirer.prompt([
|
|
321
|
+
{
|
|
322
|
+
type: "confirm",
|
|
323
|
+
name: "confirmar",
|
|
324
|
+
message: "¿Querés continuar?",
|
|
325
|
+
default: true,
|
|
326
|
+
},
|
|
327
|
+
]);
|
|
328
|
+
|
|
329
|
+
if (!confirmar) {
|
|
330
|
+
console.log("\nOperación cancelada.");
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
crearEstructura(nodePath);
|
|
335
|
+
crearArchivosBase(nodePath, nombreProyecto, modulosSeleccionados);
|
|
336
|
+
instalarDependencias(nodePath, modulosSeleccionados);
|
|
337
|
+
|
|
338
|
+
console.log("\n✅ Proyecto creado correctamente");
|
|
339
|
+
console.log(`📁 Proyecto base: ${proyectoPath}`);
|
|
340
|
+
console.log(`📁 Node: ${nodePath}`);
|
|
341
|
+
|
|
342
|
+
console.log("\nPara ejecutarlo:");
|
|
343
|
+
console.log(`cd "${nodePath}"`);
|
|
344
|
+
console.log("npm run dev");
|
|
345
|
+
} catch (error) {
|
|
346
|
+
console.error("\n❌ Ocurrió un error:");
|
|
347
|
+
console.error(error.message);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
main();
|
package/package.json
ADDED