cdd-cli 3.0.0 → 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/LICENSE +23 -0
- package/README.md +73 -161
- 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 +43 -26
- package/src/components/ContainerCreationPrompt.jsx +37 -0
- package/src/components/ContainerList.jsx +23 -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 +11 -1
- package/src/hooks/useControls.js +176 -55
- package/src/hooks/useLogsStream.js +1 -1
- package/src/index.js +13 -0
- package/test/validationHelpers.test.js +28 -0
- package/PLAN_KEYBINDINGS_Y_REALTIME.md +0 -260
- package/src/components/StatsViewer.jsx +0 -0
- package/src/helpers/dockerActions.js +0 -39
- package/src/helpers/dockerService.js +0 -88
|
@@ -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/LICENSE
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
SPDX-License-Identifier: MIT
|
|
4
|
+
|
|
5
|
+
Copyright (c) 2025 caertos
|
|
6
|
+
|
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
in the Software without restriction, including without limitation the rights
|
|
10
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
furnished to do so, subject to the following conditions:
|
|
13
|
+
|
|
14
|
+
The above copyright notice and this permission notice shall be included in all
|
|
15
|
+
copies or substantial portions of the Software.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
23
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,196 +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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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)
|
|
16
|
+
|
|
17
|
+
1. Clone the repo and install dependencies:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
git clone https://github.com/caertos/cdd.git
|
|
21
|
+
cd cdd
|
|
22
|
+
npm install
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
2. Build and run locally:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm run build
|
|
29
|
+
node dist/index.js
|
|
30
|
+
```
|
|
66
31
|
|
|
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
|
-
```
|
|
32
|
+
3. To test the CLI as a globally available command during development:
|
|
74
33
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
34
|
+
```bash
|
|
35
|
+
npm link
|
|
36
|
+
cdd
|
|
37
|
+
```
|
|
79
38
|
|
|
80
39
|
---
|
|
81
40
|
|
|
41
|
+
## Usage (interactive)
|
|
82
42
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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
|
|
87
51
|
|
|
88
|
-
|
|
89
|
-
[English version below]
|
|
52
|
+
The dashboard auto-refreshes container list every few seconds.
|
|
90
53
|
|
|
91
54
|
---
|
|
92
55
|
|
|
93
|
-
##
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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
|
-
╰────────────────────────────────────────────────────────────────────────────╯
|
|
56
|
+
## Development
|
|
57
|
+
|
|
58
|
+
- Node.js >= 18 is recommended.
|
|
59
|
+
- To run the app from source during development:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npm install
|
|
63
|
+
npm run build
|
|
64
|
+
node dist/index.js
|
|
124
65
|
```
|
|
125
66
|
|
|
126
|
-
|
|
67
|
+
If you change source files, re-run `npm run build` before running the CLI.
|
|
127
68
|
|
|
128
69
|
---
|
|
129
70
|
|
|
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.
|
|
71
|
+
## Tests
|
|
132
72
|
|
|
133
|
-
|
|
134
|
-
- Muestra nombre, imagen, estado, puertos y estadísticas de CPU/MEM.
|
|
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).
|
|
73
|
+
We use Jest for unit tests. Run:
|
|
138
74
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
2. Instala el CLI globalmente desde npm:
|
|
143
|
-
```bash
|
|
144
|
-
npm install -g cdd-cli
|
|
145
|
-
```
|
|
146
|
-
3. Ejecuta el dashboard desde cualquier terminal:
|
|
147
|
-
```bash
|
|
148
|
-
cdd
|
|
149
|
-
```
|
|
75
|
+
```bash
|
|
76
|
+
npm test
|
|
77
|
+
```
|
|
150
78
|
|
|
151
|
-
|
|
152
|
-
- Al ejecutar `cdd`, verás una tabla con todos tus contenedores Docker.
|
|
153
|
-
- Los contenedores en ejecución muestran estadísticas de CPU y memoria en tiempo real.
|
|
154
|
-
- Usa `Ctrl+C` para salir.
|
|
79
|
+
Tests are located in `test/` and cover utility helpers.
|
|
155
80
|
|
|
156
|
-
|
|
157
|
-
- 🐳 Visualización clara y compacta de todos los contenedores.
|
|
158
|
-
- 🔄 Refresco automático de datos.
|
|
159
|
-
- 📊 Estadísticas de uso de recursos para contenedores activos.
|
|
160
|
-
- 🎨 Interfaz visual con colores y emojis para estados.
|
|
161
|
-
- 👤 Autor: Carlos Cochero (2025)
|
|
81
|
+
---
|
|
162
82
|
|
|
163
|
-
##
|
|
164
|
-
- Node.js >= 18
|
|
165
|
-
- Docker instalado y corriendo (el CLI se conecta al socket local de Docker)
|
|
83
|
+
## Contributing
|
|
166
84
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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.
|
|
170
89
|
|
|
171
90
|
---
|
|
172
91
|
|
|
173
|
-
|
|
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).
|
|
174
97
|
|
|
175
|
-
|
|
176
|
-
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
|
+
---
|
|
177
99
|
|
|
178
|
-
|
|
179
|
-
- Shows name, image, state, ports, and CPU/MEM stats.
|
|
180
|
-
- Auto-refresh every 2 seconds.
|
|
181
|
-
- Friendly, colorful, emoji-rich UI.
|
|
182
|
-
- Works on Linux, macOS, and Windows (bash, cmd, PowerShell).
|
|
100
|
+
## License
|
|
183
101
|
|
|
184
|
-
|
|
102
|
+
This project is MIT/ISC licensed (see `LICENSE`).
|
|
185
103
|
|
|
186
|
-
1. Make sure you have Node.js (v18+) and Docker installed and running.
|
|
187
|
-
2. Install the CLI globally from npm:
|
|
188
|
-
```bash
|
|
189
|
-
npm install -g cdd-cli
|
|
190
|
-
```
|
|
191
|
-
3. Run the dashboard from any terminal:
|
|
192
|
-
```bash
|
|
193
|
-
cdd
|
|
194
104
|
```
|
|
195
105
|
|
|
196
106
|
## Usage
|
|
@@ -200,8 +110,10 @@ CDD-CLI is a cross-platform command-line tool (CLI) to monitor and visualize you
|
|
|
200
110
|
|
|
201
111
|
## Main features
|
|
202
112
|
- 🐳 Clear, compact visualization of all containers.
|
|
203
|
-
- 🔄 Automatic data refresh.
|
|
113
|
+
- 🔄 Automatic data refresh (every 2 seconds).
|
|
114
|
+
- ⌨️ Keyboard shortcuts for fast actions (navigate, start, stop, logs, quit).
|
|
204
115
|
- 📊 Live resource usage stats for running containers.
|
|
116
|
+
- 🪵 Real-time log streaming for selected containers.
|
|
205
117
|
- 🎨 Visual interface with colors and emojis for states.
|
|
206
118
|
- 👤 Author: Carlos Cochero (2025)
|
|
207
119
|
|
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
|
+
}
|