@openfactu/cli 0.0.6 → 0.0.8
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/LICENSE +21 -0
- package/README.md +164 -8
- package/dist/src/commands/backup.d.ts +2 -0
- package/dist/src/commands/backup.js +424 -0
- package/dist/src/commands/deploy.js +492 -69
- package/dist/src/commands/doctor.d.ts +2 -0
- package/dist/src/commands/doctor.js +295 -0
- package/dist/src/commands/install-quick.d.ts +2 -0
- package/dist/src/commands/install-quick.js +249 -0
- package/dist/src/commands/install-script.d.ts +2 -0
- package/dist/src/commands/install-script.js +474 -0
- package/dist/src/commands/install.js +969 -75
- package/dist/src/commands/monitoring.d.ts +2 -0
- package/dist/src/commands/monitoring.js +352 -0
- package/dist/src/commands/service.d.ts +2 -0
- package/dist/src/commands/service.js +402 -0
- package/dist/src/commands/setup.js +7 -2
- package/dist/src/commands/sync-ports.d.ts +2 -0
- package/dist/src/commands/sync-ports.js +298 -0
- package/dist/src/commands/uninstall.d.ts +2 -0
- package/dist/src/commands/uninstall.js +189 -0
- package/dist/src/index.js +17 -1
- package/dist/src/utils/config.d.ts +8 -0
- package/dist/src/utils/config.js +25 -1
- package/dist/src/utils/env.d.ts +11 -0
- package/dist/src/utils/env.js +31 -0
- package/dist/src/utils/helpers.d.ts +22 -0
- package/dist/src/utils/helpers.js +244 -0
- package/dist/src/utils/monitoring.d.ts +38 -0
- package/dist/src/utils/monitoring.js +353 -0
- package/dist/src/utils/paths.d.ts +1 -0
- package/dist/src/utils/paths.js +2 -0
- package/package.json +8 -5
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.registerServiceCommand = registerServiceCommand;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const ora_1 = __importDefault(require("ora"));
|
|
9
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
10
|
+
const child_process_1 = require("child_process");
|
|
11
|
+
const fs_1 = __importDefault(require("fs"));
|
|
12
|
+
const path_1 = __importDefault(require("path"));
|
|
13
|
+
const os_1 = __importDefault(require("os"));
|
|
14
|
+
const logger_1 = require("../utils/logger");
|
|
15
|
+
const paths_1 = require("../utils/paths");
|
|
16
|
+
const helpers_1 = require("../utils/helpers");
|
|
17
|
+
function getServiceName(name) {
|
|
18
|
+
return `openfactu${name !== 'openfactu' ? `-${name}` : ''}`;
|
|
19
|
+
}
|
|
20
|
+
function generateUnitFile(serviceName, workDir, composeFile, options) {
|
|
21
|
+
const dockerCmd = (0, helpers_1.getDockerComposeCommand)();
|
|
22
|
+
const user = options.user || os_1.default.userInfo().username;
|
|
23
|
+
const envFile = path_1.default.join(workDir, '.env');
|
|
24
|
+
let composeFlags = `-f ${composeFile}`;
|
|
25
|
+
if (options.includeMonitoring && options.monitoringComposeFile) {
|
|
26
|
+
composeFlags += ` -f ${options.monitoringComposeFile}`;
|
|
27
|
+
}
|
|
28
|
+
let envVars = '';
|
|
29
|
+
if (options.environment) {
|
|
30
|
+
for (const [key, value] of Object.entries(options.environment)) {
|
|
31
|
+
envVars += `Environment="${key}=${value}"\n`;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return `[Unit]
|
|
35
|
+
Description=OpenFactu ${serviceName} Service
|
|
36
|
+
After=docker.service network-online.target
|
|
37
|
+
Requires=docker.service
|
|
38
|
+
Wants=network-online.target
|
|
39
|
+
|
|
40
|
+
[Service]
|
|
41
|
+
Type=oneshot
|
|
42
|
+
RemainAfterExit=yes
|
|
43
|
+
WorkingDirectory=${workDir}
|
|
44
|
+
User=${user}
|
|
45
|
+
ExecStart=${dockerCmd} ${composeFlags} up -d
|
|
46
|
+
ExecStop=${dockerCmd} ${composeFlags} down
|
|
47
|
+
ExecReload=${dockerCmd} ${composeFlags} restart
|
|
48
|
+
Restart=${options.restartPolicy}
|
|
49
|
+
RestartSec=30
|
|
50
|
+
TimeoutStartSec=300
|
|
51
|
+
TimeoutStopSec=120
|
|
52
|
+
|
|
53
|
+
${envVars}
|
|
54
|
+
EnvironmentFile=${envFile}
|
|
55
|
+
|
|
56
|
+
StandardOutput=journal
|
|
57
|
+
StandardError=journal
|
|
58
|
+
SyslogIdentifier=${serviceName}
|
|
59
|
+
|
|
60
|
+
[Install]
|
|
61
|
+
WantedBy=multi-user.target
|
|
62
|
+
`;
|
|
63
|
+
}
|
|
64
|
+
function generateTimerFile(serviceName, interval) {
|
|
65
|
+
return `[Unit]
|
|
66
|
+
Description=OpenFactu ${serviceName} Health Check Timer
|
|
67
|
+
|
|
68
|
+
[Timer]
|
|
69
|
+
OnBootSec=5min
|
|
70
|
+
OnUnitActiveSec=${interval}
|
|
71
|
+
Persistent=true
|
|
72
|
+
|
|
73
|
+
[Install]
|
|
74
|
+
WantedBy=timers.target
|
|
75
|
+
`;
|
|
76
|
+
}
|
|
77
|
+
function generateHealthCheckScript(workDir) {
|
|
78
|
+
const dockerCmd = (0, helpers_1.getDockerComposeCommand)();
|
|
79
|
+
return `#!/bin/bash
|
|
80
|
+
# OpenFactu Health Check Script
|
|
81
|
+
set -e
|
|
82
|
+
|
|
83
|
+
cd "${workDir}"
|
|
84
|
+
|
|
85
|
+
# Check if containers are running
|
|
86
|
+
FAILED=$(${dockerCmd} ps --format '{{.Name}}:{{.Status}}' | grep -v "Up" || true)
|
|
87
|
+
|
|
88
|
+
if [ -n "$FAILED" ]; then
|
|
89
|
+
echo "$(date): Some containers are not running:"
|
|
90
|
+
echo "$FAILED"
|
|
91
|
+
echo "Attempting restart..."
|
|
92
|
+
${dockerCmd} restart
|
|
93
|
+
exit 1
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
echo "$(date): All containers healthy"
|
|
97
|
+
exit 0
|
|
98
|
+
`;
|
|
99
|
+
}
|
|
100
|
+
function registerServiceCommand(program) {
|
|
101
|
+
const serviceCmd = program
|
|
102
|
+
.command('service')
|
|
103
|
+
.description('Gestionar OpenFactu como servicio del sistema');
|
|
104
|
+
serviceCmd
|
|
105
|
+
.command('install')
|
|
106
|
+
.description('Instalar OpenFactu como servicio systemd')
|
|
107
|
+
.option('--name <name>', 'Nombre del servicio', 'openfactu')
|
|
108
|
+
.option('--restart <policy>', 'Politica de reinicio (no, on-failure, always)', 'on-failure')
|
|
109
|
+
.option('--with-monitoring', 'Incluir servicios de monitoreo')
|
|
110
|
+
.option('--healthcheck', 'Agregar health check automatico')
|
|
111
|
+
.option('--healthcheck-interval <interval>', 'Intervalo del health check', '5min')
|
|
112
|
+
.option('--user <user>', 'Usuario para ejecutar el servicio')
|
|
113
|
+
.option('--path <path>', 'Ruta del proyecto OpenFactu')
|
|
114
|
+
.action(async (opts) => {
|
|
115
|
+
console.log();
|
|
116
|
+
console.log(chalk_1.default.bold.white(' OpenFactu — Instalar Servicio'));
|
|
117
|
+
console.log(chalk_1.default.dim(' ────────────────────────────────────'));
|
|
118
|
+
console.log();
|
|
119
|
+
if (!(0, helpers_1.isSystemdAvailable)()) {
|
|
120
|
+
logger_1.log.error('systemd no esta disponible en este sistema');
|
|
121
|
+
logger_1.log.dim(' Este comando solo funciona en Linux con systemd');
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
125
|
+
const root = opts.path || (0, paths_1.getProjectRoot)();
|
|
126
|
+
const serviceName = getServiceName(opts.name);
|
|
127
|
+
// Detectar compose files
|
|
128
|
+
const composeFiles = [];
|
|
129
|
+
const possibleFiles = [
|
|
130
|
+
'docker-compose.prod.yml',
|
|
131
|
+
'docker-compose.yml',
|
|
132
|
+
];
|
|
133
|
+
for (const f of possibleFiles) {
|
|
134
|
+
if (fs_1.default.existsSync(path_1.default.join(root, f))) {
|
|
135
|
+
composeFiles.push(f);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (composeFiles.length === 0) {
|
|
139
|
+
logger_1.log.error('No se encontro docker-compose.yml en el proyecto');
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const mainCompose = composeFiles[0];
|
|
143
|
+
// Monitoring
|
|
144
|
+
let includeMonitoring = opts.withMonitoring || false;
|
|
145
|
+
let monitoringCompose;
|
|
146
|
+
if (!includeMonitoring) {
|
|
147
|
+
const { addMonitoring } = await inquirer_1.default.prompt([
|
|
148
|
+
{
|
|
149
|
+
type: 'confirm',
|
|
150
|
+
name: 'addMonitoring',
|
|
151
|
+
message: 'Incluir stack de monitoreo en el servicio?',
|
|
152
|
+
default: false,
|
|
153
|
+
},
|
|
154
|
+
]);
|
|
155
|
+
includeMonitoring = addMonitoring;
|
|
156
|
+
}
|
|
157
|
+
if (includeMonitoring) {
|
|
158
|
+
const monFiles = [
|
|
159
|
+
'docker-compose.prod.monitoring.yml',
|
|
160
|
+
'docker-compose.monitoring.yml',
|
|
161
|
+
];
|
|
162
|
+
for (const f of monFiles) {
|
|
163
|
+
if (fs_1.default.existsSync(path_1.default.join(root, f))) {
|
|
164
|
+
monitoringCompose = f;
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (!monitoringCompose) {
|
|
169
|
+
logger_1.log.warn('No se encontro compose de monitoreo, se omitira');
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// Confirmar configuracion
|
|
173
|
+
logger_1.log.blank();
|
|
174
|
+
logger_1.log.info(`${chalk_1.default.dim('Servicio:')} ${chalk_1.default.cyan(serviceName)}`);
|
|
175
|
+
logger_1.log.info(`${chalk_1.default.dim('Directorio:')} ${chalk_1.default.cyan(root)}`);
|
|
176
|
+
logger_1.log.info(`${chalk_1.default.dim('Compose:')} ${chalk_1.default.cyan(mainCompose)}`);
|
|
177
|
+
logger_1.log.info(`${chalk_1.default.dim('Reinicio:')} ${chalk_1.default.cyan(opts.restart)}`);
|
|
178
|
+
logger_1.log.blank();
|
|
179
|
+
const { confirm } = await inquirer_1.default.prompt([
|
|
180
|
+
{ type: 'confirm', name: 'confirm', message: 'Instalar servicio?', default: true },
|
|
181
|
+
]);
|
|
182
|
+
if (!confirm)
|
|
183
|
+
return;
|
|
184
|
+
// Generar unit file
|
|
185
|
+
const spinner = (0, ora_1.default)('Generando unit file...').start();
|
|
186
|
+
const unitContent = generateUnitFile(serviceName, root, mainCompose, {
|
|
187
|
+
restartPolicy: opts.restart,
|
|
188
|
+
includeMonitoring: includeMonitoring && !!monitoringCompose,
|
|
189
|
+
monitoringComposeFile: monitoringCompose,
|
|
190
|
+
user: opts.user,
|
|
191
|
+
});
|
|
192
|
+
const unitPath = `/etc/systemd/system/${serviceName}.service`;
|
|
193
|
+
const tempPath = `/tmp/${serviceName}.service`;
|
|
194
|
+
fs_1.default.writeFileSync(tempPath, unitContent);
|
|
195
|
+
// Instalar con sudo
|
|
196
|
+
(0, child_process_1.execSync)(`sudo mv ${tempPath} ${unitPath}`, { stdio: 'pipe' });
|
|
197
|
+
(0, child_process_1.execSync)('sudo systemctl daemon-reload', { stdio: 'pipe' });
|
|
198
|
+
spinner.succeed('Unit file instalado');
|
|
199
|
+
// Health check opcional
|
|
200
|
+
if (opts.healthcheck) {
|
|
201
|
+
const hcSpinner = (0, ora_1.default)('Configurando health check...').start();
|
|
202
|
+
const scriptPath = path_1.default.join(root, '.openfactu-healthcheck.sh');
|
|
203
|
+
fs_1.default.mkdirSync(path_1.default.join(root), { recursive: true });
|
|
204
|
+
fs_1.default.writeFileSync(scriptPath, generateHealthCheckScript(root));
|
|
205
|
+
(0, child_process_1.execSync)(`chmod +x "${scriptPath}"`, { stdio: 'pipe' });
|
|
206
|
+
const timerName = `${serviceName}-healthcheck`;
|
|
207
|
+
const timerContent = generateTimerFile(serviceName, opts.healthcheckInterval);
|
|
208
|
+
const timerPath = `/etc/systemd/system/${timerName}.timer`;
|
|
209
|
+
const serviceContent = `[Unit]
|
|
210
|
+
Description=OpenFactu Health Check
|
|
211
|
+
|
|
212
|
+
[Service]
|
|
213
|
+
Type=oneshot
|
|
214
|
+
ExecStart=${scriptPath}
|
|
215
|
+
`;
|
|
216
|
+
const servicePath = `/etc/systemd/system/${timerName}.service`;
|
|
217
|
+
fs_1.default.writeFileSync(`/tmp/${timerName}.timer`, timerContent);
|
|
218
|
+
fs_1.default.writeFileSync(`/tmp/${timerName}.service`, serviceContent);
|
|
219
|
+
(0, child_process_1.execSync)(`sudo mv /tmp/${timerName}.timer ${timerPath}`, { stdio: 'pipe' });
|
|
220
|
+
(0, child_process_1.execSync)(`sudo mv /tmp/${timerName}.service ${servicePath}`, { stdio: 'pipe' });
|
|
221
|
+
(0, child_process_1.execSync)('sudo systemctl daemon-reload', { stdio: 'pipe' });
|
|
222
|
+
(0, child_process_1.execSync)(`sudo systemctl enable ${timerName}.timer`, { stdio: 'pipe' });
|
|
223
|
+
hcSpinner.succeed('Health check configurado');
|
|
224
|
+
}
|
|
225
|
+
// Enable service
|
|
226
|
+
const enableSpinner = (0, ora_1.default)('Habilitando servicio...').start();
|
|
227
|
+
(0, child_process_1.execSync)(`sudo systemctl enable ${serviceName}`, { stdio: 'pipe' });
|
|
228
|
+
enableSpinner.succeed('Servicio habilitado');
|
|
229
|
+
logger_1.log.blank();
|
|
230
|
+
console.log(chalk_1.default.bold.green(' Servicio instalado'));
|
|
231
|
+
console.log(chalk_1.default.dim(' ────────────────────────────────────'));
|
|
232
|
+
logger_1.log.blank();
|
|
233
|
+
logger_1.log.dim(' Comandos utiles:');
|
|
234
|
+
logger_1.log.dim(` sudo systemctl start ${serviceName}`);
|
|
235
|
+
logger_1.log.dim(` sudo systemctl stop ${serviceName}`);
|
|
236
|
+
logger_1.log.dim(` sudo systemctl restart ${serviceName}`);
|
|
237
|
+
logger_1.log.dim(` sudo systemctl status ${serviceName}`);
|
|
238
|
+
logger_1.log.dim(` journalctl -u ${serviceName} -f`);
|
|
239
|
+
logger_1.log.blank();
|
|
240
|
+
const { startNow } = await inquirer_1.default.prompt([
|
|
241
|
+
{ type: 'confirm', name: 'startNow', message: 'Iniciar servicio ahora?', default: true },
|
|
242
|
+
]);
|
|
243
|
+
if (startNow) {
|
|
244
|
+
const startSpinner = (0, ora_1.default)('Iniciando servicio...').start();
|
|
245
|
+
try {
|
|
246
|
+
(0, child_process_1.execSync)(`sudo systemctl start ${serviceName}`, { stdio: 'pipe' });
|
|
247
|
+
startSpinner.succeed('Servicio iniciado');
|
|
248
|
+
}
|
|
249
|
+
catch (err) {
|
|
250
|
+
startSpinner.fail('Error al iniciar');
|
|
251
|
+
logger_1.log.dim(` sudo systemctl status ${serviceName}`);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
catch (err) {
|
|
256
|
+
logger_1.log.error(err.message);
|
|
257
|
+
process.exitCode = 1;
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
serviceCmd
|
|
261
|
+
.command('status')
|
|
262
|
+
.description('Ver estado del servicio')
|
|
263
|
+
.option('--name <name>', 'Nombre del servicio', 'openfactu')
|
|
264
|
+
.action(async (opts) => {
|
|
265
|
+
try {
|
|
266
|
+
const serviceName = getServiceName(opts.name);
|
|
267
|
+
const output = (0, child_process_1.execSync)(`systemctl status ${serviceName} 2>&1 || true`, { stdio: 'pipe' }).toString();
|
|
268
|
+
console.log(output);
|
|
269
|
+
}
|
|
270
|
+
catch (err) {
|
|
271
|
+
logger_1.log.error(err.message);
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
serviceCmd
|
|
275
|
+
.command('start')
|
|
276
|
+
.description('Iniciar servicio')
|
|
277
|
+
.option('--name <name>', 'Nombre del servicio', 'openfactu')
|
|
278
|
+
.action(async (opts) => {
|
|
279
|
+
try {
|
|
280
|
+
const serviceName = getServiceName(opts.name);
|
|
281
|
+
const spinner = (0, ora_1.default)('Iniciando servicio...').start();
|
|
282
|
+
(0, child_process_1.execSync)(`sudo systemctl start ${serviceName}`, { stdio: 'pipe' });
|
|
283
|
+
spinner.succeed('Servicio iniciado');
|
|
284
|
+
}
|
|
285
|
+
catch (err) {
|
|
286
|
+
logger_1.log.error(err.message);
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
serviceCmd
|
|
290
|
+
.command('stop')
|
|
291
|
+
.description('Detener servicio')
|
|
292
|
+
.option('--name <name>', 'Nombre del servicio', 'openfactu')
|
|
293
|
+
.action(async (opts) => {
|
|
294
|
+
try {
|
|
295
|
+
const serviceName = getServiceName(opts.name);
|
|
296
|
+
const spinner = (0, ora_1.default)('Deteniendo servicio...').start();
|
|
297
|
+
(0, child_process_1.execSync)(`sudo systemctl stop ${serviceName}`, { stdio: 'pipe' });
|
|
298
|
+
spinner.succeed('Servicio detenido');
|
|
299
|
+
}
|
|
300
|
+
catch (err) {
|
|
301
|
+
logger_1.log.error(err.message);
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
serviceCmd
|
|
305
|
+
.command('restart')
|
|
306
|
+
.description('Reiniciar servicio')
|
|
307
|
+
.option('--name <name>', 'Nombre del servicio', 'openfactu')
|
|
308
|
+
.action(async (opts) => {
|
|
309
|
+
try {
|
|
310
|
+
const serviceName = getServiceName(opts.name);
|
|
311
|
+
const spinner = (0, ora_1.default)('Reiniciando servicio...').start();
|
|
312
|
+
(0, child_process_1.execSync)(`sudo systemctl restart ${serviceName}`, { stdio: 'pipe' });
|
|
313
|
+
spinner.succeed('Servicio reiniciado');
|
|
314
|
+
}
|
|
315
|
+
catch (err) {
|
|
316
|
+
logger_1.log.error(err.message);
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
serviceCmd
|
|
320
|
+
.command('uninstall')
|
|
321
|
+
.description('Remover servicio systemd')
|
|
322
|
+
.option('--name <name>', 'Nombre del servicio', 'openfactu')
|
|
323
|
+
.option('--keep-data', 'Mantener datos del proyecto')
|
|
324
|
+
.action(async (opts) => {
|
|
325
|
+
console.log();
|
|
326
|
+
console.log(chalk_1.default.bold.white(' OpenFactu — Remover Servicio'));
|
|
327
|
+
console.log(chalk_1.default.dim(' ────────────────────────────────────'));
|
|
328
|
+
console.log();
|
|
329
|
+
try {
|
|
330
|
+
const serviceName = getServiceName(opts.name);
|
|
331
|
+
const { confirm } = await inquirer_1.default.prompt([
|
|
332
|
+
{
|
|
333
|
+
type: 'confirm',
|
|
334
|
+
name: 'confirm',
|
|
335
|
+
message: `Remover servicio ${serviceName}?`,
|
|
336
|
+
default: false,
|
|
337
|
+
},
|
|
338
|
+
]);
|
|
339
|
+
if (!confirm)
|
|
340
|
+
return;
|
|
341
|
+
const spinner = (0, ora_1.default)('Removiendo servicio...').start();
|
|
342
|
+
(0, child_process_1.execSync)(`sudo systemctl stop ${serviceName} 2>/dev/null || true`, { stdio: 'pipe' });
|
|
343
|
+
(0, child_process_1.execSync)(`sudo systemctl disable ${serviceName} 2>/dev/null || true`, { stdio: 'pipe' });
|
|
344
|
+
const unitPath = `/etc/systemd/system/${serviceName}.service`;
|
|
345
|
+
if (fs_1.default.existsSync(unitPath)) {
|
|
346
|
+
(0, child_process_1.execSync)(`sudo rm ${unitPath}`, { stdio: 'pipe' });
|
|
347
|
+
}
|
|
348
|
+
// Remover health check si existe
|
|
349
|
+
const timerName = `${serviceName}-healthcheck`;
|
|
350
|
+
const timerPath = `/etc/systemd/system/${timerName}.timer`;
|
|
351
|
+
const hcServicePath = `/etc/systemd/system/${timerName}.service`;
|
|
352
|
+
if (fs_1.default.existsSync(timerPath))
|
|
353
|
+
(0, child_process_1.execSync)(`sudo rm ${timerPath}`, { stdio: 'pipe' });
|
|
354
|
+
if (fs_1.default.existsSync(hcServicePath))
|
|
355
|
+
(0, child_process_1.execSync)(`sudo rm ${hcServicePath}`, { stdio: 'pipe' });
|
|
356
|
+
(0, child_process_1.execSync)('sudo systemctl daemon-reload', { stdio: 'pipe' });
|
|
357
|
+
spinner.succeed('Servicio removido');
|
|
358
|
+
if (!opts.keepData) {
|
|
359
|
+
const { removeData } = await inquirer_1.default.prompt([
|
|
360
|
+
{
|
|
361
|
+
type: 'confirm',
|
|
362
|
+
name: 'removeData',
|
|
363
|
+
message: 'Remover tambien los contenedores Docker?',
|
|
364
|
+
default: false,
|
|
365
|
+
},
|
|
366
|
+
]);
|
|
367
|
+
if (removeData) {
|
|
368
|
+
try {
|
|
369
|
+
const root = (0, paths_1.getProjectRoot)();
|
|
370
|
+
const dockerCmd = (0, helpers_1.getDockerComposeCommand)();
|
|
371
|
+
(0, child_process_1.execSync)(`${dockerCmd} down`, { cwd: root, stdio: 'pipe' });
|
|
372
|
+
logger_1.log.success('Contenedores removidos');
|
|
373
|
+
}
|
|
374
|
+
catch {
|
|
375
|
+
logger_1.log.warn('No se pudieron remover los contenedores');
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
catch (err) {
|
|
381
|
+
logger_1.log.error(err.message);
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
serviceCmd
|
|
385
|
+
.command('logs')
|
|
386
|
+
.description('Ver logs del servicio')
|
|
387
|
+
.option('--name <name>', 'Nombre del servicio', 'openfactu')
|
|
388
|
+
.option('-f, --follow', 'Seguir logs en tiempo real')
|
|
389
|
+
.option('-n, --lines <number>', 'Numero de lineas', '100')
|
|
390
|
+
.action(async (opts) => {
|
|
391
|
+
try {
|
|
392
|
+
const serviceName = getServiceName(opts.name);
|
|
393
|
+
const follow = opts.follow ? ' -f' : '';
|
|
394
|
+
(0, child_process_1.execSync)(`journalctl -u ${serviceName}${follow} -n ${opts.lines}`, {
|
|
395
|
+
stdio: 'inherit',
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
catch (err) {
|
|
399
|
+
logger_1.log.error(err.message);
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
}
|
|
@@ -8,7 +8,6 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
8
8
|
const ora_1 = __importDefault(require("ora"));
|
|
9
9
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
10
10
|
const crypto_1 = __importDefault(require("crypto"));
|
|
11
|
-
const bcrypt_1 = __importDefault(require("bcrypt"));
|
|
12
11
|
const db_1 = require("../utils/db");
|
|
13
12
|
const logger_1 = require("../utils/logger");
|
|
14
13
|
function registerSetupCommand(program) {
|
|
@@ -66,7 +65,13 @@ function registerSetupCommand(program) {
|
|
|
66
65
|
mask: '*',
|
|
67
66
|
},
|
|
68
67
|
]);
|
|
69
|
-
const hashedPassword = await
|
|
68
|
+
const hashedPassword = await new Promise((resolve, reject) => {
|
|
69
|
+
crypto_1.default.scrypt(adminPassword, 'openfactu-salt', 64, (err, derivedKey) => {
|
|
70
|
+
if (err)
|
|
71
|
+
reject(err);
|
|
72
|
+
resolve(derivedKey.toString('hex'));
|
|
73
|
+
});
|
|
74
|
+
});
|
|
70
75
|
await publicDb.insert((0, db_1.schema)().globalUsers).values({
|
|
71
76
|
id: crypto_1.default.randomUUID(),
|
|
72
77
|
email: 'admin@openfactu.com',
|