cdd-cli 3.0.1 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ci.yml +29 -0
- package/CHANGELOG.md +27 -0
- package/CODE_OF_CONDUCT.md +12 -0
- package/CONTRIBUTING.md +22 -0
- package/README.md +69 -168
- package/SECURITY.md +5 -0
- package/babel.config.cjs +6 -0
- package/dist/App.js +38 -24
- package/dist/cdd.bundle.js +8 -0
- package/dist/components/ContainerCreationPrompt.js +48 -0
- package/dist/components/ContainerCreator.js +81 -0
- package/dist/components/ContainerList.js +24 -4
- package/dist/components/ContainerRow.js +66 -13
- package/dist/components/ContainerSection.js +14 -0
- package/dist/components/Footer.js +10 -0
- package/dist/components/PromptField.js +20 -0
- package/dist/components/UsageMenu.js +8 -0
- package/dist/helpers/actionHelpers.js +0 -1
- package/dist/helpers/dockerActions.js +13 -0
- package/dist/helpers/dockerService/dockerService.js +5 -0
- package/dist/helpers/dockerService/serviceComponents/containerActions.js +163 -0
- package/dist/helpers/dockerService/serviceComponents/containerList.js +57 -0
- package/dist/helpers/dockerService/serviceComponents/containerLogs.js +24 -0
- package/dist/helpers/dockerService/serviceComponents/containerStats.js +50 -0
- package/dist/helpers/dockerService/serviceComponents/imageUtils.js +52 -0
- package/dist/helpers/dockerService.js +111 -0
- package/dist/helpers/validationHelpers.js +26 -0
- package/dist/hooks/creation/useContainerActions.js +171 -0
- package/dist/hooks/creation/useContainerCreation.js +141 -0
- package/dist/hooks/creation/useLogsViewer.js +62 -0
- package/dist/hooks/useContainers.js +11 -1
- package/dist/hooks/useControls.js +298 -78
- package/dist/hooks/useLogsStream.js +1 -1
- package/dist/index.js +11 -0
- package/esbuild.config.cjs +11 -0
- package/jest.config.cjs +6 -0
- package/package.json +10 -6
- package/src/App.jsx +32 -26
- package/src/components/ContainerCreationPrompt.jsx +37 -0
- package/src/components/ContainerList.jsx +10 -6
- package/src/components/ContainerRow.jsx +36 -19
- package/src/components/ContainerSection.jsx +10 -0
- package/src/components/Footer.jsx +10 -0
- package/src/components/PromptField.jsx +18 -0
- package/src/components/UsageMenu.jsx +17 -0
- package/src/helpers/actionHelpers.js +0 -1
- package/src/helpers/dockerService/dockerService.js +3 -0
- package/src/helpers/dockerService/serviceComponents/containerActions.js +52 -0
- package/src/helpers/dockerService/serviceComponents/containerList.js +26 -0
- package/src/helpers/dockerService/serviceComponents/containerLogs.js +19 -0
- package/src/helpers/dockerService/serviceComponents/containerStats.js +34 -0
- package/src/helpers/dockerService/serviceComponents/imageUtils.js +21 -0
- package/src/helpers/validationHelpers.js +16 -0
- package/src/hooks/creation/useContainerActions.js +68 -0
- package/src/hooks/creation/useContainerCreation.js +104 -0
- package/src/hooks/creation/useLogsViewer.js +50 -0
- package/src/hooks/useContainers.js +1 -1
- package/src/hooks/useControls.js +176 -55
- package/src/hooks/useLogsStream.js +1 -1
- package/test/validationHelpers.test.js +28 -0
- package/PLAN_KEYBINDINGS_Y_REALTIME.md +0 -260
- package/docs/en/README.md +0 -167
- package/src/components/StatsViewer.jsx +0 -0
- package/src/helpers/dockerActions.js +0 -52
- package/src/helpers/dockerService.js +0 -100
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ main ]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test-and-build:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- name: Checkout repository
|
|
14
|
+
uses: actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- name: Setup Node.js
|
|
17
|
+
uses: actions/setup-node@v4
|
|
18
|
+
with:
|
|
19
|
+
node-version: '18'
|
|
20
|
+
cache: 'npm'
|
|
21
|
+
|
|
22
|
+
- name: Install dependencies
|
|
23
|
+
run: npm ci
|
|
24
|
+
|
|
25
|
+
- name: Run tests
|
|
26
|
+
run: npm test
|
|
27
|
+
|
|
28
|
+
- name: Build
|
|
29
|
+
run: npm run build
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
6
|
+
|
|
7
|
+
## [3.1.0] - 2025-10-16
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Modularized hooks: `useContainerCreation`, `useContainerActions`, `useLogsViewer`.
|
|
12
|
+
- Validation helpers and unit tests for port validation.
|
|
13
|
+
- CI workflow (GitHub Actions) and README improvements.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- Container creation UX: English feedback messages, mandatory/validated port input, DB image warnings.
|
|
18
|
+
- Added erase action (key `E`) with confirmation to delete containers.
|
|
19
|
+
- Normalized source imports to include explicit `.js`/`.jsx` extensions for ESM compatibility.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- Various runtime & build issues after modularization (import fixes, exposing container action functions, creation flow wiring).
|
|
24
|
+
|
|
25
|
+
## [Unreleased]
|
|
26
|
+
|
|
27
|
+
- Incoming fixes and smaller tests / docs updates
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
This project follows the Contributor Covenant Code of Conduct. By participating, you agree to abide by its terms.
|
|
4
|
+
|
|
5
|
+
Please see https://www.contributor-covenant.org/ for the full text.
|
|
6
|
+
## Code of Conduct
|
|
7
|
+
|
|
8
|
+
This project follows the [Contributor Covenant](https://www.contributor-covenant.org/).
|
|
9
|
+
|
|
10
|
+
Be respectful, inclusive, and kind. Harassment, discrimination, or abusive language will not be tolerated.
|
|
11
|
+
|
|
12
|
+
If you experience or witness unacceptable behavior, please contact the maintainers.
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in contributing! Please follow these guidelines:
|
|
4
|
+
|
|
5
|
+
- Fork the repository and create a feature branch.
|
|
6
|
+
- Keep changes small and focused.
|
|
7
|
+
- Add or update tests for new behaviors.
|
|
8
|
+
- Run `npm test` and `npm run build` before opening a PR.
|
|
9
|
+
- Use conventional commits where possible.
|
|
10
|
+
|
|
11
|
+
For any design or large changes, open an issue first to discuss.
|
|
12
|
+
## Contributing to CDD-CLI
|
|
13
|
+
|
|
14
|
+
Thanks for your interest in contributing! A few guidelines to make collaboration smooth:
|
|
15
|
+
|
|
16
|
+
- Fork the repo and create a branch for your feature/fix: `git checkout -b feat/my-feature`.
|
|
17
|
+
- Write tests for any new behavior and ensure existing tests pass: `npm test`.
|
|
18
|
+
- Follow the existing code style and run `npm run build` before opening a PR.
|
|
19
|
+
- Keep PRs focused and describe motivation and changes.
|
|
20
|
+
- Tag reviewers and link related issues.
|
|
21
|
+
|
|
22
|
+
We appreciate clear, well-tested contributions.
|
package/README.md
CHANGED
|
@@ -1,205 +1,106 @@
|
|
|
1
|
-
##
|
|
1
|
+
## CDD-CLI — Docker Dashboard (Terminal)
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
```bash
|
|
11
|
-
npm install
|
|
12
|
-
```
|
|
13
|
-
3. Transpila el código fuente:
|
|
14
|
-
```bash
|
|
15
|
-
npm run build
|
|
16
|
-
```
|
|
17
|
-
4. Ejecuta el CLI localmente:
|
|
18
|
-
```bash
|
|
19
|
-
node dist/index.js
|
|
20
|
-
```
|
|
21
|
-
5. Prueba el comando global localmente:
|
|
22
|
-
```bash
|
|
23
|
-
npm link
|
|
24
|
-
cdd
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
### Testing y troubleshooting
|
|
28
|
-
- Si modificas componentes, recuerda siempre ejecutar `npm run build` antes de probar.
|
|
29
|
-
- Si tienes problemas con permisos de Docker, ejecuta la terminal como administrador o usa `sudo`.
|
|
30
|
-
- Para limpiar la instalación global:
|
|
31
|
-
```bash
|
|
32
|
-
npm uninstall -g cdd-cli
|
|
33
|
-
```
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="https://img.shields.io/npm/v/cdd-cli?color=blue&label=npm%20package" alt="npm version"/>
|
|
5
|
+
<img src="https://img.shields.io/npm/dt/cdd-cli?color=green&label=downloads" alt="npm downloads"/>
|
|
6
|
+
<a href="https://github.com/caertos/cdd/actions/workflows/ci.yml">
|
|
7
|
+
<img src="https://github.com/caertos/cdd/actions/workflows/ci.yml/badge.svg?branch=main" alt="CI status" />
|
|
8
|
+
</a>
|
|
9
|
+
</p>
|
|
34
10
|
|
|
35
|
-
|
|
36
|
-
1. Haz un fork del repositorio y crea una rama para tu feature o fix.
|
|
37
|
-
2. Asegúrate de que tu código pase el build y funcione correctamente.
|
|
38
|
-
3. Haz un Pull Request con una descripción clara de tus cambios.
|
|
11
|
+
Short, bilingual README with quickstart, development and tests.
|
|
39
12
|
|
|
40
13
|
---
|
|
41
|
-
## Advanced instructions
|
|
42
14
|
|
|
43
|
-
|
|
44
|
-
1. Clone the repository:
|
|
45
|
-
```bash
|
|
46
|
-
git clone https://github.com/caertos/cdd.git
|
|
47
|
-
cd cdd
|
|
48
|
-
```
|
|
49
|
-
2. Install dependencies:
|
|
50
|
-
```bash
|
|
51
|
-
npm install
|
|
52
|
-
```
|
|
53
|
-
3. Transpile the source code:
|
|
54
|
-
```bash
|
|
55
|
-
npm run build
|
|
56
|
-
```
|
|
57
|
-
4. Run the CLI locally:
|
|
58
|
-
```bash
|
|
59
|
-
node dist/index.js
|
|
60
|
-
```
|
|
61
|
-
5. Test the global command locally:
|
|
62
|
-
```bash
|
|
63
|
-
npm link
|
|
64
|
-
cdd
|
|
65
|
-
```
|
|
15
|
+
## Quick start (local)
|
|
66
16
|
|
|
67
|
-
|
|
68
|
-
- If you modify components, always run `npm run build` before testing.
|
|
69
|
-
- If you have Docker permission issues, run your terminal as administrator or use `sudo`.
|
|
70
|
-
- To clean up the global install:
|
|
71
|
-
```bash
|
|
72
|
-
npm uninstall -g cdd-cli
|
|
73
|
-
```
|
|
17
|
+
1. Clone the repo and install dependencies:
|
|
74
18
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
19
|
+
```bash
|
|
20
|
+
git clone https://github.com/caertos/cdd.git
|
|
21
|
+
cd cdd
|
|
22
|
+
npm install
|
|
23
|
+
```
|
|
79
24
|
|
|
80
|
-
|
|
25
|
+
2. Build and run locally:
|
|
81
26
|
|
|
27
|
+
```bash
|
|
28
|
+
npm run build
|
|
29
|
+
node dist/index.js
|
|
30
|
+
```
|
|
82
31
|
|
|
83
|
-
|
|
84
|
-
<img src="https://img.shields.io/npm/v/cdd-cli?color=blue&label=npm%20package" alt="npm version"/>
|
|
85
|
-
<img src="https://img.shields.io/npm/dt/cdd-cli?color=green&label=descargas" alt="npm downloads"/>
|
|
86
|
-
</p>
|
|
32
|
+
3. To test the CLI as a globally available command during development:
|
|
87
33
|
|
|
88
|
-
|
|
89
|
-
|
|
34
|
+
```bash
|
|
35
|
+
npm link
|
|
36
|
+
cdd
|
|
37
|
+
```
|
|
90
38
|
|
|
91
39
|
---
|
|
92
40
|
|
|
93
|
-
##
|
|
94
|
-
|
|
95
|
-
```text
|
|
96
|
-
╭────────────────────────────────────────────────────────────────────────────╮
|
|
97
|
-
│ 🐳 CDD — CLI Docker Dashboard 2 containers found │
|
|
98
|
-
│ │
|
|
99
|
-
│ mysql-dev mysql:latest 🟢 RUNNING │
|
|
100
|
-
│ CPU: ░░░░░░░░░░ 0.1% MEM: ░░░░░░░░░░ 4.9% │
|
|
101
|
-
│ │
|
|
102
|
-
│ redis-test redis:alpine 🔴 EXITED │
|
|
103
|
-
│ │
|
|
104
|
-
│ Press Ctrl+C to exit │
|
|
105
|
-
│ Crafted by Carlos Cochero • 2025 │
|
|
106
|
-
╰────────────────────────────────────────────────────────────────────────────╯
|
|
107
|
-
```
|
|
108
|
-
# 🐳 CDD-CLI — Docker Dashboard in your Terminal
|
|
109
|
-
|
|
110
|
-
## Visual example
|
|
111
|
-
|
|
112
|
-
```text
|
|
113
|
-
╭────────────────────────────────────────────────────────────────────────────╮
|
|
114
|
-
│ 🐳 CDD — CLI Docker Dashboard 2 containers found │
|
|
115
|
-
│ │
|
|
116
|
-
│ mysql-dev mysql:latest 🟢 RUNNING │
|
|
117
|
-
│ CPU: ░░░░░░░░░░ 0.1% MEM: ░░░░░░░░░░ 4.9% │
|
|
118
|
-
│ │
|
|
119
|
-
│ redis-test redis:alpine 🔴 EXITED │
|
|
120
|
-
│ │
|
|
121
|
-
│ Press Ctrl+C to exit │
|
|
122
|
-
│ Crafted by Carlos Cochero • 2025 │
|
|
123
|
-
╰────────────────────────────────────────────────────────────────────────────╯
|
|
124
|
-
```
|
|
41
|
+
## Usage (interactive)
|
|
125
42
|
|
|
126
|
-
|
|
43
|
+
- Use ↑/↓ to navigate containers.
|
|
44
|
+
- I: start selected container
|
|
45
|
+
- P: stop selected container
|
|
46
|
+
- R: restart selected container
|
|
47
|
+
- C: create container (interactive prompt)
|
|
48
|
+
- L: view logs for selected container
|
|
49
|
+
- E: erase (remove) selected container (confirmation required)
|
|
50
|
+
- Q: quit
|
|
51
|
+
|
|
52
|
+
The dashboard auto-refreshes container list every few seconds.
|
|
127
53
|
|
|
128
54
|
---
|
|
129
55
|
|
|
130
|
-
##
|
|
131
|
-
CDD-CLI es una herramienta de línea de comandos (CLI) multiplataforma que te permite monitorear y visualizar en tiempo real el estado de tus contenedores Docker directamente desde la terminal, usando una interfaz moderna y colorida basada en React e Ink.
|
|
56
|
+
## Development
|
|
132
57
|
|
|
133
|
-
-
|
|
134
|
-
-
|
|
135
|
-
- Actualización automática cada 2 segundos.
|
|
136
|
-
- Interfaz amigable, con colores y emojis.
|
|
137
|
-
- Compatible con Linux, macOS y Windows (bash, cmd, PowerShell).
|
|
58
|
+
- Node.js >= 18 is recommended.
|
|
59
|
+
- To run the app from source during development:
|
|
138
60
|
|
|
139
|
-
|
|
61
|
+
```bash
|
|
62
|
+
npm install
|
|
63
|
+
npm run build
|
|
64
|
+
node dist/index.js
|
|
65
|
+
```
|
|
140
66
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
npm install -g cdd-cli
|
|
145
|
-
```
|
|
146
|
-
3. Ejecuta el dashboard desde cualquier terminal:
|
|
147
|
-
```bash
|
|
148
|
-
cdd
|
|
149
|
-
```
|
|
67
|
+
If you change source files, re-run `npm run build` before running the CLI.
|
|
68
|
+
|
|
69
|
+
---
|
|
150
70
|
|
|
151
|
-
##
|
|
152
|
-
- Al ejecutar `cdd`, verás una tabla interactiva con todos tus contenedores Docker.
|
|
153
|
-
- Los contenedores en ejecución muestran estadísticas de CPU y memoria en tiempo real.
|
|
154
|
-
- Puedes navegar usando las flechas ↑/↓ y controlar los contenedores con atajos de teclado.
|
|
155
|
-
- Usa `Ctrl+C` o la tecla `Q` para salir.
|
|
71
|
+
## Tests
|
|
156
72
|
|
|
157
|
-
|
|
73
|
+
We use Jest for unit tests. Run:
|
|
158
74
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
- L : Ver logs en tiempo real del contenedor seleccionado
|
|
163
|
-
- Q : Salir del dashboard o de la vista de logs
|
|
75
|
+
```bash
|
|
76
|
+
npm test
|
|
77
|
+
```
|
|
164
78
|
|
|
165
|
-
|
|
166
|
-
- 🐳 Visualización clara y compacta de todos los contenedores.
|
|
167
|
-
- 🔄 Refresco automático de datos.
|
|
168
|
-
- 📊 Estadísticas de uso de recursos para contenedores activos.
|
|
169
|
-
- 🎨 Interfaz visual con colores y emojis para estados.
|
|
170
|
-
- 👤 Autor: Carlos Cochero (2025)
|
|
79
|
+
Tests are located in `test/` and cover utility helpers.
|
|
171
80
|
|
|
172
|
-
|
|
173
|
-
- Node.js >= 18
|
|
174
|
-
- Docker instalado y corriendo (el CLI se conecta al socket local de Docker)
|
|
81
|
+
---
|
|
175
82
|
|
|
176
|
-
##
|
|
177
|
-
|
|
178
|
-
|
|
83
|
+
## Contributing
|
|
84
|
+
|
|
85
|
+
1. Fork the repo and create a feature branch.
|
|
86
|
+
2. Add tests for new behavior.
|
|
87
|
+
3. Ensure `npm test` and `npm run build` pass.
|
|
88
|
+
4. Open a Pull Request with a clear description.
|
|
179
89
|
|
|
180
90
|
---
|
|
181
91
|
|
|
182
|
-
|
|
92
|
+
## Troubleshooting
|
|
93
|
+
|
|
94
|
+
- If you don't see containers, ensure Docker is running and that your user has access to the Docker socket.
|
|
95
|
+
- If Docker permissions are required, run the CLI with `sudo` (Linux/macOS) or as Administrator (Windows).
|
|
96
|
+
- The project generates `dist/` — keep it out of version control (it's in .gitignore).
|
|
183
97
|
|
|
184
|
-
|
|
185
|
-
CDD-CLI is a cross-platform command-line tool (CLI) to monitor and visualize your Docker containers in real time, right from your terminal, using a modern React+Ink interface.
|
|
98
|
+
---
|
|
186
99
|
|
|
187
|
-
|
|
188
|
-
- Shows name, image, state, ports, and CPU/MEM stats.
|
|
189
|
-
- Auto-refresh every 2 seconds.
|
|
190
|
-
- Friendly, colorful, emoji-rich UI.
|
|
191
|
-
- Works on Linux, macOS, and Windows (bash, cmd, PowerShell).
|
|
100
|
+
## License
|
|
192
101
|
|
|
193
|
-
|
|
102
|
+
This project is MIT/ISC licensed (see `LICENSE`).
|
|
194
103
|
|
|
195
|
-
1. Make sure you have Node.js (v18+) and Docker installed and running.
|
|
196
|
-
2. Install the CLI globally from npm:
|
|
197
|
-
```bash
|
|
198
|
-
npm install -g cdd-cli
|
|
199
|
-
```
|
|
200
|
-
3. Run the dashboard from any terminal:
|
|
201
|
-
```bash
|
|
202
|
-
cdd
|
|
203
104
|
```
|
|
204
105
|
|
|
205
106
|
## Usage
|
package/SECURITY.md
ADDED
package/babel.config.cjs
ADDED
package/dist/App.js
CHANGED
|
@@ -1,21 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main React component for the CDD CLI UI.
|
|
3
|
+
* Componente principal de React para la UI del CLI CDD.
|
|
4
|
+
*
|
|
5
|
+
* @component
|
|
6
|
+
* @returns {JSX.Element} The rendered app / La app renderizada
|
|
7
|
+
* @example
|
|
8
|
+
* // EN: Render the app
|
|
9
|
+
* // ES: Renderizar la app
|
|
10
|
+
* <App />
|
|
11
|
+
*/
|
|
1
12
|
import React from "react";
|
|
2
13
|
import { Box, Text, Spacer } from "ink";
|
|
3
14
|
import { useContainers } from "./hooks/useContainers.js";
|
|
4
15
|
import { useControls } from "./hooks/useControls.js";
|
|
5
|
-
import
|
|
6
|
-
import MessageFeedback from "./components/MessageFeedback.
|
|
7
|
-
import Header from "./components/Header.
|
|
8
|
-
import LogViewer from "./components/LogViewer.
|
|
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";
|
|
9
23
|
export default function App() {
|
|
10
24
|
var _useContainers = useContainers(),
|
|
11
25
|
containers = _useContainers.containers;
|
|
12
|
-
var
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
26
|
+
var controls = useControls(containers);
|
|
27
|
+
if (controls.creatingContainer) {
|
|
28
|
+
return /*#__PURE__*/React.createElement(ContainerCreationPrompt, {
|
|
29
|
+
step: controls.creationStep,
|
|
30
|
+
imageName: controls.imageNameInput,
|
|
31
|
+
containerName: controls.containerNameInput,
|
|
32
|
+
portInput: controls.portInput,
|
|
33
|
+
envInput: controls.envInput,
|
|
34
|
+
message: controls.message,
|
|
35
|
+
messageColor: controls.messageColor
|
|
36
|
+
});
|
|
37
|
+
}
|
|
19
38
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Box, {
|
|
20
39
|
flexDirection: "column",
|
|
21
40
|
borderStyle: "round",
|
|
@@ -23,20 +42,15 @@ export default function App() {
|
|
|
23
42
|
padding: 1
|
|
24
43
|
}, /*#__PURE__*/React.createElement(Header, {
|
|
25
44
|
count: containers.length
|
|
26
|
-
}), /*#__PURE__*/React.createElement(Text, null, " "),
|
|
45
|
+
}), /*#__PURE__*/React.createElement(Text, null, " "), /*#__PURE__*/React.createElement(ContainerSection, {
|
|
27
46
|
containers: containers,
|
|
28
|
-
selected: selected
|
|
47
|
+
selected: controls.selected
|
|
29
48
|
}), /*#__PURE__*/React.createElement(Spacer, null), /*#__PURE__*/React.createElement(MessageFeedback, {
|
|
30
|
-
message: message,
|
|
31
|
-
color: messageColor
|
|
32
|
-
}), /*#__PURE__*/React.createElement(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
dimColor: true
|
|
37
|
-
}, "Crafted by Carlos Cochero \u2022 2025"))), showLogs && /*#__PURE__*/React.createElement(LogViewer, {
|
|
38
|
-
logs: logs,
|
|
39
|
-
onExit: exitLogs,
|
|
40
|
-
container: containers[selected]
|
|
49
|
+
message: controls.message,
|
|
50
|
+
color: controls.messageColor
|
|
51
|
+
}), /*#__PURE__*/React.createElement(UsageMenu, null), /*#__PURE__*/React.createElement(Footer, null)), controls.showLogs && /*#__PURE__*/React.createElement(LogViewer, {
|
|
52
|
+
logs: controls.logs,
|
|
53
|
+
onExit: controls.exitLogs,
|
|
54
|
+
container: containers[controls.selected]
|
|
41
55
|
}));
|
|
42
56
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import Rt from"react";import{render as $t}from"ink";import x from"react";import{Box as Lt,Text as jt,Spacer as Dt}from"ink";import{useState as tt,useEffect as rt}from"react";import et from"dockerode";var f=new et({socketPath:"/var/run/docker.sock"});async function Ee(){return(await f.listContainers({all:!0})).map(e=>({id:e.Id,name:e.Names[0].replace("/",""),image:e.Image,state:e.State,status:e.Status,ports:[...new Set(e.Ports.filter(r=>r.PublicPort).map(r=>`${r.PublicPort}:${r.PrivatePort}`))]}))}function Ie(){let[t,e]=tt([]);return rt(()=>{let r=async()=>e(await Ee());r();let o=setInterval(r,3e3);return()=>clearInterval(o)},[]),{containers:t}}import{useState as T,useRef as ot}from"react";import{useInput as nt}from"ink";async function Oe(t){return(await f.listImages()).some(r=>(r.RepoTags||[]).includes(t)||(r.RepoDigests||[]).some(o=>o.includes(t)))}async function Be(t){await new Promise((e,r)=>{f.pull(t,(o,n)=>{if(o)return r(new Error("Error al hacer pull de la imagen: "+o.message));f.modem.followProgress(n,s=>{s?r(new Error("Error durante el pull: "+s.message)):e()})})})}async function ve(t,e={}){let r;try{r=await Oe(t)}catch(n){throw new Error("Error al listar im\xE1genes locales: "+n.message)}if(!r)try{await Be(t)}catch(n){throw new Error("No se pudo descargar la imagen: "+n.message)}let o={Image:t,Tty:!0,...e};try{let n=await f.createContainer(o);return n.id||n.Id}catch(n){throw new Error("Error al crear el contenedor: "+n.message)}}async function Se(t){await f.getContainer(t).start()}async function Ae(t){await f.getContainer(t).stop()}async function Ne(t){await f.getContainer(t).restart()}function Pe(t,e,r,o){f.getContainer(t).logs({follow:!0,stdout:!0,stderr:!0,tail:100},(s,i)=>{if(s){o?.(s);return}i.on("data",u=>e?.(u.toString())),i.on("end",()=>r?.()),i.on("error",u=>o?.(u))})}async function Y({containers:t,selected:e,actionFn:r,actionLabel:o,setMessage:n,setMessageColor:s,stateCheck:i}){let u=t[e];if(u){if(i&&i(u)){n(i(u)),s("red"),setTimeout(()=>n(""),2e3);return}n(`${o} container...`),s("green");try{await r(u.id),n(`${o} container...`),s("green"),setTimeout(()=>n(""),3e3)}catch{n(`Failed to ${o.toLowerCase()} container.`),s("red"),setTimeout(()=>n(""),3e3)}}}import{spawn as Fe}from"child_process";function _e({setMessage:t,setMessageColor:e,message:r="Exiting...",color:o="yellow",delay:n=1500}){t(r),e(o),setTimeout(()=>{t(""),process.platform==="win32"?Fe("cmd",["/c","cls"],{stdio:"inherit"}):Fe("clear",[],{stdio:"inherit"}),process.exit()},n)}function Me(t=[]){let[e,r]=T(0),[o,n]=T(""),[s,i]=T("yellow"),[u,w]=T(!1),[E,b]=T([]),[m,C]=T(!1),[B,F]=T(""),[z,G]=T(""),[Q,_]=T(""),[X,M]=T(""),[p,S]=T(0),J=ot(null),U=t.length,Z=()=>{w(!1),b([]),J.current&&(J.current.destroy?.(),J.current=null)};return nt(async(d,V)=>{if(u){(d==="q"||V.escape)&&Z();return}if(m){if(V.escape){C(!1),F(""),G(""),_(""),M(""),S(0),n("Creaci\xF3n cancelada"),i("yellow");return}if(d==="\r"){if(p===0){if(!B.trim()){n("El nombre de la imagen no puede estar vac\xEDo."),i("red");return}S(1),n("Opcional: Ingresa el nombre del contenedor o deja vac\xEDo y presiona Enter"),i("yellow");return}if(p===1){S(2),n("Opcional: Ingresa puertos (formato 8080:80,443:443) o deja vac\xEDo y presiona Enter"),i("yellow");return}if(p===2){S(3),n("Opcional: Ingresa variables de entorno (formato VAR1=val1,VAR2=val2) o deja vac\xEDo y presiona Enter"),i("yellow");return}if(p===3){let a={};if(z.trim()&&(a.name=z.trim()),Q.trim()){let h=Q.split(",").map(ee=>ee.trim()).filter(Boolean);a.ExposedPorts={},a.HostConfig={PortBindings:{}},h.forEach(ee=>{let[we,te]=ee.split(":");we&&te&&(a.ExposedPorts[`${te}/tcp`]={},a.HostConfig.PortBindings[`${te}/tcp`]=[{HostPort:we}])})}X.trim()&&(a.Env=X.split(",").map(h=>h.trim()).filter(Boolean)),n("Creando contenedor..."),i("yellow");try{let h=await ve(B.trim(),a);n(`Contenedor creado con ID: ${h}`),i("green")}catch(h){n(`Error: ${h.message}`),i("red")}setTimeout(()=>{C(!1),F(""),G(""),_(""),M(""),S(0)},2500);return}}else d==="\x7F"?(p===0&&F(a=>a.slice(0,-1)),p===1&&G(a=>a.slice(0,-1)),p===2&&_(a=>a.slice(0,-1)),p===3&&M(a=>a.slice(0,-1))):(p===0&&F(a=>a+d),p===1&&G(a=>a+d),p===2&&_(a=>a+d),p===3&&M(a=>a+d));return}if(V.upArrow&&U>0&&r(a=>a===0?U-1:a-1),V.downArrow&&U>0&&r(a=>a===U-1?0:a+1),d==="q"){_e({setMessage:n,setMessageColor:i});return}if(d==="i"&&Y({containers:t,selected:e,actionFn:Se,actionLabel:"Starting",setMessage:n,setMessageColor:i,stateCheck:a=>(a.state==="running"||a.status==="running")&&"Container is already running."}),d==="p"&&Y({containers:t,selected:e,actionFn:Ae,actionLabel:"Stopping",setMessage:n,setMessageColor:i,stateCheck:a=>(a.state==="exited"||a.status==="exited"||a.state==="stopped"||a.status==="stopped")&&"Container is already stopped."}),d==="r"&&Y({containers:t,selected:e,actionFn:Ne,actionLabel:"Restarting",setMessage:n,setMessageColor:i}),d==="l"&&t[e])return w(!0),b([]),Pe(t[e].id,a=>b(h=>[...h,...a.split(`
|
|
3
|
+
`).filter(Boolean)]),()=>{},a=>b(h=>[...h,`Error: ${a.message}`])),{selected:e,setSelected:r,message:o,messageColor:s,showLogs:u,logs:E,exitLogs:Z};d==="c"&&(C(!0),F(""),_(""),M(""),S(0),n("Ingresa el nombre de la imagen Docker y presiona Enter"),i("yellow"))}),{selected:e,setSelected:r,message:o,messageColor:s,showLogs:u,logs:E,exitLogs:Z,creatingContainer:m,imageNameInput:B,containerNameInput:z,portInput:Q,envInput:X,creationStep:p}}import D from"react";import{Box as It,Text as Ot}from"ink";import I,{useState as Ke,useEffect as wt}from"react";import{Box as le,Text as j}from"ink";async function ke(t){let r=await f.getContainer(t).stats({stream:!1}),o=r.cpu_stats.cpu_usage.total_usage-r.precpu_stats.cpu_usage.total_usage,n=r.cpu_stats.system_cpu_usage-r.precpu_stats.system_cpu_usage,s=n>0?o/n*100:0,i=r.memory_stats.usage||0,u=r.memory_stats.limit||1,w=i/u*100,E=r.networks?Object.values(r.networks).map(m=>m.rx_bytes).reduce((m,C)=>m+C,0):0,b=r.networks?Object.values(r.networks).map(m=>m.tx_bytes).reduce((m,C)=>m+C,0):0;return{cpuPercent:s.toFixed(1),memPercent:w.toFixed(1),netIO:{rx:E,tx:b}}}import Tt from"react";import{Text as yt}from"ink";var Le=(t=0)=>e=>`\x1B[${e+t}m`,je=(t=0)=>e=>`\x1B[${38+t};5;${e}m`,De=(t=0)=>(e,r,o)=>`\x1B[${38+t};2;${e};${r};${o}m`,l={modifier:{reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],overline:[53,55],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],blackBright:[90,39],gray:[90,39],grey:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],bgBlackBright:[100,49],bgGray:[100,49],bgGrey:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]}},gr=Object.keys(l.modifier),it=Object.keys(l.color),st=Object.keys(l.bgColor),xr=[...it,...st];function at(){let t=new Map;for(let[e,r]of Object.entries(l)){for(let[o,n]of Object.entries(r))l[o]={open:`\x1B[${n[0]}m`,close:`\x1B[${n[1]}m`},r[o]=l[o],t.set(n[0],n[1]);Object.defineProperty(l,e,{value:r,enumerable:!1})}return Object.defineProperty(l,"codes",{value:t,enumerable:!1}),l.color.close="\x1B[39m",l.bgColor.close="\x1B[49m",l.color.ansi=Le(),l.color.ansi256=je(),l.color.ansi16m=De(),l.bgColor.ansi=Le(10),l.bgColor.ansi256=je(10),l.bgColor.ansi16m=De(10),Object.defineProperties(l,{rgbToAnsi256:{value(e,r,o){return e===r&&r===o?e<8?16:e>248?231:Math.round((e-8)/247*24)+232:16+36*Math.round(e/255*5)+6*Math.round(r/255*5)+Math.round(o/255*5)},enumerable:!1},hexToRgb:{value(e){let r=/[a-f\d]{6}|[a-f\d]{3}/i.exec(e.toString(16));if(!r)return[0,0,0];let[o]=r;o.length===3&&(o=[...o].map(s=>s+s).join(""));let n=Number.parseInt(o,16);return[n>>16&255,n>>8&255,n&255]},enumerable:!1},hexToAnsi256:{value:e=>l.rgbToAnsi256(...l.hexToRgb(e)),enumerable:!1},ansi256ToAnsi:{value(e){if(e<8)return 30+e;if(e<16)return 90+(e-8);let r,o,n;if(e>=232)r=((e-232)*10+8)/255,o=r,n=r;else{e-=16;let u=e%36;r=Math.floor(e/36)/5,o=Math.floor(u/6)/5,n=u%6/5}let s=Math.max(r,o,n)*2;if(s===0)return 30;let i=30+(Math.round(n)<<2|Math.round(o)<<1|Math.round(r));return s===2&&(i+=60),i},enumerable:!1},rgbToAnsi:{value:(e,r,o)=>l.ansi256ToAnsi(l.rgbToAnsi256(e,r,o)),enumerable:!1},hexToAnsi:{value:e=>l.ansi256ToAnsi(l.hexToAnsi256(e)),enumerable:!1}}),l}var lt=at(),y=lt;import re from"node:process";import ct from"node:os";import Re from"node:tty";function g(t,e=globalThis.Deno?globalThis.Deno.args:re.argv){let r=t.startsWith("-")?"":t.length===1?"-":"--",o=e.indexOf(r+t),n=e.indexOf("--");return o!==-1&&(n===-1||o<n)}var{env:c}=re,q;g("no-color")||g("no-colors")||g("color=false")||g("color=never")?q=0:(g("color")||g("colors")||g("color=true")||g("color=always"))&&(q=1);function ut(){if("FORCE_COLOR"in c)return c.FORCE_COLOR==="true"?1:c.FORCE_COLOR==="false"?0:c.FORCE_COLOR.length===0?1:Math.min(Number.parseInt(c.FORCE_COLOR,10),3)}function mt(t){return t===0?!1:{level:t,hasBasic:!0,has256:t>=2,has16m:t>=3}}function ft(t,{streamIsTTY:e,sniffFlags:r=!0}={}){let o=ut();o!==void 0&&(q=o);let n=r?q:o;if(n===0)return 0;if(r){if(g("color=16m")||g("color=full")||g("color=truecolor"))return 3;if(g("color=256"))return 2}if("TF_BUILD"in c&&"AGENT_NAME"in c)return 1;if(t&&!e&&n===void 0)return 0;let s=n||0;if(c.TERM==="dumb")return s;if(re.platform==="win32"){let i=ct.release().split(".");return Number(i[0])>=10&&Number(i[2])>=10586?Number(i[2])>=14931?3:2:1}if("CI"in c)return["GITHUB_ACTIONS","GITEA_ACTIONS","CIRCLECI"].some(i=>i in c)?3:["TRAVIS","APPVEYOR","GITLAB_CI","BUILDKITE","DRONE"].some(i=>i in c)||c.CI_NAME==="codeship"?1:s;if("TEAMCITY_VERSION"in c)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(c.TEAMCITY_VERSION)?1:0;if(c.COLORTERM==="truecolor"||c.TERM==="xterm-kitty"||c.TERM==="xterm-ghostty"||c.TERM==="wezterm")return 3;if("TERM_PROGRAM"in c){let i=Number.parseInt((c.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(c.TERM_PROGRAM){case"iTerm.app":return i>=3?3:2;case"Apple_Terminal":return 2}}return/-256(color)?$/i.test(c.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(c.TERM)||"COLORTERM"in c?1:s}function $e(t,e={}){let r=ft(t,{streamIsTTY:t&&t.isTTY,...e});return mt(r)}var pt={stdout:$e({isTTY:Re.isatty(1)}),stderr:$e({isTTY:Re.isatty(2)})},Ge=pt;function Ue(t,e,r){let o=t.indexOf(e);if(o===-1)return t;let n=e.length,s=0,i="";do i+=t.slice(s,o)+e+r,s=o+n,o=t.indexOf(e,s);while(o!==-1);return i+=t.slice(s),i}function Ve(t,e,r,o){let n=0,s="";do{let i=t[o-1]==="\r";s+=t.slice(n,i?o-1:o)+e+(i?`\r
|
|
4
|
+
`:`
|
|
5
|
+
`)+r,n=o+1,o=t.indexOf(`
|
|
6
|
+
`,n)}while(o!==-1);return s+=t.slice(n),s}var{stdout:Ye,stderr:qe}=Ge,oe=Symbol("GENERATOR"),A=Symbol("STYLER"),k=Symbol("IS_EMPTY"),We=["ansi","ansi","ansi256","ansi16m"],N=Object.create(null),dt=(t,e={})=>{if(e.level&&!(Number.isInteger(e.level)&&e.level>=0&&e.level<=3))throw new Error("The `level` option should be an integer from 0 to 3");let r=Ye?Ye.level:0;t.level=e.level===void 0?r:e.level};var gt=t=>{let e=(...r)=>r.join(" ");return dt(e,t),Object.setPrototypeOf(e,L.prototype),e};function L(t){return gt(t)}Object.setPrototypeOf(L.prototype,Function.prototype);for(let[t,e]of Object.entries(y))N[t]={get(){let r=W(this,ie(e.open,e.close,this[A]),this[k]);return Object.defineProperty(this,t,{value:r}),r}};N.visible={get(){let t=W(this,this[A],!0);return Object.defineProperty(this,"visible",{value:t}),t}};var ne=(t,e,r,...o)=>t==="rgb"?e==="ansi16m"?y[r].ansi16m(...o):e==="ansi256"?y[r].ansi256(y.rgbToAnsi256(...o)):y[r].ansi(y.rgbToAnsi(...o)):t==="hex"?ne("rgb",e,r,...y.hexToRgb(...o)):y[r][t](...o),xt=["rgb","hex","ansi256"];for(let t of xt){N[t]={get(){let{level:r}=this;return function(...o){let n=ie(ne(t,We[r],"color",...o),y.color.close,this[A]);return W(this,n,this[k])}}};let e="bg"+t[0].toUpperCase()+t.slice(1);N[e]={get(){let{level:r}=this;return function(...o){let n=ie(ne(t,We[r],"bgColor",...o),y.bgColor.close,this[A]);return W(this,n,this[k])}}}}var bt=Object.defineProperties(()=>{},{...N,level:{enumerable:!0,get(){return this[oe].level},set(t){this[oe].level=t}}}),ie=(t,e,r)=>{let o,n;return r===void 0?(o=t,n=e):(o=r.openAll+t,n=e+r.closeAll),{open:t,close:e,openAll:o,closeAll:n,parent:r}},W=(t,e,r)=>{let o=(...n)=>Ct(o,n.length===1?""+n[0]:n.join(" "));return Object.setPrototypeOf(o,bt),o[oe]=t,o[A]=e,o[k]=r,o},Ct=(t,e)=>{if(t.level<=0||!e)return t[k]?"":e;let r=t[A];if(r===void 0)return e;let{openAll:o,closeAll:n}=r;if(e.includes("\x1B"))for(;r!==void 0;)e=Ue(e,r.close,r.open),r=r.parent;let s=e.indexOf(`
|
|
7
|
+
`);return s!==-1&&(e=Ve(e,n,o,s)),o+e+n};Object.defineProperties(L.prototype,N);var ht=L(),Br=L({level:qe?qe.level:0});var P=ht;function ae({cpu:t,mem:e}){let r=He(t),o=He(e);return Tt.createElement(yt,null,"CPU: ",r," ",se(t),"% MEM: ",o," ",se(e),"%")}function He(t){let e=Math.round(t/10),r=10-e,o="\u2593".repeat(e)+"\u2591".repeat(r);return se(t,o)}function se(t,e=t.toString()){return t<50?P.greenBright(e):t<80?P.yellowBright(e):P.redBright(e)}var Et=t=>t==="running"?{text:"\u{1F7E2} RUNNING",color:"green"}:t==="exited"?{text:"\u{1F534} EXITED",color:"red"}:t==="paused"?{text:"\u{1F7E0} PAUSED",color:"yellow"}:{text:t.toUpperCase(),color:"gray"};function ce({container:t}){let{id:e,name:r,image:o,state:n}=t,[s,i]=Ke({cpuPercent:0,memPercent:0,netIO:{rx:0,tx:0}}),u=m=>!m||m.length===0?"":Array.isArray(m)?m.map((C,B)=>`\u{1F517} ${C}`).join(" "):`\u{1F517} ${m}`,[w,E]=Ke("");wt(()=>{if(n!=="running")return;let m=async()=>{try{let B=await ke(e);i(B),E("")}catch{i({cpuPercent:0,memPercent:0,netIO:{rx:0,tx:0}}),E("No se pudo obtener stats")}};m();let C=setInterval(m,1500);return()=>clearInterval(C)},[e,n]);let b=Et(n);return I.createElement(le,{flexDirection:"column",marginBottom:1},I.createElement(le,null,I.createElement(j,{color:"cyan"},r.padEnd(20))," ",I.createElement(j,{color:"gray"},o.padEnd(20))," ",I.createElement(j,{color:b.color},b.text)," ",I.createElement(j,{color:"yellow"},u(t.ports))),n==="running"&&I.createElement(le,{marginLeft:2},I.createElement(ae,{cpu:parseFloat(s.cpuPercent),mem:parseFloat(s.memPercent)}),w&&I.createElement(j,{color:"red"},w)))}function ue({containers:t,selected:e}){return D.createElement(D.Fragment,null,t.map((r,o)=>D.createElement(It,{key:r.id,flexDirection:"row",alignItems:"center"},D.createElement(Ot,{color:o===e?"green":void 0},o===e?"\u27A4":" "),D.createElement(ce,{container:r,isSelected:o===e}))))}import ze from"react";import{Text as Bt}from"ink";function me({containers:t,selected:e}){return t.length===0?ze.createElement(Bt,null,"No containers found"):ze.createElement(ue,{containers:t,selected:e})}import Qe from"react";import{Box as vt,Text as St}from"ink";function fe({message:t,color:e}){return t?Qe.createElement(vt,{marginBottom:1},Qe.createElement(St,{color:e},t)):null}import H from"react";import{Box as At,Text as pe}from"ink";function de({count:t}){return H.createElement(At,{justifyContent:"space-between"},H.createElement(pe,{color:"cyanBright"},"\u{1F433} ",P.bold("CDD"),H.createElement(pe,{color:"gray"}," \u2014 CLI Docker Dashboard")),H.createElement(pe,{color:"gray"},t," container",t===1?"":"s"," found"))}import R from"react";import{Text as ge,useInput as Nt}from"ink";function xe({logs:t,onExit:e,container:r}){Nt((n,s)=>{s.escape&&e()});let o=t.slice(-15);return R.createElement(R.Fragment,null,R.createElement(ge,{color:"green"},r?.name||"Container"," logs, press ESC to exit"),o.length===0?R.createElement(ge,{dimColor:!0},"No logs..."):o.map((n,s)=>R.createElement(ge,{key:s},n)))}import K from"react";import{Box as Pt,Text as Ft}from"ink";import $ from"react";import{Text as be}from"ink";function Xe({label:t,value:e,required:r}){let o=r&&!e.trim();return $.createElement($.Fragment,null,$.createElement(be,null,t),$.createElement(be,{color:o?"red":"cyan"},e,"_"))}function Je({message:t,color:e}){return t?$.createElement(be,{color:e||"yellow"},t):null}function Ce(t){let{step:e,imageName:r,containerName:o,portInput:n,envInput:s,message:i,messageColor:u}=t,w=[{label:"Nombre de la imagen Docker:",value:r,required:!0},{label:"Nombre del contenedor (opcional):",value:o,required:!1},{label:"Puertos (opcional, formato 8080:80,443:443):",value:n,required:!1},{label:"Variables de entorno (opcional, formato VAR1=val1,VAR2=val2):",value:s,required:!1}],{label:E,value:b,required:m}=w[e]||{};return K.createElement(Pt,{flexDirection:"column",borderStyle:"round",borderColor:"yellow",padding:1},K.createElement(Xe,{label:E,value:b,required:m}),K.createElement(Je,{message:i,color:u}),K.createElement(Ft,{dimColor:!0},"Presiona Enter para continuar, Escape para cancelar"))}import O from"react";import{Box as _t,Text as v}from"ink";function he(){return O.createElement(_t,{flexDirection:"column",marginTop:1},O.createElement(v,null,"Use \u2191/\u2193 for navigation"),O.createElement(v,null,"\u2022I to initiate selected container"),O.createElement(v,null,"\u2022P to stop selected container"),O.createElement(v,null,"\u2022R to restart selected container"),O.createElement(v,null,"\u2022C to create a container"),O.createElement(v,null,"\u2022L to view logs of selected container"),O.createElement(v,null,"\u2022Q to quit"))}import Ze from"react";import{Box as Mt,Text as kt}from"ink";function Te(){return Ze.createElement(Mt,{justifyContent:"flex-end",width:"100%"},Ze.createElement(kt,{dimColor:!0},"Crafted by Carlos Cochero \u2022 2025"))}function ye(){let{containers:t}=Ie(),e=Me(t);return e.creatingContainer?x.createElement(Ce,{step:e.creationStep,imageName:e.imageNameInput,containerName:e.containerNameInput,portInput:e.portInput,envInput:e.envInput,message:e.message,messageColor:e.messageColor}):x.createElement(x.Fragment,null,x.createElement(Lt,{flexDirection:"column",borderStyle:"round",borderColor:"cyan",padding:1},x.createElement(de,{count:t.length}),x.createElement(jt,null," "),x.createElement(me,{containers:t,selected:e.selected}),x.createElement(Dt,null),x.createElement(fe,{message:e.message,color:e.messageColor}),x.createElement(he,null),x.createElement(Te,null)),e.showLogs&&x.createElement(xe,{logs:e.logs,onExit:e.exitLogs,container:t[e.selected]}))}$t(Rt.createElement(ye,null));
|
|
8
|
+
//# sourceMappingURL=cdd.bundle.js.map
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Box, Text } from "ink";
|
|
3
|
+
import { PromptField, PromptMessage } from "./PromptField.jsx";
|
|
4
|
+
export default function ContainerCreationPrompt(props) {
|
|
5
|
+
var step = props.step,
|
|
6
|
+
imageName = props.imageName,
|
|
7
|
+
containerName = props.containerName,
|
|
8
|
+
portInput = props.portInput,
|
|
9
|
+
envInput = props.envInput,
|
|
10
|
+
message = props.message,
|
|
11
|
+
messageColor = props.messageColor;
|
|
12
|
+
var prompts = [{
|
|
13
|
+
label: "Name of the image to create (e.g., nginx:latest):",
|
|
14
|
+
value: imageName,
|
|
15
|
+
required: true
|
|
16
|
+
}, {
|
|
17
|
+
label: "Name of the container (optional):",
|
|
18
|
+
value: containerName,
|
|
19
|
+
required: false
|
|
20
|
+
}, {
|
|
21
|
+
label: "Ports (optional, format 8080:80,443:443):",
|
|
22
|
+
value: portInput,
|
|
23
|
+
required: false
|
|
24
|
+
}, {
|
|
25
|
+
label: "Environment variables (optional, format VAR1=val1,VAR2=val2):",
|
|
26
|
+
value: envInput,
|
|
27
|
+
required: false
|
|
28
|
+
}];
|
|
29
|
+
var _ref = prompts[step] || {},
|
|
30
|
+
label = _ref.label,
|
|
31
|
+
value = _ref.value,
|
|
32
|
+
required = _ref.required;
|
|
33
|
+
return /*#__PURE__*/React.createElement(Box, {
|
|
34
|
+
flexDirection: "column",
|
|
35
|
+
borderStyle: "round",
|
|
36
|
+
borderColor: "yellow",
|
|
37
|
+
padding: 1
|
|
38
|
+
}, /*#__PURE__*/React.createElement(PromptField, {
|
|
39
|
+
label: label,
|
|
40
|
+
value: value,
|
|
41
|
+
required: required
|
|
42
|
+
}), /*#__PURE__*/React.createElement(PromptMessage, {
|
|
43
|
+
message: message,
|
|
44
|
+
color: messageColor
|
|
45
|
+
}), /*#__PURE__*/React.createElement(Text, {
|
|
46
|
+
dimColor: true
|
|
47
|
+
}, "Press Enter to continue, Escape to cancel"));
|
|
48
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
2
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
3
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
4
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
5
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
6
|
+
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
7
|
+
import React from "react";
|
|
8
|
+
import { Box, Text } from "ink";
|
|
9
|
+
import { createContainer } from "../helpers/dockerService.js";
|
|
10
|
+
export default function ContainerCreator(_ref) {
|
|
11
|
+
var onClose = _ref.onClose;
|
|
12
|
+
var _React$useState = React.useState(""),
|
|
13
|
+
_React$useState2 = _slicedToArray(_React$useState, 2),
|
|
14
|
+
imageName = _React$useState2[0],
|
|
15
|
+
setImageName = _React$useState2[1];
|
|
16
|
+
var _React$useState3 = React.useState(""),
|
|
17
|
+
_React$useState4 = _slicedToArray(_React$useState3, 2),
|
|
18
|
+
message = _React$useState4[0],
|
|
19
|
+
setMessage = _React$useState4[1];
|
|
20
|
+
var handleInput = function handleInput(data) {
|
|
21
|
+
var _char = String(data);
|
|
22
|
+
if (_char === "\r") {
|
|
23
|
+
// Enter key
|
|
24
|
+
if (imageName.trim() === "") {
|
|
25
|
+
setMessage("Image name cannot be empty.");
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
createContainer(imageName.trim()).then(function (id) {
|
|
29
|
+
setMessage("Container created with ID: ".concat(id));
|
|
30
|
+
setTimeout(onClose, 2000);
|
|
31
|
+
})["catch"](function (err) {
|
|
32
|
+
setMessage("Error: ".concat(err.message));
|
|
33
|
+
});
|
|
34
|
+
} else if (_char === "\x03") {
|
|
35
|
+
// Ctrl+C
|
|
36
|
+
onClose();
|
|
37
|
+
} else if (_char === "\x7F") {
|
|
38
|
+
// Backspace
|
|
39
|
+
setImageName(function (prev) {
|
|
40
|
+
return prev.slice(0, -1);
|
|
41
|
+
});
|
|
42
|
+
} else {
|
|
43
|
+
setImageName(function (prev) {
|
|
44
|
+
return prev + _char;
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
React.useEffect(function () {
|
|
49
|
+
process.stdin.setRawMode(true);
|
|
50
|
+
process.stdin.resume();
|
|
51
|
+
process.stdin.on("data", handleInput);
|
|
52
|
+
return function () {
|
|
53
|
+
process.stdin.setRawMode(false);
|
|
54
|
+
process.stdin.pause();
|
|
55
|
+
process.stdin.removeListener("data", handleInput);
|
|
56
|
+
};
|
|
57
|
+
}, [imageName]);
|
|
58
|
+
return /*#__PURE__*/React.createElement(Box, {
|
|
59
|
+
flexDirection: "column",
|
|
60
|
+
borderStyle: "round",
|
|
61
|
+
borderColor: "yellow",
|
|
62
|
+
padding: 1
|
|
63
|
+
}, /*#__PURE__*/React.createElement(Text, null, "Enter Docker Image Name:"), /*#__PURE__*/React.createElement(Text, {
|
|
64
|
+
color: "cyan"
|
|
65
|
+
}, imageName, "_"), message && /*#__PURE__*/React.createElement(Text, {
|
|
66
|
+
color: "green"
|
|
67
|
+
}, message), /*#__PURE__*/React.createElement(Text, {
|
|
68
|
+
dimColor: true
|
|
69
|
+
}, "Press Enter to create or Ctrl+C to cancel"));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Docker service helper functions.
|
|
74
|
+
* Funciones auxiliares para el servicio Docker.
|
|
75
|
+
*
|
|
76
|
+
* @module dockerService
|
|
77
|
+
* @example
|
|
78
|
+
* // EN: Create a new container
|
|
79
|
+
* // ES: Crear un nuevo contenedor
|
|
80
|
+
* const containerId = await createContainer("my-image");
|
|
81
|
+
* */
|