@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,474 @@
|
|
|
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.registerInstallScriptCommand = registerInstallScriptCommand;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const ora_1 = __importDefault(require("ora"));
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const logger_1 = require("../utils/logger");
|
|
11
|
+
const REPO_URL = 'https://github.com/OpenFactu/platform.git';
|
|
12
|
+
function registerInstallScriptCommand(program) {
|
|
13
|
+
program
|
|
14
|
+
.command('install:script')
|
|
15
|
+
.description('Generar script de instalacion standalone (sin CLI)')
|
|
16
|
+
.option('-o, --output <file>', 'Archivo de salida', './install-openfactu.sh')
|
|
17
|
+
.option('--tag <tag>', 'Version fija en el script')
|
|
18
|
+
.option('--dir <dir>', 'Directorio por defecto')
|
|
19
|
+
.option('-m, --monitoring', 'Incluir opcion de monitoreo en el script')
|
|
20
|
+
.option('-s, --service', 'Incluir opcion de servicio systemd en el script')
|
|
21
|
+
.action(async (opts) => {
|
|
22
|
+
console.log();
|
|
23
|
+
console.log(chalk_1.default.bold.white(' OpenFactu — Generar Script de Instalacion'));
|
|
24
|
+
console.log(chalk_1.default.dim(' ────────────────────────────────────'));
|
|
25
|
+
console.log();
|
|
26
|
+
try {
|
|
27
|
+
const tag = opts.tag || '${TAG:-latest}';
|
|
28
|
+
const defaultDir = opts.dir || '$HOME/openfactu';
|
|
29
|
+
const includeMonitoring = opts.monitoring || false;
|
|
30
|
+
const includeService = opts.service || false;
|
|
31
|
+
if (!opts.output.includes('.sh')) {
|
|
32
|
+
opts.output += '.sh';
|
|
33
|
+
}
|
|
34
|
+
const script = generateInstallScript({
|
|
35
|
+
repoUrl: REPO_URL,
|
|
36
|
+
tag,
|
|
37
|
+
defaultDir,
|
|
38
|
+
includeMonitoring,
|
|
39
|
+
includeService,
|
|
40
|
+
});
|
|
41
|
+
const spinner = (0, ora_1.default)('Generando script...').start();
|
|
42
|
+
fs_1.default.writeFileSync(opts.output, script);
|
|
43
|
+
fs_1.default.chmodSync(opts.output, 0o755);
|
|
44
|
+
spinner.succeed(`Script generado: ${chalk_1.default.cyan(opts.output)}`);
|
|
45
|
+
const fileSize = fs_1.default.statSync(opts.output).size;
|
|
46
|
+
logger_1.log.info(`Tamano: ${(fileSize / 1024).toFixed(1)}KB`);
|
|
47
|
+
logger_1.log.blank();
|
|
48
|
+
logger_1.log.dim(' Para usar el script:');
|
|
49
|
+
logger_1.log.dim(` chmod +x ${opts.output}`);
|
|
50
|
+
logger_1.log.dim(` ./${opts.output}`);
|
|
51
|
+
logger_1.log.blank();
|
|
52
|
+
logger_1.log.dim(' O remotamente:');
|
|
53
|
+
logger_1.log.dim(` curl -sL <url> | bash`);
|
|
54
|
+
logger_1.log.blank();
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
logger_1.log.error(err.message);
|
|
58
|
+
process.exitCode = 1;
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
function generateInstallScript(options) {
|
|
63
|
+
const { repoUrl, tag, defaultDir, includeMonitoring, includeService } = options;
|
|
64
|
+
return `#!/bin/bash
|
|
65
|
+
# ============================================================
|
|
66
|
+
# OpenFactu - Script de Instalacion Automatica
|
|
67
|
+
# Generado por @openfactu/cli
|
|
68
|
+
# ============================================================
|
|
69
|
+
|
|
70
|
+
set -e
|
|
71
|
+
|
|
72
|
+
# Colors
|
|
73
|
+
RED='\\033[0;31m'
|
|
74
|
+
GREEN='\\033[0;32m'
|
|
75
|
+
YELLOW='\\033[1;33m'
|
|
76
|
+
BLUE='\\033[0;34m'
|
|
77
|
+
NC='\\033[0m'
|
|
78
|
+
|
|
79
|
+
# Config
|
|
80
|
+
REPO_URL="${repoUrl}"
|
|
81
|
+
TAG="${tag}"
|
|
82
|
+
INSTALL_DIR="${defaultDir}"
|
|
83
|
+
MONITORING=false
|
|
84
|
+
SERVICE=false
|
|
85
|
+
SKIP_DOCKER=false
|
|
86
|
+
|
|
87
|
+
# ============================================================
|
|
88
|
+
# Functions
|
|
89
|
+
# ============================================================
|
|
90
|
+
|
|
91
|
+
log_info() {
|
|
92
|
+
echo -e "\${BLUE}[INFO]\${NC} $1"
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
log_success() {
|
|
96
|
+
echo -e "\${GREEN}[OK]\${NC} $1"
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
log_warn() {
|
|
100
|
+
echo -e "\${YELLOW}[WARN]\${NC} $1"
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
log_error() {
|
|
104
|
+
echo -e "\${RED}[ERROR]\${NC} $1"
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
check_command() {
|
|
108
|
+
if ! command -v $1 &> /dev/null; then
|
|
109
|
+
return 1
|
|
110
|
+
fi
|
|
111
|
+
return 0
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
generate_password() {
|
|
115
|
+
# Solo alfanumericos: '$' rompe la interpolacion del .env en Docker Compose
|
|
116
|
+
# y '@ # % /' rompen el DATABASE_URL. Ver generatePassword() en la CLI.
|
|
117
|
+
openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | head -c 24
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
# ============================================================
|
|
121
|
+
# Banner
|
|
122
|
+
# ============================================================
|
|
123
|
+
|
|
124
|
+
echo ""
|
|
125
|
+
echo " ╔══════════════════════════════════════════╗"
|
|
126
|
+
echo " ║ OpenFactu - Instalador Automatico ║"
|
|
127
|
+
echo " ╚══════════════════════════════════════════╝"
|
|
128
|
+
echo ""
|
|
129
|
+
|
|
130
|
+
# ============================================================
|
|
131
|
+
# Parse arguments
|
|
132
|
+
# ============================================================
|
|
133
|
+
|
|
134
|
+
while [[ $# -gt 0 ]]; do
|
|
135
|
+
case $1 in
|
|
136
|
+
--tag)
|
|
137
|
+
TAG="$2"
|
|
138
|
+
shift 2
|
|
139
|
+
;;
|
|
140
|
+
--dir)
|
|
141
|
+
INSTALL_DIR="$2"
|
|
142
|
+
shift 2
|
|
143
|
+
;;
|
|
144
|
+
--monitoring)
|
|
145
|
+
MONITORING=true
|
|
146
|
+
shift
|
|
147
|
+
;;
|
|
148
|
+
--service)
|
|
149
|
+
SERVICE=true
|
|
150
|
+
shift
|
|
151
|
+
;;
|
|
152
|
+
--skip-docker)
|
|
153
|
+
SKIP_DOCKER=true
|
|
154
|
+
shift
|
|
155
|
+
;;
|
|
156
|
+
--help|-h)
|
|
157
|
+
echo "Uso: $0 [opciones]"
|
|
158
|
+
echo ""
|
|
159
|
+
echo "Opciones:"
|
|
160
|
+
echo " --tag <version> Version a instalar (default: latest)"
|
|
161
|
+
echo " --dir <ruta> Directorio de instalacion"
|
|
162
|
+
echo " --monitoring Incluir stack de monitoreo"
|
|
163
|
+
echo " --service Instalar como servicio systemd"
|
|
164
|
+
echo " --skip-docker Solo descargar, no usar Docker"
|
|
165
|
+
echo " --help, -h Mostrar esta ayuda"
|
|
166
|
+
exit 0
|
|
167
|
+
;;
|
|
168
|
+
*)
|
|
169
|
+
log_error "Opcion desconocida: $1"
|
|
170
|
+
exit 1
|
|
171
|
+
;;
|
|
172
|
+
esac
|
|
173
|
+
done
|
|
174
|
+
|
|
175
|
+
# ============================================================
|
|
176
|
+
# Pre-flight checks
|
|
177
|
+
# ============================================================
|
|
178
|
+
|
|
179
|
+
log_info "Verificando requisitos..."
|
|
180
|
+
|
|
181
|
+
# Check OS
|
|
182
|
+
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
|
183
|
+
log_success "Sistema: Linux"
|
|
184
|
+
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
|
185
|
+
log_success "Sistema: macOS"
|
|
186
|
+
else
|
|
187
|
+
log_warn "Sistema no verificado: $OSTYPE"
|
|
188
|
+
fi
|
|
189
|
+
|
|
190
|
+
# Check Git
|
|
191
|
+
if check_command git; then
|
|
192
|
+
log_success "Git: $(git --version)"
|
|
193
|
+
else
|
|
194
|
+
log_error "Git no esta instalado"
|
|
195
|
+
log_info "Instala Git: https://git-scm.com/downloads"
|
|
196
|
+
exit 1
|
|
197
|
+
fi
|
|
198
|
+
|
|
199
|
+
# Check Docker
|
|
200
|
+
if check_command docker; then
|
|
201
|
+
log_success "Docker: $(docker --version)"
|
|
202
|
+
if docker compose version &> /dev/null || docker-compose --version &> /dev/null; then
|
|
203
|
+
log_success "Docker Compose: disponible"
|
|
204
|
+
else
|
|
205
|
+
log_error "Docker Compose no esta instalado"
|
|
206
|
+
exit 1
|
|
207
|
+
fi
|
|
208
|
+
else
|
|
209
|
+
if [ "$SKIP_DOCKER" = false ]; then
|
|
210
|
+
log_warn "Docker no esta instalado"
|
|
211
|
+
log_info "Instala Docker: https://docs.docker.com/get-docker/"
|
|
212
|
+
log_info "Usa --skip-docker para solo descargar el codigo"
|
|
213
|
+
exit 1
|
|
214
|
+
fi
|
|
215
|
+
fi
|
|
216
|
+
|
|
217
|
+
# Check disk space
|
|
218
|
+
AVAILABLE_GB=$(df -BG "$HOME" | tail -1 | awk '{print $4}' | tr -d 'G')
|
|
219
|
+
if [ "$AVAILABLE_GB" -lt 5 ]; then
|
|
220
|
+
log_error "Espacio insuficiente: \${AVAILABLE_GB}GB disponibles (minimo 5GB)"
|
|
221
|
+
exit 1
|
|
222
|
+
fi
|
|
223
|
+
log_success "Espacio en disco: \${AVAILABLE_GB}GB disponibles"
|
|
224
|
+
|
|
225
|
+
echo ""
|
|
226
|
+
|
|
227
|
+
# ============================================================
|
|
228
|
+
# Interactive prompts (if not all options provided)
|
|
229
|
+
# ============================================================
|
|
230
|
+
|
|
231
|
+
if [ "$TAG" = "\${TAG:-latest}" ]; then
|
|
232
|
+
read -p "Version a instalar (dejar vacio para latest): " USER_TAG
|
|
233
|
+
if [ -n "$USER_TAG" ]; then
|
|
234
|
+
TAG="$USER_TAG"
|
|
235
|
+
fi
|
|
236
|
+
fi
|
|
237
|
+
|
|
238
|
+
read -p "Directorio de instalacion [$INSTALL_DIR]: " USER_DIR
|
|
239
|
+
if [ -n "$USER_DIR" ]; then
|
|
240
|
+
INSTALL_DIR="$USER_DIR"
|
|
241
|
+
fi
|
|
242
|
+
|
|
243
|
+
if [ "$SKIP_DOCKER" = false ]; then
|
|
244
|
+
if [ "$MONITORING" = false ]; then
|
|
245
|
+
read -p "Incluir stack de monitoreo (Grafana, Prometheus)? [y/N]: " MON_ANSWER
|
|
246
|
+
if [[ "$MON_ANSWER" =~ ^[Yy]$ ]]; then
|
|
247
|
+
MONITORING=true
|
|
248
|
+
fi
|
|
249
|
+
fi
|
|
250
|
+
|
|
251
|
+
${includeService ? ` if [ "$SERVICE" = false ]; then
|
|
252
|
+
read -p "Instalar como servicio systemd (auto-start)? [y/N]: " SVC_ANSWER
|
|
253
|
+
if [[ "$SVC_ANSWER" =~ ^[Yy]$ ]]; then
|
|
254
|
+
SERVICE=true
|
|
255
|
+
fi
|
|
256
|
+
fi` : ''}
|
|
257
|
+
fi
|
|
258
|
+
|
|
259
|
+
echo ""
|
|
260
|
+
|
|
261
|
+
# ============================================================
|
|
262
|
+
# Resolve tag
|
|
263
|
+
# ============================================================
|
|
264
|
+
|
|
265
|
+
if [ "$TAG" = "latest" ]; then
|
|
266
|
+
log_info "Obteniendo ultima version..."
|
|
267
|
+
LATEST=$(curl -s https://api.github.com/repos/OpenFactu/platform/releases | grep -m1 '"tag_name"' | cut -d'"' -f4)
|
|
268
|
+
if [ -n "$LATEST" ]; then
|
|
269
|
+
TAG="$LATEST"
|
|
270
|
+
log_success "Version seleccionada: $TAG"
|
|
271
|
+
else
|
|
272
|
+
TAG="main"
|
|
273
|
+
log_warn "No se pudo obtener la ultima version, usando main"
|
|
274
|
+
fi
|
|
275
|
+
fi
|
|
276
|
+
|
|
277
|
+
# ============================================================
|
|
278
|
+
# Clone repository
|
|
279
|
+
# ============================================================
|
|
280
|
+
|
|
281
|
+
log_info "Descargando OpenFactu..."
|
|
282
|
+
|
|
283
|
+
if [ -d "$INSTALL_DIR" ]; then
|
|
284
|
+
if [ "$(ls -A $INSTALL_DIR)" ]; then
|
|
285
|
+
log_warn "El directorio $INSTALL_DIR no esta vacio"
|
|
286
|
+
read -p "Continuar? [y/N]: " OVERWRITE
|
|
287
|
+
if [[ ! "$OVERWRITE" =~ ^[Yy]$ ]]; then
|
|
288
|
+
log_info "Instalacion cancelada"
|
|
289
|
+
exit 0
|
|
290
|
+
fi
|
|
291
|
+
fi
|
|
292
|
+
else
|
|
293
|
+
mkdir -p "$INSTALL_DIR"
|
|
294
|
+
fi
|
|
295
|
+
|
|
296
|
+
IS_TAG=false
|
|
297
|
+
if [[ "$TAG" == v* ]]; then
|
|
298
|
+
IS_TAG=true
|
|
299
|
+
fi
|
|
300
|
+
|
|
301
|
+
if [ "$IS_TAG" = true ]; then
|
|
302
|
+
git clone --depth 1 --branch "$TAG" "$REPO_URL" "$INSTALL_DIR" 2>/dev/null || {
|
|
303
|
+
log_warn "Clon por tag fallo, intentando metodo alternativo..."
|
|
304
|
+
git clone "$REPO_URL" "$INSTALL_DIR"
|
|
305
|
+
cd "$INSTALL_DIR"
|
|
306
|
+
git checkout "$TAG"
|
|
307
|
+
}
|
|
308
|
+
else
|
|
309
|
+
git clone --branch "$TAG" "$REPO_URL" "$INSTALL_DIR" 2>/dev/null || {
|
|
310
|
+
git clone "$REPO_URL" "$INSTALL_DIR"
|
|
311
|
+
cd "$INSTALL_DIR"
|
|
312
|
+
git checkout "$TAG"
|
|
313
|
+
}
|
|
314
|
+
fi
|
|
315
|
+
|
|
316
|
+
log_success "Codigo descargado en $INSTALL_DIR"
|
|
317
|
+
|
|
318
|
+
# ============================================================
|
|
319
|
+
# Generate .env
|
|
320
|
+
# ============================================================
|
|
321
|
+
|
|
322
|
+
log_info "Generando configuracion..."
|
|
323
|
+
|
|
324
|
+
cd "$INSTALL_DIR"
|
|
325
|
+
|
|
326
|
+
if [ -f ".env.example" ] && [ ! -f ".env" ]; then
|
|
327
|
+
cp .env.example .env
|
|
328
|
+
fi
|
|
329
|
+
|
|
330
|
+
DB_PASSWORD=$(generate_password)
|
|
331
|
+
JWT_SECRET=$(generate_password)
|
|
332
|
+
ADMIN_PASSWORD=$(generate_password)
|
|
333
|
+
|
|
334
|
+
cat >> .env << EOF
|
|
335
|
+
|
|
336
|
+
# Generated by installer
|
|
337
|
+
POSTGRES_USER=openfactu
|
|
338
|
+
POSTGRES_PASSWORD=$DB_PASSWORD
|
|
339
|
+
POSTGRES_DB=openfactudb
|
|
340
|
+
DATABASE_URL=postgresql://openfactu:$DB_PASSWORD@db:5432/openfactudb
|
|
341
|
+
JWT_SECRET=$JWT_SECRET
|
|
342
|
+
SESSION_SECRET=$(generate_password)
|
|
343
|
+
NODE_ENV=production
|
|
344
|
+
HOST=localhost
|
|
345
|
+
CORS_ORIGIN=http://localhost:8080
|
|
346
|
+
VITE_API_URL=http://localhost:3000
|
|
347
|
+
ADMIN_EMAIL=admin@openfactu.local
|
|
348
|
+
ADMIN_PASSWORD=$ADMIN_PASSWORD
|
|
349
|
+
EOF
|
|
350
|
+
|
|
351
|
+
log_success "Configuracion generada"
|
|
352
|
+
echo ""
|
|
353
|
+
log_warn "Guarda estas credenciales:"
|
|
354
|
+
echo " DB Password: $DB_PASSWORD"
|
|
355
|
+
echo " Admin: admin@openfactu.local / $ADMIN_PASSWORD"
|
|
356
|
+
echo ""
|
|
357
|
+
|
|
358
|
+
# ============================================================
|
|
359
|
+
# Docker setup
|
|
360
|
+
# ============================================================
|
|
361
|
+
|
|
362
|
+
if [ "$SKIP_DOCKER" = false ]; then
|
|
363
|
+
log_info "Construyendo contenedores Docker..."
|
|
364
|
+
|
|
365
|
+
if command -v docker &> /dev/null && (docker compose version &> /dev/null || docker-compose --version &> /dev/null); then
|
|
366
|
+
DOCKER_CMD="docker compose"
|
|
367
|
+
if ! docker compose version &> /dev/null; then
|
|
368
|
+
DOCKER_CMD="docker-compose"
|
|
369
|
+
fi
|
|
370
|
+
|
|
371
|
+
# Build
|
|
372
|
+
$DOCKER_CMD build || {
|
|
373
|
+
log_warn "Build fallo, puedes ejecutarlo manualmente despues"
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
# Up
|
|
377
|
+
COMPOSE_FLAGS="-f docker-compose.yml"
|
|
378
|
+
if [ -f "docker-compose.prod.yml" ]; then
|
|
379
|
+
COMPOSE_FLAGS="-f docker-compose.prod.yml"
|
|
380
|
+
fi
|
|
381
|
+
|
|
382
|
+
if [ "$MONITORING" = true ] && [ -f "docker-compose.monitoring.yml" ]; then
|
|
383
|
+
COMPOSE_FLAGS="$COMPOSE_FLAGS -f docker-compose.monitoring.yml"
|
|
384
|
+
fi
|
|
385
|
+
|
|
386
|
+
log_info "Levantando servicios..."
|
|
387
|
+
$DOCKER_CMD $COMPOSE_FLAGS up -d
|
|
388
|
+
|
|
389
|
+
log_success "Servicios levantados"
|
|
390
|
+
|
|
391
|
+
# Wait for services
|
|
392
|
+
log_info "Esperando que los servicios inicien..."
|
|
393
|
+
sleep 10
|
|
394
|
+
|
|
395
|
+
# Health check
|
|
396
|
+
if curl -s http://localhost:3000/api/health &> /dev/null; then
|
|
397
|
+
log_success "API esta operativa"
|
|
398
|
+
else
|
|
399
|
+
log_warn "API aun no responde, puede tardar unos segundos"
|
|
400
|
+
fi
|
|
401
|
+
else
|
|
402
|
+
log_error "Docker no disponible"
|
|
403
|
+
fi
|
|
404
|
+
fi
|
|
405
|
+
|
|
406
|
+
# ============================================================
|
|
407
|
+
# Install systemd service
|
|
408
|
+
# ============================================================
|
|
409
|
+
|
|
410
|
+
${includeService ? `if [ "$SERVICE" = true ]; then
|
|
411
|
+
if [ -d "/run/systemd/system" ]; then
|
|
412
|
+
log_info "Instalando servicio systemd..."
|
|
413
|
+
|
|
414
|
+
DOCKER_CMD="docker compose"
|
|
415
|
+
if ! docker compose version &> /dev/null; then
|
|
416
|
+
DOCKER_CMD="docker-compose"
|
|
417
|
+
fi
|
|
418
|
+
|
|
419
|
+
cat > /tmp/openfactu.service << SVCEOF
|
|
420
|
+
[Unit]
|
|
421
|
+
Description=OpenFactu ERP Platform
|
|
422
|
+
After=docker.service network-online.target
|
|
423
|
+
Requires=docker.service
|
|
424
|
+
|
|
425
|
+
[Service]
|
|
426
|
+
Type=oneshot
|
|
427
|
+
RemainAfterExit=yes
|
|
428
|
+
WorkingDirectory=$INSTALL_DIR
|
|
429
|
+
ExecStart=$DOCKER_CMD -f docker-compose.yml up -d
|
|
430
|
+
ExecStop=$DOCKER_CMD -f docker-compose.yml down
|
|
431
|
+
Restart=on-failure
|
|
432
|
+
RestartSec=30
|
|
433
|
+
|
|
434
|
+
[Install]
|
|
435
|
+
WantedBy=multi-user.target
|
|
436
|
+
SVCEOF
|
|
437
|
+
|
|
438
|
+
sudo mv /tmp/openfactu.service /etc/systemd/system/openfactu.service
|
|
439
|
+
sudo systemctl daemon-reload
|
|
440
|
+
sudo systemctl enable openfactu
|
|
441
|
+
|
|
442
|
+
log_success "Servicio systemd instalado"
|
|
443
|
+
log_info "Iniciar con: sudo systemctl start openfactu"
|
|
444
|
+
else
|
|
445
|
+
log_warn "systemd no disponible, omitiendo servicio"
|
|
446
|
+
fi
|
|
447
|
+
fi` : ''}
|
|
448
|
+
|
|
449
|
+
# ============================================================
|
|
450
|
+
# Summary
|
|
451
|
+
# ============================================================
|
|
452
|
+
|
|
453
|
+
echo ""
|
|
454
|
+
echo " ╔══════════════════════════════════════════╗"
|
|
455
|
+
echo " ║ Instalacion Completada! ║"
|
|
456
|
+
echo " ╚══════════════════════════════════════════╝"
|
|
457
|
+
echo ""
|
|
458
|
+
echo " Directorio: $INSTALL_DIR"
|
|
459
|
+
echo " Version: $TAG"
|
|
460
|
+
echo ""
|
|
461
|
+
echo " Proximos pasos:"
|
|
462
|
+
echo " cd $INSTALL_DIR"
|
|
463
|
+
echo " openfactu setup # Configurar base de datos"
|
|
464
|
+
echo " openfactu deploy # Configurar acceso externo"
|
|
465
|
+
echo " openfactu doctor # Verificar instalacion"
|
|
466
|
+
echo ""
|
|
467
|
+
if [ "$SKIP_DOCKER" = false ]; then
|
|
468
|
+
echo " URLs:"
|
|
469
|
+
echo " Web: http://localhost:8080"
|
|
470
|
+
echo " API: http://localhost:3000"
|
|
471
|
+
echo ""
|
|
472
|
+
fi
|
|
473
|
+
`;
|
|
474
|
+
}
|