cdd-cli 3.1.1 → 3.1.3
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/AUDIT_REPORT.md +1004 -0
- package/CHANGELOG.md +22 -0
- package/FIXES_APPLIED.md +421 -0
- package/dist/App.js +7 -9
- package/dist/components/ContainerCreationPrompt.js +1 -1
- package/dist/components/ContainerList.js +2 -4
- package/dist/components/ContainerRow.js +20 -14
- package/dist/components/ContainerSection.js +1 -1
- package/dist/helpers/actionHelpers.js +14 -1
- package/dist/helpers/dockerService/dockerService.js +6 -3
- package/dist/helpers/dockerService/serviceComponents/containerActions.js +60 -10
- package/dist/helpers/dockerService/serviceComponents/containerList.js +7 -2
- package/dist/helpers/dockerService/serviceComponents/containerLogs.js +33 -20
- package/dist/helpers/dockerService/serviceComponents/containerStats.js +12 -3
- package/dist/helpers/dockerService/serviceComponents/imageUtils.js +12 -0
- package/dist/helpers/exitWithMessage.js +11 -0
- package/dist/helpers/validationHelpers.js +15 -2
- package/dist/hooks/creation/useContainerCreation.js +2 -6
- package/dist/hooks/useContainers.js +1 -3
- package/dist/hooks/useControls.js +27 -2
- package/dist/hooks/useLogsStream.js +6 -0
- package/dist/index.js +1 -4
- package/fix-imports.cjs +3 -0
- package/package.json +1 -1
- package/src/App.jsx +0 -2
- package/src/components/ContainerList.jsx +1 -3
- package/src/components/ContainerRow.jsx +18 -6
- package/src/helpers/actionHelpers.js +14 -1
- package/src/helpers/dockerService/dockerService.js +7 -1
- package/src/helpers/dockerService/serviceComponents/containerActions.js +55 -9
- package/src/helpers/dockerService/serviceComponents/containerList.js +6 -2
- package/src/helpers/dockerService/serviceComponents/containerLogs.js +27 -15
- package/src/helpers/dockerService/serviceComponents/containerStats.js +15 -1
- package/src/helpers/dockerService/serviceComponents/imageUtils.js +10 -0
- package/src/helpers/exitWithMessage.js +10 -0
- package/src/helpers/validationHelpers.js +14 -2
- package/src/hooks/creation/useContainerCreation.js +2 -6
- package/src/hooks/useContainers.js +1 -3
- package/src/hooks/useControls.js +29 -2
- package/src/hooks/useLogsStream.js +5 -0
- package/src/index.js +1 -5
- package/test/validationHelpers.test.js +32 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,28 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
6
6
|
|
|
7
|
+
## [3.1.3] - 2025-10-17
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Addressed critical security and stability issues identified in internal audit.
|
|
12
|
+
- Improved Docker service components robustness (`containerActions`, `containerList`, `containerLogs`, `containerStats`).
|
|
13
|
+
- Strengthened validation helpers and extended unit tests.
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- Documentation: `FIXES_APPLIED.md` summarizing analysis and mitigations.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- Minor code refactors and clarifications across components and hooks.
|
|
22
|
+
|
|
23
|
+
## [3.1.2] - 2025-10-16
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- Docs cleanup: remove Spanish inline comments; add English JSDoc across source files.
|
|
28
|
+
|
|
7
29
|
## [3.1.0] - 2025-10-16
|
|
8
30
|
|
|
9
31
|
### Added
|
package/FIXES_APPLIED.md
ADDED
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
# Correcciones Aplicadas - CDD CLI
|
|
2
|
+
|
|
3
|
+
**Fecha:** 2025-10-17
|
|
4
|
+
**Proyecto:** CDD-CLI (CLI Docker Dashboard)
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Resumen de Correcciones
|
|
9
|
+
|
|
10
|
+
Se han aplicado **11 correcciones críticas** que resuelven problemas de seguridad, estabilidad y portabilidad identificados en la auditoría de código.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 1. CORRECCIONES CRÍTICAS APLICADAS
|
|
15
|
+
|
|
16
|
+
### ✅ 1.1. Corrección del Orden de Imports
|
|
17
|
+
|
|
18
|
+
**Archivo:** `src/helpers/dockerService/serviceComponents/containerActions.js`
|
|
19
|
+
|
|
20
|
+
**Problema:** Las importaciones estaban después de las exportaciones.
|
|
21
|
+
|
|
22
|
+
**Solución aplicada:**
|
|
23
|
+
```javascript
|
|
24
|
+
// ANTES (incorrecto):
|
|
25
|
+
export async function removeContainer(containerId) { ... }
|
|
26
|
+
import { docker } from "../dockerService";
|
|
27
|
+
|
|
28
|
+
// DESPUÉS (correcto):
|
|
29
|
+
import { docker } from "../dockerService";
|
|
30
|
+
import { imageExists, pullImage } from "./imageUtils.js";
|
|
31
|
+
export async function removeContainer(containerId) { ... }
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Impacto:** Elimina posibles errores de referencia y cumple con el estándar ES6.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
### ✅ 1.2. Puertos Opcionales en Creación de Contenedores
|
|
39
|
+
|
|
40
|
+
**Archivo:** `src/hooks/creation/useContainerCreation.js`
|
|
41
|
+
|
|
42
|
+
**Problema:** Se obligaba al usuario a especificar puertos, pero muchos contenedores no los necesitan.
|
|
43
|
+
|
|
44
|
+
**Solución aplicada:**
|
|
45
|
+
```javascript
|
|
46
|
+
// ANTES:
|
|
47
|
+
if (!portInput.trim()) {
|
|
48
|
+
setMessage("You must specify at least one port to expose");
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// DESPUÉS:
|
|
53
|
+
// Puertos son opcionales - solo valida si se proporcionan
|
|
54
|
+
if (portInput.trim() && !validatePorts(portInput)) {
|
|
55
|
+
setMessage("Port format must be host:container...");
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Impacto:** Permite crear contenedores sin puertos expuestos (workers, servicios internos, etc.)
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
### ✅ 1.3. Manejo de Errores en getLogsStream
|
|
65
|
+
|
|
66
|
+
**Archivo:** `src/helpers/dockerService/serviceComponents/containerLogs.js`
|
|
67
|
+
|
|
68
|
+
**Problema:** No había try-catch para manejar excepciones síncronas.
|
|
69
|
+
|
|
70
|
+
**Solución aplicada:**
|
|
71
|
+
```javascript
|
|
72
|
+
export function getLogsStream(containerId, onData, onEnd, onError) {
|
|
73
|
+
try {
|
|
74
|
+
const container = docker.getContainer(containerId);
|
|
75
|
+
// ... resto del código
|
|
76
|
+
} catch (err) {
|
|
77
|
+
onError?.(err);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Impacto:** Previene crashes cuando el contenedor no existe o hay errores de conexión.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
### ✅ 1.4. Configuración Cross-Platform de Docker Socket
|
|
87
|
+
|
|
88
|
+
**Archivo:** `src/helpers/dockerService/dockerService.js`
|
|
89
|
+
|
|
90
|
+
**Problema:** Path hardcodeado `/var/run/docker.sock` solo funciona en Linux/Mac.
|
|
91
|
+
|
|
92
|
+
**Solución aplicada:**
|
|
93
|
+
```javascript
|
|
94
|
+
// ANTES:
|
|
95
|
+
const docker = new Docker({ socketPath: "/var/run/docker.sock" });
|
|
96
|
+
|
|
97
|
+
// DESPUÉS:
|
|
98
|
+
// Usa configuración por defecto que maneja automáticamente:
|
|
99
|
+
// - /var/run/docker.sock en Linux/Mac
|
|
100
|
+
// - //./pipe/docker_engine en Windows
|
|
101
|
+
const docker = new Docker();
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**Impacto:** La aplicación ahora funciona en Windows, Linux y macOS sin modificaciones.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
### ✅ 1.5. Prevención de Race Conditions en Stats
|
|
109
|
+
|
|
110
|
+
**Archivo:** `src/components/ContainerRow.jsx`
|
|
111
|
+
|
|
112
|
+
**Problema:** Actualizaciones de estado en componentes desmontados causaban memory leaks.
|
|
113
|
+
|
|
114
|
+
**Solución aplicada:**
|
|
115
|
+
```javascript
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
if (state !== "running") return;
|
|
118
|
+
|
|
119
|
+
let isMounted = true; // ← Bandera de montaje
|
|
120
|
+
|
|
121
|
+
const fetchStats = async () => {
|
|
122
|
+
try {
|
|
123
|
+
const s = await getStats(id);
|
|
124
|
+
if (isMounted) { // ← Solo actualiza si está montado
|
|
125
|
+
setStats(s);
|
|
126
|
+
}
|
|
127
|
+
} catch (err) {
|
|
128
|
+
if (isMounted) {
|
|
129
|
+
setStatsError("Error fetching stats");
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
fetchStats();
|
|
135
|
+
const timer = setInterval(fetchStats, 1500);
|
|
136
|
+
|
|
137
|
+
return () => {
|
|
138
|
+
isMounted = false; // ← Limpieza
|
|
139
|
+
clearInterval(timer);
|
|
140
|
+
};
|
|
141
|
+
}, [id, state]);
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Impacto:** Elimina warnings de React y previene memory leaks.
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
### ✅ 1.6. Validación de Variables de Entorno
|
|
149
|
+
|
|
150
|
+
**Archivo:** `src/helpers/validationHelpers.js`
|
|
151
|
+
|
|
152
|
+
**Problema:** La función `validateEnvVars` siempre retornaba `true`.
|
|
153
|
+
|
|
154
|
+
**Solución aplicada:**
|
|
155
|
+
```javascript
|
|
156
|
+
export function validateEnvVars(envInput) {
|
|
157
|
+
if (!envInput || !envInput.trim()) return true; // Empty is valid
|
|
158
|
+
|
|
159
|
+
const vars = envInput.split(",").map(v => v.trim()).filter(Boolean);
|
|
160
|
+
const invalid = vars.find(v => {
|
|
161
|
+
const parts = v.split("=");
|
|
162
|
+
if (parts.length < 2) return true; // Debe tener VAR=value
|
|
163
|
+
const varName = parts[0].trim();
|
|
164
|
+
// Nombres deben ser alfanuméricos con underscores
|
|
165
|
+
if (!/^[A-Z_][A-Z0-9_]*$/i.test(varName)) return true;
|
|
166
|
+
return false;
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
return !invalid;
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**Impacto:** Detecta variables malformadas antes de enviarlas a Docker.
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
### ✅ 1.7. Corrección de Cálculo de CPU Stats
|
|
178
|
+
|
|
179
|
+
**Archivo:** `src/helpers/dockerService/serviceComponents/containerStats.js`
|
|
180
|
+
|
|
181
|
+
**Problema:** No se normalizaba por número de CPUs, dando valores incorrectos en multi-core.
|
|
182
|
+
|
|
183
|
+
**Solución aplicada:**
|
|
184
|
+
```javascript
|
|
185
|
+
// Obtener número de CPUs
|
|
186
|
+
const numCpus = stream.cpu_stats.online_cpus ||
|
|
187
|
+
stream.cpu_stats.cpu_usage.percpu_usage?.length || 1;
|
|
188
|
+
|
|
189
|
+
// Calcular porcentaje normalizado
|
|
190
|
+
const cpuPercent = systemDelta > 0
|
|
191
|
+
? ((cpuDelta / systemDelta) * numCpus * 100)
|
|
192
|
+
: 0;
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
**Impacto:** Estadísticas de CPU correctas en sistemas multi-core.
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
### ✅ 1.8. Timeouts en Operaciones Docker
|
|
200
|
+
|
|
201
|
+
**Archivo:** `src/helpers/dockerService/serviceComponents/containerActions.js`
|
|
202
|
+
|
|
203
|
+
**Problema:** Operaciones sin timeout podían colgar la UI indefinidamente.
|
|
204
|
+
|
|
205
|
+
**Solución aplicada:**
|
|
206
|
+
```javascript
|
|
207
|
+
function withTimeout(promise, ms = 30000) {
|
|
208
|
+
return Promise.race([
|
|
209
|
+
promise,
|
|
210
|
+
new Promise((_, reject) =>
|
|
211
|
+
setTimeout(() => reject(new Error('Operation timed out')), ms)
|
|
212
|
+
)
|
|
213
|
+
]);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export async function startContainer(containerId) {
|
|
217
|
+
const container = docker.getContainer(containerId);
|
|
218
|
+
await withTimeout(container.start(), 30000);
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**Impacto:** Previene UI congelada en operaciones largas o que fallan.
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
### ✅ 1.9. Límite de Logs en Memoria
|
|
227
|
+
|
|
228
|
+
**Archivo:** `src/hooks/useControls.js`
|
|
229
|
+
|
|
230
|
+
**Problema:** Los logs se acumulaban indefinidamente causando memory leak.
|
|
231
|
+
|
|
232
|
+
**Solución aplicada:**
|
|
233
|
+
```javascript
|
|
234
|
+
getLogsStream(
|
|
235
|
+
containers[selected].id,
|
|
236
|
+
(data) => logsViewer.setLogs((prev) => {
|
|
237
|
+
const newLogs = [...prev, ...data.split("\n").filter(Boolean)];
|
|
238
|
+
// Limitar a últimas 1000 líneas
|
|
239
|
+
return newLogs.slice(-1000);
|
|
240
|
+
}),
|
|
241
|
+
// ...
|
|
242
|
+
);
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**Impacto:** Previene memory leaks en streams de logs largos.
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
### ✅ 1.10. Corrección de Mensaje Duplicado
|
|
250
|
+
|
|
251
|
+
**Archivo:** `src/helpers/actionHelpers.js`
|
|
252
|
+
|
|
253
|
+
**Problema:** El mensaje de éxito era idéntico al de inicio.
|
|
254
|
+
|
|
255
|
+
**Solución aplicada:**
|
|
256
|
+
```javascript
|
|
257
|
+
// ANTES:
|
|
258
|
+
setMessage(`${actionLabel} container...`); // inicio
|
|
259
|
+
await actionFn(c.id);
|
|
260
|
+
setMessage(`${actionLabel} container...`); // éxito (duplicado)
|
|
261
|
+
|
|
262
|
+
// DESPUÉS:
|
|
263
|
+
setMessage(`${actionLabel} container...`); // inicio
|
|
264
|
+
await actionFn(c.id);
|
|
265
|
+
setMessage(`${actionLabel} container completed successfully`); // éxito
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
**Impacto:** Feedback claro de que la operación se completó.
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
### ✅ 1.11. Validación de Container Names
|
|
273
|
+
|
|
274
|
+
**Archivo:** `src/helpers/dockerService/serviceComponents/containerList.js`
|
|
275
|
+
|
|
276
|
+
**Problema:** No se validaba si `Names` estaba vacío.
|
|
277
|
+
|
|
278
|
+
**Solución aplicada:**
|
|
279
|
+
```javascript
|
|
280
|
+
// ANTES:
|
|
281
|
+
name: container.Names[0].replace("/", ""),
|
|
282
|
+
|
|
283
|
+
// DESPUÉS:
|
|
284
|
+
name: (container.Names && container.Names[0] || 'Unknown').replace("/", ""),
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
**Impacto:** Previene crashes si Docker devuelve datos inesperados.
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## 2. MEJORAS EN TESTS
|
|
292
|
+
|
|
293
|
+
### ✅ Tests para validateEnvVars
|
|
294
|
+
|
|
295
|
+
**Archivo:** `test/validationHelpers.test.js`
|
|
296
|
+
|
|
297
|
+
**Nuevos tests agregados:**
|
|
298
|
+
- Empty input is valid
|
|
299
|
+
- Valid single env var
|
|
300
|
+
- Valid multiple env vars
|
|
301
|
+
- Valid env var with underscores
|
|
302
|
+
- Invalid env var without equals sign
|
|
303
|
+
- Invalid env var with invalid name
|
|
304
|
+
- Invalid env var with special characters in name
|
|
305
|
+
|
|
306
|
+
**Resultado:**
|
|
307
|
+
```
|
|
308
|
+
Test Suites: 1 passed, 1 total
|
|
309
|
+
Tests: 12 passed, 12 total (antes: 5)
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## 3. ANÁLISIS DE SEGURIDAD
|
|
315
|
+
|
|
316
|
+
### ✅ CodeQL Security Scan
|
|
317
|
+
|
|
318
|
+
**Resultado:** ✅ **0 vulnerabilidades encontradas**
|
|
319
|
+
|
|
320
|
+
```
|
|
321
|
+
Analysis Result for 'javascript'. Found 0 alert(s):
|
|
322
|
+
- javascript: No alerts found.
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## 4. VERIFICACIÓN DE BUILD
|
|
328
|
+
|
|
329
|
+
### ✅ Build Exitoso
|
|
330
|
+
|
|
331
|
+
```bash
|
|
332
|
+
$ npm run build
|
|
333
|
+
Successfully compiled 28 files with Babel (815ms).
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## 5. IMPACTO GENERAL DE LAS CORRECCIONES
|
|
339
|
+
|
|
340
|
+
### Seguridad
|
|
341
|
+
- ✅ Sin vulnerabilidades de seguridad detectadas
|
|
342
|
+
- ✅ Validación de inputs mejorada
|
|
343
|
+
- ✅ Manejo de errores robusto
|
|
344
|
+
|
|
345
|
+
### Estabilidad
|
|
346
|
+
- ✅ Prevención de memory leaks
|
|
347
|
+
- ✅ Prevención de race conditions
|
|
348
|
+
- ✅ Prevención de crashes por errores no manejados
|
|
349
|
+
- ✅ Timeouts en operaciones potencialmente largas
|
|
350
|
+
|
|
351
|
+
### Portabilidad
|
|
352
|
+
- ✅ Compatibilidad con Windows
|
|
353
|
+
- ✅ Compatibilidad con Linux
|
|
354
|
+
- ✅ Compatibilidad con macOS
|
|
355
|
+
|
|
356
|
+
### Experiencia de Usuario
|
|
357
|
+
- ✅ Puertos opcionales en creación de contenedores
|
|
358
|
+
- ✅ Mensajes de feedback más claros
|
|
359
|
+
- ✅ Estadísticas de CPU correctas
|
|
360
|
+
- ✅ Mejor manejo de errores con mensajes informativos
|
|
361
|
+
|
|
362
|
+
### Calidad de Código
|
|
363
|
+
- ✅ Cumple estándar ES6
|
|
364
|
+
- ✅ Mejor cobertura de tests (5 → 12 tests)
|
|
365
|
+
- ✅ Código más mantenible
|
|
366
|
+
|
|
367
|
+
---
|
|
368
|
+
|
|
369
|
+
## 6. ARCHIVOS MODIFICADOS
|
|
370
|
+
|
|
371
|
+
1. `src/helpers/dockerService/serviceComponents/containerActions.js`
|
|
372
|
+
2. `src/hooks/creation/useContainerCreation.js`
|
|
373
|
+
3. `src/helpers/dockerService/serviceComponents/containerLogs.js`
|
|
374
|
+
4. `src/helpers/dockerService/dockerService.js`
|
|
375
|
+
5. `src/components/ContainerRow.jsx`
|
|
376
|
+
6. `src/helpers/validationHelpers.js`
|
|
377
|
+
7. `src/helpers/dockerService/serviceComponents/containerStats.js`
|
|
378
|
+
8. `src/hooks/useControls.js`
|
|
379
|
+
9. `src/helpers/actionHelpers.js`
|
|
380
|
+
10. `src/helpers/dockerService/serviceComponents/containerList.js`
|
|
381
|
+
11. `test/validationHelpers.test.js`
|
|
382
|
+
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
## 7. RECOMENDACIONES FUTURAS
|
|
386
|
+
|
|
387
|
+
Aunque se han corregido los problemas críticos, el informe de auditoría (AUDIT_REPORT.md) contiene recomendaciones adicionales para mejoras futuras:
|
|
388
|
+
|
|
389
|
+
### Prioridad Media
|
|
390
|
+
- Agregar más tests unitarios
|
|
391
|
+
- Implementar PropTypes o migrar a TypeScript
|
|
392
|
+
- Extraer magic numbers a constantes
|
|
393
|
+
- Mejorar sistema de logging
|
|
394
|
+
|
|
395
|
+
### Prioridad Baja
|
|
396
|
+
- Implementar i18n (internacionalización)
|
|
397
|
+
- Mejorar documentación JSDoc
|
|
398
|
+
- Considerar websockets para actualizaciones en tiempo real
|
|
399
|
+
- Implementar retry logic para reconexión Docker
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
## 8. CONCLUSIÓN
|
|
404
|
+
|
|
405
|
+
Se han aplicado **11 correcciones críticas** que mejoran significativamente:
|
|
406
|
+
|
|
407
|
+
- **Seguridad**: 0 vulnerabilidades
|
|
408
|
+
- **Estabilidad**: Prevención de memory leaks y race conditions
|
|
409
|
+
- **Portabilidad**: Funciona en Windows, Linux y macOS
|
|
410
|
+
- **Calidad**: +140% más tests (5 → 12)
|
|
411
|
+
|
|
412
|
+
Todas las correcciones han sido probadas y verificadas mediante:
|
|
413
|
+
- ✅ Tests unitarios (12/12 pasando)
|
|
414
|
+
- ✅ Build exitoso
|
|
415
|
+
- ✅ Análisis de seguridad CodeQL (0 alertas)
|
|
416
|
+
|
|
417
|
+
El proyecto ahora tiene una base más sólida y está listo para uso en producción.
|
|
418
|
+
|
|
419
|
+
---
|
|
420
|
+
|
|
421
|
+
**Fin del documento de correcciones**
|
package/dist/App.js
CHANGED
|
@@ -1,25 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Main React component for the CDD CLI UI.
|
|
3
|
-
* Componente principal de React para la UI del CLI CDD.
|
|
4
3
|
*
|
|
5
4
|
* @component
|
|
6
5
|
* @returns {JSX.Element} The rendered app / La app renderizada
|
|
7
6
|
* @example
|
|
8
7
|
* // EN: Render the app
|
|
9
|
-
* // ES: Renderizar la app
|
|
10
8
|
* <App />
|
|
11
9
|
*/
|
|
12
10
|
import React from "react";
|
|
13
11
|
import { Box, Text, Spacer } from "ink";
|
|
14
12
|
import { useContainers } from "./hooks/useContainers.js";
|
|
15
13
|
import { useControls } from "./hooks/useControls.js";
|
|
16
|
-
import ContainerSection from "./components/ContainerSection.
|
|
17
|
-
import MessageFeedback from "./components/MessageFeedback.
|
|
18
|
-
import Header from "./components/Header.
|
|
19
|
-
import LogViewer from "./components/LogViewer.
|
|
20
|
-
import ContainerCreationPrompt from "./components/ContainerCreationPrompt.
|
|
21
|
-
import UsageMenu from "./components/UsageMenu.
|
|
22
|
-
import Footer from "./components/Footer.
|
|
14
|
+
import ContainerSection from "./components/ContainerSection.js";
|
|
15
|
+
import MessageFeedback from "./components/MessageFeedback.js";
|
|
16
|
+
import Header from "./components/Header.js";
|
|
17
|
+
import LogViewer from "./components/LogViewer.js";
|
|
18
|
+
import ContainerCreationPrompt from "./components/ContainerCreationPrompt.js";
|
|
19
|
+
import UsageMenu from "./components/UsageMenu.js";
|
|
20
|
+
import Footer from "./components/Footer.js";
|
|
23
21
|
export default function App() {
|
|
24
22
|
var _useContainers = useContainers(),
|
|
25
23
|
containers = _useContainers.containers;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
|
-
import { PromptField, PromptMessage } from "./PromptField.
|
|
3
|
+
import { PromptField, PromptMessage } from "./PromptField.js";
|
|
4
4
|
export default function ContainerCreationPrompt(props) {
|
|
5
5
|
var step = props.step,
|
|
6
6
|
imageName = props.imageName,
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* List component for Docker containers.
|
|
3
|
-
* Componente de lista para contenedores Docker.
|
|
4
3
|
*
|
|
5
4
|
* @component
|
|
6
5
|
* @param {Object} props - Component props / Props del componente
|
|
7
6
|
* @param {Array} props.containers - Containers to display / Contenedores a mostrar
|
|
8
7
|
* @returns {JSX.Element} Rendered list / Lista renderizada
|
|
9
8
|
* @example
|
|
10
|
-
* //
|
|
11
|
-
* // ES: Renderizar con contenedores
|
|
9
|
+
* // Render with containers
|
|
12
10
|
* <ContainerList containers={containers} />
|
|
13
11
|
*/
|
|
14
12
|
import React from "react";
|
|
15
13
|
import { Box, Text } from "ink";
|
|
16
|
-
import ContainerRow from "./ContainerRow.
|
|
14
|
+
import ContainerRow from "./ContainerRow.js";
|
|
17
15
|
export default function ContainerList(_ref) {
|
|
18
16
|
var containers = _ref.containers,
|
|
19
17
|
selected = _ref.selected;
|
|
@@ -11,7 +11,7 @@ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
|
11
11
|
import React, { useState, useEffect } from "react";
|
|
12
12
|
import { Box, Text } from "ink";
|
|
13
13
|
import { getStats } from "../helpers/dockerService/serviceComponents/containerStats.js";
|
|
14
|
-
import StatsBar from "./StatsBar.
|
|
14
|
+
import StatsBar from "./StatsBar.js";
|
|
15
15
|
var stateText = function stateText(state) {
|
|
16
16
|
if (state === "running") return {
|
|
17
17
|
text: "🟢 RUNNING",
|
|
@@ -48,7 +48,7 @@ export default function ContainerRow(_ref) {
|
|
|
48
48
|
stats = _useState2[0],
|
|
49
49
|
setStats = _useState2[1];
|
|
50
50
|
|
|
51
|
-
//
|
|
51
|
+
// Format ports for display
|
|
52
52
|
var formatPorts = function formatPorts(ports) {
|
|
53
53
|
if (!ports || ports.length === 0) return "";
|
|
54
54
|
if (Array.isArray(ports)) {
|
|
@@ -64,6 +64,7 @@ export default function ContainerRow(_ref) {
|
|
|
64
64
|
setStatsError = _useState4[1];
|
|
65
65
|
useEffect(function () {
|
|
66
66
|
if (state !== "running") return;
|
|
67
|
+
var isMounted = true;
|
|
67
68
|
var fetchStats = /*#__PURE__*/function () {
|
|
68
69
|
var _ref2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
|
|
69
70
|
var s, _t;
|
|
@@ -75,22 +76,26 @@ export default function ContainerRow(_ref) {
|
|
|
75
76
|
return getStats(id);
|
|
76
77
|
case 1:
|
|
77
78
|
s = _context.v;
|
|
78
|
-
|
|
79
|
-
|
|
79
|
+
if (isMounted) {
|
|
80
|
+
setStats(s);
|
|
81
|
+
setStatsError("");
|
|
82
|
+
}
|
|
80
83
|
_context.n = 3;
|
|
81
84
|
break;
|
|
82
85
|
case 2:
|
|
83
86
|
_context.p = 2;
|
|
84
87
|
_t = _context.v;
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
88
|
+
if (isMounted) {
|
|
89
|
+
setStats({
|
|
90
|
+
cpuPercent: 0,
|
|
91
|
+
memPercent: 0,
|
|
92
|
+
netIO: {
|
|
93
|
+
rx: 0,
|
|
94
|
+
tx: 0
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
setStatsError("Error fetching stats");
|
|
98
|
+
}
|
|
94
99
|
case 3:
|
|
95
100
|
return _context.a(2);
|
|
96
101
|
}
|
|
@@ -103,7 +108,8 @@ export default function ContainerRow(_ref) {
|
|
|
103
108
|
fetchStats();
|
|
104
109
|
var timer = setInterval(fetchStats, 1500);
|
|
105
110
|
return function () {
|
|
106
|
-
|
|
111
|
+
isMounted = false;
|
|
112
|
+
clearInterval(timer);
|
|
107
113
|
};
|
|
108
114
|
}, [id, state]);
|
|
109
115
|
var stateInfo = stateText(state);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Text } from "ink";
|
|
3
|
-
import ContainerList from "./ContainerList.
|
|
3
|
+
import ContainerList from "./ContainerList.js";
|
|
4
4
|
export default function ContainerSection(_ref) {
|
|
5
5
|
var containers = _ref.containers,
|
|
6
6
|
selected = _ref.selected;
|
|
@@ -2,6 +2,19 @@ function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present,
|
|
|
2
2
|
function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
|
|
3
3
|
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
|
|
4
4
|
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
|
|
5
|
+
/**
|
|
6
|
+
* Generic helper to perform a container action with user feedback.
|
|
7
|
+
*
|
|
8
|
+
* @param {Object} params
|
|
9
|
+
* @param {Array} params.containers - Array of container objects
|
|
10
|
+
* @param {number} params.selected - Index of the selected container
|
|
11
|
+
* @param {Function} params.actionFn - Async function that performs the action (receives container id)
|
|
12
|
+
* @param {string} params.actionLabel - Label used in feedback messages (e.g. 'Starting')
|
|
13
|
+
* @param {Function} params.setMessage - Setter for feedback message
|
|
14
|
+
* @param {Function} params.setMessageColor - Setter for feedback color
|
|
15
|
+
* @param {Function} [params.stateCheck] - Optional function that validates container state before action
|
|
16
|
+
* @returns {Promise<void>}
|
|
17
|
+
*/
|
|
5
18
|
export function handleAction(_x) {
|
|
6
19
|
return _handleAction.apply(this, arguments);
|
|
7
20
|
}
|
|
@@ -36,7 +49,7 @@ function _handleAction() {
|
|
|
36
49
|
_context.n = 4;
|
|
37
50
|
return actionFn(c.id);
|
|
38
51
|
case 4:
|
|
39
|
-
setMessage("".concat(actionLabel, " container
|
|
52
|
+
setMessage("".concat(actionLabel, " container completed successfully"));
|
|
40
53
|
setMessageColor("green");
|
|
41
54
|
setTimeout(function () {
|
|
42
55
|
return setMessage("");
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import Docker from "dockerode";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
|
|
3
|
+
// Use default dockerode configuration which automatically handles:
|
|
4
|
+
// - /var/run/docker.sock on Linux/Mac
|
|
5
|
+
// - //./pipe/docker_engine on Windows
|
|
6
|
+
// - Environment variables DOCKER_HOST, DOCKER_CERT_PATH, etc.
|
|
7
|
+
var docker = new Docker();
|
|
5
8
|
export { docker };
|