cdd-cli 3.1.7 → 3.1.9
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/.eslintrc.json +1 -1
- package/.github/workflows/ci.yml +3 -0
- package/.github/workflows/docs.yml +8 -1
- package/CHANGELOG.md +23 -0
- package/CONTRIBUTING.md +28 -15
- package/README.md +56 -88
- package/babel.config.cjs +18 -1
- package/dist/components/ContainerRow.js +5 -78
- package/dist/components/LogViewer.js +4 -9
- package/dist/helpers/containerOptionsBuilder.js +58 -0
- package/dist/hooks/creation/useContainerCreation.js +16 -1
- package/dist/hooks/debug/useDebugLogs.js +46 -0
- package/dist/hooks/navigation/useContainerSelection.js +36 -0
- package/dist/hooks/useContainerCommandRouter.js +151 -0
- package/dist/{helpers/actionHelpers.js → hooks/useContainerStats.js} +76 -78
- package/dist/hooks/useControls.js +83 -342
- package/dist/hooks/useEraseConfirmation.js +47 -0
- package/dist/hooks/useExitHandler.js +68 -0
- package/jest.config.cjs +1 -1
- package/package.json +2 -3
- package/src/components/ContainerRow.jsx +3 -38
- package/src/components/LogViewer.jsx +4 -10
- package/src/helpers/containerOptionsBuilder.js +42 -0
- package/src/hooks/creation/useContainerCreation.js +15 -0
- package/src/hooks/debug/useDebugLogs.js +29 -0
- package/src/hooks/navigation/useContainerSelection.js +25 -0
- package/src/hooks/useContainerCommandRouter.js +110 -0
- package/src/hooks/useContainerStats.js +44 -0
- package/src/hooks/useControls.js +68 -272
- package/src/hooks/useEraseConfirmation.js +39 -0
- package/src/hooks/useExitHandler.js +66 -0
- package/test/useContainerCreation.dom.test.js +3 -0
- package/.babelrc +0 -6
- package/FIXES_APPLIED.md +0 -419
- package/SECURITY.md +0 -5
- package/dist/hooks/useLogsStream.js +0 -41
- package/docs/_config.yml +0 -13
- package/docs/components_ContainerCreationPrompt.jsx.html +0 -114
- package/docs/components_ContainerRow.jsx.html +0 -151
- package/docs/components_ContainerSection.jsx.html +0 -75
- package/docs/components_Footer.jsx.html +0 -66
- package/docs/components_Header.jsx.html +0 -84
- package/docs/components_LogViewer.jsx.html +0 -91
- package/docs/components_MessageFeedback.jsx.html +0 -76
- package/docs/components_PromptField.jsx.html +0 -99
- package/docs/components_StatsBar.jsx.html +0 -105
- package/docs/components_UsageMenu.jsx.html +0 -73
- package/docs/fonts/OpenSans-Bold-webfont.eot +0 -0
- package/docs/fonts/OpenSans-Bold-webfont.svg +0 -1830
- package/docs/fonts/OpenSans-Bold-webfont.woff +0 -0
- package/docs/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
- package/docs/fonts/OpenSans-BoldItalic-webfont.svg +0 -1830
- package/docs/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
- package/docs/fonts/OpenSans-Italic-webfont.eot +0 -0
- package/docs/fonts/OpenSans-Italic-webfont.svg +0 -1830
- package/docs/fonts/OpenSans-Italic-webfont.woff +0 -0
- package/docs/fonts/OpenSans-Light-webfont.eot +0 -0
- package/docs/fonts/OpenSans-Light-webfont.svg +0 -1831
- package/docs/fonts/OpenSans-Light-webfont.woff +0 -0
- package/docs/fonts/OpenSans-LightItalic-webfont.eot +0 -0
- package/docs/fonts/OpenSans-LightItalic-webfont.svg +0 -1835
- package/docs/fonts/OpenSans-LightItalic-webfont.woff +0 -0
- package/docs/fonts/OpenSans-Regular-webfont.eot +0 -0
- package/docs/fonts/OpenSans-Regular-webfont.svg +0 -1831
- package/docs/fonts/OpenSans-Regular-webfont.woff +0 -0
- package/docs/global.html +0 -6145
- package/docs/helpers_actionHelpers.js.html +0 -94
- package/docs/helpers_constants.js.html +0 -81
- package/docs/helpers_dockerService_dockerService.js.html +0 -79
- package/docs/helpers_dockerService_serviceComponents_containerActions.js.html +0 -153
- package/docs/helpers_dockerService_serviceComponents_containerList.js.html +0 -81
- package/docs/helpers_dockerService_serviceComponents_containerLogs.js.html +0 -85
- package/docs/helpers_dockerService_serviceComponents_containerStats.js.html +0 -107
- package/docs/helpers_dockerService_serviceComponents_imageUtils.js.html +0 -82
- package/docs/helpers_exitWithMessage.js.html +0 -77
- package/docs/helpers_safeCall.js.html +0 -68
- package/docs/helpers_validationHelpers.js.html +0 -96
- package/docs/hooks_creation_useContainerActions.js.html +0 -120
- package/docs/hooks_creation_useContainerCreation.js.html +0 -152
- package/docs/hooks_creation_useLogsViewer.js.html +0 -102
- package/docs/hooks_useControls.js.html +0 -298
- package/docs/hooks_useLogsStream.js.html +0 -82
- package/docs/index.html +0 -65
- package/docs/index.js.html +0 -65
- package/docs/module-index.html +0 -171
- package/docs/scripts/linenumber.js +0 -25
- package/docs/scripts/prettify/Apache-License-2.0.txt +0 -202
- package/docs/scripts/prettify/lang-css.js +0 -2
- package/docs/scripts/prettify/prettify.js +0 -28
- package/docs/styles/jsdoc-default.css +0 -358
- package/docs/styles/prettify-jsdoc.css +0 -111
- package/docs/styles/prettify-tomorrow.css +0 -132
- package/esbuild.config.cjs +0 -11
- package/src/helpers/actionHelpers.js +0 -52
- package/src/hooks/useLogsStream.js +0 -31
- package/test/actionHelpers.test.js +0 -106
package/.eslintrc.json
CHANGED
package/.github/workflows/ci.yml
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
name: Build and deploy docs
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
|
-
|
|
4
|
+
workflow_run:
|
|
5
|
+
workflows: ["CI"]
|
|
6
|
+
types:
|
|
7
|
+
- completed
|
|
5
8
|
branches:
|
|
6
9
|
- main
|
|
7
10
|
|
|
8
11
|
jobs:
|
|
9
12
|
build-and-deploy:
|
|
13
|
+
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
|
10
14
|
runs-on: ubuntu-latest
|
|
11
15
|
permissions:
|
|
12
16
|
contents: write
|
|
@@ -28,6 +32,9 @@ jobs:
|
|
|
28
32
|
- name: Build docs
|
|
29
33
|
run: npm run docs
|
|
30
34
|
|
|
35
|
+
- name: Ensure .nojekyll
|
|
36
|
+
run: mkdir -p docs && touch docs/.nojekyll
|
|
37
|
+
|
|
31
38
|
- name: Deploy to GitHub Pages (push to gh-pages)
|
|
32
39
|
uses: peaceiris/actions-gh-pages@v3
|
|
33
40
|
with:
|
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,29 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
- Nothing yet.
|
|
9
9
|
|
|
10
|
+
## [3.1.9] - 2026-04-11
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- CI: added lint step to the test-and-build job; docs deploy now waits for CI to pass successfully via `workflow_run` trigger.
|
|
15
|
+
|
|
16
|
+
## [3.1.8] - 2026-04-11
|
|
17
|
+
|
|
18
|
+
### Refactored
|
|
19
|
+
|
|
20
|
+
- Removed dead code: `actionHelpers`, `useLogsStream`, and esbuild-related artifacts that were no longer in use.
|
|
21
|
+
- Consolidated Babel configuration into a single env-aware file, eliminating duplicate/split config files.
|
|
22
|
+
- Decomposed `useControls` god hook into focused single-responsibility hooks, each owning one concern.
|
|
23
|
+
- Extracted `useContainerStats` hook from `ContainerRow` to separate data-fetching from rendering.
|
|
24
|
+
- Set Jest default environment to `node`; `jsdom` is now opt-in per test file, reducing unnecessary DOM overhead.
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
|
|
28
|
+
- Removed generated JSDoc output from the repository; added the generated docs directory to `.gitignore`.
|
|
29
|
+
- Enabled `react/prop-types` ESLint rule project-wide and resolved all resulting warnings.
|
|
30
|
+
- Rewrote `README.md` and `CONTRIBUTING.md`: consolidated overlapping content, removed duplication, and updated both for accuracy.
|
|
31
|
+
- Various `docs(style)` and `docs` commits between v3.1.5 and the refactor wave: dark theme, sticky nav, landing page rewrite, CSS consolidation, and English translation for the JSDoc home (GitHub Pages site).
|
|
32
|
+
|
|
10
33
|
## [3.1.5] - 2025-10-18
|
|
11
34
|
_Note: I'm sorry about the issues you've run into; this is a brand-new app and I'm still learning, but I'm moving as quickly as I can to deliver a quality experience._
|
|
12
35
|
|
package/CONTRIBUTING.md
CHANGED
|
@@ -1,22 +1,35 @@
|
|
|
1
|
-
# Contributing
|
|
1
|
+
# Contributing to CDD-CLI
|
|
2
2
|
|
|
3
|
-
Thanks for your interest in contributing!
|
|
3
|
+
Thanks for your interest in contributing! Here are the guidelines to make collaboration smooth.
|
|
4
4
|
|
|
5
|
-
|
|
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.
|
|
5
|
+
## Getting started
|
|
10
6
|
|
|
11
|
-
|
|
12
|
-
## Contributing to CDD-CLI
|
|
7
|
+
1. Fork the repo and create a branch for your feature or fix:
|
|
13
8
|
|
|
14
|
-
|
|
9
|
+
```bash
|
|
10
|
+
git checkout -b feat/my-feature
|
|
11
|
+
```
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
2. Install dependencies and verify everything works before making changes:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install
|
|
17
|
+
npm test
|
|
18
|
+
npm run build
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Guidelines
|
|
22
|
+
|
|
23
|
+
- Keep changes small and focused — one concern per PR.
|
|
24
|
+
- Write tests for any new behavior and ensure existing tests pass (`npm test`).
|
|
25
|
+
- Run `npm run build` and verify the CLI starts (`node dist/index.js`) before opening a PR.
|
|
26
|
+
- Use [Conventional Commits](https://www.conventionalcommits.org/) for commit messages.
|
|
27
|
+
- For large or design-changing contributions, open an issue first to discuss the approach.
|
|
28
|
+
|
|
29
|
+
## Opening a Pull Request
|
|
30
|
+
|
|
31
|
+
- Describe the motivation and what changed.
|
|
32
|
+
- Link any related issues.
|
|
33
|
+
- Tag reviewers if applicable.
|
|
21
34
|
|
|
22
35
|
We appreciate clear, well-tested contributions.
|
package/README.md
CHANGED
|
@@ -6,34 +6,47 @@
|
|
|
6
6
|
<a href="https://github.com/caertos/cdd/actions/workflows/ci.yml">
|
|
7
7
|
<img src="https://github.com/caertos/cdd/actions/workflows/ci.yml/badge.svg?branch=main" alt="CI status" />
|
|
8
8
|
</a>
|
|
9
|
-
<!-- Documentation published to GitHub Pages -->
|
|
10
9
|
<a href="https://caertos.github.io/cdd/">
|
|
11
10
|
<img src="https://img.shields.io/badge/docs-GitHub%20Pages-blue" alt="Docs" />
|
|
12
11
|
</a>
|
|
12
|
+
<a href="https://deepwiki.com/Caertos/cdd"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"></a>
|
|
13
13
|
</p>
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
A terminal dashboard for monitoring and managing Docker containers in real time. Shows live CPU/memory stats, supports keyboard-driven actions, and requires no GUI.
|
|
16
16
|
|
|
17
17
|
---
|
|
18
18
|
|
|
19
|
-
##
|
|
19
|
+
## Features
|
|
20
|
+
|
|
21
|
+
- 🐳 Clear, compact view of all Docker containers
|
|
22
|
+
- 🔄 Auto-refresh every few seconds
|
|
23
|
+
- ⌨️ Keyboard shortcuts for fast actions (navigate, start, stop, logs, quit)
|
|
24
|
+
- 📊 Live CPU and memory stats for running containers
|
|
25
|
+
- 🪵 Real-time log streaming for selected containers
|
|
26
|
+
- 🎨 Color-coded states and visual feedback
|
|
20
27
|
|
|
21
|
-
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Install globally
|
|
22
31
|
|
|
23
32
|
```bash
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
npm install
|
|
33
|
+
npm install -g cdd-cli
|
|
34
|
+
cdd
|
|
27
35
|
```
|
|
28
36
|
|
|
29
|
-
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Quick start (local)
|
|
30
40
|
|
|
31
41
|
```bash
|
|
42
|
+
git clone https://github.com/caertos/cdd.git
|
|
43
|
+
cd cdd
|
|
44
|
+
npm install
|
|
32
45
|
npm run build
|
|
33
46
|
node dist/index.js
|
|
34
47
|
```
|
|
35
48
|
|
|
36
|
-
|
|
49
|
+
To use it as a global command during development:
|
|
37
50
|
|
|
38
51
|
```bash
|
|
39
52
|
npm link
|
|
@@ -42,96 +55,65 @@ cdd
|
|
|
42
55
|
|
|
43
56
|
---
|
|
44
57
|
|
|
45
|
-
## Usage
|
|
58
|
+
## Usage
|
|
46
59
|
|
|
47
|
-
|
|
48
|
-
- I: start selected container
|
|
49
|
-
- P: stop selected container
|
|
50
|
-
- R: restart selected container
|
|
51
|
-
- C: create container (interactive prompt)
|
|
52
|
-
- L: view logs for selected container
|
|
53
|
-
- D: toggle the on-screen debug log panel
|
|
54
|
-
- E: erase (remove) selected container (confirmation required)
|
|
55
|
-
- Q: quit
|
|
60
|
+
Use ↑/↓ to navigate containers. Available keyboard shortcuts:
|
|
56
61
|
|
|
57
|
-
|
|
62
|
+
| Key | Action |
|
|
63
|
+
|-----|--------|
|
|
64
|
+
| `I` | Start selected container |
|
|
65
|
+
| `P` | Stop selected container |
|
|
66
|
+
| `R` | Restart selected container |
|
|
67
|
+
| `C` | Create container (interactive prompt) |
|
|
68
|
+
| `L` | View logs for selected container |
|
|
69
|
+
| `E` | Erase (remove) selected container — confirmation required |
|
|
70
|
+
| `D` | Toggle live debug log panel |
|
|
71
|
+
| `Q` | Quit |
|
|
58
72
|
|
|
59
73
|
---
|
|
60
74
|
|
|
61
|
-
##
|
|
62
|
-
|
|
63
|
-
To install the CLI globally so you can run `cdd` from any terminal, use:
|
|
64
|
-
|
|
65
|
-
```bash
|
|
66
|
-
npm install -g cdd-cli
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
After installing globally, run the CLI with:
|
|
75
|
+
## Requirements
|
|
70
76
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
```
|
|
77
|
+
- Node.js >= 18
|
|
78
|
+
- Docker installed and running (CLI connects to the local Docker socket)
|
|
74
79
|
|
|
75
80
|
---
|
|
76
81
|
|
|
77
82
|
## Development
|
|
78
83
|
|
|
79
|
-
- Node.js >= 18 is recommended.
|
|
80
|
-
- To run the app from source during development:
|
|
81
|
-
|
|
82
84
|
```bash
|
|
83
85
|
npm install
|
|
84
|
-
npm run build
|
|
85
|
-
node dist/index.js
|
|
86
|
+
npm run build # compile src/ → dist/
|
|
87
|
+
node dist/index.js # run from compiled output
|
|
86
88
|
```
|
|
87
89
|
|
|
88
|
-
|
|
90
|
+
Re-run `npm run build` after any source changes.
|
|
89
91
|
|
|
90
92
|
---
|
|
91
93
|
|
|
92
94
|
## Tests
|
|
93
95
|
|
|
94
|
-
We use Jest for unit tests. Run:
|
|
95
|
-
|
|
96
96
|
```bash
|
|
97
97
|
npm test
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
-
Tests are
|
|
101
|
-
|
|
102
|
-
---
|
|
103
|
-
|
|
104
|
-
## Contributing
|
|
105
|
-
|
|
106
|
-
1. Fork the repo and create a feature branch.
|
|
107
|
-
2. Add tests for new behavior.
|
|
108
|
-
3. Ensure `npm test` and `npm run build` pass.
|
|
109
|
-
4. Open a Pull Request with a clear description.
|
|
110
|
-
|
|
111
|
-
---
|
|
112
|
-
|
|
113
|
-
## Troubleshooting
|
|
114
|
-
|
|
115
|
-
- If you don't see containers, ensure Docker is running and that your user has access to the Docker socket.
|
|
116
|
-
- If Docker permissions are required, run the CLI with `sudo` (Linux/macOS) or as Administrator (Windows).
|
|
117
|
-
- The project generates `dist/` — keep it out of version control (it's in .gitignore).
|
|
100
|
+
Tests are in `test/` and cover helpers, services, and hooks.
|
|
118
101
|
|
|
119
102
|
---
|
|
120
103
|
|
|
121
104
|
## Logging
|
|
122
105
|
|
|
123
|
-
|
|
124
|
-
- When you need deeper diagnostics (for example, to troubleshoot why stats or logs are not updating), start the CLI with debug logging enabled:
|
|
106
|
+
By default the CLI shows `info`, `warn`, and `error` messages. For deeper diagnostics:
|
|
125
107
|
|
|
126
108
|
```bash
|
|
127
|
-
CDD_LOG_LEVEL=debug cdd
|
|
109
|
+
CDD_LOG_LEVEL=debug cdd
|
|
128
110
|
# or
|
|
129
111
|
CDD_LOG_LEVEL=debug node dist/index.js
|
|
130
112
|
```
|
|
131
113
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
114
|
+
Press `D` inside the CLI to toggle the live debug panel. Press `D` again or `Esc` to hide it.
|
|
115
|
+
|
|
116
|
+
To capture logs to a file:
|
|
135
117
|
|
|
136
118
|
```bash
|
|
137
119
|
CDD_LOG_LEVEL=debug cdd > cdd-debug.log 2>&1
|
|
@@ -139,34 +121,20 @@ CDD_LOG_LEVEL=debug cdd > cdd-debug.log 2>&1
|
|
|
139
121
|
|
|
140
122
|
---
|
|
141
123
|
|
|
142
|
-
##
|
|
143
|
-
|
|
144
|
-
This project is MIT/ISC licensed (see `LICENSE`).
|
|
124
|
+
## Troubleshooting
|
|
145
125
|
|
|
146
|
-
|
|
126
|
+
- If you don't see containers, ensure Docker is running and your user has access to the Docker socket.
|
|
127
|
+
- On Linux/macOS, try `sudo cdd` if you have permission issues. On Windows, run as Administrator.
|
|
128
|
+
- `dist/` is generated by the build — it's in `.gitignore` and should not be committed.
|
|
147
129
|
|
|
148
|
-
|
|
149
|
-
- When you run `cdd`, you'll see a table with all your Docker containers.
|
|
150
|
-
- Running containers show live CPU and memory stats.
|
|
151
|
-
- Use `Ctrl+C` to exit.
|
|
152
|
-
|
|
153
|
-
## Main features
|
|
154
|
-
- 🐳 Clear, compact visualization of all containers.
|
|
155
|
-
- 🔄 Automatic data refresh (every 2 seconds).
|
|
156
|
-
- ⌨️ Keyboard shortcuts for fast actions (navigate, start, stop, logs, quit).
|
|
157
|
-
- 📊 Live resource usage stats for running containers.
|
|
158
|
-
- 🪵 Real-time log streaming for selected containers.
|
|
159
|
-
- 🎨 Visual interface with colors and emojis for states.
|
|
160
|
-
- 👤 Author: Carlos Cochero (2025)
|
|
130
|
+
---
|
|
161
131
|
|
|
162
|
-
##
|
|
163
|
-
- Node.js >= 18
|
|
164
|
-
- Docker installed and running (CLI connects to local Docker socket)
|
|
132
|
+
## Contributing
|
|
165
133
|
|
|
166
|
-
|
|
167
|
-
- If you don't see containers, make sure Docker is running and your user has permission to access the Docker socket.
|
|
168
|
-
- If you have issues with global install, try with `sudo` (Linux/macOS) or run terminal as administrator (Windows).
|
|
134
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
169
135
|
|
|
170
136
|
---
|
|
171
137
|
|
|
172
|
-
|
|
138
|
+
## License
|
|
139
|
+
|
|
140
|
+
MIT/ISC — see [`LICENSE`](LICENSE).
|
package/babel.config.cjs
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
module.exports = {
|
|
2
|
+
env: {
|
|
3
|
+
test: {
|
|
4
|
+
// Jest necesita CJS (transpila módulos) + React
|
|
5
|
+
presets: [
|
|
6
|
+
['@babel/preset-env', { targets: { node: 'current' } }],
|
|
7
|
+
'@babel/preset-react'
|
|
8
|
+
]
|
|
9
|
+
},
|
|
10
|
+
// build (NODE_ENV != 'test') → mantiene ESM para el output final
|
|
11
|
+
production: {
|
|
12
|
+
presets: [
|
|
13
|
+
['@babel/preset-env', { modules: false }],
|
|
14
|
+
'@babel/preset-react'
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
// Fallback para cualquier otro entorno (desarrollo local, etc.)
|
|
2
19
|
presets: [
|
|
3
|
-
['@babel/preset-env', {
|
|
20
|
+
['@babel/preset-env', { modules: false }],
|
|
4
21
|
'@babel/preset-react'
|
|
5
22
|
]
|
|
6
23
|
};
|
|
@@ -1,19 +1,8 @@
|
|
|
1
|
-
|
|
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
|
-
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
|
-
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
|
-
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
6
|
-
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."); }
|
|
7
|
-
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; } }
|
|
8
|
-
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; }
|
|
9
|
-
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; } }
|
|
10
|
-
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
11
|
-
import React, { useState, useEffect } from "react";
|
|
1
|
+
import React from "react";
|
|
12
2
|
import { Box, Text } from "ink";
|
|
13
|
-
import { getStats } from "../helpers/dockerService/serviceComponents/containerStats.js";
|
|
14
|
-
import { REFRESH_INTERVALS } from "../helpers/constants.js";
|
|
15
3
|
import StatsBar from "./StatsBar.js";
|
|
16
4
|
import PropTypes from 'prop-types';
|
|
5
|
+
import { useContainerStats } from '../hooks/useContainerStats.js';
|
|
17
6
|
var stateText = function stateText(state) {
|
|
18
7
|
if (state === "running") return {
|
|
19
8
|
text: "🟢 RUNNING",
|
|
@@ -48,17 +37,9 @@ export default function ContainerRow(_ref) {
|
|
|
48
37
|
name = container.name,
|
|
49
38
|
image = container.image,
|
|
50
39
|
state = container.state;
|
|
51
|
-
var
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
netIO: {
|
|
55
|
-
rx: 0,
|
|
56
|
-
tx: 0
|
|
57
|
-
}
|
|
58
|
-
}),
|
|
59
|
-
_useState2 = _slicedToArray(_useState, 2),
|
|
60
|
-
stats = _useState2[0],
|
|
61
|
-
setStats = _useState2[1];
|
|
40
|
+
var _useContainerStats = useContainerStats(id, state),
|
|
41
|
+
stats = _useContainerStats.stats,
|
|
42
|
+
statsError = _useContainerStats.statsError;
|
|
62
43
|
|
|
63
44
|
// Format ports for display (no leading space to avoid layout shifts)
|
|
64
45
|
var formatPorts = function formatPorts(ports) {
|
|
@@ -77,60 +58,6 @@ export default function ContainerRow(_ref) {
|
|
|
77
58
|
if (!s) return "";
|
|
78
59
|
return s.length > max ? s.slice(0, max - 1) + "…" : s;
|
|
79
60
|
};
|
|
80
|
-
var _useState3 = useState(""),
|
|
81
|
-
_useState4 = _slicedToArray(_useState3, 2),
|
|
82
|
-
statsError = _useState4[0],
|
|
83
|
-
setStatsError = _useState4[1];
|
|
84
|
-
useEffect(function () {
|
|
85
|
-
if (state !== "running") return;
|
|
86
|
-
var isMounted = true;
|
|
87
|
-
var fetchStats = /*#__PURE__*/function () {
|
|
88
|
-
var _ref2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
|
|
89
|
-
var s, _t;
|
|
90
|
-
return _regenerator().w(function (_context) {
|
|
91
|
-
while (1) switch (_context.p = _context.n) {
|
|
92
|
-
case 0:
|
|
93
|
-
_context.p = 0;
|
|
94
|
-
_context.n = 1;
|
|
95
|
-
return getStats(id);
|
|
96
|
-
case 1:
|
|
97
|
-
s = _context.v;
|
|
98
|
-
if (isMounted) {
|
|
99
|
-
setStats(s);
|
|
100
|
-
setStatsError("");
|
|
101
|
-
}
|
|
102
|
-
_context.n = 3;
|
|
103
|
-
break;
|
|
104
|
-
case 2:
|
|
105
|
-
_context.p = 2;
|
|
106
|
-
_t = _context.v;
|
|
107
|
-
if (isMounted) {
|
|
108
|
-
setStats({
|
|
109
|
-
cpuPercent: 0,
|
|
110
|
-
memPercent: 0,
|
|
111
|
-
netIO: {
|
|
112
|
-
rx: 0,
|
|
113
|
-
tx: 0
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
setStatsError("Error fetching stats");
|
|
117
|
-
}
|
|
118
|
-
case 3:
|
|
119
|
-
return _context.a(2);
|
|
120
|
-
}
|
|
121
|
-
}, _callee, null, [[0, 2]]);
|
|
122
|
-
}));
|
|
123
|
-
return function fetchStats() {
|
|
124
|
-
return _ref2.apply(this, arguments);
|
|
125
|
-
};
|
|
126
|
-
}();
|
|
127
|
-
fetchStats();
|
|
128
|
-
var timer = setInterval(fetchStats, REFRESH_INTERVALS.CONTAINER_STATS);
|
|
129
|
-
return function () {
|
|
130
|
-
isMounted = false;
|
|
131
|
-
clearInterval(timer);
|
|
132
|
-
};
|
|
133
|
-
}, [id, state]);
|
|
134
61
|
var stateInfo = stateText(state);
|
|
135
62
|
return /*#__PURE__*/React.createElement(Box, {
|
|
136
63
|
flexDirection: "column",
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { Text
|
|
3
|
-
import { safeCall } from "../helpers/safeCall.js";
|
|
2
|
+
import { Text } from "ink";
|
|
4
3
|
import PropTypes from 'prop-types';
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
|
-
* Log viewer overlay component. Shows the most recent lines
|
|
6
|
+
* Log viewer overlay component. Shows the most recent lines.
|
|
7
|
+
* Purely presentational — keyboard handling is centralized in useControls.
|
|
8
8
|
*
|
|
9
9
|
* @param {Object} props
|
|
10
10
|
* @param {Array<string>} props.logs - Array of log lines
|
|
@@ -15,13 +15,8 @@ import PropTypes from 'prop-types';
|
|
|
15
15
|
export default function LogViewer(_ref) {
|
|
16
16
|
var _container$name;
|
|
17
17
|
var logs = _ref.logs,
|
|
18
|
-
|
|
18
|
+
_onExit = _ref.onExit,
|
|
19
19
|
container = _ref.container;
|
|
20
|
-
useInput(function (input, key) {
|
|
21
|
-
if (key.escape) {
|
|
22
|
-
safeCall(onExit);
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
20
|
var visibleLogs = logs.slice(-15);
|
|
26
21
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Text, {
|
|
27
22
|
color: "green"
|
|
@@ -0,0 +1,58 @@
|
|
|
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
|
+
/**
|
|
8
|
+
* Builds Docker container creation options from raw user inputs.
|
|
9
|
+
*
|
|
10
|
+
* This is a pure function — it has no side effects and calls no services.
|
|
11
|
+
* It mirrors exactly the option-building logic in useControls.js onCreate callback.
|
|
12
|
+
*
|
|
13
|
+
* @param {object} params
|
|
14
|
+
* @param {string} params.imageName - Docker image name (e.g. "nginx:alpine")
|
|
15
|
+
* @param {string} [params.containerName] - Optional container name
|
|
16
|
+
* @param {string} [params.portInput] - Comma-separated host:container port pairs
|
|
17
|
+
* (e.g. "8080:80,3000:3000")
|
|
18
|
+
* @param {string} [params.envInput] - Comma-separated KEY=VALUE pairs
|
|
19
|
+
* (e.g. "NODE_ENV=production,PORT=3000")
|
|
20
|
+
* @returns {object} Docker container options ready to pass to createContainer
|
|
21
|
+
*/
|
|
22
|
+
export function buildContainerOptions(_ref) {
|
|
23
|
+
var _imageName = _ref.imageName,
|
|
24
|
+
containerName = _ref.containerName,
|
|
25
|
+
portInput = _ref.portInput,
|
|
26
|
+
envInput = _ref.envInput;
|
|
27
|
+
var env = (envInput || "").split(",").map(function (s) {
|
|
28
|
+
return s.trim();
|
|
29
|
+
}).filter(Boolean);
|
|
30
|
+
var ports = (portInput || "").split(",").map(function (s) {
|
|
31
|
+
return s.trim();
|
|
32
|
+
}).filter(Boolean);
|
|
33
|
+
var ExposedPorts = {};
|
|
34
|
+
var PortBindings = {};
|
|
35
|
+
ports.forEach(function (pair) {
|
|
36
|
+
var _pair$split = pair.split(":"),
|
|
37
|
+
_pair$split2 = _slicedToArray(_pair$split, 2),
|
|
38
|
+
host = _pair$split2[0],
|
|
39
|
+
cont = _pair$split2[1];
|
|
40
|
+
if (!host || !cont) return;
|
|
41
|
+
var key = "".concat(cont, "/tcp");
|
|
42
|
+
ExposedPorts[key] = {};
|
|
43
|
+
PortBindings[key] = PortBindings[key] || [];
|
|
44
|
+
PortBindings[key].push({
|
|
45
|
+
HostPort: "".concat(host)
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
var options = {
|
|
49
|
+
Tty: true
|
|
50
|
+
};
|
|
51
|
+
if (Object.keys(ExposedPorts).length) options.ExposedPorts = ExposedPorts;
|
|
52
|
+
if (Object.keys(PortBindings).length) options.HostConfig = {
|
|
53
|
+
PortBindings: PortBindings
|
|
54
|
+
};
|
|
55
|
+
if (env.length) options.Env = env;
|
|
56
|
+
if (containerName) options.name = containerName;
|
|
57
|
+
return options;
|
|
58
|
+
}
|
|
@@ -117,6 +117,20 @@ export function useContainerCreation(_ref) {
|
|
|
117
117
|
setMessageColor("yellow");
|
|
118
118
|
safeCall(onCancel);
|
|
119
119
|
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Resets all creation state to initial values without triggering onCancel.
|
|
123
|
+
* Used by the command router when the user presses 'c' to open the creation wizard.
|
|
124
|
+
*/
|
|
125
|
+
function resetCreation() {
|
|
126
|
+
setStep(0);
|
|
127
|
+
setImageName("");
|
|
128
|
+
setContainerName("");
|
|
129
|
+
setPortInput("");
|
|
130
|
+
setEnvInput("");
|
|
131
|
+
setMessage("Insert the name of the image to create: ");
|
|
132
|
+
setMessageColor("yellow");
|
|
133
|
+
}
|
|
120
134
|
return {
|
|
121
135
|
step: step,
|
|
122
136
|
setStep: setStep,
|
|
@@ -133,6 +147,7 @@ export function useContainerCreation(_ref) {
|
|
|
133
147
|
messageColor: messageColor,
|
|
134
148
|
setMessageColor: setMessageColor,
|
|
135
149
|
nextStep: nextStep,
|
|
136
|
-
cancelCreation: cancelCreation
|
|
150
|
+
cancelCreation: cancelCreation,
|
|
151
|
+
resetCreation: resetCreation
|
|
137
152
|
};
|
|
138
153
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
|
|
2
|
+
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
3
|
+
function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
|
|
4
|
+
function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
|
|
5
|
+
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
6
|
+
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."); }
|
|
7
|
+
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; } }
|
|
8
|
+
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; }
|
|
9
|
+
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; } }
|
|
10
|
+
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
11
|
+
import { useState, useEffect } from 'react';
|
|
12
|
+
import { logger } from '../../helpers/logger.js';
|
|
13
|
+
export function useDebugLogs() {
|
|
14
|
+
var _useState = useState(false),
|
|
15
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
16
|
+
showDebugLogs = _useState2[0],
|
|
17
|
+
setShowDebugLogs = _useState2[1];
|
|
18
|
+
var _useState3 = useState([]),
|
|
19
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
20
|
+
debugLogs = _useState4[0],
|
|
21
|
+
setDebugLogs = _useState4[1];
|
|
22
|
+
useEffect(function () {
|
|
23
|
+
var unsubscribe = logger.subscribe(function (entry) {
|
|
24
|
+
setDebugLogs(function (prev) {
|
|
25
|
+
var extras = (entry.args || []).map(function (arg) {
|
|
26
|
+
if (typeof arg === "string") return arg;
|
|
27
|
+
if (typeof arg === "number" || typeof arg === "boolean") return String(arg);
|
|
28
|
+
try {
|
|
29
|
+
return JSON.stringify(arg);
|
|
30
|
+
} catch (err) {
|
|
31
|
+
return "[unserializable]";
|
|
32
|
+
}
|
|
33
|
+
}).filter(Boolean);
|
|
34
|
+
var line = extras.length ? "".concat(entry.formatted, " ").concat(extras.join(" ")) : entry.formatted;
|
|
35
|
+
var next = [].concat(_toConsumableArray(prev), [line]);
|
|
36
|
+
return next.slice(-200);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
return unsubscribe;
|
|
40
|
+
}, []);
|
|
41
|
+
return {
|
|
42
|
+
showDebugLogs: showDebugLogs,
|
|
43
|
+
setShowDebugLogs: setShowDebugLogs,
|
|
44
|
+
debugLogs: debugLogs
|
|
45
|
+
};
|
|
46
|
+
}
|