mgpanel-cli 1.0.1 → 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.
Files changed (3) hide show
  1. package/README.md +5 -1
  2. package/bin/mgpanel.js +604 -20
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -38,5 +38,9 @@ npm -v
38
38
  ## Comandos disponibles
39
39
 
40
40
  Crear un módulo:
41
+ ```bash
42
+ mgpanel make page nombre-pagina
43
+ mgpanel make module nombre-modulo
44
+ mgpanel add module nombre-modulo --to nombre-pagina
41
45
 
42
- mgpanel make module home
46
+ ```
package/bin/mgpanel.js CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ const http = require("http");
3
4
  const fs = require("fs");
4
5
  const path = require("path");
5
6
 
@@ -9,11 +10,24 @@ MGPanel CLI
9
10
 
10
11
  Uso:
11
12
  mgpanel init <nombre-proyecto>
13
+
14
+ mgpanel make page <nombre-pagina>
12
15
  mgpanel make module <nombre-modulo>
13
16
 
17
+ mgpanel add module <nombre-modulo> --to <nombre-pagina>
18
+
19
+ mgpanel dev [puerto]
20
+
14
21
  Ejemplos:
15
22
  mgpanel init miweb
16
- mgpanel make module home
23
+ cd miweb
24
+
25
+ mgpanel make page home
26
+ mgpanel make module header
27
+ mgpanel add module header --to home
28
+
29
+ mgpanel dev
30
+ mgpanel dev 8080
17
31
  `);
18
32
  }
19
33
 
@@ -27,6 +41,19 @@ function writeFileIfNotExists(filePath, content) {
27
41
  return true;
28
42
  }
29
43
 
44
+ function readJSON(filePath) {
45
+ const raw = fs.readFileSync(filePath, "utf8");
46
+ return JSON.parse(raw);
47
+ }
48
+
49
+ function writeJSON(filePath, obj) {
50
+ fs.writeFileSync(filePath, JSON.stringify(obj, null, 2), "utf8");
51
+ }
52
+
53
+ function isValidSlug(name) {
54
+ return /^[a-z0-9-]+$/i.test(name);
55
+ }
56
+
30
57
  /**
31
58
  * mgpanel init <projectName>
32
59
  */
@@ -40,27 +67,460 @@ function cmdInit(projectName = "mgpanel-project") {
40
67
 
41
68
  console.log("🚀 Creando proyecto MGPanel:", projectName);
42
69
 
70
+ // base
43
71
  ensureDir(projectPath);
72
+ ensureDir(path.join(projectPath, "pages"));
44
73
  ensureDir(path.join(projectPath, "modules"));
74
+ ensureDir(path.join(projectPath, "dev"));
45
75
  ensureDir(path.join(projectPath, "assets", "css"));
46
76
  ensureDir(path.join(projectPath, "assets", "js"));
47
77
 
78
+ // Global CSS/JS
79
+ const globalCSS = `/* MGPanel Global Styles */
80
+ :root { color-scheme: light; }
81
+ body { margin: 0; font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
82
+ `;
83
+ fs.writeFileSync(path.join(projectPath, "assets", "css", "style.css"), globalCSS, "utf8");
84
+
85
+ const globalJS = `// MGPanel Global JS
86
+ console.log("[MGPanel] Global JS loaded");
87
+ `;
88
+ fs.writeFileSync(path.join(projectPath, "assets", "js", "app.js"), globalJS, "utf8");
89
+
90
+ // index.html solo preview local
48
91
  const indexHTML = `<!doctype html>
49
92
  <html lang="es">
50
93
  <head>
51
94
  <meta charset="utf-8" />
52
95
  <meta name="viewport" content="width=device-width, initial-scale=1" />
53
- <title>MGPanel</title>
96
+ <title>MGPanel (Local Preview)</title>
97
+
98
+ <link rel="stylesheet" href="assets/css/style.css" />
99
+ <script src="assets/js/app.js" defer></script>
54
100
  </head>
55
101
  <body>
56
- <h1>Hola Mundo desde MGPanel 🚀</h1>
102
+ <div id="app"></div>
103
+ <script src="dev/preview.js"></script>
57
104
  </body>
58
105
  </html>
59
106
  `;
60
-
61
107
  fs.writeFileSync(path.join(projectPath, "index.html"), indexHTML, "utf8");
62
108
 
109
+ // dev/preview.js: carga una page leyendo page.json y componiendo módulos
110
+ const previewJS = `async function loadModule(name) {
111
+ const base = \`modules/\${name}/\${name}\`;
112
+
113
+ // HTML
114
+ const html = await fetch(\`\${base}.html\`).then(r => r.text());
115
+
116
+ // CSS
117
+ const cssHref = \`\${base}.css\`;
118
+ if (!document.querySelector(\`link[data-mgpanel-css="\${cssHref}"]\`)) {
119
+ const link = document.createElement("link");
120
+ link.rel = "stylesheet";
121
+ link.href = cssHref;
122
+ link.setAttribute("data-mgpanel-css", cssHref);
123
+ document.head.appendChild(link);
124
+ }
125
+
126
+ // JS
127
+ const jsSrc = \`\${base}.js\`;
128
+ if (!document.querySelector(\`script[data-mgpanel-js="\${jsSrc}"]\`)) {
129
+ const script = document.createElement("script");
130
+ script.src = jsSrc;
131
+ script.defer = true;
132
+ script.setAttribute("data-mgpanel-js", jsSrc);
133
+ document.body.appendChild(script);
134
+ }
135
+
136
+ return html;
137
+ }
138
+
139
+ async function renderPage(pageName) {
140
+ const configPath = \`pages/\${pageName}/page.json\`;
141
+ const page = await fetch(configPath).then(r => r.json());
142
+
143
+ // Title
144
+ if (page.title) document.title = page.title;
145
+
146
+ // Meta description
147
+ if (page.description) {
148
+ let meta = document.querySelector('meta[name="description"]');
149
+ if (!meta) {
150
+ meta = document.createElement("meta");
151
+ meta.setAttribute("name", "description");
152
+ document.head.appendChild(meta);
153
+ }
154
+ meta.setAttribute("content", page.description);
155
+ }
156
+
157
+ const app = document.getElementById("app");
158
+ app.innerHTML = "";
159
+
160
+ for (const item of (page.modules || [])) {
161
+ const html = await loadModule(item.name);
162
+ const wrapper = document.createElement("div");
163
+ wrapper.setAttribute("data-mgpanel-module", item.name);
164
+ wrapper.innerHTML = html;
165
+ app.appendChild(wrapper);
166
+ }
167
+ }
168
+
169
+ const pageFromPath = () => {
170
+ const p = window.location.pathname.replace(/^\\/+/g, "").replace(/\\/+$/g, "");
171
+ return p === "" ? "home" : p;
172
+ };
173
+
174
+ renderPage(pageFromPath()).catch(err => {
175
+ console.error("[MGPanel Preview] Error:", err);
176
+ document.getElementById("app").innerHTML =
177
+ "<h2>Error cargando la página. ¿Existe pages/&lt;page&gt;/page.json?</h2>";
178
+ });
179
+ `;
180
+ fs.writeFileSync(path.join(projectPath, "dev", "preview.js"), previewJS, "utf8");
181
+
182
+ // Crear page home por defecto
183
+ ensureDir(path.join(projectPath, "pages", "home"));
184
+ const homePage = {
185
+ route: "/",
186
+ title: "Home",
187
+ description: "Página principal creada con MGPanel.",
188
+ modules: []
189
+ };
190
+ fs.writeFileSync(
191
+ path.join(projectPath, "pages", "home", "page.json"),
192
+ JSON.stringify(homePage, null, 2),
193
+ "utf8"
194
+ );
195
+
196
+ // dev/config.md: Documentación para IDEs (Cursor, etc.)
197
+ const configMD = `# MGPanel - Configuración de Desarrollo
198
+
199
+ Esta documentación está diseñada para ayudar a IDEs como Cursor y otros editores a entender el contexto de desarrollo con MGPanel.
200
+
201
+ ## ¿Qué es MGPanel?
202
+
203
+ MGPanel es un sistema de gestión de contenido (CMS) basado en Node.js y MongoDB que permite crear sitios web usando HTML, CSS y JavaScript puro, sin frameworks complejos. Los proyectos MGPanel utilizan una arquitectura modular donde las páginas se componen de módulos reutilizables.
204
+
205
+ ## Estructura del Proyecto
206
+
207
+ \`\`\`
208
+ proyecto/
209
+ ├── pages/ # Páginas del sitio
210
+ │ └── <nombre-pagina>/
211
+ │ └── page.json # Configuración de la página (ruta, título, módulos)
212
+ ├── modules/ # Módulos reutilizables
213
+ │ └── <nombre-modulo>/
214
+ │ ├── <nombre-modulo>.html
215
+ │ ├── <nombre-modulo>.css
216
+ │ └── <nombre-modulo>.js
217
+ ├── assets/ # Archivos estáticos globales
218
+ │ ├── css/
219
+ │ │ └── style.css
220
+ │ └── js/
221
+ │ └── app.js
222
+ ├── dev/ # Utilidades de desarrollo
223
+ │ ├── config.md # Este archivo
224
+ │ └── preview.js # Script para preview local
225
+ └── index.html # Punto de entrada para preview local
226
+ \`\`\`
227
+
228
+ ## Comandos Disponibles
229
+
230
+ ### Crear una Página
231
+
232
+ \`\`\`bash
233
+ mgpanel make page <nombre-pagina>
234
+ \`\`\`
235
+
236
+ **Ejemplo:**
237
+ \`\`\`bash
238
+ mgpanel make page about
239
+ mgpanel make page contacto
240
+ \`\`\`
241
+
242
+ Esto crea:
243
+ - \`pages/<nombre-pagina>/page.json\` - Archivo de configuración de la página
244
+
245
+ **Estructura de page.json:**
246
+ \`\`\`json
247
+ {
248
+ "route": "/about",
249
+ "title": "About",
250
+ "description": "Descripción de la página about.",
251
+ "modules": []
252
+ }
253
+ \`\`\`
254
+
255
+ ### Crear un Módulo
256
+
257
+ \`\`\`bash
258
+ mgpanel make module <nombre-modulo>
259
+ \`\`\`
260
+
261
+ **Ejemplo:**
262
+ \`\`\`bash
263
+ mgpanel make module header
264
+ mgpanel make module hero-banner
265
+ mgpanel make module footer
266
+ \`\`\`
267
+
268
+ Esto crea en \`modules/<nombre-modulo>/\`:
269
+ - \`<nombre-modulo>.html\` - Estructura HTML del módulo
270
+ - \`<nombre-modulo>.css\` - Estilos CSS del módulo
271
+ - \`<nombre-modulo>.js\` - Lógica JavaScript del módulo
272
+
273
+ ### Asociar un Módulo a una Página
274
+
275
+ \`\`\`bash
276
+ mgpanel add module <nombre-modulo> --to <nombre-pagina>
277
+ \`\`\`
278
+
279
+ **Ejemplo:**
280
+ \`\`\`bash
281
+ mgpanel add module header --to home
282
+ mgpanel add module hero-banner --to home
283
+ mgpanel add module footer --to home
284
+ \`\`\`
285
+
286
+ Esto actualiza el archivo \`pages/<nombre-pagina>/page.json\` añadiendo el módulo al array \`modules\`:
287
+
288
+ \`\`\`json
289
+ {
290
+ "route": "/",
291
+ "title": "Home",
292
+ "description": "Página principal.",
293
+ "modules": [
294
+ { "name": "header" },
295
+ { "name": "hero-banner" },
296
+ { "name": "footer" }
297
+ ]
298
+ }
299
+ \`\`\`
300
+
301
+ **Importante:** Los módulos se renderizan en el orden en que aparecen en el array \`modules\`.
302
+
303
+ ### Servidor de Desarrollo
304
+
305
+ \`\`\`bash
306
+ mgpanel dev [puerto]
307
+ \`\`\`
308
+
309
+ Inicia un servidor HTTP local para previsualizar el proyecto.
310
+
311
+ - **Puerto por defecto:** 3000
312
+ - **Acceso:** http://localhost:3000 (o el puerto especificado)
313
+
314
+ El servidor:
315
+ - Sirve archivos estáticos (HTML, CSS, JS, imágenes)
316
+ - Implementa routing SPA: rutas sin extensión devuelven \`index.html\`
317
+ - Soporta hot-reload manual (refrescar el navegador)
318
+
319
+ **Ejemplos:**
320
+ \`\`\`bash
321
+ mgpanel dev # Puerto 3000
322
+ mgpanel dev 8080 # Puerto 8080
323
+ \`\`\`
324
+
325
+ ## Flujo de Trabajo Recomendado
326
+
327
+ 1. **Crear un módulo:**
328
+ \`\`\`bash
329
+ mgpanel make module header
330
+ \`\`\`
331
+
332
+ 2. **Editar el módulo:**
333
+ - Edita \`modules/header/header.html\`
334
+ - Edita \`modules/header/header.css\`
335
+ - Edita \`modules/header/header.js\`
336
+
337
+ 3. **Crear/editar una página:**
338
+ \`\`\`bash
339
+ mgpanel make page home
340
+ \`\`\`
341
+
342
+ 4. **Asociar módulos a la página:**
343
+ \`\`\`bash
344
+ mgpanel add module header --to home
345
+ mgpanel add module hero --to home
346
+ mgpanel add module footer --to home
347
+ \`\`\`
348
+
349
+ 5. **Iniciar servidor de desarrollo:**
350
+ \`\`\`bash
351
+ mgpanel dev
352
+ \`\`\`
353
+
354
+ 6. **Acceder a la página:**
355
+ - http://localhost:3000 (página home)
356
+ - http://localhost:3000/about (si existe la página about)
357
+
358
+ ## Convenciones y Reglas
359
+
360
+ ### Nombres de Páginas y Módulos
361
+
362
+ - Usar solo letras minúsculas, números y guiones
363
+ - No usar espacios ni caracteres especiales
364
+ - Ejemplos válidos: \`home\`, \`about-us\`, \`contacto\`, \`header\`, \`hero-banner\`
365
+ - Ejemplos inválidos: \`About Us\`, \`contact_page\`, \`mi@modulo\`
366
+
367
+ ### Estructura de Módulos
368
+
369
+ Cada módulo debe tener exactamente 3 archivos con el mismo nombre base:
370
+
371
+ \`\`\`
372
+ modules/<nombre-modulo>/
373
+ ├── <nombre-modulo>.html
374
+ ├── <nombre-modulo>.css
375
+ └── <nombre-modulo>.js
376
+ \`\`\`
377
+
378
+ ### CSS y JavaScript Globales
379
+
380
+ - **Global CSS:** \`assets/css/style.css\` - Se carga en todas las páginas
381
+ - **Global JS:** \`assets/js/app.js\` - Se carga en todas las páginas
382
+ - **Módulo CSS:** Se carga automáticamente cuando el módulo es usado
383
+ - **Módulo JS:** Se carga automáticamente cuando el módulo es usado
384
+
385
+ ### Preview Local
386
+
387
+ El archivo \`index.html\` y \`dev/preview.js\` permiten previsualizar las páginas localmente:
388
+
389
+ - Lee \`pages/<nombre>/page.json\`
390
+ - Carga los módulos especificados en el orden definido
391
+ - Inyecta CSS y JS de cada módulo automáticamente
392
+ - Soporta routing basado en la URL
393
+
394
+ ## Integración con MGPanel CMS
395
+
396
+ Cuando despliegues el proyecto en MGPanel:
397
+
398
+ 1. Las páginas se sincronizan con el CMS
399
+ 2. Los módulos se pueden reutilizar entre páginas
400
+ 3. El contenido puede ser editado desde el panel de administración
401
+ 4. La estructura de archivos se mantiene compatible
402
+
403
+ ## Consejos para IDEs
404
+
405
+ - Los archivos \`page.json\` definen la configuración de cada página
406
+ - Los módulos son componentes independientes y reutilizables
407
+ - El orden de los módulos en \`page.json\` determina el orden de renderizado
408
+ - Usa autocompletado para referencias entre módulos y páginas
409
+ - Valida los nombres de módulos antes de asociarlos a páginas
410
+ `;
411
+
412
+ fs.writeFileSync(path.join(projectPath, "dev", "config.md"), configMD, "utf8");
413
+
414
+ // README.md en la raíz del proyecto
415
+ const readmeMD = `# Proyecto MGPanel
416
+
417
+ Este proyecto ha sido creado con **MGPanel CLI**, un sistema para desarrollar sitios web usando HTML, CSS y JavaScript puro, organizados de forma modular.
418
+
419
+ ## 📚 Documentación de Desarrollo
420
+
421
+ Para entender completamente cómo trabajar con este proyecto, consulta la documentación completa en:
422
+
423
+ **\`dev/config.md\`**
424
+
425
+ Este archivo contiene información detallada sobre:
426
+ - Comandos para crear páginas y módulos
427
+ - Cómo asociar módulos a páginas
428
+ - Estructura del proyecto
429
+ - Flujo de trabajo recomendado
430
+ - Convenciones y mejores prácticas
431
+
432
+ ## 🚀 Inicio Rápido
433
+
434
+ 1. **Crear un módulo:**
435
+ \`\`\`bash
436
+ mgpanel make module nombre-modulo
437
+ \`\`\`
438
+
439
+ 2. **Crear una página:**
440
+ \`\`\`bash
441
+ mgpanel make page nombre-pagina
442
+ \`\`\`
443
+
444
+ 3. **Asociar módulo a página:**
445
+ \`\`\`bash
446
+ mgpanel add module nombre-modulo --to nombre-pagina
447
+ \`\`\`
448
+
449
+ 4. **Iniciar servidor de desarrollo:**
450
+ \`\`\`bash
451
+ mgpanel dev
452
+ \`\`\`
453
+
454
+ ## 📁 Estructura del Proyecto
455
+
456
+ \`\`\`
457
+ .
458
+ ├── pages/ # Páginas del sitio
459
+ │ └── <nombre>/page.json
460
+ ├── modules/ # Módulos reutilizables
461
+ │ └── <nombre>/
462
+ │ ├── <nombre>.html
463
+ │ ├── <nombre>.css
464
+ │ └── <nombre>.js
465
+ ├── assets/ # Recursos globales
466
+ │ ├── css/style.css
467
+ │ └── js/app.js
468
+ ├── dev/ # Desarrollo
469
+ │ ├── config.md # 📖 Documentación completa para IDEs
470
+ │ └── preview.js
471
+ └── index.html # Preview local
472
+ \`\`\`
473
+
474
+ ## 🔗 Más Información
475
+
476
+ - **Documentación de desarrollo:** Ver \`dev/config.md\`
477
+ - **MGPanel CLI:** https://github.com/miguayaba/mgpanel-cli
478
+ `;
479
+
480
+ fs.writeFileSync(path.join(projectPath, "README.md"), readmeMD, "utf8");
481
+
63
482
  console.log("✅ Proyecto creado correctamente");
483
+ console.log("👉 Ejecuta: cd " + projectName + " && mgpanel dev");
484
+ }
485
+
486
+ /**
487
+ * mgpanel make page <pageName>
488
+ */
489
+ function cmdMakePage(pageName) {
490
+ if (!pageName) {
491
+ console.log("❌ Falta el nombre de la página");
492
+ console.log("👉 Usa: mgpanel make page <nombre-pagina>");
493
+ process.exit(1);
494
+ }
495
+ if (!isValidSlug(pageName)) {
496
+ console.log("❌ Nombre de página inválido. Usa letras/números/guiones. Ej: home, about-us");
497
+ process.exit(1);
498
+ }
499
+
500
+ const pagesDir = path.join(process.cwd(), "pages");
501
+ const pageDir = path.join(pagesDir, pageName);
502
+ ensureDir(pageDir);
503
+
504
+ const pageJsonPath = path.join(pageDir, "page.json");
505
+ const created = writeFileIfNotExists(
506
+ pageJsonPath,
507
+ JSON.stringify(
508
+ {
509
+ route: `/${pageName === "home" ? "" : pageName}`.replace(/\/$/, "/"),
510
+ title: pageName.charAt(0).toUpperCase() + pageName.slice(1),
511
+ description: `Descripción de la página ${pageName}.`,
512
+ modules: []
513
+ },
514
+ null,
515
+ 2
516
+ )
517
+ );
518
+
519
+ if (created) {
520
+ console.log(`📄 Página "${pageName}" creada en: pages/${pageName}/page.json`);
521
+ } else {
522
+ console.log(`↩️ La página "${pageName}" ya existe: pages/${pageName}/page.json`);
523
+ }
64
524
  }
65
525
 
66
526
  /**
@@ -72,18 +532,13 @@ function cmdMakeModule(moduleName) {
72
532
  console.log("👉 Usa: mgpanel make module <nombre-modulo>");
73
533
  process.exit(1);
74
534
  }
75
-
76
- // Validación básica: slug simple
77
- const valid = /^[a-z0-9-]+$/i.test(moduleName);
78
- if (!valid) {
79
- console.log("❌ Nombre de módulo inválido. Usa letras/números/guiones, ej: home, about-us");
535
+ if (!isValidSlug(moduleName)) {
536
+ console.log("❌ Nombre de módulo inválido. Usa letras/números/guiones. Ej: header, hero-banner");
80
537
  process.exit(1);
81
538
  }
82
539
 
83
- const cwd = process.cwd();
84
- const modulesDir = path.join(cwd, "modules");
540
+ const modulesDir = path.join(process.cwd(), "modules");
85
541
  const moduleDir = path.join(modulesDir, moduleName);
86
-
87
542
  ensureDir(moduleDir);
88
543
 
89
544
  const htmlPath = path.join(moduleDir, `${moduleName}.html`);
@@ -119,23 +574,152 @@ console.log("[MGPanel] Module loaded:", "${moduleName}");
119
574
  if (skipped.length) console.log("↩️ Ya existían:", skipped.join(", "));
120
575
  }
121
576
 
122
- // ------------------ Router simple ------------------
577
+ /**
578
+ * mgpanel add module <moduleName> --to <pageName>
579
+ */
580
+ function cmdAddModule(moduleName, pageName) {
581
+ if (!moduleName || !pageName) {
582
+ console.log("❌ Uso inválido");
583
+ console.log("👉 Usa: mgpanel add module <modulo> --to <pagina>");
584
+ process.exit(1);
585
+ }
123
586
 
124
- const args = process.argv.slice(2);
587
+ const moduleDir = path.join(process.cwd(), "modules", moduleName);
588
+ if (!fs.existsSync(moduleDir)) {
589
+ console.log(`❌ El módulo "${moduleName}" no existe en modules/${moduleName}/`);
590
+ console.log(`👉 Crea el módulo primero: mgpanel make module ${moduleName}`);
591
+ process.exit(1);
592
+ }
593
+
594
+ const pageJsonPath = path.join(process.cwd(), "pages", pageName, "page.json");
595
+ if (!fs.existsSync(pageJsonPath)) {
596
+ console.log(`❌ La página "${pageName}" no existe (pages/${pageName}/page.json)`);
597
+ console.log(`👉 Crea la página primero: mgpanel make page ${pageName}`);
598
+ process.exit(1);
599
+ }
600
+
601
+ const page = readJSON(pageJsonPath);
602
+ page.modules = Array.isArray(page.modules) ? page.modules : [];
603
+
604
+ const already = page.modules.some(m => m && m.name === moduleName);
605
+ if (already) {
606
+ console.log(`↩️ El módulo "${moduleName}" ya está agregado a la página "${pageName}".`);
607
+ return;
608
+ }
609
+
610
+ page.modules.push({ name: moduleName });
611
+ writeJSON(pageJsonPath, page);
612
+
613
+ console.log(`✅ Módulo "${moduleName}" agregado a pages/${pageName}/page.json`);
614
+ }
615
+
616
+ function cmdDev(port = 3000) {
617
+ const root = process.cwd();
618
+
619
+ const server = http.createServer((req, res) => {
620
+ // 1) Normalizar URL (sin querystring)
621
+ let urlPath = req.url || "/";
622
+ urlPath = decodeURIComponent(urlPath.split("?")[0]);
623
+
624
+ // 2) Seguridad básica: bloquear path traversal
625
+ if (urlPath.includes("..")) {
626
+ res.writeHead(400, { "Content-Type": "text/plain" });
627
+ res.end("400 Bad Request");
628
+ return;
629
+ }
630
+
631
+ // 3) Root -> index.html
632
+ if (urlPath === "/") urlPath = "/index.html";
633
+
634
+ // 4) SPA fallback: si NO hay extensión (ej: /nosotros), devolver index.html
635
+ const hasExtension = path.extname(urlPath) !== "";
636
+ if (!hasExtension) {
637
+ urlPath = "/index.html";
638
+ }
639
+
640
+ const fullPath = path.join(root, urlPath);
641
+
642
+ fs.readFile(fullPath, (err, content) => {
643
+ if (err) {
644
+ res.writeHead(404, { "Content-Type": "text/plain" });
645
+ res.end("404 Not Found");
646
+ return;
647
+ }
648
+
649
+ const ext = path.extname(fullPath).toLowerCase();
650
+ const types = {
651
+ ".html": "text/html; charset=utf-8",
652
+ ".js": "application/javascript; charset=utf-8",
653
+ ".css": "text/css; charset=utf-8",
654
+ ".json": "application/json; charset=utf-8",
655
+ ".png": "image/png",
656
+ ".jpg": "image/jpeg",
657
+ ".jpeg": "image/jpeg",
658
+ ".svg": "image/svg+xml"
659
+ };
660
+
661
+ res.writeHead(200, {
662
+ "Content-Type": types[ext] || "application/octet-stream",
663
+ "Cache-Control": "no-store"
664
+ });
665
+ res.end(content);
666
+ });
667
+ });
668
+
669
+ server.listen(port, () => {
670
+ console.log(`🚀 MGPanel Dev Server`);
671
+ console.log(`👉 http://localhost:${port}`);
672
+ console.log(`🛑 Ctrl + C para detener`);
673
+ });
674
+ }
675
+
676
+ // ------------------ Router CLI ------------------
125
677
 
678
+ const args = process.argv.slice(2);
126
679
  if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
127
680
  printHelp();
128
681
  process.exit(0);
129
682
  }
130
683
 
131
- const [cmd1, cmd2, cmd3] = args;
684
+ const [cmd1, cmd2, cmd3, cmd4, cmd5] = args;
132
685
 
133
686
  if (cmd1 === "init") {
134
687
  cmdInit(cmd2);
135
- } else if (cmd1 === "make" && cmd2 === "module") {
688
+ process.exit(0);
689
+ }
690
+
691
+ if (cmd1 === "make" && cmd2 === "page") {
692
+ cmdMakePage(cmd3);
693
+ process.exit(0);
694
+ }
695
+
696
+ if (cmd1 === "make" && cmd2 === "module") {
136
697
  cmdMakeModule(cmd3);
137
- } else {
138
- console.log("❌ Comando no reconocido.");
139
- printHelp();
140
- process.exit(1);
698
+ process.exit(0);
141
699
  }
700
+
701
+ if (cmd1 === "add" && cmd2 === "module") {
702
+ const moduleName = cmd3;
703
+ const flag = cmd4;
704
+ const pageName = cmd5;
705
+
706
+ if (flag !== "--to") {
707
+ console.log("❌ Falta --to <pagina>");
708
+ console.log("👉 Usa: mgpanel add module <modulo> --to <pagina>");
709
+ process.exit(1);
710
+ }
711
+
712
+ cmdAddModule(moduleName, pageName);
713
+ process.exit(0);
714
+ }
715
+
716
+ if (cmd1 === "dev") {
717
+ const port = cmd2 ? Number(cmd2) : 3000;
718
+ cmdDev(port);
719
+ // NO process.exit aquí, el server debe quedarse vivo
720
+ return;
721
+ }
722
+
723
+ console.log("❌ Comando no reconocido.");
724
+ printHelp();
725
+ process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mgpanel-cli",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "MGPanel CLI",
5
5
  "bin": {
6
6
  "mgpanel": "./bin/mgpanel.js"