cdd-cli 3.1.4 → 3.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/.eslintrc.json +30 -0
  2. package/.github/workflows/docs.yml +35 -0
  3. package/CHANGELOG.md +37 -4
  4. package/README.md +26 -0
  5. package/_config.yml +13 -0
  6. package/dist/App.js +20 -3
  7. package/dist/components/ContainerCreationPrompt.js +27 -1
  8. package/dist/components/ContainerList.js +11 -15
  9. package/dist/components/ContainerRow.js +73 -14
  10. package/dist/components/ContainerSection.js +16 -2
  11. package/dist/components/Footer.js +7 -1
  12. package/dist/components/Header.js +27 -3
  13. package/dist/components/LogViewer.js +21 -3
  14. package/dist/components/MessageFeedback.js +15 -1
  15. package/dist/components/PromptField.js +31 -1
  16. package/dist/components/StatsBar.js +47 -8
  17. package/dist/components/UsageMenu.js +30 -1
  18. package/dist/helpers/actionHelpers.js +17 -6
  19. package/dist/helpers/appInfo.js +21 -0
  20. package/dist/helpers/constants.js +30 -0
  21. package/dist/helpers/dockerService/dockerService.js +19 -0
  22. package/dist/helpers/dockerService/serviceComponents/containerActions.js +194 -35
  23. package/dist/helpers/dockerService/serviceComponents/containerList.js +45 -8
  24. package/dist/helpers/dockerService/serviceComponents/containerLogs.js +16 -6
  25. package/dist/helpers/dockerService/serviceComponents/containerStats.js +28 -9
  26. package/dist/helpers/exitWithMessage.js +2 -1
  27. package/dist/helpers/logger.js +126 -0
  28. package/dist/helpers/safeCall.js +21 -0
  29. package/dist/helpers/validationHelpers.js +20 -1
  30. package/dist/hooks/creation/useContainerActions.js +2 -1
  31. package/dist/hooks/creation/useContainerCreation.js +5 -4
  32. package/dist/hooks/creation/useLogsViewer.js +3 -2
  33. package/dist/hooks/useContainers.js +6 -3
  34. package/dist/hooks/useControls.js +253 -122
  35. package/dist/hooks/useLogsStream.js +3 -2
  36. package/dist/index.js +1 -0
  37. package/docs/_config.yml +13 -0
  38. package/docs/components_ContainerCreationPrompt.jsx.html +114 -0
  39. package/docs/components_ContainerRow.jsx.html +151 -0
  40. package/docs/components_ContainerSection.jsx.html +75 -0
  41. package/docs/components_Footer.jsx.html +66 -0
  42. package/docs/components_Header.jsx.html +84 -0
  43. package/docs/components_LogViewer.jsx.html +91 -0
  44. package/docs/components_MessageFeedback.jsx.html +76 -0
  45. package/docs/components_PromptField.jsx.html +99 -0
  46. package/docs/components_StatsBar.jsx.html +105 -0
  47. package/docs/components_UsageMenu.jsx.html +73 -0
  48. package/docs/fonts/OpenSans-Bold-webfont.eot +0 -0
  49. package/docs/fonts/OpenSans-Bold-webfont.svg +1830 -0
  50. package/docs/fonts/OpenSans-Bold-webfont.woff +0 -0
  51. package/docs/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
  52. package/docs/fonts/OpenSans-BoldItalic-webfont.svg +1830 -0
  53. package/docs/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
  54. package/docs/fonts/OpenSans-Italic-webfont.eot +0 -0
  55. package/docs/fonts/OpenSans-Italic-webfont.svg +1830 -0
  56. package/docs/fonts/OpenSans-Italic-webfont.woff +0 -0
  57. package/docs/fonts/OpenSans-Light-webfont.eot +0 -0
  58. package/docs/fonts/OpenSans-Light-webfont.svg +1831 -0
  59. package/docs/fonts/OpenSans-Light-webfont.woff +0 -0
  60. package/docs/fonts/OpenSans-LightItalic-webfont.eot +0 -0
  61. package/docs/fonts/OpenSans-LightItalic-webfont.svg +1835 -0
  62. package/docs/fonts/OpenSans-LightItalic-webfont.woff +0 -0
  63. package/docs/fonts/OpenSans-Regular-webfont.eot +0 -0
  64. package/docs/fonts/OpenSans-Regular-webfont.svg +1831 -0
  65. package/docs/fonts/OpenSans-Regular-webfont.woff +0 -0
  66. package/docs/global.html +6145 -0
  67. package/docs/helpers_actionHelpers.js.html +94 -0
  68. package/docs/helpers_constants.js.html +81 -0
  69. package/docs/helpers_dockerService_dockerService.js.html +79 -0
  70. package/docs/helpers_dockerService_serviceComponents_containerActions.js.html +153 -0
  71. package/docs/helpers_dockerService_serviceComponents_containerList.js.html +81 -0
  72. package/docs/helpers_dockerService_serviceComponents_containerLogs.js.html +85 -0
  73. package/docs/helpers_dockerService_serviceComponents_containerStats.js.html +107 -0
  74. package/docs/helpers_dockerService_serviceComponents_imageUtils.js.html +82 -0
  75. package/docs/helpers_exitWithMessage.js.html +77 -0
  76. package/docs/helpers_safeCall.js.html +68 -0
  77. package/docs/helpers_validationHelpers.js.html +96 -0
  78. package/docs/hooks_creation_useContainerActions.js.html +120 -0
  79. package/docs/hooks_creation_useContainerCreation.js.html +152 -0
  80. package/docs/hooks_creation_useLogsViewer.js.html +102 -0
  81. package/docs/hooks_useControls.js.html +298 -0
  82. package/docs/hooks_useLogsStream.js.html +82 -0
  83. package/docs/index.html +65 -0
  84. package/docs/index.js.html +65 -0
  85. package/docs/module-index.html +171 -0
  86. package/docs/scripts/linenumber.js +25 -0
  87. package/docs/scripts/prettify/Apache-License-2.0.txt +202 -0
  88. package/docs/scripts/prettify/lang-css.js +2 -0
  89. package/docs/scripts/prettify/prettify.js +28 -0
  90. package/docs/styles/jsdoc-default.css +358 -0
  91. package/docs/styles/prettify-jsdoc.css +111 -0
  92. package/docs/styles/prettify-tomorrow.css +132 -0
  93. package/fix-imports.cjs +33 -6
  94. package/jest.config.cjs +2 -1
  95. package/package.json +19 -9
  96. package/src/App.jsx +16 -2
  97. package/src/components/ContainerCreationPrompt.jsx +26 -0
  98. package/src/components/ContainerList.jsx +12 -13
  99. package/src/components/ContainerRow.jsx +55 -20
  100. package/src/components/ContainerSection.jsx +15 -1
  101. package/src/components/Footer.jsx +6 -1
  102. package/src/components/Header.jsx +27 -3
  103. package/src/components/LogViewer.jsx +19 -2
  104. package/src/components/MessageFeedback.jsx +14 -0
  105. package/src/components/PromptField.jsx +30 -0
  106. package/src/components/StatsBar.jsx +47 -8
  107. package/src/components/UsageMenu.jsx +38 -8
  108. package/src/helpers/actionHelpers.js +16 -7
  109. package/src/helpers/appInfo.js +23 -0
  110. package/src/helpers/constants.js +30 -0
  111. package/src/helpers/dockerService/dockerService.js +19 -0
  112. package/src/helpers/dockerService/serviceComponents/containerActions.js +123 -12
  113. package/src/helpers/dockerService/serviceComponents/containerList.js +61 -23
  114. package/src/helpers/dockerService/serviceComponents/containerLogs.js +20 -6
  115. package/src/helpers/dockerService/serviceComponents/containerStats.js +24 -5
  116. package/src/helpers/dockerService/serviceComponents/imageUtils.js +1 -1
  117. package/src/helpers/exitWithMessage.js +2 -1
  118. package/src/helpers/logger.js +113 -0
  119. package/src/helpers/safeCall.js +18 -0
  120. package/src/helpers/validationHelpers.js +21 -3
  121. package/src/hooks/creation/useContainerActions.js +4 -3
  122. package/src/hooks/creation/useContainerCreation.js +5 -4
  123. package/src/hooks/creation/useLogsViewer.js +2 -1
  124. package/src/hooks/useContainers.js +6 -3
  125. package/src/hooks/useControls.js +244 -91
  126. package/src/hooks/useLogsStream.js +2 -1
  127. package/src/index.js +1 -0
  128. package/test/actionHelpers.test.js +106 -0
  129. package/test/containerActions.test.js +138 -0
  130. package/test/containerList.test.js +79 -0
  131. package/test/jest.setup.js +7 -0
  132. package/test/safeCall.test.js +25 -0
  133. package/test/useContainerCreation.dom.test.js +97 -0
  134. package/test/validationHelpers.test.js +2 -2
  135. package/dist/cdd.bundle.js +0 -8
  136. package/dist/components/ContainerCreator.js +0 -81
  137. package/dist/components/StatsViewer.js +0 -0
  138. package/dist/helpers/dockerActions.js +0 -64
  139. package/dist/helpers/dockerService.js +0 -284
  140. package/dist/hooks/useStatsPolling.js +0 -54
@@ -0,0 +1,138 @@
1
+ import { jest } from '@jest/globals';
2
+
3
+ describe('containerActions service functions (mocked ESM imports)', () => {
4
+ afterEach(() => jest.resetModules());
5
+
6
+ test('createContainer returns id when image exists', async () => {
7
+ // mock imageUtils and dockerService before importing the module under test
8
+ const imageUtilsMock = {
9
+ imageExists: jest.fn().mockResolvedValue(true),
10
+ pullImage: jest.fn()
11
+ };
12
+
13
+ const inspectMock = jest.fn().mockResolvedValue({ Config: { ExposedPorts: {} } });
14
+ const dockerMock = {
15
+ createContainer: jest.fn().mockResolvedValue({ id: 'cid-123' }),
16
+ getImage: jest.fn().mockReturnValue({ inspect: inspectMock }),
17
+ listContainers: jest.fn().mockResolvedValue([])
18
+ };
19
+
20
+ await jest.unstable_mockModule('../src/helpers/dockerService/serviceComponents/imageUtils.js', () => ({
21
+ ...imageUtilsMock
22
+ }));
23
+
24
+ await jest.unstable_mockModule('../src/helpers/dockerService/dockerService.js', () => ({
25
+ docker: dockerMock
26
+ }));
27
+
28
+ const mod = await import('../src/helpers/dockerService/serviceComponents/containerActions.js');
29
+
30
+ const id = await mod.createContainer('nginx:latest', { Name: 'test' });
31
+ expect(id).toBe('cid-123');
32
+ const imageUtils = await import('../src/helpers/dockerService/serviceComponents/imageUtils.js');
33
+ expect(imageUtils.imageExists).toHaveBeenCalledWith('nginx:latest');
34
+ const ds = await import('../src/helpers/dockerService/dockerService.js');
35
+ expect(ds.docker.createContainer).toHaveBeenCalled();
36
+ expect(ds.docker.getImage).toHaveBeenCalledWith('nginx:latest');
37
+ });
38
+
39
+ test('createContainer pulls image when not present and returns Id', async () => {
40
+ const imageUtilsMock = {
41
+ imageExists: jest.fn().mockResolvedValue(false),
42
+ pullImage: jest.fn().mockResolvedValue(true)
43
+ };
44
+
45
+ const inspectMock = jest.fn().mockResolvedValue({ Config: { ExposedPorts: {} } });
46
+ const dockerMock = {
47
+ createContainer: jest.fn().mockResolvedValue({ Id: 'CID-456' }),
48
+ getImage: jest.fn().mockReturnValue({ inspect: inspectMock }),
49
+ listContainers: jest.fn().mockResolvedValue([])
50
+ };
51
+
52
+ await jest.unstable_mockModule('../src/helpers/dockerService/serviceComponents/imageUtils.js', () => ({
53
+ ...imageUtilsMock
54
+ }));
55
+
56
+ await jest.unstable_mockModule('../src/helpers/dockerService/dockerService.js', () => ({
57
+ docker: dockerMock
58
+ }));
59
+
60
+ const mod = await import('../src/helpers/dockerService/serviceComponents/containerActions.js');
61
+ const id = await mod.createContainer('busybox:1.0');
62
+ expect(id).toBe('CID-456');
63
+ const imageUtils = await import('../src/helpers/dockerService/serviceComponents/imageUtils.js');
64
+ expect(imageUtils.pullImage).toHaveBeenCalledWith('busybox:1.0');
65
+ });
66
+
67
+ test('createContainer auto maps exposed ports when ports not provided', async () => {
68
+ const imageUtilsMock = {
69
+ imageExists: jest.fn().mockResolvedValue(true),
70
+ pullImage: jest.fn()
71
+ };
72
+
73
+ const inspectMock = jest.fn().mockResolvedValue({ Config: { ExposedPorts: { '80/tcp': {} } } });
74
+ const createContainerMock = jest.fn().mockResolvedValue({ id: 'cid-auto' });
75
+ const dockerMock = {
76
+ createContainer: createContainerMock,
77
+ getImage: jest.fn().mockReturnValue({ inspect: inspectMock }),
78
+ listContainers: jest.fn().mockResolvedValue([
79
+ { Ports: [{ PublicPort: 80, PrivatePort: 80 }] }
80
+ ])
81
+ };
82
+
83
+ await jest.unstable_mockModule('../src/helpers/dockerService/serviceComponents/imageUtils.js', () => ({
84
+ ...imageUtilsMock
85
+ }));
86
+
87
+ await jest.unstable_mockModule('../src/helpers/dockerService/dockerService.js', () => ({
88
+ docker: dockerMock
89
+ }));
90
+
91
+ const mod = await import('../src/helpers/dockerService/serviceComponents/containerActions.js');
92
+ await mod.createContainer('nginx:alpine');
93
+
94
+ const [[createArgs]] = createContainerMock.mock.calls;
95
+ expect(createArgs.ExposedPorts).toEqual({ '80/tcp': {} });
96
+ expect(createArgs.HostConfig.PortBindings['80/tcp']).toEqual([{ HostPort: '81' }]);
97
+ expect(dockerMock.listContainers).toHaveBeenCalled();
98
+ });
99
+
100
+ test('removeContainer calls docker.remove with force', async () => {
101
+ const removeMock = jest.fn().mockResolvedValue(undefined);
102
+ const dockerMock = {
103
+ getContainer: jest.fn().mockReturnValue({ remove: removeMock })
104
+ };
105
+
106
+ await jest.unstable_mockModule('../src/helpers/dockerService/dockerService.js', () => ({ docker: dockerMock }));
107
+ await jest.unstable_mockModule('../src/helpers/dockerService/serviceComponents/imageUtils.js', () => ({ imageExists: jest.fn(), pullImage: jest.fn() }));
108
+
109
+ const mod = await import('../src/helpers/dockerService/serviceComponents/containerActions.js');
110
+ await mod.removeContainer('abc');
111
+ const ds = await import('../src/helpers/dockerService/dockerService.js');
112
+ expect(ds.docker.getContainer).toHaveBeenCalledWith('abc');
113
+ expect(removeMock).toHaveBeenCalledWith({ force: true });
114
+ });
115
+
116
+ test('start/stop/restart call respective container methods', async () => {
117
+ const startMock = jest.fn().mockResolvedValue(undefined);
118
+ const stopMock = jest.fn().mockResolvedValue(undefined);
119
+ const restartMock = jest.fn().mockResolvedValue(undefined);
120
+
121
+ const dockerMock = {
122
+ getContainer: jest.fn().mockReturnValue({ start: startMock, stop: stopMock, restart: restartMock })
123
+ };
124
+
125
+ await jest.unstable_mockModule('../src/helpers/dockerService/dockerService.js', () => ({ docker: dockerMock }));
126
+ await jest.unstable_mockModule('../src/helpers/dockerService/serviceComponents/imageUtils.js', () => ({ imageExists: jest.fn(), pullImage: jest.fn() }));
127
+
128
+ const mod = await import('../src/helpers/dockerService/serviceComponents/containerActions.js');
129
+
130
+ await mod.startContainer('c1');
131
+ await mod.stopContainer('c1');
132
+ await mod.restartContainer('c1');
133
+
134
+ expect(startMock).toHaveBeenCalled();
135
+ expect(stopMock).toHaveBeenCalled();
136
+ expect(restartMock).toHaveBeenCalled();
137
+ });
138
+ });
@@ -0,0 +1,79 @@
1
+ import { jest } from '@jest/globals';
2
+
3
+ describe('containerList.getContainers', () => {
4
+ afterEach(() => jest.resetModules());
5
+
6
+ const baseContainer = {
7
+ Id: 'abc123',
8
+ Image: 'nginx:latest',
9
+ State: 'running',
10
+ Status: 'Up 5 minutes',
11
+ Ports: []
12
+ };
13
+
14
+ test('falls back to container.Name when Names array is missing', async () => {
15
+ const dockerMock = {
16
+ listContainers: jest.fn().mockResolvedValue([
17
+ {
18
+ ...baseContainer,
19
+ Names: undefined,
20
+ Name: '/custom-container'
21
+ }
22
+ ])
23
+ };
24
+
25
+ await jest.unstable_mockModule('../src/helpers/dockerService/dockerService.js', () => ({
26
+ docker: dockerMock
27
+ }));
28
+
29
+ const mod = await import('../src/helpers/dockerService/serviceComponents/containerList.js');
30
+ const containers = await mod.getContainers();
31
+
32
+ expect(containers).toHaveLength(1);
33
+ expect(containers[0].name).toBe('custom-container');
34
+ });
35
+
36
+ test('returns Unknown when no usable name data is present', async () => {
37
+ const dockerMock = {
38
+ listContainers: jest.fn().mockResolvedValue([
39
+ {
40
+ ...baseContainer,
41
+ Names: [],
42
+ Name: '',
43
+ Id: 'def456'
44
+ }
45
+ ])
46
+ };
47
+
48
+ await jest.unstable_mockModule('../src/helpers/dockerService/dockerService.js', () => ({
49
+ docker: dockerMock
50
+ }));
51
+
52
+ const mod = await import('../src/helpers/dockerService/serviceComponents/containerList.js');
53
+ const containers = await mod.getContainers();
54
+
55
+ expect(containers).toHaveLength(1);
56
+ expect(containers[0].name).toBe('Unknown');
57
+ });
58
+
59
+ test('normalizes first entry in Names array', async () => {
60
+ const dockerMock = {
61
+ listContainers: jest.fn().mockResolvedValue([
62
+ {
63
+ ...baseContainer,
64
+ Names: ['///leading/slash', '/ignored-second']
65
+ }
66
+ ])
67
+ };
68
+
69
+ await jest.unstable_mockModule('../src/helpers/dockerService/dockerService.js', () => ({
70
+ docker: dockerMock
71
+ }));
72
+
73
+ const mod = await import('../src/helpers/dockerService/serviceComponents/containerList.js');
74
+ const containers = await mod.getContainers();
75
+
76
+ expect(containers).toHaveLength(1);
77
+ expect(containers[0].name).toBe('leading/slash');
78
+ });
79
+ });
@@ -0,0 +1,7 @@
1
+ // Minimal test setup for React/DOM environment
2
+ // Could add more global matchers here
3
+ import '@testing-library/jest-dom';
4
+
5
+ // Silence act() warnings in environments where receiver isn't concurrent
6
+ // (react-test-renderer/act warnings are printed, but tests can proceed)
7
+ // If needed, configure global helpers here.
@@ -0,0 +1,25 @@
1
+ import { safeCall } from '../src/helpers/safeCall.js';
2
+
3
+ describe('safeCall', () => {
4
+ test('calls function and returns value', () => {
5
+ function fn(a, b) {
6
+ fn.called = true;
7
+ fn.args = [a, b];
8
+ return a + b;
9
+ }
10
+ const res = safeCall(fn, 2, 3);
11
+ expect(fn.called).toBe(true);
12
+ expect(fn.args).toEqual([2, 3]);
13
+ expect(res).toBe(5);
14
+ });
15
+
16
+ test('returns undefined when fn is not a function', () => {
17
+ const res = safeCall(undefined, 1, 2);
18
+ expect(res).toBeUndefined();
19
+ });
20
+
21
+ test('catches errors thrown by function and does not rethrow', () => {
22
+ const bad = () => { throw new Error('boom'); };
23
+ expect(() => safeCall(bad)).not.toThrow();
24
+ });
25
+ });
@@ -0,0 +1,97 @@
1
+ import React, { useEffect } from 'react';
2
+ import { render, act } from '@testing-library/react';
3
+ import { useContainerCreation } from '../src/hooks/creation/useContainerCreation.js';
4
+
5
+ function HookTester({ onCreate, onCancel, dbImages, expose }) {
6
+ const hook = useContainerCreation({ onCreate, onCancel, dbImages });
7
+ // keep exposing the latest hook values on every render
8
+ useEffect(() => {
9
+ if (expose) expose.current = hook;
10
+ });
11
+ return null;
12
+ }
13
+
14
+ describe('useContainerCreation (DOM render)', () => {
15
+ test('image empty shows error and does not advance', () => {
16
+ const expose = { current: null };
17
+ render(<HookTester onCreate={() => {}} onCancel={() => {}} dbImages={[]} expose={expose} />);
18
+
19
+ expect(expose.current.step).toBe(0);
20
+
21
+ act(() => {
22
+ expose.current.nextStep();
23
+ });
24
+
25
+ expect(expose.current.message).toBe('Image name cannot be empty.');
26
+ expect(expose.current.step).toBe(0);
27
+ });
28
+
29
+ test('ports validation: invalid ports shows error', () => {
30
+ const expose = { current: null };
31
+ render(<HookTester onCreate={() => {}} onCancel={() => {}} dbImages={[]} expose={expose} />);
32
+
33
+ act(() => {
34
+ expose.current.setImageName('nginx');
35
+ });
36
+
37
+ act(() => {
38
+ expose.current.nextStep(); // to name
39
+ });
40
+
41
+ act(() => {
42
+ expose.current.nextStep(); // to ports
43
+ });
44
+
45
+ expect(expose.current.step).toBe(2);
46
+
47
+ act(() => {
48
+ expose.current.setPortInput('notaport');
49
+ });
50
+
51
+ act(() => {
52
+ expose.current.nextStep();
53
+ });
54
+
55
+ expect(expose.current.message).toBe('Port format must be host:container and both must be numbers (e.g. 8080:80)');
56
+ expect(expose.current.step).toBe(2);
57
+ });
58
+
59
+ test('complete flow calls onCreate with data', () => {
60
+ const created = [];
61
+ const onCreate = (data) => created.push(data);
62
+ const expose = { current: null };
63
+
64
+ render(<HookTester onCreate={onCreate} onCancel={() => {}} dbImages={[]} expose={expose} />);
65
+
66
+ act(() => {
67
+ expose.current.setImageName('redis');
68
+ });
69
+
70
+ act(() => {
71
+ expose.current.nextStep(); // to name
72
+ });
73
+
74
+ act(() => {
75
+ expose.current.nextStep(); // to ports
76
+ });
77
+
78
+ act(() => {
79
+ expose.current.setPortInput('');
80
+ });
81
+
82
+ act(() => {
83
+ expose.current.nextStep(); // to env
84
+ });
85
+
86
+ act(() => {
87
+ expose.current.setEnvInput('FOO=bar');
88
+ });
89
+
90
+ act(() => {
91
+ expose.current.nextStep(); // final create
92
+ });
93
+
94
+ expect(created.length).toBe(1);
95
+ expect(created[0]).toEqual({ imageName: 'redis', containerName: '', portInput: '', envInput: 'FOO=bar' });
96
+ });
97
+ });
@@ -24,8 +24,8 @@ describe('validatePorts', () => {
24
24
  expect(validatePorts('eighty:80')).toBe(false);
25
25
  });
26
26
 
27
- test('empty input returns false (must specify at least one port)', () => {
28
- expect(validatePorts('')).toBe(false);
27
+ test('empty input is valid (ports are optional)', () => {
28
+ expect(validatePorts('')).toBe(true);
29
29
  });
30
30
  });
31
31
 
@@ -1,8 +0,0 @@
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
@@ -1,81 +0,0 @@
1
- function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
2
- function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
3
- function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
4
- function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
5
- function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
6
- function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
7
- import React from "react";
8
- import { Box, Text } from "ink";
9
- import { createContainer } from "../helpers/dockerService.js";
10
- export default function ContainerCreator(_ref) {
11
- var onClose = _ref.onClose;
12
- var _React$useState = React.useState(""),
13
- _React$useState2 = _slicedToArray(_React$useState, 2),
14
- imageName = _React$useState2[0],
15
- setImageName = _React$useState2[1];
16
- var _React$useState3 = React.useState(""),
17
- _React$useState4 = _slicedToArray(_React$useState3, 2),
18
- message = _React$useState4[0],
19
- setMessage = _React$useState4[1];
20
- var handleInput = function handleInput(data) {
21
- var _char = String(data);
22
- if (_char === "\r") {
23
- // Enter key
24
- if (imageName.trim() === "") {
25
- setMessage("Image name cannot be empty.");
26
- return;
27
- }
28
- createContainer(imageName.trim()).then(function (id) {
29
- setMessage("Container created with ID: ".concat(id));
30
- setTimeout(onClose, 2000);
31
- })["catch"](function (err) {
32
- setMessage("Error: ".concat(err.message));
33
- });
34
- } else if (_char === "\x03") {
35
- // Ctrl+C
36
- onClose();
37
- } else if (_char === "\x7F") {
38
- // Backspace
39
- setImageName(function (prev) {
40
- return prev.slice(0, -1);
41
- });
42
- } else {
43
- setImageName(function (prev) {
44
- return prev + _char;
45
- });
46
- }
47
- };
48
- React.useEffect(function () {
49
- process.stdin.setRawMode(true);
50
- process.stdin.resume();
51
- process.stdin.on("data", handleInput);
52
- return function () {
53
- process.stdin.setRawMode(false);
54
- process.stdin.pause();
55
- process.stdin.removeListener("data", handleInput);
56
- };
57
- }, [imageName]);
58
- return /*#__PURE__*/React.createElement(Box, {
59
- flexDirection: "column",
60
- borderStyle: "round",
61
- borderColor: "yellow",
62
- padding: 1
63
- }, /*#__PURE__*/React.createElement(Text, null, "Enter Docker Image Name:"), /*#__PURE__*/React.createElement(Text, {
64
- color: "cyan"
65
- }, imageName, "_"), message && /*#__PURE__*/React.createElement(Text, {
66
- color: "green"
67
- }, message), /*#__PURE__*/React.createElement(Text, {
68
- dimColor: true
69
- }, "Press Enter to create or Ctrl+C to cancel"));
70
- }
71
-
72
- /**
73
- * Docker service helper functions.
74
- * Funciones auxiliares para el servicio Docker.
75
- *
76
- * @module dockerService
77
- * @example
78
- * // EN: Create a new container
79
- * // ES: Crear un nuevo contenedor
80
- * const containerId = await createContainer("my-image");
81
- * */
File without changes
@@ -1,64 +0,0 @@
1
- /**
2
- * Run a Docker action by name (start, stop, remove).
3
- * Ejecuta una acción Docker por nombre (start, stop, remove).
4
- *
5
- * @param {string} action - Action to perform / Acción a realizar
6
- * @param {string} container - Container name / Nombre del contenedor
7
- * @returns {Promise<boolean>} True if successful / True si es exitoso
8
- * @throws {Error} If Docker is not running / Si Docker no está corriendo
9
- * @example
10
- * // EN: Start a container
11
- * // ES: Iniciar un contenedor
12
- * await runDockerAction('start', 'my_container');
13
- */
14
- import { spawn } from "child_process";
15
-
16
- /**
17
- * Ejecuta una acción de Docker sobre un contenedor y maneja feedback visual.
18
- * @param {Object} params
19
- * @param {Array} params.containers - Lista de contenedores.
20
- * @param {number} params.selected - Índice del contenedor seleccionado.
21
- * @param {string} params.action - Acción docker (start, stop, restart).
22
- * @param {string} params.actionLabel - Texto para feedback (Starting, Stopping, etc).
23
- * @param {Function} params.setMessage - Setter de mensaje visual.
24
- * @param {Function} params.setMessageColor - Setter de color del mensaje.
25
- */
26
- export function handleDockerAction(_ref) {
27
- var containers = _ref.containers,
28
- selected = _ref.selected,
29
- action = _ref.action,
30
- actionLabel = _ref.actionLabel,
31
- setMessage = _ref.setMessage,
32
- setMessageColor = _ref.setMessageColor;
33
- if (containers[selected]) {
34
- var c = containers[selected];
35
- var id = c.id || c.name;
36
- // Validación de estado
37
- if (action === "start" && (c.state === "running" || c.status === "running")) {
38
- setMessage("Container is already running.");
39
- setMessageColor("red");
40
- setTimeout(function () {
41
- return setMessage("");
42
- }, 2000);
43
- return;
44
- }
45
- if (action === "stop" && (c.state === "exited" || c.status === "exited" || c.state === "stopped" || c.status === "stopped")) {
46
- setMessage("Container is already stopped.");
47
- setMessageColor("red");
48
- setTimeout(function () {
49
- return setMessage("");
50
- }, 2000);
51
- return;
52
- }
53
- setMessage("".concat(actionLabel, " container..."));
54
- setMessageColor("green");
55
- var child = spawn("docker", [action, id]);
56
- child.on("close", function () {
57
- setMessage("".concat(actionLabel, " container..."));
58
- setMessageColor("green");
59
- setTimeout(function () {
60
- return setMessage("");
61
- }, 3000);
62
- });
63
- }
64
- }