novatec-cli 3.0.4 → 3.0.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/lib/create.js CHANGED
@@ -118,18 +118,65 @@ export async function runCreate(nameArg, options) {
118
118
 
119
119
  // ── ARQUITECTURA ──────────────────────────────────────────────────────────────
120
120
  async function applyArchitecture(config, root) {
121
- const beDir = path.join(root, 'backend', 'src');
122
121
  const arch = config.architecture || 'mvc';
123
122
 
124
- const dirs = {
123
+ // Backend
124
+ const beDirs = {
125
125
  mvc: ['controllers', 'models', 'routes', 'middlewares', 'services'],
126
126
  hexagonal: ['domain/entities', 'domain/ports', 'application/usecases', 'infrastructure/adapters', 'infrastructure/repositories', 'interfaces/http'],
127
127
  clean: ['domain/entities', 'domain/usecases', 'data/repositories', 'data/datasources', 'presentation/controllers', 'presentation/routes'],
128
128
  };
129
+ const beBase = path.join(root, 'backend', 'src');
130
+ for (const dir of (beDirs[arch] || beDirs.mvc)) {
131
+ await fse.ensureDir(path.join(beBase, dir));
132
+ await fse.writeFile(path.join(beBase, dir, '.gitkeep'), '');
133
+ }
134
+
135
+ // Frontend — estructura de src según arquitectura
136
+ const feDirs = {
137
+ mvc: [
138
+ 'components',
139
+ 'pages',
140
+ 'services',
141
+ 'hooks',
142
+ 'utils',
143
+ 'assets',
144
+ ],
145
+ hexagonal: [
146
+ 'domain/entities',
147
+ 'domain/ports',
148
+ 'application/usecases',
149
+ 'infrastructure/api',
150
+ 'infrastructure/storage',
151
+ 'presentation/components',
152
+ 'presentation/pages',
153
+ 'presentation/hooks',
154
+ ],
155
+ clean: [
156
+ 'domain/entities',
157
+ 'domain/usecases',
158
+ 'data/repositories',
159
+ 'data/datasources',
160
+ 'presentation/components',
161
+ 'presentation/pages',
162
+ 'presentation/hooks',
163
+ 'core/utils',
164
+ ],
165
+ };
129
166
 
130
- for (const dir of (dirs[arch] || dirs.mvc)) {
131
- await fse.ensureDir(path.join(beDir, dir));
132
- await fse.writeFile(path.join(beDir, dir, '.gitkeep'), '');
167
+ const feBase = path.join(root, 'frontend', 'src');
168
+ // Solo crear si existe el directorio src (algunos frameworks lo generan, otros no)
169
+ if (await fse.pathExists(feBase)) {
170
+ for (const dir of (feDirs[arch] || feDirs.mvc)) {
171
+ await fse.ensureDir(path.join(feBase, dir));
172
+ await fse.writeFile(path.join(feBase, dir, '.gitkeep'), '');
173
+ }
174
+ } else {
175
+ // Si no existe src aún (ej: nuxt, astro), crearlo igual
176
+ for (const dir of (feDirs[arch] || feDirs.mvc)) {
177
+ await fse.ensureDir(path.join(feBase, dir));
178
+ await fse.writeFile(path.join(feBase, dir, '.gitkeep'), '');
179
+ }
133
180
  }
134
181
  }
135
182
 
package/lib/doctor.js CHANGED
@@ -7,6 +7,7 @@ function getVersion(cmd) {
7
7
  }
8
8
 
9
9
  const CHECKS = [
10
+ // ── REQUERIDOS ──────────────────────────────────────────────────────────────
10
11
  {
11
12
  name: 'Node.js',
12
13
  cmd: 'node',
@@ -15,22 +16,35 @@ const CHECKS = [
15
16
  fix: 'Descarga desde https://nodejs.org (versión LTS)',
16
17
  getVer: () => getVersion('node'),
17
18
  parseVer: v => parseInt(v?.replace('v', '')),
19
+ needed: 'Requerido para React, Vue, Next.js, Nuxt, Astro, Svelte, SolidJS, Angular, Remix, Qwik, Express, NestJS, Fastify, Hono',
18
20
  },
19
21
  {
20
22
  name: 'npm',
21
23
  cmd: 'npm',
22
24
  required: true,
23
25
  minVersion: 9,
24
- fix: 'Se instala con Node.js. Actualiza con: npm install -g npm@latest',
26
+ fix: 'Se instala con Node.js. Actualiza: npm install -g npm@latest',
25
27
  getVer: () => getVersion('npm'),
26
28
  parseVer: v => parseInt(v),
29
+ needed: 'Package manager principal',
27
30
  },
31
+ {
32
+ name: 'Git',
33
+ cmd: 'git',
34
+ required: true,
35
+ fix: 'Descarga desde https://git-scm.com',
36
+ getVer: () => getVersion('git'),
37
+ needed: 'Control de versiones',
38
+ },
39
+
40
+ // ── PACKAGE MANAGERS OPCIONALES ─────────────────────────────────────────────
28
41
  {
29
42
  name: 'pnpm',
30
43
  cmd: 'pnpm',
31
44
  required: false,
32
45
  fix: 'npm install -g pnpm',
33
46
  getVer: () => getVersion('pnpm'),
47
+ needed: 'Package manager alternativo (opcional)',
34
48
  },
35
49
  {
36
50
  name: 'yarn',
@@ -38,74 +52,119 @@ const CHECKS = [
38
52
  required: false,
39
53
  fix: 'npm install -g yarn',
40
54
  getVer: () => getVersion('yarn'),
55
+ needed: 'Package manager alternativo (opcional)',
41
56
  },
42
- {
43
- name: 'Git',
44
- cmd: 'git',
45
- required: true,
46
- fix: 'Descarga desde https://git-scm.com',
47
- getVer: () => getVersion('git'),
48
- },
49
- {
50
- name: 'Docker',
51
- cmd: 'docker',
52
- required: false,
53
- fix: 'Descarga Docker Desktop desde https://docker.com',
54
- getVer: () => getVersion('docker'),
55
- },
57
+
58
+ // ── PYTHON (FastAPI, Django, Flask) ─────────────────────────────────────────
56
59
  {
57
60
  name: 'Python',
58
61
  cmd: 'python',
59
62
  required: false,
60
- fix: 'Descarga desde https://python.org (requerido para FastAPI/Django/Flask)',
63
+ minVersion: 3.8,
64
+ fix: 'Descarga desde https://python.org (versión 3.8+)',
61
65
  getVer: () => getVersion('python') || getVersion('python3'),
66
+ parseVer: v => {
67
+ const m = v?.match(/(\d+)\.(\d+)/);
68
+ return m ? parseInt(m[1]) * 100 + parseInt(m[2]) : 0;
69
+ },
70
+ minVersion: 308, // 3.8 → 308
71
+ minVersionLabel: '3.8',
72
+ needed: 'Requerido para FastAPI, Django, Flask',
62
73
  },
63
74
  {
64
75
  name: 'pip',
65
76
  cmd: 'pip',
66
77
  required: false,
67
- fix: 'Se instala con Python. Actualiza con: python -m pip install --upgrade pip',
78
+ fix: 'Se instala con Python. Actualiza: python -m pip install --upgrade pip',
68
79
  getVer: () => getVersion('pip') || getVersion('pip3'),
80
+ needed: 'Gestor de paquetes Python (FastAPI, Django, Flask)',
69
81
  },
82
+
83
+ // ── JAVA (Spring Boot) ──────────────────────────────────────────────────────
70
84
  {
71
85
  name: 'Java',
72
86
  cmd: 'java',
73
87
  required: false,
74
- fix: 'Descarga JDK desde https://adoptium.net (requerido para Spring Boot)',
75
- getVer: () => { try { return execSync('java -version 2>&1', { encoding: 'utf8' }).trim().split('\n')[0]; } catch { return null; } },
88
+ minVersion: 17,
89
+ fix: 'Descarga JDK 17+ desde https://adoptium.net',
90
+ getVer: () => {
91
+ try {
92
+ const out = execSync('java -version 2>&1', { encoding: 'utf8' }).trim();
93
+ return out.split('\n')[0];
94
+ } catch { return null; }
95
+ },
96
+ parseVer: v => parseInt(v?.match(/version "(\d+)/)?.[1]),
97
+ needed: 'Requerido para Spring Boot',
76
98
  },
99
+ {
100
+ name: 'Maven',
101
+ cmd: 'mvn',
102
+ required: false,
103
+ fix: 'Descarga desde https://maven.apache.org',
104
+ getVer: () => getVersion('mvn'),
105
+ needed: 'Build tool para Spring Boot',
106
+ },
107
+
108
+ // ── GO (Go/Gin) ─────────────────────────────────────────────────────────────
77
109
  {
78
110
  name: 'Go',
79
111
  cmd: 'go',
80
112
  required: false,
81
- fix: 'Descarga desde https://go.dev (requerido para Go/Gin)',
113
+ minVersion: 119,
114
+ minVersionLabel: '1.19',
115
+ fix: 'Descarga desde https://go.dev',
82
116
  getVer: () => getVersion('go'),
117
+ parseVer: v => { const m = v?.match(/go(\d+)\.(\d+)/); return m ? parseInt(m[1]) * 100 + parseInt(m[2]) : 0; },
118
+ needed: 'Requerido para Go/Gin backend',
83
119
  },
120
+
121
+ // ── DENO (Deno/Oak) ─────────────────────────────────────────────────────────
84
122
  {
85
123
  name: 'Deno',
86
124
  cmd: 'deno',
87
125
  required: false,
88
- fix: 'irm https://deno.land/install.ps1 | iex (PowerShell)',
126
+ fix: 'PowerShell: irm https://deno.land/install.ps1 | iex',
89
127
  getVer: () => getVersion('deno'),
128
+ needed: 'Requerido para Deno/Oak backend',
129
+ },
130
+
131
+ // ── HERRAMIENTAS ADICIONALES ───────────────────────────────────────────────
132
+ {
133
+ name: 'Docker',
134
+ cmd: 'docker',
135
+ required: false,
136
+ fix: 'Descarga Docker Desktop desde https://docker.com',
137
+ getVer: () => getVersion('docker'),
138
+ needed: 'Para contenedores y despliegue',
139
+ },
140
+ {
141
+ name: 'VS Code',
142
+ cmd: 'code',
143
+ required: false,
144
+ fix: 'Descarga desde https://code.visualstudio.com',
145
+ getVer: () => getVersion('code'),
146
+ needed: 'Editor recomendado (se abre automáticamente)',
90
147
  },
91
148
  ];
92
149
 
93
150
  export async function runDoctor() {
94
151
  console.log();
95
152
  console.log(boxen(
96
- chalk.bold.white(' NOVATEC DOCTOR — Verificación del entorno'),
97
- { padding: { top: 0, bottom: 0, left: 1, right: 4 }, margin: { left: 2 }, borderStyle: 'round', borderColor: 'white', dimBorder: true }
153
+ chalk.bold.white(' NOVATEC DOCTOR — Verificación del entorno\n\n') +
154
+ chalk.gray(' Verifica todas las herramientas necesarias para\n') +
155
+ chalk.gray(' crear proyectos con cualquier tecnología del CLI'),
156
+ { padding: 1, margin: { left: 2 }, borderStyle: 'round', borderColor: 'white', dimBorder: true }
98
157
  ));
99
158
  console.log();
100
159
 
101
160
  const results = [];
102
161
  let allRequired = true;
103
162
 
163
+ // ── VERIFICAR TODAS LAS HERRAMIENTAS ───────────────────────────────────────
104
164
  for (const tool of CHECKS) {
105
165
  const ver = tool.getVer ? tool.getVer() : null;
106
166
  const ok = !!ver;
107
167
 
108
- // Verificar versión mínima
109
168
  let versionOk = true;
110
169
  if (ok && tool.minVersion && tool.parseVer) {
111
170
  const parsed = tool.parseVer(ver);
@@ -117,45 +176,71 @@ export async function runDoctor() {
117
176
 
118
177
  results.push({ ...tool, ver, status });
119
178
 
120
- const icon = status === 'ok' ? chalk.white('✔') : status === 'outdated' ? chalk.yellow('⚠') : chalk.gray('✗');
179
+ const icon = status === 'ok' ? chalk.green('✔') : status === 'outdated' ? chalk.yellow('⚠') : chalk.gray('✗');
121
180
  const label = chalk.white(tool.name.padEnd(12));
122
181
  const value = status === 'ok' ? chalk.gray(ver || '') :
123
- status === 'outdated' ? chalk.yellow(ver + ` (requiere >= ${tool.minVersion})`) :
124
- chalk.gray(tool.required ? 'no encontrado [requerido]' : 'no instalado [opcional]');
182
+ status === 'outdated' ? chalk.yellow(ver + ` (requiere >= ${tool.minVersionLabel || tool.minVersion})`) :
183
+ chalk.gray(tool.required ? 'no encontrado [REQUERIDO]' : 'no instalado');
125
184
 
126
185
  console.log(` ${icon} ${label} ${value}`);
127
186
  }
128
187
 
129
188
  console.log();
130
189
 
131
- // Mostrar soluciones para los que fallan
132
- const problems = results.filter(r => r.status !== 'ok' && r.required);
133
- const warnings = results.filter(r => r.status !== 'ok' && !r.required);
190
+ // ── RESUMEN POR CATEGORÍA ──────────────────────────────────────────────────
191
+ const required = results.filter(r => r.required);
192
+ const optional = results.filter(r => !r.required);
193
+
194
+ const reqOk = required.filter(r => r.status === 'ok').length;
195
+ const optOk = optional.filter(r => r.status === 'ok').length;
196
+
197
+ console.log(boxen(
198
+ chalk.bold.white(' RESUMEN\n\n') +
199
+ chalk.white(` Requeridas: ${reqOk}/${required.length} `) + (reqOk === required.length ? chalk.green('✔') : chalk.red('✖')) + '\n' +
200
+ chalk.white(` Opcionales: ${optOk}/${optional.length} `) + chalk.gray('(para tecnologías específicas)'),
201
+ { padding: 1, margin: { left: 2 }, borderStyle: 'round', borderColor: reqOk === required.length ? 'green' : 'yellow', dimBorder: true }
202
+ ));
134
203
 
204
+ // ── PROBLEMAS CRÍTICOS ─────────────────────────────────────────────────────
205
+ const problems = results.filter(r => r.status !== 'ok' && r.required);
135
206
  if (problems.length) {
136
207
  console.log(boxen(
137
- chalk.bold.white(' PROBLEMAS ENCONTRADOS\n\n') +
208
+ chalk.bold.red(' PROBLEMAS CRÍTICOS\n\n') +
138
209
  problems.map(p =>
139
210
  chalk.white(` ${p.name}\n`) +
140
- chalk.gray(` ${p.status === 'outdated' ? 'Versión desactualizada' : 'No instalado'}\n`) +
211
+ chalk.gray(` Estado: ${p.status === 'outdated' ? 'Versión desactualizada' : 'No instalado'}\n`) +
141
212
  chalk.gray(` Solución: ${p.fix}`)
142
213
  ).join('\n\n'),
143
- { padding: 1, margin: { left: 2 }, borderStyle: 'round', borderColor: 'red', dimBorder: true }
214
+ { padding: 1, margin: { left: 2 }, borderStyle: 'round', borderColor: 'red' }
144
215
  ));
145
216
  }
146
217
 
218
+ // ── HERRAMIENTAS OPCIONALES FALTANTES ──────────────────────────────────────
219
+ const warnings = results.filter(r => r.status !== 'ok' && !r.required);
147
220
  if (warnings.length) {
148
221
  console.log(boxen(
149
- chalk.bold.white(' OPCIONALES NO INSTALADOS\n\n') +
150
- warnings.map(w => chalk.gray(` ${w.name.padEnd(10)} → ${w.fix}`)).join('\n'),
222
+ chalk.bold.white(' OPCIONALES NO INSTALADAS\n\n') +
223
+ chalk.gray(' Instala según las tecnologías que uses:\n\n') +
224
+ warnings.map(w =>
225
+ chalk.white(` ${w.name}\n`) +
226
+ chalk.gray(` ${w.needed}\n`) +
227
+ chalk.gray(` Instalar: ${w.fix}`)
228
+ ).join('\n\n'),
151
229
  { padding: 1, margin: { left: 2 }, borderStyle: 'single', borderColor: 'gray', dimBorder: true }
152
230
  ));
153
231
  }
154
232
 
233
+ // ── MENSAJE FINAL ──────────────────────────────────────────────────────────
234
+ console.log();
155
235
  if (allRequired) {
156
- console.log(' ' + chalk.white('✔ Entorno listo para usar NovaTec CLI'));
236
+ console.log(' ' + chalk.green('✔ Entorno listo para usar NovaTec CLI'));
237
+ console.log(' ' + chalk.gray(' Puedes crear proyectos con Node.js, React, Vue, Express, etc.'));
238
+ if (warnings.length) {
239
+ console.log(' ' + chalk.gray(' Instala herramientas opcionales para más tecnologías'));
240
+ }
157
241
  } else {
158
- console.log(' ' + chalk.yellow(' Instala las herramientas requeridas antes de continuar'));
242
+ console.log(' ' + chalk.red(' Faltan herramientas requeridas'));
243
+ console.log(' ' + chalk.gray(' Instala Node.js, npm y Git antes de continuar'));
159
244
  }
160
245
  console.log();
161
246
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "novatec-cli",
3
- "version": "3.0.4",
3
+ "version": "3.0.6",
4
4
  "description": "🚀 NOVATEC FULLSTACK CLI — Generador profesional de proyectos full stack | React, Next.js, Vue, Express, NestJS, FastAPI y más",
5
5
  "type": "module",
6
6
  "main": "./lib/create.js",