novatec-cli 1.0.1 → 2.0.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.
- package/bin/index.js +146 -64
- package/lib/create.js +312 -212
- package/lib/prompts.js +187 -260
- package/lib/utils.js +22 -9
- package/package.json +2 -2
package/bin/index.js
CHANGED
|
@@ -4,89 +4,89 @@ import { program } from 'commander';
|
|
|
4
4
|
import chalk from 'chalk';
|
|
5
5
|
import figlet from 'figlet';
|
|
6
6
|
import boxen from 'boxen';
|
|
7
|
+
import { execSync } from 'child_process';
|
|
8
|
+
import { createRequire } from 'module';
|
|
7
9
|
import { checkRequirements } from '../lib/utils.js';
|
|
8
10
|
import { runCreate } from '../lib/create.js';
|
|
9
11
|
|
|
12
|
+
const require = createRequire(import.meta.url);
|
|
13
|
+
const pkg = require('../package.json');
|
|
14
|
+
|
|
10
15
|
function sleep(ms) {
|
|
11
16
|
return new Promise(r => setTimeout(r, ms));
|
|
12
17
|
}
|
|
13
18
|
|
|
19
|
+
// Verifica si hay una versión más nueva en npm (silencioso)
|
|
20
|
+
async function checkForUpdates() {
|
|
21
|
+
try {
|
|
22
|
+
const latest = execSync(`npm show ${pkg.name} version`, { encoding: 'utf8', timeout: 3000 }).trim();
|
|
23
|
+
if (latest && latest !== pkg.version) {
|
|
24
|
+
console.log(
|
|
25
|
+
boxen(
|
|
26
|
+
chalk.yellow(' Nueva versión disponible!\n\n') +
|
|
27
|
+
chalk.gray(' Actual : ') + chalk.white(pkg.version) + '\n' +
|
|
28
|
+
chalk.gray(' Nueva : ') + chalk.bold.white(latest) + '\n\n' +
|
|
29
|
+
chalk.white(' npm install -g novatec-cli'),
|
|
30
|
+
{ padding: 1, margin: { left: 2 }, borderStyle: 'round', borderColor: 'yellow', dimBorder: true }
|
|
31
|
+
)
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
} catch { /* sin internet o error, ignorar */ }
|
|
35
|
+
}
|
|
36
|
+
|
|
14
37
|
async function showBanner() {
|
|
15
38
|
console.clear();
|
|
16
39
|
|
|
17
|
-
|
|
18
|
-
const logo = figlet.textSync('NOVATEC', { font: 'ANSI Shadow' });
|
|
40
|
+
const logo = figlet.textSync('NOVATEC', { font: 'Slant' });
|
|
19
41
|
const lines = logo.split('\n').filter(l => l.trim());
|
|
20
42
|
|
|
21
43
|
console.log();
|
|
22
|
-
lines.forEach(line =>
|
|
23
|
-
console.log(' ' + chalk.bold.white(line));
|
|
24
|
-
});
|
|
25
|
-
|
|
44
|
+
lines.forEach(line => console.log(' ' + chalk.bold.white(line)));
|
|
26
45
|
console.log();
|
|
27
46
|
|
|
28
|
-
//
|
|
29
|
-
const
|
|
30
|
-
|
|
47
|
+
// Versión + fecha
|
|
48
|
+
const now = new Date();
|
|
49
|
+
const fecha = now.toLocaleDateString('es-MX', { day: '2-digit', month: 'short', year: 'numeric' });
|
|
50
|
+
console.log(
|
|
51
|
+
' ' + chalk.gray('v' + pkg.version) +
|
|
52
|
+
chalk.gray(' · ') +
|
|
53
|
+
chalk.gray('NOVATEC FULLSTACK CLI') +
|
|
54
|
+
chalk.gray(' · ') +
|
|
55
|
+
chalk.gray(fecha)
|
|
56
|
+
);
|
|
31
57
|
console.log();
|
|
32
|
-
|
|
33
|
-
// Separador
|
|
34
|
-
console.log(' ' + chalk.white('─'.repeat(66)));
|
|
58
|
+
console.log(' ' + chalk.white('─'.repeat(60)));
|
|
35
59
|
console.log();
|
|
36
60
|
|
|
37
|
-
// Stats
|
|
61
|
+
// Stats
|
|
38
62
|
console.log(
|
|
39
63
|
' ' +
|
|
40
|
-
chalk.white
|
|
41
|
-
chalk.
|
|
42
|
-
chalk.white
|
|
43
|
-
chalk.
|
|
44
|
-
chalk.white
|
|
64
|
+
chalk.bold.white('10') + chalk.gray(' frontends') +
|
|
65
|
+
chalk.gray(' · ') +
|
|
66
|
+
chalk.bold.white('10') + chalk.gray(' backends') +
|
|
67
|
+
chalk.gray(' · ') +
|
|
68
|
+
chalk.bold.white('TypeScript') + chalk.gray(' ready') +
|
|
69
|
+
chalk.gray(' · ') +
|
|
70
|
+
chalk.bold.white('Docker') + chalk.gray(' ready')
|
|
45
71
|
);
|
|
46
72
|
console.log();
|
|
47
73
|
|
|
48
|
-
// Caja
|
|
74
|
+
// Caja tecnologías
|
|
49
75
|
console.log(
|
|
50
76
|
boxen(
|
|
51
|
-
chalk.bold.white(' TECNOLOGÍAS
|
|
52
|
-
|
|
77
|
+
chalk.bold.white(' TECNOLOGÍAS\n\n') +
|
|
53
78
|
chalk.white.bold(' Frontend') + chalk.gray(' │ ') +
|
|
54
|
-
[
|
|
55
|
-
chalk.white('
|
|
56
|
-
chalk.white('Next.js'),
|
|
57
|
-
chalk.white('Vue'),
|
|
58
|
-
chalk.white('Nuxt'),
|
|
59
|
-
chalk.white('Astro'),
|
|
60
|
-
chalk.white('Svelte'),
|
|
61
|
-
chalk.white('SolidJS'),
|
|
62
|
-
chalk.white('Angular'),
|
|
63
|
-
chalk.white('Remix'),
|
|
64
|
-
chalk.white('Qwik'),
|
|
65
|
-
].join(chalk.gray(' · ')) + '\n\n' +
|
|
66
|
-
|
|
79
|
+
['React', 'Next.js', 'Vue', 'Nuxt', 'Astro', 'Svelte', 'SolidJS', 'Angular', 'Remix', 'Qwik']
|
|
80
|
+
.map(f => chalk.white(f)).join(chalk.gray(' · ')) + '\n\n' +
|
|
67
81
|
chalk.white.bold(' Backend ') + chalk.gray(' │ ') +
|
|
68
|
-
[
|
|
69
|
-
chalk.white('
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
chalk.white('
|
|
73
|
-
chalk.white('FastAPI'),
|
|
74
|
-
chalk.white('Django'),
|
|
75
|
-
chalk.white('Flask'),
|
|
76
|
-
chalk.white('Spring'),
|
|
77
|
-
chalk.white('Deno'),
|
|
78
|
-
chalk.white('Go/Gin'),
|
|
79
|
-
].join(chalk.gray(' · ')) + '\n\n' +
|
|
80
|
-
|
|
82
|
+
['Express', 'NestJS', 'Fastify', 'Hono', 'FastAPI', 'Django', 'Flask', 'Spring', 'Deno', 'Go/Gin']
|
|
83
|
+
.map(b => chalk.white(b)).join(chalk.gray(' · ')) + '\n\n' +
|
|
84
|
+
chalk.white.bold(' Database') + chalk.gray(' │ ') +
|
|
85
|
+
['PostgreSQL', 'MySQL', 'MongoDB', 'SQLite']
|
|
86
|
+
.map(d => chalk.white(d)).join(chalk.gray(' · ')) + '\n\n' +
|
|
81
87
|
chalk.white.bold(' Extras ') + chalk.gray(' │ ') +
|
|
82
|
-
[
|
|
83
|
-
chalk.gray('
|
|
84
|
-
chalk.gray('ESLint + Prettier'),
|
|
85
|
-
chalk.gray('Husky'),
|
|
86
|
-
chalk.gray('Jest / Vitest'),
|
|
87
|
-
chalk.gray('GitHub Actions'),
|
|
88
|
-
chalk.gray('.env'),
|
|
89
|
-
].join(chalk.gray(' · ')),
|
|
88
|
+
['Docker', 'JWT Auth', 'ESLint', 'Husky', 'Vitest', 'GitHub Actions', 'Tailwind']
|
|
89
|
+
.map(e => chalk.gray(e)).join(chalk.gray(' · ')),
|
|
90
90
|
{
|
|
91
91
|
padding: { top: 1, bottom: 1, left: 2, right: 4 },
|
|
92
92
|
margin: { left: 2 },
|
|
@@ -97,14 +97,14 @@ async function showBanner() {
|
|
|
97
97
|
)
|
|
98
98
|
);
|
|
99
99
|
|
|
100
|
-
console.log();
|
|
101
|
-
|
|
102
100
|
// Uso rápido
|
|
103
101
|
console.log(
|
|
104
102
|
boxen(
|
|
105
103
|
chalk.gray(' Uso rápido\n\n') +
|
|
106
|
-
chalk.white(' $ novatec
|
|
107
|
-
chalk.white(' $ novatec
|
|
104
|
+
chalk.white(' $ novatec create ') + chalk.gray('<nombre>') + '\n' +
|
|
105
|
+
chalk.white(' $ novatec create my-app ') + chalk.gray('--frontend react --backend express --yes') + '\n' +
|
|
106
|
+
chalk.white(' $ novatec list') + chalk.gray(' # ver frameworks') + '\n' +
|
|
107
|
+
chalk.white(' $ novatec update') + chalk.gray(' # actualizar CLI'),
|
|
108
108
|
{
|
|
109
109
|
padding: { top: 0, bottom: 0, left: 1, right: 4 },
|
|
110
110
|
margin: { left: 2 },
|
|
@@ -116,22 +116,30 @@ async function showBanner() {
|
|
|
116
116
|
);
|
|
117
117
|
|
|
118
118
|
console.log();
|
|
119
|
-
console.log(' ' + chalk.white('─'.repeat(
|
|
119
|
+
console.log(' ' + chalk.white('─'.repeat(60)));
|
|
120
120
|
console.log();
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
+
// ── COMANDOS ──────────────────────────────────────────────────────────────────
|
|
124
|
+
|
|
123
125
|
program
|
|
124
|
-
.name('novatec
|
|
126
|
+
.name('novatec')
|
|
125
127
|
.description('NOVATEC FULLSTACK CLI — Generador profesional de proyectos full stack')
|
|
126
|
-
.version(
|
|
128
|
+
.version(pkg.version, '-v, --version', 'Mostrar versión');
|
|
127
129
|
|
|
130
|
+
// CREATE
|
|
128
131
|
program
|
|
129
132
|
.command('create [name]')
|
|
130
133
|
.description('Crear un nuevo proyecto full stack')
|
|
131
|
-
.option('--frontend <type>', '
|
|
132
|
-
.option('--backend <type>', '
|
|
134
|
+
.option('--frontend <type>', 'Framework frontend')
|
|
135
|
+
.option('--backend <type>', 'Framework backend')
|
|
136
|
+
.option('--db <type>', 'Base de datos: postgres | mysql | mongo | sqlite')
|
|
137
|
+
.option('--typescript', 'Usar TypeScript en el proyecto')
|
|
138
|
+
.option('--yes', 'Saltar prompts y usar valores por defecto')
|
|
139
|
+
.option('--preset <name>', 'Usar preset guardado')
|
|
133
140
|
.action(async (name, options) => {
|
|
134
141
|
await showBanner();
|
|
142
|
+
await checkForUpdates();
|
|
135
143
|
try {
|
|
136
144
|
await checkRequirements();
|
|
137
145
|
await runCreate(name, options);
|
|
@@ -146,9 +154,83 @@ program
|
|
|
146
154
|
}
|
|
147
155
|
});
|
|
148
156
|
|
|
157
|
+
// LIST
|
|
158
|
+
program
|
|
159
|
+
.command('list')
|
|
160
|
+
.description('Ver todos los frameworks y tecnologías disponibles')
|
|
161
|
+
.action(() => {
|
|
162
|
+
console.log();
|
|
163
|
+
console.log(
|
|
164
|
+
boxen(
|
|
165
|
+
chalk.bold.white(' FRAMEWORKS DISPONIBLES\n\n') +
|
|
166
|
+
|
|
167
|
+
chalk.bold.white(' Frontend\n') +
|
|
168
|
+
[
|
|
169
|
+
' react — React 18 + Vite',
|
|
170
|
+
' next — Next.js 14 (App Router)',
|
|
171
|
+
' vue — Vue 3 + Vite',
|
|
172
|
+
' nuxt — Nuxt 3',
|
|
173
|
+
' astro — Astro 4',
|
|
174
|
+
' svelte — SvelteKit',
|
|
175
|
+
' solid — SolidJS + Vite',
|
|
176
|
+
' angular — Angular 17',
|
|
177
|
+
' remix — Remix 2',
|
|
178
|
+
' qwik — Qwik City',
|
|
179
|
+
].map(l => chalk.gray(l)).join('\n') + '\n\n' +
|
|
180
|
+
|
|
181
|
+
chalk.bold.white(' Backend\n') +
|
|
182
|
+
[
|
|
183
|
+
' express — Express.js (Node)',
|
|
184
|
+
' nestjs — NestJS (Node + TypeScript)',
|
|
185
|
+
' fastify — Fastify (Node)',
|
|
186
|
+
' hono — Hono (Edge-ready)',
|
|
187
|
+
' fastapi — FastAPI (Python)',
|
|
188
|
+
' django — Django (Python)',
|
|
189
|
+
' flask — Flask (Python)',
|
|
190
|
+
' spring — Spring Boot (Java)',
|
|
191
|
+
' deno — Deno + Oak',
|
|
192
|
+
' gin — Go + Gin',
|
|
193
|
+
].map(l => chalk.gray(l)).join('\n') + '\n\n' +
|
|
194
|
+
|
|
195
|
+
chalk.bold.white(' Bases de datos\n') +
|
|
196
|
+
[
|
|
197
|
+
' postgres — PostgreSQL',
|
|
198
|
+
' mysql — MySQL',
|
|
199
|
+
' mongo — MongoDB',
|
|
200
|
+
' sqlite — SQLite',
|
|
201
|
+
].map(l => chalk.gray(l)).join('\n'),
|
|
202
|
+
{
|
|
203
|
+
padding: { top: 1, bottom: 1, left: 2, right: 6 },
|
|
204
|
+
margin: { left: 2 },
|
|
205
|
+
borderStyle: 'round',
|
|
206
|
+
borderColor: 'white',
|
|
207
|
+
dimBorder: true,
|
|
208
|
+
}
|
|
209
|
+
)
|
|
210
|
+
);
|
|
211
|
+
console.log();
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// UPDATE
|
|
215
|
+
program
|
|
216
|
+
.command('update')
|
|
217
|
+
.description('Actualizar novatec-cli a la última versión')
|
|
218
|
+
.action(async () => {
|
|
219
|
+
const ora = (await import('ora')).default;
|
|
220
|
+
const spinner = ora({ text: chalk.white('Actualizando novatec-cli...'), spinner: 'dots', color: 'white' }).start();
|
|
221
|
+
try {
|
|
222
|
+
execSync('npm install -g novatec-cli@latest', { stdio: 'pipe', encoding: 'utf8' });
|
|
223
|
+
const newVer = execSync('npm show novatec-cli version', { encoding: 'utf8' }).trim();
|
|
224
|
+
spinner.succeed(chalk.white('Actualizado a v' + newVer));
|
|
225
|
+
} catch (e) {
|
|
226
|
+
spinner.fail(chalk.red('Error al actualizar: ' + e.message));
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
|
|
149
230
|
if (!process.argv.slice(2).length) {
|
|
150
231
|
(async () => {
|
|
151
232
|
await showBanner();
|
|
233
|
+
await checkForUpdates();
|
|
152
234
|
program.outputHelp();
|
|
153
235
|
})();
|
|
154
236
|
} else {
|