cdd-cli 3.1.4 → 3.1.5
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 +30 -0
- package/.github/workflows/docs.yml +35 -0
- package/CHANGELOG.md +37 -4
- package/README.md +26 -0
- package/dist/App.js +20 -3
- package/dist/components/ContainerCreationPrompt.js +27 -1
- package/dist/components/ContainerList.js +11 -15
- package/dist/components/ContainerRow.js +73 -14
- package/dist/components/ContainerSection.js +16 -2
- package/dist/components/Footer.js +7 -1
- package/dist/components/Header.js +17 -1
- package/dist/components/LogViewer.js +21 -3
- package/dist/components/MessageFeedback.js +15 -1
- package/dist/components/PromptField.js +31 -1
- package/dist/components/StatsBar.js +46 -8
- package/dist/components/UsageMenu.js +30 -1
- package/dist/helpers/actionHelpers.js +17 -6
- package/dist/helpers/constants.js +30 -0
- package/dist/helpers/dockerService/dockerService.js +19 -0
- package/dist/helpers/dockerService/serviceComponents/containerActions.js +194 -35
- package/dist/helpers/dockerService/serviceComponents/containerList.js +45 -8
- package/dist/helpers/dockerService/serviceComponents/containerLogs.js +16 -6
- package/dist/helpers/dockerService/serviceComponents/containerStats.js +28 -9
- package/dist/helpers/exitWithMessage.js +2 -1
- package/dist/helpers/logger.js +112 -0
- package/dist/helpers/safeCall.js +21 -0
- package/dist/helpers/validationHelpers.js +20 -1
- package/dist/hooks/creation/useContainerActions.js +2 -1
- package/dist/hooks/creation/useContainerCreation.js +5 -4
- package/dist/hooks/creation/useLogsViewer.js +3 -2
- package/dist/hooks/useContainers.js +6 -3
- package/dist/hooks/useControls.js +253 -122
- package/dist/hooks/useLogsStream.js +3 -2
- package/dist/index.js +1 -0
- package/docs/components_ContainerCreationPrompt.jsx.html +114 -0
- package/docs/components_ContainerRow.jsx.html +151 -0
- package/docs/components_ContainerSection.jsx.html +75 -0
- package/docs/components_Footer.jsx.html +66 -0
- package/docs/components_Header.jsx.html +84 -0
- package/docs/components_LogViewer.jsx.html +91 -0
- package/docs/components_MessageFeedback.jsx.html +76 -0
- package/docs/components_PromptField.jsx.html +99 -0
- package/docs/components_StatsBar.jsx.html +105 -0
- package/docs/components_UsageMenu.jsx.html +73 -0
- package/docs/fonts/OpenSans-Bold-webfont.eot +0 -0
- package/docs/fonts/OpenSans-Bold-webfont.svg +1830 -0
- 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 +1830 -0
- 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 +1830 -0
- 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 +1831 -0
- 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 +1835 -0
- 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 +1831 -0
- package/docs/fonts/OpenSans-Regular-webfont.woff +0 -0
- package/docs/global.html +6145 -0
- package/docs/helpers_actionHelpers.js.html +94 -0
- package/docs/helpers_constants.js.html +81 -0
- package/docs/helpers_dockerService_dockerService.js.html +79 -0
- package/docs/helpers_dockerService_serviceComponents_containerActions.js.html +153 -0
- package/docs/helpers_dockerService_serviceComponents_containerList.js.html +81 -0
- package/docs/helpers_dockerService_serviceComponents_containerLogs.js.html +85 -0
- package/docs/helpers_dockerService_serviceComponents_containerStats.js.html +107 -0
- package/docs/helpers_dockerService_serviceComponents_imageUtils.js.html +82 -0
- package/docs/helpers_exitWithMessage.js.html +77 -0
- package/docs/helpers_safeCall.js.html +68 -0
- package/docs/helpers_validationHelpers.js.html +96 -0
- package/docs/hooks_creation_useContainerActions.js.html +120 -0
- package/docs/hooks_creation_useContainerCreation.js.html +152 -0
- package/docs/hooks_creation_useLogsViewer.js.html +102 -0
- package/docs/hooks_useControls.js.html +298 -0
- package/docs/hooks_useLogsStream.js.html +82 -0
- package/docs/index.html +65 -0
- package/docs/index.js.html +65 -0
- package/docs/module-index.html +171 -0
- package/docs/scripts/linenumber.js +25 -0
- package/docs/scripts/prettify/Apache-License-2.0.txt +202 -0
- package/docs/scripts/prettify/lang-css.js +2 -0
- package/docs/scripts/prettify/prettify.js +28 -0
- package/docs/styles/jsdoc-default.css +358 -0
- package/docs/styles/prettify-jsdoc.css +111 -0
- package/docs/styles/prettify-tomorrow.css +132 -0
- package/fix-imports.cjs +33 -6
- package/jest.config.cjs +2 -1
- package/package.json +19 -9
- package/src/App.jsx +16 -2
- package/src/components/ContainerCreationPrompt.jsx +26 -0
- package/src/components/ContainerList.jsx +12 -13
- package/src/components/ContainerRow.jsx +55 -20
- package/src/components/ContainerSection.jsx +15 -1
- package/src/components/Footer.jsx +6 -1
- package/src/components/Header.jsx +16 -0
- package/src/components/LogViewer.jsx +19 -2
- package/src/components/MessageFeedback.jsx +14 -0
- package/src/components/PromptField.jsx +30 -0
- package/src/components/StatsBar.jsx +47 -8
- package/src/components/UsageMenu.jsx +38 -8
- package/src/helpers/actionHelpers.js +16 -7
- package/src/helpers/constants.js +30 -0
- package/src/helpers/dockerService/dockerService.js +19 -0
- package/src/helpers/dockerService/serviceComponents/containerActions.js +123 -12
- package/src/helpers/dockerService/serviceComponents/containerList.js +61 -23
- package/src/helpers/dockerService/serviceComponents/containerLogs.js +20 -6
- package/src/helpers/dockerService/serviceComponents/containerStats.js +24 -5
- package/src/helpers/dockerService/serviceComponents/imageUtils.js +1 -1
- package/src/helpers/exitWithMessage.js +2 -1
- package/src/helpers/logger.js +113 -0
- package/src/helpers/safeCall.js +18 -0
- package/src/helpers/validationHelpers.js +21 -3
- package/src/hooks/creation/useContainerActions.js +4 -3
- package/src/hooks/creation/useContainerCreation.js +5 -4
- package/src/hooks/creation/useLogsViewer.js +2 -1
- package/src/hooks/useContainers.js +6 -3
- package/src/hooks/useControls.js +244 -91
- package/src/hooks/useLogsStream.js +2 -1
- package/src/index.js +1 -0
- package/test/actionHelpers.test.js +106 -0
- package/test/containerActions.test.js +138 -0
- package/test/containerList.test.js +79 -0
- package/test/jest.setup.js +7 -0
- package/test/safeCall.test.js +25 -0
- package/test/useContainerCreation.dom.test.js +97 -0
- package/test/validationHelpers.test.js +2 -2
- package/dist/cdd.bundle.js +0 -8
- package/dist/components/ContainerCreator.js +0 -81
- package/dist/components/StatsViewer.js +0 -0
- package/dist/helpers/dockerActions.js +0 -64
- package/dist/helpers/dockerService.js +0 -284
- package/dist/hooks/useStatsPolling.js +0 -54
|
@@ -16,9 +16,11 @@ import React from "react";
|
|
|
16
16
|
import { useContainerActions } from "./creation/useContainerActions.js";
|
|
17
17
|
import { useContainerCreation } from "./creation/useContainerCreation.js";
|
|
18
18
|
import { useLogsViewer } from "./creation/useLogsViewer.js";
|
|
19
|
-
import { useInput } from "ink";
|
|
19
|
+
import { useInput, useApp } from "ink";
|
|
20
20
|
import { getLogsStream } from "../helpers/dockerService/serviceComponents/containerLogs.js";
|
|
21
|
+
import { EXIT_DELAY } from "../helpers/constants.js";
|
|
21
22
|
import { createContainer as svcCreateContainer } from "../helpers/dockerService/serviceComponents/containerActions.js";
|
|
23
|
+
import { logger } from "../helpers/logger.js";
|
|
22
24
|
|
|
23
25
|
// Principal hook to manage user inputs and control the app state
|
|
24
26
|
/**
|
|
@@ -43,6 +45,9 @@ import { createContainer as svcCreateContainer } from "../helpers/dockerService/
|
|
|
43
45
|
* @property {Object} creation - The creation hook API (setters and helpers)
|
|
44
46
|
* @property {Object} actions - The actions hook API (helpers to start/stop/remove)
|
|
45
47
|
* @property {Object} logsViewer - The logs viewer hook API
|
|
48
|
+
* @property {boolean} showDebugLogs - Whether the debug log panel is visible
|
|
49
|
+
* @property {Array<string>} debugLogs - Buffered log lines captured from the shared logger
|
|
50
|
+
* @property {boolean} confirmErase - Whether the erase confirmation dialog is active
|
|
46
51
|
*/
|
|
47
52
|
export function useControls() {
|
|
48
53
|
var containers = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
@@ -58,7 +63,17 @@ export function useControls() {
|
|
|
58
63
|
_React$useState6 = _slicedToArray(_React$useState5, 2),
|
|
59
64
|
confirmErase = _React$useState6[0],
|
|
60
65
|
setConfirmErase = _React$useState6[1];
|
|
66
|
+
var _React$useState7 = React.useState(false),
|
|
67
|
+
_React$useState8 = _slicedToArray(_React$useState7, 2),
|
|
68
|
+
showDebugLogs = _React$useState8[0],
|
|
69
|
+
setShowDebugLogs = _React$useState8[1];
|
|
70
|
+
var _React$useState9 = React.useState([]),
|
|
71
|
+
_React$useState0 = _slicedToArray(_React$useState9, 2),
|
|
72
|
+
debugLogs = _React$useState0[0],
|
|
73
|
+
setDebugLogs = _React$useState0[1];
|
|
61
74
|
var total = containers.length;
|
|
75
|
+
var _useApp = useApp(),
|
|
76
|
+
exit = _useApp.exit;
|
|
62
77
|
|
|
63
78
|
// Modular hooks
|
|
64
79
|
var actions = useContainerActions({
|
|
@@ -142,120 +157,174 @@ export function useControls() {
|
|
|
142
157
|
|
|
143
158
|
// Handler to exit logs (delegated to logsViewer)
|
|
144
159
|
var exitLogs = logsViewer.closeLogs;
|
|
145
|
-
useInput(function (input, key) {
|
|
146
|
-
// Erase confirmation
|
|
147
|
-
if (confirmErase) {
|
|
148
|
-
if (input === "y" || input === "Y") {
|
|
149
|
-
actions.handleAction({
|
|
150
|
-
actionFn: function () {
|
|
151
|
-
var _actionFn = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(id) {
|
|
152
|
-
return _regenerator().w(function (_context2) {
|
|
153
|
-
while (1) switch (_context2.n) {
|
|
154
|
-
case 0:
|
|
155
|
-
_context2.n = 1;
|
|
156
|
-
return actions.removeContainer(id);
|
|
157
|
-
case 1:
|
|
158
|
-
return _context2.a(2, _context2.v);
|
|
159
|
-
}
|
|
160
|
-
}, _callee2);
|
|
161
|
-
}));
|
|
162
|
-
function actionFn(_x2) {
|
|
163
|
-
return _actionFn.apply(this, arguments);
|
|
164
|
-
}
|
|
165
|
-
return actionFn;
|
|
166
|
-
}(),
|
|
167
|
-
actionLabel: "Erasing",
|
|
168
|
-
selected: selected
|
|
169
|
-
});
|
|
170
|
-
setConfirmErase(false);
|
|
171
|
-
actions.setMessageColor("yellow");
|
|
172
|
-
return;
|
|
173
|
-
} else if (input === "n" || input === "N" || key.escape) {
|
|
174
|
-
setConfirmErase(false);
|
|
175
|
-
actions.setMessage("");
|
|
176
|
-
actions.setMessageColor("");
|
|
177
|
-
return;
|
|
178
|
-
} else {
|
|
179
|
-
actions.setMessage("Are you sure you want to erase this container? (y/n)");
|
|
180
|
-
actions.setMessageColor("yellow");
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
160
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
161
|
+
/**
|
|
162
|
+
* Pipe container logs into the viewer while applying a hard limit.
|
|
163
|
+
* @param {string} containerId - Container identifier used by Docker.
|
|
164
|
+
*/
|
|
165
|
+
var startLogsStream = React.useCallback(function (containerId) {
|
|
166
|
+
getLogsStream(containerId, function (data) {
|
|
167
|
+
return logsViewer.setLogs(function (prev) {
|
|
168
|
+
var newLogs = [].concat(_toConsumableArray(prev), _toConsumableArray(data.split("\n").filter(Boolean)));
|
|
169
|
+
return newLogs.slice(-1000);
|
|
170
|
+
});
|
|
171
|
+
}, function () {}, function (err) {
|
|
172
|
+
return logsViewer.setLogs(function (prev) {
|
|
173
|
+
return [].concat(_toConsumableArray(prev), ["Error: ".concat(err.message)]);
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
}, [logsViewer]);
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Manage the erase confirmation short-circuit flow.
|
|
180
|
+
*/
|
|
181
|
+
var processEraseConfirmation = React.useCallback(function (input, key) {
|
|
182
|
+
if (input === "y" || input === "Y") {
|
|
183
|
+
actions.handleAction({
|
|
184
|
+
actionFn: function () {
|
|
185
|
+
var _actionFn = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(id) {
|
|
186
|
+
return _regenerator().w(function (_context2) {
|
|
187
|
+
while (1) switch (_context2.n) {
|
|
188
|
+
case 0:
|
|
189
|
+
_context2.n = 1;
|
|
190
|
+
return actions.removeContainer(id);
|
|
191
|
+
case 1:
|
|
192
|
+
return _context2.a(2, _context2.v);
|
|
193
|
+
}
|
|
194
|
+
}, _callee2);
|
|
195
|
+
}));
|
|
196
|
+
function actionFn(_x2) {
|
|
197
|
+
return _actionFn.apply(this, arguments);
|
|
198
|
+
}
|
|
199
|
+
return actionFn;
|
|
200
|
+
}(),
|
|
201
|
+
actionLabel: "Erasing",
|
|
202
|
+
selected: selected
|
|
203
|
+
});
|
|
204
|
+
setConfirmErase(false);
|
|
205
|
+
actions.setMessageColor("yellow");
|
|
190
206
|
return;
|
|
191
207
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
var appendCharToField = function appendCharToField(setter, value, ch) {
|
|
197
|
-
setter((value || "") + ch);
|
|
198
|
-
};
|
|
199
|
-
// Escape -> cancel
|
|
200
|
-
if (key.escape) {
|
|
201
|
-
creation.cancelCreation();
|
|
202
|
-
setCreatingContainer(false);
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
// Enter -> next step
|
|
206
|
-
if (input === "\r" || input === "\n") {
|
|
207
|
-
creation.nextStep();
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
// Backspace/Delete support
|
|
211
|
-
if (key.backspace || key["delete"]) {
|
|
212
|
-
if (step === 0) creation.setImageName(function (v) {
|
|
213
|
-
return (v || "").slice(0, -1);
|
|
214
|
-
});
|
|
215
|
-
if (step === 1) creation.setContainerName(function (v) {
|
|
216
|
-
return (v || "").slice(0, -1);
|
|
217
|
-
});
|
|
218
|
-
if (step === 2) creation.setPortInput(function (v) {
|
|
219
|
-
return (v || "").slice(0, -1);
|
|
220
|
-
});
|
|
221
|
-
if (step === 3) creation.setEnvInput(function (v) {
|
|
222
|
-
return (v || "").slice(0, -1);
|
|
223
|
-
});
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
// Printable character input (append)
|
|
227
|
-
if (input && input.length === 1 && !key.ctrl && !key.meta) {
|
|
228
|
-
if (step === 0) appendCharToField(creation.setImageName, creation.imageName, input);
|
|
229
|
-
if (step === 1) appendCharToField(creation.setContainerName, creation.containerName, input);
|
|
230
|
-
if (step === 2) appendCharToField(creation.setPortInput, creation.portInput, input);
|
|
231
|
-
if (step === 3) appendCharToField(creation.setEnvInput, creation.envInput, input);
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
234
|
-
// Otherwise ignore
|
|
208
|
+
if (input === "n" || input === "N" || key.escape) {
|
|
209
|
+
setConfirmErase(false);
|
|
210
|
+
actions.setMessage("");
|
|
211
|
+
actions.setMessageColor("");
|
|
235
212
|
return;
|
|
236
213
|
}
|
|
214
|
+
actions.setMessage("Are you sure you want to erase this container? (y/n)");
|
|
215
|
+
actions.setMessageColor("yellow");
|
|
216
|
+
}, [actions, selected]);
|
|
237
217
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
218
|
+
/**
|
|
219
|
+
* Handle inputs while the logs viewer is active.
|
|
220
|
+
*/
|
|
221
|
+
var processLogsInput = React.useCallback(function (input, key) {
|
|
222
|
+
if (input === "q" || key.escape) {
|
|
223
|
+
logsViewer.closeLogs();
|
|
224
|
+
}
|
|
225
|
+
}, [logsViewer]);
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Route keystrokes to the container creation wizard.
|
|
229
|
+
*/
|
|
230
|
+
var processCreationInput = React.useCallback(function (input, key) {
|
|
231
|
+
var step = creation.step;
|
|
232
|
+
var removeLastChar = function removeLastChar(setter) {
|
|
233
|
+
return setter(function (value) {
|
|
234
|
+
return (value || "").slice(0, -1);
|
|
235
|
+
});
|
|
236
|
+
};
|
|
237
|
+
var appendChar = function appendChar(setter, current, ch) {
|
|
238
|
+
return setter((current || "") + ch);
|
|
239
|
+
};
|
|
240
|
+
if (key.escape) {
|
|
241
|
+
creation.cancelCreation();
|
|
242
|
+
setCreatingContainer(false);
|
|
253
243
|
return;
|
|
254
244
|
}
|
|
245
|
+
if (input === "\r" || input === "\n") {
|
|
246
|
+
creation.nextStep();
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
if (key.backspace || key["delete"]) {
|
|
250
|
+
if (step === 0) removeLastChar(creation.setImageName);
|
|
251
|
+
if (step === 1) removeLastChar(creation.setContainerName);
|
|
252
|
+
if (step === 2) removeLastChar(creation.setPortInput);
|
|
253
|
+
if (step === 3) removeLastChar(creation.setEnvInput);
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
if (input && input.length === 1 && !key.ctrl && !key.meta) {
|
|
257
|
+
if (step === 0) appendChar(creation.setImageName, creation.imageName, input);
|
|
258
|
+
if (step === 1) appendChar(creation.setContainerName, creation.containerName, input);
|
|
259
|
+
if (step === 2) appendChar(creation.setPortInput, creation.portInput, input);
|
|
260
|
+
if (step === 3) appendChar(creation.setEnvInput, creation.envInput, input);
|
|
261
|
+
}
|
|
262
|
+
}, [creation, setCreatingContainer]);
|
|
255
263
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
264
|
+
/**
|
|
265
|
+
* Navigate the container list using arrow keys.
|
|
266
|
+
* @returns {boolean} True when the input was consumed.
|
|
267
|
+
*/
|
|
268
|
+
var handleNavigation = React.useCallback(function (input, key) {
|
|
269
|
+
if (total === 0) {
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
if (key.upArrow) {
|
|
273
|
+
setSelected(function (i) {
|
|
274
|
+
return i === 0 ? total - 1 : i - 1;
|
|
275
|
+
});
|
|
276
|
+
return true;
|
|
277
|
+
}
|
|
278
|
+
if (key.downArrow) {
|
|
279
|
+
setSelected(function (i) {
|
|
280
|
+
return i === total - 1 ? 0 : i + 1;
|
|
281
|
+
});
|
|
282
|
+
return true;
|
|
283
|
+
}
|
|
284
|
+
return false;
|
|
285
|
+
}, [total]);
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Handle the quit command.
|
|
289
|
+
* @returns {boolean} True when the input was consumed.
|
|
290
|
+
*/
|
|
291
|
+
var handleExitCommand = React.useCallback(function (input) {
|
|
292
|
+
if (input !== "q") {
|
|
293
|
+
return false;
|
|
294
|
+
}
|
|
295
|
+
actions.setMessage("Exiting...");
|
|
296
|
+
actions.setMessageColor("yellow");
|
|
297
|
+
logsViewer.closeLogs();
|
|
298
|
+
setShowDebugLogs(false);
|
|
299
|
+
var clearTerminal = function clearTerminal() {
|
|
300
|
+
try {
|
|
301
|
+
if (process.stdout && process.stdout.isTTY) {
|
|
302
|
+
process.stdout.write("\x1Bc");
|
|
303
|
+
} else {
|
|
304
|
+
console.clear();
|
|
305
|
+
}
|
|
306
|
+
} catch (err) {
|
|
307
|
+
// Ignore clear errors to avoid blocking exit.
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
setTimeout(function () {
|
|
311
|
+
clearTerminal();
|
|
312
|
+
exit();
|
|
313
|
+
if (process.env.NODE_ENV !== "test") {
|
|
314
|
+
setTimeout(function () {
|
|
315
|
+
return process.exit(0);
|
|
316
|
+
}, 50);
|
|
317
|
+
}
|
|
318
|
+
}, EXIT_DELAY);
|
|
319
|
+
return true;
|
|
320
|
+
}, [actions, exit, logsViewer]);
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Execute Docker-related commands and prompt transitions.
|
|
324
|
+
* @returns {boolean} True when the input was consumed.
|
|
325
|
+
*/
|
|
326
|
+
var handleDockerCommands = React.useCallback(function (input) {
|
|
327
|
+
var container = containers[selected];
|
|
259
328
|
if (input === "i") {
|
|
260
329
|
actions.handleAction({
|
|
261
330
|
actionFn: function () {
|
|
@@ -281,6 +350,7 @@ export function useControls() {
|
|
|
281
350
|
return (c.state === "running" || c.status === "running") && "Container is already running.";
|
|
282
351
|
}
|
|
283
352
|
});
|
|
353
|
+
return true;
|
|
284
354
|
}
|
|
285
355
|
if (input === "p") {
|
|
286
356
|
actions.handleAction({
|
|
@@ -307,6 +377,7 @@ export function useControls() {
|
|
|
307
377
|
return (c.state === "exited" || c.status === "exited" || c.state === "stopped" || c.status === "stopped") && "Container is already stopped.";
|
|
308
378
|
}
|
|
309
379
|
});
|
|
380
|
+
return true;
|
|
310
381
|
}
|
|
311
382
|
if (input === "r") {
|
|
312
383
|
actions.handleAction({
|
|
@@ -330,27 +401,24 @@ export function useControls() {
|
|
|
330
401
|
actionLabel: "Restarting",
|
|
331
402
|
selected: selected
|
|
332
403
|
});
|
|
404
|
+
return true;
|
|
333
405
|
}
|
|
334
|
-
if (input === "e"
|
|
406
|
+
if (input === "e") {
|
|
407
|
+
if (!container) {
|
|
408
|
+
return true;
|
|
409
|
+
}
|
|
335
410
|
setConfirmErase(true);
|
|
336
411
|
actions.setMessage("Are you sure you want to erase this container? (y/n)");
|
|
337
412
|
actions.setMessageColor("yellow");
|
|
338
|
-
return;
|
|
413
|
+
return true;
|
|
339
414
|
}
|
|
340
|
-
if (input === "l"
|
|
415
|
+
if (input === "l") {
|
|
416
|
+
if (!container) {
|
|
417
|
+
return true;
|
|
418
|
+
}
|
|
341
419
|
logsViewer.openLogs();
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
var newLogs = [].concat(_toConsumableArray(prev), _toConsumableArray(data.split("\n").filter(Boolean)));
|
|
345
|
-
// Limit to last 1000 lines to prevent memory leak
|
|
346
|
-
return newLogs.slice(-1000);
|
|
347
|
-
});
|
|
348
|
-
}, function () {}, function (err) {
|
|
349
|
-
return logsViewer.setLogs(function (prev) {
|
|
350
|
-
return [].concat(_toConsumableArray(prev), ["Error: ".concat(err.message)]);
|
|
351
|
-
});
|
|
352
|
-
});
|
|
353
|
-
return;
|
|
420
|
+
startLogsStream(container.id);
|
|
421
|
+
return true;
|
|
354
422
|
}
|
|
355
423
|
if (input === "c") {
|
|
356
424
|
setCreatingContainer(true);
|
|
@@ -361,8 +429,69 @@ export function useControls() {
|
|
|
361
429
|
creation.setEnvInput("");
|
|
362
430
|
creation.setMessage("Insert the name of the image to create: ");
|
|
363
431
|
creation.setMessageColor("yellow");
|
|
432
|
+
return true;
|
|
433
|
+
}
|
|
434
|
+
if (input === "d") {
|
|
435
|
+
setShowDebugLogs(function (prev) {
|
|
436
|
+
return !prev;
|
|
437
|
+
});
|
|
438
|
+
return true;
|
|
364
439
|
}
|
|
440
|
+
return false;
|
|
441
|
+
}, [actions, containers, creation, logsViewer, selected, setConfirmErase, setCreatingContainer, startLogsStream, setShowDebugLogs]);
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Default handler executed when no special mode is active.
|
|
445
|
+
*/
|
|
446
|
+
var processGlobalInput = React.useCallback(function (input, key) {
|
|
447
|
+
if (handleNavigation(input, key)) {
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
if (handleExitCommand(input)) {
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
handleDockerCommands(input);
|
|
454
|
+
}, [handleDockerCommands, handleExitCommand, handleNavigation]);
|
|
455
|
+
useInput(function (input, key) {
|
|
456
|
+
if (confirmErase) {
|
|
457
|
+
processEraseConfirmation(input, key);
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
if (logsViewer.showLogs) {
|
|
461
|
+
processLogsInput(input, key);
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
if (creatingContainer) {
|
|
465
|
+
processCreationInput(input, key);
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
if (showDebugLogs && key.escape) {
|
|
469
|
+
setShowDebugLogs(false);
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
processGlobalInput(input, key);
|
|
365
473
|
});
|
|
474
|
+
|
|
475
|
+
// Mirror global logger entries so the D shortcut can surface them without leaving the CLI.
|
|
476
|
+
React.useEffect(function () {
|
|
477
|
+
var unsubscribe = logger.subscribe(function (entry) {
|
|
478
|
+
setDebugLogs(function (prev) {
|
|
479
|
+
var extras = (entry.args || []).map(function (arg) {
|
|
480
|
+
if (typeof arg === "string") return arg;
|
|
481
|
+
if (typeof arg === "number" || typeof arg === "boolean") return String(arg);
|
|
482
|
+
try {
|
|
483
|
+
return JSON.stringify(arg);
|
|
484
|
+
} catch (err) {
|
|
485
|
+
return "[unserializable]";
|
|
486
|
+
}
|
|
487
|
+
}).filter(Boolean);
|
|
488
|
+
var line = extras.length ? "".concat(entry.formatted, " ").concat(extras.join(" ")) : entry.formatted;
|
|
489
|
+
var next = [].concat(_toConsumableArray(prev), [line]);
|
|
490
|
+
return next.slice(-200);
|
|
491
|
+
});
|
|
492
|
+
});
|
|
493
|
+
return unsubscribe;
|
|
494
|
+
}, []);
|
|
366
495
|
return {
|
|
367
496
|
selected: selected,
|
|
368
497
|
setSelected: setSelected,
|
|
@@ -382,6 +511,8 @@ export function useControls() {
|
|
|
382
511
|
creation: creation,
|
|
383
512
|
actions: actions,
|
|
384
513
|
logsViewer: logsViewer,
|
|
385
|
-
confirmErase: confirmErase
|
|
514
|
+
confirmErase: confirmErase,
|
|
515
|
+
showDebugLogs: showDebugLogs,
|
|
516
|
+
debugLogs: debugLogs
|
|
386
517
|
};
|
|
387
518
|
}
|
|
@@ -6,6 +6,7 @@ function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(
|
|
|
6
6
|
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; }
|
|
7
7
|
import React, { useRef, useCallback } from "react";
|
|
8
8
|
import { getLogsStream } from "../helpers/dockerService/serviceComponents/containerLogs.js";
|
|
9
|
+
import { safeCall } from "../helpers/safeCall.js";
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Hook that manages opening and closing a logs stream for a container.
|
|
@@ -28,8 +29,8 @@ export function useLogsStream() {
|
|
|
28
29
|
}, []);
|
|
29
30
|
var closeLogs = useCallback(function () {
|
|
30
31
|
if (logsStreamRef.current) {
|
|
31
|
-
var _logsStreamRef$curren
|
|
32
|
-
(_logsStreamRef$curren =
|
|
32
|
+
var _logsStreamRef$curren;
|
|
33
|
+
safeCall((_logsStreamRef$curren = logsStreamRef.current.destroy) === null || _logsStreamRef$curren === void 0 ? void 0 : _logsStreamRef$curren.bind(logsStreamRef.current));
|
|
33
34
|
logsStreamRef.current = null;
|
|
34
35
|
}
|
|
35
36
|
}, []);
|
package/dist/index.js
CHANGED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>JSDoc: Source: components/ContainerCreationPrompt.jsx</title>
|
|
6
|
+
|
|
7
|
+
<script src="scripts/prettify/prettify.js"> </script>
|
|
8
|
+
<script src="scripts/prettify/lang-css.js"> </script>
|
|
9
|
+
<!--[if lt IE 9]>
|
|
10
|
+
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
|
11
|
+
<![endif]-->
|
|
12
|
+
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
|
13
|
+
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
|
14
|
+
</head>
|
|
15
|
+
|
|
16
|
+
<body>
|
|
17
|
+
|
|
18
|
+
<div id="main">
|
|
19
|
+
|
|
20
|
+
<h1 class="page-title">Source: components/ContainerCreationPrompt.jsx</h1>
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
<section>
|
|
28
|
+
<article>
|
|
29
|
+
<pre class="prettyprint source linenums"><code>import React from "react";
|
|
30
|
+
import { Box, Text } from "ink";
|
|
31
|
+
import { PromptField, PromptMessage } from "./PromptField.jsx";
|
|
32
|
+
import PropTypes from 'prop-types';
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Prompt UI shown when creating a new container.
|
|
36
|
+
* Presents a step-by-step form (image, name, ports, env) and displays
|
|
37
|
+
* a contextual message provided by the creation hook.
|
|
38
|
+
*
|
|
39
|
+
* @param {Object} props
|
|
40
|
+
* @param {number} props.step - Current step index (0..3)
|
|
41
|
+
* @param {string} props.imageName - Value for the image name field
|
|
42
|
+
* @param {string} props.containerName - Value for the container name field
|
|
43
|
+
* @param {string} props.portInput - Value for the ports input field
|
|
44
|
+
* @param {string} props.envInput - Value for the environment variables field
|
|
45
|
+
* @param {string} props.message - Contextual message to display (errors/hints)
|
|
46
|
+
* @param {string} props.messageColor - Color for the contextual message
|
|
47
|
+
* @returns {JSX.Element}
|
|
48
|
+
*/
|
|
49
|
+
export default function ContainerCreationPrompt(props) {
|
|
50
|
+
const { step, imageName, containerName, portInput, envInput, message, messageColor } = props;
|
|
51
|
+
const prompts = [
|
|
52
|
+
{
|
|
53
|
+
label: "Name of the image to create (e.g., nginx:latest):",
|
|
54
|
+
value: imageName,
|
|
55
|
+
required: true,
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
label: "Name of the container (optional):",
|
|
59
|
+
value: containerName,
|
|
60
|
+
required: false,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
label: "Ports (optional, format 8080:80,443:443):",
|
|
64
|
+
value: portInput,
|
|
65
|
+
required: false,
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
label: "Environment variables (optional, format VAR1=val1,VAR2=val2):",
|
|
69
|
+
value: envInput,
|
|
70
|
+
required: false,
|
|
71
|
+
},
|
|
72
|
+
];
|
|
73
|
+
const { label, value, required } = prompts[step] || {};
|
|
74
|
+
return (
|
|
75
|
+
<Box flexDirection="column" borderStyle="round" borderColor="yellow" padding={1}>
|
|
76
|
+
<PromptField label={label} value={value} required={required} />
|
|
77
|
+
<PromptMessage message={message} color={messageColor} />
|
|
78
|
+
<Text dimColor>Press Enter to continue, Escape to cancel</Text>
|
|
79
|
+
</Box>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
ContainerCreationPrompt.propTypes = {
|
|
84
|
+
step: PropTypes.number.isRequired,
|
|
85
|
+
imageName: PropTypes.string,
|
|
86
|
+
containerName: PropTypes.string,
|
|
87
|
+
portInput: PropTypes.string,
|
|
88
|
+
envInput: PropTypes.string,
|
|
89
|
+
message: PropTypes.string,
|
|
90
|
+
messageColor: PropTypes.string,
|
|
91
|
+
};
|
|
92
|
+
</code></pre>
|
|
93
|
+
</article>
|
|
94
|
+
</section>
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
<nav>
|
|
102
|
+
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-index.html">index</a></li></ul><h3>Global</h3><ul><li><a href="global.html#EXIT_DELAY">EXIT_DELAY</a></li><li><a href="global.html#MESSAGE_TIMEOUTS">MESSAGE_TIMEOUTS</a></li><li><a href="global.html#PromptField">PromptField</a></li><li><a href="global.html#PromptMessage">PromptMessage</a></li><li><a href="global.html#REFRESH_INTERVALS">REFRESH_INTERVALS</a></li><li><a href="global.html#TIMEOUTS">TIMEOUTS</a></li><li><a href="global.html#colorize">colorize</a></li><li><a href="global.html#createContainer">createContainer</a></li><li><a href="global.html#docker">docker</a></li><li><a href="global.html#exitWithMessage">exitWithMessage</a></li><li><a href="global.html#getContainers">getContainers</a></li><li><a href="global.html#getLogsStream">getLogsStream</a></li><li><a href="global.html#getStats">getStats</a></li><li><a href="global.html#handleAction">handleAction</a></li><li><a href="global.html#imageExists">imageExists</a></li><li><a href="global.html#makeBar">makeBar</a></li><li><a href="global.html#pullImage">pullImage</a></li><li><a href="global.html#removeContainer">removeContainer</a></li><li><a href="global.html#restartContainer">restartContainer</a></li><li><a href="global.html#safeCall">safeCall</a></li><li><a href="global.html#startContainer">startContainer</a></li><li><a href="global.html#stopContainer">stopContainer</a></li><li><a href="global.html#useContainerActions">useContainerActions</a></li><li><a href="global.html#useContainerCreation">useContainerCreation</a></li><li><a href="global.html#useControls">useControls</a></li><li><a href="global.html#useLogsStream">useLogsStream</a></li><li><a href="global.html#useLogsViewer">useLogsViewer</a></li><li><a href="global.html#validateEnvVars">validateEnvVars</a></li><li><a href="global.html#validatePorts">validatePorts</a></li><li><a href="global.html#withTimeout">withTimeout</a></li></ul>
|
|
103
|
+
</nav>
|
|
104
|
+
|
|
105
|
+
<br class="clear">
|
|
106
|
+
|
|
107
|
+
<footer>
|
|
108
|
+
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.5</a> on Fri Oct 17 2025 16:07:18 GMT-0500 (hora estándar de Colombia)
|
|
109
|
+
</footer>
|
|
110
|
+
|
|
111
|
+
<script> prettyPrint(); </script>
|
|
112
|
+
<script src="scripts/linenumber.js"> </script>
|
|
113
|
+
</body>
|
|
114
|
+
</html>
|