cdd-cli 4.0.0 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/README.es.md +60 -26
  2. package/README.md +60 -26
  3. package/dist/App.js +1 -0
  4. package/dist/components/ContainerCreationPrompt.js +14 -0
  5. package/dist/components/PromptField.js +13 -6
  6. package/dist/components/TextField.js +54 -0
  7. package/dist/components/UsageMenu.js +1 -1
  8. package/dist/helpers/appState.js +26 -0
  9. package/dist/helpers/dockerService/serviceComponents/containerExec.js +211 -0
  10. package/dist/helpers/textEditing.js +293 -0
  11. package/dist/hooks/creation/useContainerCreation.js +132 -15
  12. package/dist/hooks/useContainerCommandRouter.js +12 -2
  13. package/dist/hooks/useControls.js +21 -26
  14. package/dist/hooks/useShellMode.js +101 -0
  15. package/dist/index.js +3 -1
  16. package/package.json +4 -1
  17. package/.atl/skill-registry.md +0 -30
  18. package/.editorconfig +0 -12
  19. package/.eslintrc.json +0 -30
  20. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -30
  21. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -19
  22. package/.github/PULL_REQUEST_TEMPLATE/pull_request.md +0 -14
  23. package/.github/workflows/ci.yml +0 -32
  24. package/.github/workflows/docs.yml +0 -42
  25. package/.prettierignore +0 -4
  26. package/.prettierrc +0 -8
  27. package/.~lock.ROADMAP.md# +0 -1
  28. package/CHANGELOG.md +0 -216
  29. package/CODE_OF_CONDUCT.md +0 -12
  30. package/CONTRIBUTING.md +0 -35
  31. package/ROADMAP.md +0 -647
  32. package/SECURITY.md +0 -5
  33. package/__mocks__/ink.cjs +0 -17
  34. package/_config.yml +0 -13
  35. package/babel.config.cjs +0 -23
  36. package/coverage/clover.xml +0 -575
  37. package/coverage/coverage-final.json +0 -17
  38. package/coverage/lcov-report/ContainerCreationPrompt.jsx.html +0 -400
  39. package/coverage/lcov-report/ControlsHUD.jsx.html +0 -256
  40. package/coverage/lcov-report/base.css +0 -224
  41. package/coverage/lcov-report/block-navigation.js +0 -87
  42. package/coverage/lcov-report/components/ContainerCreationPrompt.jsx.html +0 -394
  43. package/coverage/lcov-report/components/PromptField.jsx.html +0 -229
  44. package/coverage/lcov-report/components/SuggestionPanel.jsx.html +0 -268
  45. package/coverage/lcov-report/components/index.html +0 -146
  46. package/coverage/lcov-report/favicon.png +0 -0
  47. package/coverage/lcov-report/helpers/constants.js.html +0 -352
  48. package/coverage/lcov-report/helpers/containerOptionsBuilder.js.html +0 -244
  49. package/coverage/lcov-report/helpers/dockerHubService.js.html +0 -310
  50. package/coverage/lcov-report/helpers/dockerService/serviceComponents/containerActions.js.html +0 -931
  51. package/coverage/lcov-report/helpers/dockerService/serviceComponents/containerList.js.html +0 -307
  52. package/coverage/lcov-report/helpers/dockerService/serviceComponents/index.html +0 -131
  53. package/coverage/lcov-report/helpers/imageNameUtils.js.html +0 -181
  54. package/coverage/lcov-report/helpers/index.html +0 -206
  55. package/coverage/lcov-report/helpers/logger.js.html +0 -424
  56. package/coverage/lcov-report/helpers/safeCall.js.html +0 -139
  57. package/coverage/lcov-report/helpers/validationHelpers.js.html +0 -346
  58. package/coverage/lcov-report/hooks/creation/index.html +0 -146
  59. package/coverage/lcov-report/hooks/creation/useContainerActions.js.html +0 -313
  60. package/coverage/lcov-report/hooks/creation/useContainerCreation.js.html +0 -982
  61. package/coverage/lcov-report/hooks/creation/useLogsViewer.js.html +0 -238
  62. package/coverage/lcov-report/hooks/debug/index.html +0 -116
  63. package/coverage/lcov-report/hooks/debug/useDebugLogs.js.html +0 -187
  64. package/coverage/lcov-report/hooks/index.html +0 -161
  65. package/coverage/lcov-report/hooks/navigation/index.html +0 -116
  66. package/coverage/lcov-report/hooks/navigation/useContainerSelection.js.html +0 -169
  67. package/coverage/lcov-report/hooks/useContainerCommandRouter.js.html +0 -454
  68. package/coverage/lcov-report/hooks/useControls.js.html +0 -868
  69. package/coverage/lcov-report/hooks/useEraseConfirmation.js.html +0 -202
  70. package/coverage/lcov-report/hooks/useExitHandler.js.html +0 -292
  71. package/coverage/lcov-report/index.html +0 -176
  72. package/coverage/lcov-report/prettify.css +0 -1
  73. package/coverage/lcov-report/prettify.js +0 -2
  74. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  75. package/coverage/lcov-report/sorter.js +0 -210
  76. package/coverage/lcov.info +0 -1163
  77. package/fix-imports.cjs +0 -54
  78. package/jest.config.cjs +0 -14
  79. package/src/App.jsx +0 -102
  80. package/src/components/ContainerCreationPrompt.jsx +0 -107
  81. package/src/components/ContainerList.jsx +0 -32
  82. package/src/components/ContainerRow.jsx +0 -84
  83. package/src/components/ContainerSection.jsx +0 -24
  84. package/src/components/ControlsHUD.jsx +0 -66
  85. package/src/components/Footer.jsx +0 -15
  86. package/src/components/Header.jsx +0 -41
  87. package/src/components/LogViewer.jsx +0 -36
  88. package/src/components/MessageFeedback.jsx +0 -25
  89. package/src/components/PromptField.jsx +0 -48
  90. package/src/components/StatsBar.jsx +0 -70
  91. package/src/components/SuggestionPanel.jsx +0 -61
  92. package/src/components/UsageMenu.jsx +0 -52
  93. package/src/helpers/appInfo.js +0 -23
  94. package/src/helpers/constants.js +0 -89
  95. package/src/helpers/containerOptionsBuilder.js +0 -53
  96. package/src/helpers/dockerHubService.js +0 -75
  97. package/src/helpers/dockerService/dockerService.js +0 -28
  98. package/src/helpers/dockerService/serviceComponents/containerActions.js +0 -282
  99. package/src/helpers/dockerService/serviceComponents/containerList.js +0 -74
  100. package/src/helpers/dockerService/serviceComponents/containerLogs.js +0 -60
  101. package/src/helpers/dockerService/serviceComponents/containerStats.js +0 -69
  102. package/src/helpers/dockerService/serviceComponents/imageUtils.js +0 -32
  103. package/src/helpers/exitWithMessage.js +0 -32
  104. package/src/helpers/imageNameUtils.js +0 -32
  105. package/src/helpers/logger.js +0 -112
  106. package/src/helpers/safeCall.js +0 -18
  107. package/src/helpers/validationHelpers.js +0 -87
  108. package/src/hooks/creation/useContainerActions.js +0 -89
  109. package/src/hooks/creation/useContainerCreation.js +0 -377
  110. package/src/hooks/creation/useLogsViewer.js +0 -51
  111. package/src/hooks/debug/useDebugLogs.js +0 -34
  112. package/src/hooks/navigation/useContainerSelection.js +0 -28
  113. package/src/hooks/useContainerCommandRouter.js +0 -123
  114. package/src/hooks/useContainerStats.js +0 -44
  115. package/src/hooks/useContainers.js +0 -26
  116. package/src/hooks/useControls.js +0 -263
  117. package/src/hooks/useEraseConfirmation.js +0 -39
  118. package/src/hooks/useExitHandler.js +0 -69
  119. package/src/index.js +0 -20
  120. package/test/ContainerCreationPrompt.dom.test.js +0 -313
  121. package/test/ControlsHUD.dom.test.js +0 -125
  122. package/test/SuggestionPanel.dom.test.js +0 -83
  123. package/test/constants.test.js +0 -41
  124. package/test/containerActions.test.js +0 -229
  125. package/test/containerList.test.js +0 -79
  126. package/test/containerOptionsBuilder.test.js +0 -36
  127. package/test/dockerHubService.test.js +0 -213
  128. package/test/jest.setup.js +0 -7
  129. package/test/logger.test.js +0 -58
  130. package/test/resolveImageTag.test.js +0 -26
  131. package/test/safeCall.test.js +0 -25
  132. package/test/useContainerCreation.dom.test.js +0 -567
  133. package/test/useContainerCreationHub.dom.test.js +0 -184
  134. package/test/useControls.dom.test.js +0 -519
  135. package/test/validationHelpers.test.js +0 -111
@@ -1,184 +0,0 @@
1
- /**
2
- * @jest-environment jsdom
3
- *
4
- * Tests for Hub-search additions to useContainerCreation:
5
- * - isSearchingHub state
6
- * - hubResults state (string[] after formatHubResult mapping)
7
- * - triggerHubSearch() guards (empty input, already searching)
8
- * - stale response ignored via requestId
9
- * - updateImageInput() aborts in-flight search and clears hubResults
10
- */
11
- import React, { useEffect } from 'react';
12
- import { render, act } from '@testing-library/react';
13
- import { jest } from '@jest/globals';
14
-
15
- // ── Mock dockerHubService BEFORE any import that might pull it in ─────────────
16
- jest.unstable_mockModule('../src/helpers/dockerHubService.js', () => ({
17
- searchDockerHub: jest.fn(),
18
- formatHubResult: jest.fn((r) => r.name), // identity-like stub: returns name string
19
- }));
20
-
21
- // Dynamic import resolves AFTER jest.unstable_mockModule is registered
22
- const { useContainerCreation } = await import('../src/hooks/creation/useContainerCreation.js');
23
- const { searchDockerHub } = await import('../src/helpers/dockerHubService.js');
24
-
25
- const mockSearchDockerHub = searchDockerHub;
26
-
27
- // ── Test harness ─────────────────────────────────────────────────────────────
28
-
29
- function HookTester({ onCreate, onCancel, dbImages, imageProfiles, expose }) {
30
- const hook = useContainerCreation({
31
- onCreate: onCreate ?? (() => {}),
32
- onCancel: onCancel ?? (() => {}),
33
- dbImages: dbImages ?? [],
34
- imageProfiles: imageProfiles ?? {},
35
- });
36
- useEffect(() => {
37
- if (expose) expose.current = hook;
38
- });
39
- return null;
40
- }
41
-
42
- function makeExpose() {
43
- const expose = { current: null };
44
- render(<HookTester expose={expose} />);
45
- return expose;
46
- }
47
-
48
- // ── Tests ─────────────────────────────────────────────────────────────────────
49
-
50
- describe('useContainerCreation — Hub search state', () => {
51
- beforeEach(() => {
52
- mockSearchDockerHub.mockReset();
53
- });
54
-
55
- test('exposes isSearchingHub (initially false) and hubResults (initially null)', () => {
56
- const expose = makeExpose();
57
-
58
- expect(expose.current.isSearchingHub).toBe(false);
59
- expect(expose.current.hubResults).toBeNull();
60
- });
61
-
62
- test('triggerHubSearch() ignores empty imageName', async () => {
63
- const expose = makeExpose();
64
- // imageName is '' by default
65
- await act(async () => {
66
- expose.current.triggerHubSearch();
67
- });
68
- expect(mockSearchDockerHub).not.toHaveBeenCalled();
69
- expect(expose.current.isSearchingHub).toBe(false);
70
- });
71
-
72
- test('triggerHubSearch() sets isSearchingHub=true during the request', async () => {
73
- const expose = makeExpose();
74
- let resolveSearch;
75
- mockSearchDockerHub.mockReturnValue(
76
- new Promise((res) => { resolveSearch = res; })
77
- );
78
-
79
- act(() => { expose.current.updateImageInput('nginx'); });
80
-
81
- let searchPromise;
82
- act(() => { searchPromise = expose.current.triggerHubSearch(); });
83
-
84
- expect(expose.current.isSearchingHub).toBe(true);
85
-
86
- await act(async () => { resolveSearch([]); await searchPromise; });
87
- expect(expose.current.isSearchingHub).toBe(false);
88
- });
89
-
90
- test('triggerHubSearch() ignores call when isSearchingHub is already true', async () => {
91
- const expose = makeExpose();
92
- let resolveFirst;
93
- mockSearchDockerHub.mockReturnValue(
94
- new Promise((res) => { resolveFirst = res; })
95
- );
96
-
97
- act(() => { expose.current.updateImageInput('nginx'); });
98
- act(() => { expose.current.triggerHubSearch(); }); // first call — now searching
99
- expect(expose.current.isSearchingHub).toBe(true);
100
-
101
- // second call — should be ignored
102
- act(() => { expose.current.triggerHubSearch(); });
103
- expect(mockSearchDockerHub).toHaveBeenCalledTimes(1);
104
-
105
- // cleanup
106
- await act(async () => { resolveFirst([]); });
107
- });
108
-
109
- test('triggerHubSearch() stores formatted results (strings) in hubResults on success', async () => {
110
- const expose = makeExpose();
111
- const fakeResults = [
112
- { name: 'library/nginx', isOfficial: true, pullCount: 1e9, description: 'official' },
113
- ];
114
- mockSearchDockerHub.mockResolvedValue(fakeResults);
115
-
116
- act(() => { expose.current.updateImageInput('nginx'); });
117
- await act(async () => { await expose.current.triggerHubSearch(); });
118
-
119
- // hubResults should be string[] (after formatHubResult mapping)
120
- expect(Array.isArray(expose.current.hubResults)).toBe(true);
121
- expect(expose.current.hubResults).toHaveLength(1);
122
- expect(typeof expose.current.hubResults[0]).toBe('string');
123
- expect(expose.current.isSearchingHub).toBe(false);
124
- });
125
-
126
- test('stale response is ignored — only the latest requestId wins', async () => {
127
- const expose = makeExpose();
128
-
129
- let resolveFirst;
130
- let resolveSecond;
131
-
132
- mockSearchDockerHub
133
- .mockReturnValueOnce(new Promise((res) => { resolveFirst = res; }))
134
- .mockReturnValueOnce(new Promise((res) => { resolveSecond = res; }));
135
-
136
- act(() => { expose.current.updateImageInput('nginx'); });
137
- act(() => { expose.current.triggerHubSearch(); }); // request #1 starts, isSearchingHub=true
138
-
139
- // Simulate user typing (aborts #1, clears hub state)
140
- act(() => { expose.current.updateImageInput('ngi'); });
141
- // Now trigger again (request #2)
142
- act(() => { expose.current.triggerHubSearch(); });
143
-
144
- const secondResults = [{ name: 'ngi/x', isOfficial: false, pullCount: 0, description: '' }];
145
-
146
- // Resolve second first (fresh), then first (stale)
147
- await act(async () => { resolveSecond(secondResults); });
148
- await act(async () => { resolveFirst([{ name: 'stale', isOfficial: false, pullCount: 0, description: '' }]); });
149
-
150
- // Only second results should be stored (as strings)
151
- expect(Array.isArray(expose.current.hubResults)).toBe(true);
152
- expect(expose.current.hubResults).toHaveLength(1);
153
- expect(expose.current.hubResults[0]).toBe('ngi/x');
154
- });
155
-
156
- test('updateImageInput() clears hubResults and sets isSearchingHub=false', async () => {
157
- const expose = makeExpose();
158
- mockSearchDockerHub.mockResolvedValue([
159
- { name: 'library/nginx', isOfficial: true, pullCount: 1e9, description: '' },
160
- ]);
161
-
162
- act(() => { expose.current.updateImageInput('nginx'); });
163
- await act(async () => { await expose.current.triggerHubSearch(); });
164
- expect(expose.current.hubResults).not.toBeNull();
165
-
166
- // Typing clears Hub results
167
- act(() => { expose.current.updateImageInput('nginy'); });
168
- expect(expose.current.hubResults).toBeNull();
169
- expect(expose.current.isSearchingHub).toBe(false);
170
- });
171
-
172
- test('failed Hub search (non-abort) sets hubResults=null silently', async () => {
173
- const expose = makeExpose();
174
- mockSearchDockerHub.mockRejectedValue(new Error('Network Error'));
175
-
176
- act(() => { expose.current.updateImageInput('nginx'); });
177
- await act(async () => {
178
- try { await expose.current.triggerHubSearch(); } catch (_) { /* silenced */ }
179
- });
180
-
181
- expect(expose.current.hubResults).toBeNull();
182
- expect(expose.current.isSearchingHub).toBe(false);
183
- });
184
- });