entexto-cli 1.0.0 → 1.1.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/entexto.js +12 -1
- package/lib/commands/pull.js +105 -0
- package/lib/utils/api.js +6 -1
- package/package.json +1 -1
package/bin/entexto.js
CHANGED
|
@@ -55,7 +55,18 @@ program
|
|
|
55
55
|
saveConfig({ token: null, user: null });
|
|
56
56
|
console.log('Sesión cerrada.');
|
|
57
57
|
});
|
|
58
|
-
|
|
58
|
+
// ─── entexto pull / clone ────────────────────────────
|
|
59
|
+
const pullAction = require('../lib/commands/pull');
|
|
60
|
+
[
|
|
61
|
+
program.command('pull'),
|
|
62
|
+
program.command('clone'),
|
|
63
|
+
].forEach(cmd => {
|
|
64
|
+
cmd
|
|
65
|
+
.description('Descargar archivos de un proyecto al disco local')
|
|
66
|
+
.option('-i, --id <uuid>', 'UUID del proyecto a descargar')
|
|
67
|
+
.option('-d, --dir <path>', 'Carpeta destino (default: carpeta actual)', '.')
|
|
68
|
+
.action(pullAction);
|
|
69
|
+
});
|
|
59
70
|
program.parse(process.argv);
|
|
60
71
|
|
|
61
72
|
if (!process.argv.slice(2).length) {
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const inquirer = require('inquirer');
|
|
6
|
+
const chalk = require('chalk');
|
|
7
|
+
const ora = require('ora');
|
|
8
|
+
const { getToken } = require('../utils/config');
|
|
9
|
+
const { getProjects, pullProject } = require('../utils/api');
|
|
10
|
+
|
|
11
|
+
module.exports = async function pull(options) {
|
|
12
|
+
if (!getToken()) {
|
|
13
|
+
console.error(chalk.red('✖ No has iniciado sesión. Ejecuta: entexto login'));
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let uuid = options.id || null;
|
|
18
|
+
|
|
19
|
+
// Si no se pasó --id, mostrar selector interactivo
|
|
20
|
+
if (!uuid) {
|
|
21
|
+
let proyectos;
|
|
22
|
+
const spinner = ora('Cargando proyectos...').start();
|
|
23
|
+
try {
|
|
24
|
+
proyectos = await getProjects();
|
|
25
|
+
spinner.stop();
|
|
26
|
+
} catch (err) {
|
|
27
|
+
spinner.stop();
|
|
28
|
+
console.error(chalk.red('✖ Error al obtener proyectos:'), err.message);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (!proyectos || proyectos.length === 0) {
|
|
33
|
+
console.log(chalk.yellow('No tienes proyectos todavía.'));
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const choices = proyectos.map((p, i) => ({
|
|
38
|
+
name: `${String(i + 1).padStart(2, ' ')}. ${p.name}${p.is_published ? chalk.green(' [publicado]') : ''} ${chalk.gray(p.project_uuid)}`,
|
|
39
|
+
value: p.project_uuid,
|
|
40
|
+
short: p.name,
|
|
41
|
+
}));
|
|
42
|
+
|
|
43
|
+
const { selectedUuid } = await inquirer.prompt([{
|
|
44
|
+
type: 'list',
|
|
45
|
+
name: 'selectedUuid',
|
|
46
|
+
message: 'Elige el proyecto a descargar:',
|
|
47
|
+
choices,
|
|
48
|
+
pageSize: 15,
|
|
49
|
+
}]);
|
|
50
|
+
|
|
51
|
+
uuid = selectedUuid;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Carpeta destino
|
|
55
|
+
let destDir = options.dir || null;
|
|
56
|
+
if (!destDir) {
|
|
57
|
+
const { dir } = await inquirer.prompt([{
|
|
58
|
+
type: 'input',
|
|
59
|
+
name: 'dir',
|
|
60
|
+
message: 'Carpeta de destino (Enter = carpeta actual):',
|
|
61
|
+
default: '.',
|
|
62
|
+
}]);
|
|
63
|
+
destDir = dir || '.';
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const absDir = path.resolve(destDir);
|
|
67
|
+
|
|
68
|
+
// Descargar
|
|
69
|
+
const spinnerPull = ora('Descargando archivos...').start();
|
|
70
|
+
let data;
|
|
71
|
+
try {
|
|
72
|
+
data = await pullProject(uuid);
|
|
73
|
+
spinnerPull.succeed(`Proyecto "${data.proyecto.name}" — ${data.total} archivo(s)`);
|
|
74
|
+
} catch (err) {
|
|
75
|
+
spinnerPull.fail('Error al descargar');
|
|
76
|
+
const msg = err.response ? err.response.data : err.message;
|
|
77
|
+
console.error(chalk.red(typeof msg === 'object' ? msg.error : msg));
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!data.archivos || data.archivos.length === 0) {
|
|
82
|
+
console.log(chalk.yellow('El proyecto no tiene archivos.'));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Escribir archivos localmente
|
|
87
|
+
let escritos = 0;
|
|
88
|
+
for (const { ruta, content } of data.archivos) {
|
|
89
|
+
const destFile = path.join(absDir, ruta);
|
|
90
|
+
const dir = path.dirname(destFile);
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
94
|
+
fs.writeFileSync(destFile, content, 'utf8');
|
|
95
|
+
escritos++;
|
|
96
|
+
} catch (err) {
|
|
97
|
+
console.warn(chalk.yellow(` ⚠ No se pudo escribir: ${ruta} — ${err.message}`));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
console.log(chalk.green(`\n✔ ${escritos} archivo(s) descargados en: ${absDir}`));
|
|
102
|
+
if (data.proyecto.slug) {
|
|
103
|
+
console.log(chalk.gray(` Preview: https://entexto.com/p/${data.proyecto.slug}`));
|
|
104
|
+
}
|
|
105
|
+
};
|
package/lib/utils/api.js
CHANGED
|
@@ -59,4 +59,9 @@ async function publishProject(uuid) {
|
|
|
59
59
|
return res.data;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
async function pullProject(uuid) {
|
|
63
|
+
const res = await client().get(`/api/cli/pull/${uuid}`);
|
|
64
|
+
return res.data;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
module.exports = { login, getProjects, deployFiles, deployWithPublish, publishProject, pullProject };
|