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.
Files changed (42) hide show
  1. package/AUDIT_REPORT.md +1004 -0
  2. package/CHANGELOG.md +22 -0
  3. package/FIXES_APPLIED.md +421 -0
  4. package/dist/App.js +7 -9
  5. package/dist/components/ContainerCreationPrompt.js +1 -1
  6. package/dist/components/ContainerList.js +2 -4
  7. package/dist/components/ContainerRow.js +20 -14
  8. package/dist/components/ContainerSection.js +1 -1
  9. package/dist/helpers/actionHelpers.js +14 -1
  10. package/dist/helpers/dockerService/dockerService.js +6 -3
  11. package/dist/helpers/dockerService/serviceComponents/containerActions.js +60 -10
  12. package/dist/helpers/dockerService/serviceComponents/containerList.js +7 -2
  13. package/dist/helpers/dockerService/serviceComponents/containerLogs.js +33 -20
  14. package/dist/helpers/dockerService/serviceComponents/containerStats.js +12 -3
  15. package/dist/helpers/dockerService/serviceComponents/imageUtils.js +12 -0
  16. package/dist/helpers/exitWithMessage.js +11 -0
  17. package/dist/helpers/validationHelpers.js +15 -2
  18. package/dist/hooks/creation/useContainerCreation.js +2 -6
  19. package/dist/hooks/useContainers.js +1 -3
  20. package/dist/hooks/useControls.js +27 -2
  21. package/dist/hooks/useLogsStream.js +6 -0
  22. package/dist/index.js +1 -4
  23. package/fix-imports.cjs +3 -0
  24. package/package.json +1 -1
  25. package/src/App.jsx +0 -2
  26. package/src/components/ContainerList.jsx +1 -3
  27. package/src/components/ContainerRow.jsx +18 -6
  28. package/src/helpers/actionHelpers.js +14 -1
  29. package/src/helpers/dockerService/dockerService.js +7 -1
  30. package/src/helpers/dockerService/serviceComponents/containerActions.js +55 -9
  31. package/src/helpers/dockerService/serviceComponents/containerList.js +6 -2
  32. package/src/helpers/dockerService/serviceComponents/containerLogs.js +27 -15
  33. package/src/helpers/dockerService/serviceComponents/containerStats.js +15 -1
  34. package/src/helpers/dockerService/serviceComponents/imageUtils.js +10 -0
  35. package/src/helpers/exitWithMessage.js +10 -0
  36. package/src/helpers/validationHelpers.js +14 -2
  37. package/src/hooks/creation/useContainerCreation.js +2 -6
  38. package/src/hooks/useContainers.js +1 -3
  39. package/src/hooks/useControls.js +29 -2
  40. package/src/hooks/useLogsStream.js +5 -0
  41. package/src/index.js +1 -5
  42. 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
@@ -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.jsx";
17
- import MessageFeedback from "./components/MessageFeedback.jsx";
18
- import Header from "./components/Header.jsx";
19
- import LogViewer from "./components/LogViewer.jsx";
20
- import ContainerCreationPrompt from "./components/ContainerCreationPrompt.jsx";
21
- import UsageMenu from "./components/UsageMenu.jsx";
22
- import Footer from "./components/Footer.jsx";
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.jsx";
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
- * // EN: Render with containers
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.jsx";
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.jsx";
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
- // Formatear puertos
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
- setStats(s);
79
- setStatsError("");
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
- setStats({
86
- cpuPercent: 0,
87
- memPercent: 0,
88
- netIO: {
89
- rx: 0,
90
- tx: 0
91
- }
92
- });
93
- setStatsError("Error fetching stats");
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
- return clearInterval(timer);
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.jsx";
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
- var docker = new Docker({
3
- socketPath: "/var/run/docker.sock"
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 };