cdd-cli 3.2.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.atl/skill-registry.md +30 -0
- package/.editorconfig +12 -0
- package/.eslintrc.json +1 -1
- package/.prettierignore +4 -0
- package/.prettierrc +8 -0
- package/.~lock.ROADMAP.md# +1 -0
- package/CHANGELOG.md +80 -0
- package/README.es.md +198 -0
- package/README.md +81 -23
- package/ROADMAP.md +647 -0
- package/SECURITY.md +5 -0
- package/__mocks__/ink.cjs +17 -0
- package/coverage/clover.xml +471 -500
- package/coverage/coverage-final.json +16 -16
- package/coverage/lcov-report/ContainerCreationPrompt.jsx.html +400 -0
- package/coverage/lcov-report/ControlsHUD.jsx.html +256 -0
- package/coverage/lcov-report/components/ContainerCreationPrompt.jsx.html +394 -0
- package/coverage/lcov-report/components/PromptField.jsx.html +229 -0
- package/coverage/lcov-report/components/SuggestionPanel.jsx.html +268 -0
- package/coverage/lcov-report/components/index.html +146 -0
- package/coverage/lcov-report/helpers/constants.js.html +139 -22
- package/coverage/lcov-report/helpers/containerOptionsBuilder.js.html +75 -42
- package/coverage/lcov-report/helpers/dockerHubService.js.html +310 -0
- package/coverage/lcov-report/helpers/dockerService/serviceComponents/containerActions.js.html +162 -84
- package/coverage/lcov-report/helpers/dockerService/serviceComponents/containerList.js.html +50 -32
- package/coverage/lcov-report/helpers/dockerService/serviceComponents/index.html +21 -21
- package/coverage/lcov-report/helpers/imageNameUtils.js.html +181 -0
- package/coverage/lcov-report/helpers/index.html +84 -54
- package/coverage/lcov-report/helpers/logger.js.html +68 -68
- package/coverage/lcov-report/helpers/safeCall.js.html +15 -15
- package/coverage/lcov-report/helpers/validationHelpers.js.html +66 -114
- package/coverage/lcov-report/hooks/creation/index.html +20 -20
- package/coverage/lcov-report/hooks/creation/useContainerActions.js.html +38 -17
- package/coverage/lcov-report/hooks/creation/useContainerCreation.js.html +593 -89
- package/coverage/lcov-report/hooks/creation/useLogsViewer.js.html +7 -7
- package/coverage/lcov-report/hooks/debug/index.html +5 -5
- package/coverage/lcov-report/hooks/debug/useDebugLogs.js.html +35 -20
- package/coverage/lcov-report/hooks/index.html +40 -40
- package/coverage/lcov-report/hooks/navigation/index.html +19 -19
- package/coverage/lcov-report/hooks/navigation/useContainerSelection.js.html +38 -29
- package/coverage/lcov-report/hooks/useContainerCommandRouter.js.html +119 -80
- package/coverage/lcov-report/hooks/useControls.js.html +306 -123
- package/coverage/lcov-report/hooks/useEraseConfirmation.js.html +8 -8
- package/coverage/lcov-report/hooks/useExitHandler.js.html +50 -41
- package/coverage/lcov-report/index.html +52 -67
- package/coverage/lcov.info +899 -952
- package/dist/App.js +18 -12
- package/dist/components/ContainerCreationPrompt.js +50 -13
- package/dist/components/ContainerList.js +3 -3
- package/dist/components/ContainerRow.js +20 -20
- package/dist/components/ContainerSection.js +3 -3
- package/dist/components/ControlsHUD.js +106 -0
- package/dist/components/Footer.js +2 -2
- package/dist/components/Header.js +7 -7
- package/dist/components/LogViewer.js +3 -3
- package/dist/components/MessageFeedback.js +2 -2
- package/dist/components/PromptField.js +4 -4
- package/dist/components/StatsBar.js +5 -5
- package/dist/components/SuggestionPanel.js +53 -0
- package/dist/components/UsageMenu.js +3 -3
- package/dist/helpers/appInfo.js +7 -7
- package/dist/helpers/constants.js +154 -1
- package/dist/helpers/containerOptionsBuilder.js +3 -3
- package/dist/helpers/dockerHubService.js +111 -0
- package/dist/helpers/dockerService/dockerService.js +1 -1
- package/dist/helpers/dockerService/serviceComponents/containerActions.js +99 -40
- package/dist/helpers/dockerService/serviceComponents/containerList.js +11 -11
- package/dist/helpers/dockerService/serviceComponents/containerLogs.js +9 -9
- package/dist/helpers/dockerService/serviceComponents/containerStats.js +5 -5
- package/dist/helpers/dockerService/serviceComponents/imageUtils.js +1 -1
- package/dist/helpers/exitWithMessage.js +10 -10
- package/dist/helpers/imageNameUtils.js +32 -0
- package/dist/helpers/logger.js +13 -13
- package/dist/helpers/safeCall.js +2 -2
- package/dist/helpers/validationHelpers.js +76 -21
- package/dist/hooks/creation/useContainerActions.js +28 -11
- package/dist/hooks/creation/useContainerCreation.js +452 -62
- package/dist/hooks/creation/useLogsViewer.js +2 -2
- package/dist/hooks/debug/useDebugLogs.js +4 -4
- package/dist/hooks/useContainerCommandRouter.js +14 -14
- package/dist/hooks/useContainers.js +3 -3
- package/dist/hooks/useControls.js +85 -38
- package/dist/hooks/useEraseConfirmation.js +3 -3
- package/dist/index.js +9 -2
- package/jest.config.cjs +7 -0
- package/package.json +7 -3
- package/src/App.jsx +39 -16
- package/src/components/ContainerCreationPrompt.jsx +54 -10
- package/src/components/ContainerList.jsx +3 -3
- package/src/components/ContainerRow.jsx +19 -16
- package/src/components/ContainerSection.jsx +3 -3
- package/src/components/ControlsHUD.jsx +66 -0
- package/src/components/Footer.jsx +2 -2
- package/src/components/Header.jsx +7 -7
- package/src/components/LogViewer.jsx +5 -3
- package/src/components/MessageFeedback.jsx +2 -2
- package/src/components/PromptField.jsx +4 -4
- package/src/components/StatsBar.jsx +11 -7
- package/src/components/SuggestionPanel.jsx +61 -0
- package/src/components/UsageMenu.jsx +18 -13
- package/src/helpers/appInfo.js +7 -7
- package/src/helpers/constants.js +48 -9
- package/src/helpers/containerOptionsBuilder.js +16 -5
- package/src/helpers/dockerHubService.js +75 -0
- package/src/helpers/dockerService/dockerService.js +1 -1
- package/src/helpers/dockerService/serviceComponents/containerActions.js +87 -61
- package/src/helpers/dockerService/serviceComponents/containerList.js +31 -25
- package/src/helpers/dockerService/serviceComponents/containerLogs.js +41 -26
- package/src/helpers/dockerService/serviceComponents/containerStats.js +13 -11
- package/src/helpers/dockerService/serviceComponents/imageUtils.js +5 -4
- package/src/helpers/exitWithMessage.js +13 -7
- package/src/helpers/imageNameUtils.js +32 -0
- package/src/helpers/logger.js +15 -16
- package/src/helpers/safeCall.js +2 -2
- package/src/helpers/validationHelpers.js +13 -29
- package/src/hooks/creation/useContainerActions.js +32 -12
- package/src/hooks/creation/useContainerCreation.js +293 -47
- package/src/hooks/creation/useLogsViewer.js +2 -2
- package/src/hooks/debug/useDebugLogs.js +15 -10
- package/src/hooks/navigation/useContainerSelection.js +17 -14
- package/src/hooks/useContainerCommandRouter.js +71 -58
- package/src/hooks/useContainers.js +4 -4
- package/src/hooks/useControls.js +135 -72
- package/src/hooks/useEraseConfirmation.js +3 -3
- package/src/hooks/useExitHandler.js +29 -26
- package/src/index.js +8 -4
- package/test/ContainerCreationPrompt.dom.test.js +313 -0
- package/test/ControlsHUD.dom.test.js +125 -0
- package/test/SuggestionPanel.dom.test.js +83 -0
- package/test/constants.test.js +41 -0
- package/test/dockerHubService.test.js +213 -0
- package/test/logger.test.js +58 -0
- package/test/resolveImageTag.test.js +26 -0
- package/test/useContainerCreation.dom.test.js +428 -2
- package/test/useContainerCreationHub.dom.test.js +184 -0
- package/test/useControls.dom.test.js +406 -4
|
@@ -23,30 +23,30 @@
|
|
|
23
23
|
<div class='clearfix'>
|
|
24
24
|
|
|
25
25
|
<div class='fl pad1y space-right2'>
|
|
26
|
-
<span class="strong">
|
|
26
|
+
<span class="strong">87.4% </span>
|
|
27
27
|
<span class="quiet">Statements</span>
|
|
28
|
-
<span class='fraction'>
|
|
28
|
+
<span class='fraction'>118/135</span>
|
|
29
29
|
</div>
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
<div class='fl pad1y space-right2'>
|
|
33
|
-
<span class="strong">
|
|
33
|
+
<span class="strong">87.03% </span>
|
|
34
34
|
<span class="quiet">Branches</span>
|
|
35
|
-
<span class='fraction'>
|
|
35
|
+
<span class='fraction'>47/54</span>
|
|
36
36
|
</div>
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
<div class='fl pad1y space-right2'>
|
|
40
|
-
<span class="strong">
|
|
40
|
+
<span class="strong">91.66% </span>
|
|
41
41
|
<span class="quiet">Functions</span>
|
|
42
|
-
<span class='fraction'>
|
|
42
|
+
<span class='fraction'>11/12</span>
|
|
43
43
|
</div>
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
<div class='fl pad1y space-right2'>
|
|
47
|
-
<span class="strong">
|
|
47
|
+
<span class="strong">88.28% </span>
|
|
48
48
|
<span class="quiet">Lines</span>
|
|
49
|
-
<span class='fraction'>
|
|
49
|
+
<span class='fraction'>113/128</span>
|
|
50
50
|
</div>
|
|
51
51
|
|
|
52
52
|
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
</div>
|
|
62
62
|
</template>
|
|
63
63
|
</div>
|
|
64
|
-
<div class='status-line
|
|
64
|
+
<div class='status-line high'></div>
|
|
65
65
|
<pre><table class="coverage">
|
|
66
66
|
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
|
|
67
67
|
<a name='L2'></a><a href='#L2'>2</a>
|
|
@@ -194,7 +194,175 @@
|
|
|
194
194
|
<a name='L129'></a><a href='#L129'>129</a>
|
|
195
195
|
<a name='L130'></a><a href='#L130'>130</a>
|
|
196
196
|
<a name='L131'></a><a href='#L131'>131</a>
|
|
197
|
-
<a name='L132'></a><a href='#L132'>132</a
|
|
197
|
+
<a name='L132'></a><a href='#L132'>132</a>
|
|
198
|
+
<a name='L133'></a><a href='#L133'>133</a>
|
|
199
|
+
<a name='L134'></a><a href='#L134'>134</a>
|
|
200
|
+
<a name='L135'></a><a href='#L135'>135</a>
|
|
201
|
+
<a name='L136'></a><a href='#L136'>136</a>
|
|
202
|
+
<a name='L137'></a><a href='#L137'>137</a>
|
|
203
|
+
<a name='L138'></a><a href='#L138'>138</a>
|
|
204
|
+
<a name='L139'></a><a href='#L139'>139</a>
|
|
205
|
+
<a name='L140'></a><a href='#L140'>140</a>
|
|
206
|
+
<a name='L141'></a><a href='#L141'>141</a>
|
|
207
|
+
<a name='L142'></a><a href='#L142'>142</a>
|
|
208
|
+
<a name='L143'></a><a href='#L143'>143</a>
|
|
209
|
+
<a name='L144'></a><a href='#L144'>144</a>
|
|
210
|
+
<a name='L145'></a><a href='#L145'>145</a>
|
|
211
|
+
<a name='L146'></a><a href='#L146'>146</a>
|
|
212
|
+
<a name='L147'></a><a href='#L147'>147</a>
|
|
213
|
+
<a name='L148'></a><a href='#L148'>148</a>
|
|
214
|
+
<a name='L149'></a><a href='#L149'>149</a>
|
|
215
|
+
<a name='L150'></a><a href='#L150'>150</a>
|
|
216
|
+
<a name='L151'></a><a href='#L151'>151</a>
|
|
217
|
+
<a name='L152'></a><a href='#L152'>152</a>
|
|
218
|
+
<a name='L153'></a><a href='#L153'>153</a>
|
|
219
|
+
<a name='L154'></a><a href='#L154'>154</a>
|
|
220
|
+
<a name='L155'></a><a href='#L155'>155</a>
|
|
221
|
+
<a name='L156'></a><a href='#L156'>156</a>
|
|
222
|
+
<a name='L157'></a><a href='#L157'>157</a>
|
|
223
|
+
<a name='L158'></a><a href='#L158'>158</a>
|
|
224
|
+
<a name='L159'></a><a href='#L159'>159</a>
|
|
225
|
+
<a name='L160'></a><a href='#L160'>160</a>
|
|
226
|
+
<a name='L161'></a><a href='#L161'>161</a>
|
|
227
|
+
<a name='L162'></a><a href='#L162'>162</a>
|
|
228
|
+
<a name='L163'></a><a href='#L163'>163</a>
|
|
229
|
+
<a name='L164'></a><a href='#L164'>164</a>
|
|
230
|
+
<a name='L165'></a><a href='#L165'>165</a>
|
|
231
|
+
<a name='L166'></a><a href='#L166'>166</a>
|
|
232
|
+
<a name='L167'></a><a href='#L167'>167</a>
|
|
233
|
+
<a name='L168'></a><a href='#L168'>168</a>
|
|
234
|
+
<a name='L169'></a><a href='#L169'>169</a>
|
|
235
|
+
<a name='L170'></a><a href='#L170'>170</a>
|
|
236
|
+
<a name='L171'></a><a href='#L171'>171</a>
|
|
237
|
+
<a name='L172'></a><a href='#L172'>172</a>
|
|
238
|
+
<a name='L173'></a><a href='#L173'>173</a>
|
|
239
|
+
<a name='L174'></a><a href='#L174'>174</a>
|
|
240
|
+
<a name='L175'></a><a href='#L175'>175</a>
|
|
241
|
+
<a name='L176'></a><a href='#L176'>176</a>
|
|
242
|
+
<a name='L177'></a><a href='#L177'>177</a>
|
|
243
|
+
<a name='L178'></a><a href='#L178'>178</a>
|
|
244
|
+
<a name='L179'></a><a href='#L179'>179</a>
|
|
245
|
+
<a name='L180'></a><a href='#L180'>180</a>
|
|
246
|
+
<a name='L181'></a><a href='#L181'>181</a>
|
|
247
|
+
<a name='L182'></a><a href='#L182'>182</a>
|
|
248
|
+
<a name='L183'></a><a href='#L183'>183</a>
|
|
249
|
+
<a name='L184'></a><a href='#L184'>184</a>
|
|
250
|
+
<a name='L185'></a><a href='#L185'>185</a>
|
|
251
|
+
<a name='L186'></a><a href='#L186'>186</a>
|
|
252
|
+
<a name='L187'></a><a href='#L187'>187</a>
|
|
253
|
+
<a name='L188'></a><a href='#L188'>188</a>
|
|
254
|
+
<a name='L189'></a><a href='#L189'>189</a>
|
|
255
|
+
<a name='L190'></a><a href='#L190'>190</a>
|
|
256
|
+
<a name='L191'></a><a href='#L191'>191</a>
|
|
257
|
+
<a name='L192'></a><a href='#L192'>192</a>
|
|
258
|
+
<a name='L193'></a><a href='#L193'>193</a>
|
|
259
|
+
<a name='L194'></a><a href='#L194'>194</a>
|
|
260
|
+
<a name='L195'></a><a href='#L195'>195</a>
|
|
261
|
+
<a name='L196'></a><a href='#L196'>196</a>
|
|
262
|
+
<a name='L197'></a><a href='#L197'>197</a>
|
|
263
|
+
<a name='L198'></a><a href='#L198'>198</a>
|
|
264
|
+
<a name='L199'></a><a href='#L199'>199</a>
|
|
265
|
+
<a name='L200'></a><a href='#L200'>200</a>
|
|
266
|
+
<a name='L201'></a><a href='#L201'>201</a>
|
|
267
|
+
<a name='L202'></a><a href='#L202'>202</a>
|
|
268
|
+
<a name='L203'></a><a href='#L203'>203</a>
|
|
269
|
+
<a name='L204'></a><a href='#L204'>204</a>
|
|
270
|
+
<a name='L205'></a><a href='#L205'>205</a>
|
|
271
|
+
<a name='L206'></a><a href='#L206'>206</a>
|
|
272
|
+
<a name='L207'></a><a href='#L207'>207</a>
|
|
273
|
+
<a name='L208'></a><a href='#L208'>208</a>
|
|
274
|
+
<a name='L209'></a><a href='#L209'>209</a>
|
|
275
|
+
<a name='L210'></a><a href='#L210'>210</a>
|
|
276
|
+
<a name='L211'></a><a href='#L211'>211</a>
|
|
277
|
+
<a name='L212'></a><a href='#L212'>212</a>
|
|
278
|
+
<a name='L213'></a><a href='#L213'>213</a>
|
|
279
|
+
<a name='L214'></a><a href='#L214'>214</a>
|
|
280
|
+
<a name='L215'></a><a href='#L215'>215</a>
|
|
281
|
+
<a name='L216'></a><a href='#L216'>216</a>
|
|
282
|
+
<a name='L217'></a><a href='#L217'>217</a>
|
|
283
|
+
<a name='L218'></a><a href='#L218'>218</a>
|
|
284
|
+
<a name='L219'></a><a href='#L219'>219</a>
|
|
285
|
+
<a name='L220'></a><a href='#L220'>220</a>
|
|
286
|
+
<a name='L221'></a><a href='#L221'>221</a>
|
|
287
|
+
<a name='L222'></a><a href='#L222'>222</a>
|
|
288
|
+
<a name='L223'></a><a href='#L223'>223</a>
|
|
289
|
+
<a name='L224'></a><a href='#L224'>224</a>
|
|
290
|
+
<a name='L225'></a><a href='#L225'>225</a>
|
|
291
|
+
<a name='L226'></a><a href='#L226'>226</a>
|
|
292
|
+
<a name='L227'></a><a href='#L227'>227</a>
|
|
293
|
+
<a name='L228'></a><a href='#L228'>228</a>
|
|
294
|
+
<a name='L229'></a><a href='#L229'>229</a>
|
|
295
|
+
<a name='L230'></a><a href='#L230'>230</a>
|
|
296
|
+
<a name='L231'></a><a href='#L231'>231</a>
|
|
297
|
+
<a name='L232'></a><a href='#L232'>232</a>
|
|
298
|
+
<a name='L233'></a><a href='#L233'>233</a>
|
|
299
|
+
<a name='L234'></a><a href='#L234'>234</a>
|
|
300
|
+
<a name='L235'></a><a href='#L235'>235</a>
|
|
301
|
+
<a name='L236'></a><a href='#L236'>236</a>
|
|
302
|
+
<a name='L237'></a><a href='#L237'>237</a>
|
|
303
|
+
<a name='L238'></a><a href='#L238'>238</a>
|
|
304
|
+
<a name='L239'></a><a href='#L239'>239</a>
|
|
305
|
+
<a name='L240'></a><a href='#L240'>240</a>
|
|
306
|
+
<a name='L241'></a><a href='#L241'>241</a>
|
|
307
|
+
<a name='L242'></a><a href='#L242'>242</a>
|
|
308
|
+
<a name='L243'></a><a href='#L243'>243</a>
|
|
309
|
+
<a name='L244'></a><a href='#L244'>244</a>
|
|
310
|
+
<a name='L245'></a><a href='#L245'>245</a>
|
|
311
|
+
<a name='L246'></a><a href='#L246'>246</a>
|
|
312
|
+
<a name='L247'></a><a href='#L247'>247</a>
|
|
313
|
+
<a name='L248'></a><a href='#L248'>248</a>
|
|
314
|
+
<a name='L249'></a><a href='#L249'>249</a>
|
|
315
|
+
<a name='L250'></a><a href='#L250'>250</a>
|
|
316
|
+
<a name='L251'></a><a href='#L251'>251</a>
|
|
317
|
+
<a name='L252'></a><a href='#L252'>252</a>
|
|
318
|
+
<a name='L253'></a><a href='#L253'>253</a>
|
|
319
|
+
<a name='L254'></a><a href='#L254'>254</a>
|
|
320
|
+
<a name='L255'></a><a href='#L255'>255</a>
|
|
321
|
+
<a name='L256'></a><a href='#L256'>256</a>
|
|
322
|
+
<a name='L257'></a><a href='#L257'>257</a>
|
|
323
|
+
<a name='L258'></a><a href='#L258'>258</a>
|
|
324
|
+
<a name='L259'></a><a href='#L259'>259</a>
|
|
325
|
+
<a name='L260'></a><a href='#L260'>260</a>
|
|
326
|
+
<a name='L261'></a><a href='#L261'>261</a>
|
|
327
|
+
<a name='L262'></a><a href='#L262'>262</a>
|
|
328
|
+
<a name='L263'></a><a href='#L263'>263</a>
|
|
329
|
+
<a name='L264'></a><a href='#L264'>264</a>
|
|
330
|
+
<a name='L265'></a><a href='#L265'>265</a>
|
|
331
|
+
<a name='L266'></a><a href='#L266'>266</a>
|
|
332
|
+
<a name='L267'></a><a href='#L267'>267</a>
|
|
333
|
+
<a name='L268'></a><a href='#L268'>268</a>
|
|
334
|
+
<a name='L269'></a><a href='#L269'>269</a>
|
|
335
|
+
<a name='L270'></a><a href='#L270'>270</a>
|
|
336
|
+
<a name='L271'></a><a href='#L271'>271</a>
|
|
337
|
+
<a name='L272'></a><a href='#L272'>272</a>
|
|
338
|
+
<a name='L273'></a><a href='#L273'>273</a>
|
|
339
|
+
<a name='L274'></a><a href='#L274'>274</a>
|
|
340
|
+
<a name='L275'></a><a href='#L275'>275</a>
|
|
341
|
+
<a name='L276'></a><a href='#L276'>276</a>
|
|
342
|
+
<a name='L277'></a><a href='#L277'>277</a>
|
|
343
|
+
<a name='L278'></a><a href='#L278'>278</a>
|
|
344
|
+
<a name='L279'></a><a href='#L279'>279</a>
|
|
345
|
+
<a name='L280'></a><a href='#L280'>280</a>
|
|
346
|
+
<a name='L281'></a><a href='#L281'>281</a>
|
|
347
|
+
<a name='L282'></a><a href='#L282'>282</a>
|
|
348
|
+
<a name='L283'></a><a href='#L283'>283</a>
|
|
349
|
+
<a name='L284'></a><a href='#L284'>284</a>
|
|
350
|
+
<a name='L285'></a><a href='#L285'>285</a>
|
|
351
|
+
<a name='L286'></a><a href='#L286'>286</a>
|
|
352
|
+
<a name='L287'></a><a href='#L287'>287</a>
|
|
353
|
+
<a name='L288'></a><a href='#L288'>288</a>
|
|
354
|
+
<a name='L289'></a><a href='#L289'>289</a>
|
|
355
|
+
<a name='L290'></a><a href='#L290'>290</a>
|
|
356
|
+
<a name='L291'></a><a href='#L291'>291</a>
|
|
357
|
+
<a name='L292'></a><a href='#L292'>292</a>
|
|
358
|
+
<a name='L293'></a><a href='#L293'>293</a>
|
|
359
|
+
<a name='L294'></a><a href='#L294'>294</a>
|
|
360
|
+
<a name='L295'></a><a href='#L295'>295</a>
|
|
361
|
+
<a name='L296'></a><a href='#L296'>296</a>
|
|
362
|
+
<a name='L297'></a><a href='#L297'>297</a>
|
|
363
|
+
<a name='L298'></a><a href='#L298'>298</a>
|
|
364
|
+
<a name='L299'></a><a href='#L299'>299</a>
|
|
365
|
+
<a name='L300'></a><a href='#L300'>300</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
|
198
366
|
<span class="cline-any cline-neutral"> </span>
|
|
199
367
|
<span class="cline-any cline-neutral"> </span>
|
|
200
368
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -203,66 +371,219 @@
|
|
|
203
371
|
<span class="cline-any cline-neutral"> </span>
|
|
204
372
|
<span class="cline-any cline-neutral"> </span>
|
|
205
373
|
<span class="cline-any cline-neutral"> </span>
|
|
374
|
+
<span class="cline-any cline-yes">2x</span>
|
|
375
|
+
<span class="cline-any cline-neutral"> </span>
|
|
376
|
+
<span class="cline-any cline-neutral"> </span>
|
|
377
|
+
<span class="cline-any cline-neutral"> </span>
|
|
378
|
+
<span class="cline-any cline-neutral"> </span>
|
|
379
|
+
<span class="cline-any cline-neutral"> </span>
|
|
380
|
+
<span class="cline-any cline-neutral"> </span>
|
|
381
|
+
<span class="cline-any cline-neutral"> </span>
|
|
382
|
+
<span class="cline-any cline-neutral"> </span>
|
|
383
|
+
<span class="cline-any cline-neutral"> </span>
|
|
384
|
+
<span class="cline-any cline-neutral"> </span>
|
|
385
|
+
<span class="cline-any cline-neutral"> </span>
|
|
386
|
+
<span class="cline-any cline-neutral"> </span>
|
|
387
|
+
<span class="cline-any cline-neutral"> </span>
|
|
388
|
+
<span class="cline-any cline-neutral"> </span>
|
|
389
|
+
<span class="cline-any cline-neutral"> </span>
|
|
390
|
+
<span class="cline-any cline-neutral"> </span>
|
|
391
|
+
<span class="cline-any cline-neutral"> </span>
|
|
392
|
+
<span class="cline-any cline-neutral"> </span>
|
|
393
|
+
<span class="cline-any cline-yes">204x</span>
|
|
394
|
+
<span class="cline-any cline-yes">204x</span>
|
|
395
|
+
<span class="cline-any cline-yes">204x</span>
|
|
396
|
+
<span class="cline-any cline-yes">204x</span>
|
|
397
|
+
<span class="cline-any cline-yes">204x</span>
|
|
398
|
+
<span class="cline-any cline-yes">204x</span>
|
|
399
|
+
<span class="cline-any cline-yes">204x</span>
|
|
400
|
+
<span class="cline-any cline-neutral"> </span>
|
|
401
|
+
<span class="cline-any cline-neutral"> </span>
|
|
402
|
+
<span class="cline-any cline-yes">204x</span>
|
|
403
|
+
<span class="cline-any cline-yes">204x</span>
|
|
404
|
+
<span class="cline-any cline-yes">204x</span>
|
|
405
|
+
<span class="cline-any cline-neutral"> </span>
|
|
406
|
+
<span class="cline-any cline-neutral"> </span>
|
|
407
|
+
<span class="cline-any cline-yes">204x</span>
|
|
408
|
+
<span class="cline-any cline-yes">204x</span>
|
|
409
|
+
<span class="cline-any cline-neutral"> </span>
|
|
410
|
+
<span class="cline-any cline-yes">204x</span>
|
|
411
|
+
<span class="cline-any cline-neutral"> </span>
|
|
412
|
+
<span class="cline-any cline-neutral"> </span>
|
|
413
|
+
<span class="cline-any cline-neutral"> </span>
|
|
414
|
+
<span class="cline-any cline-neutral"> </span>
|
|
415
|
+
<span class="cline-any cline-neutral"> </span>
|
|
416
|
+
<span class="cline-any cline-neutral"> </span>
|
|
417
|
+
<span class="cline-any cline-neutral"> </span>
|
|
418
|
+
<span class="cline-any cline-neutral"> </span>
|
|
419
|
+
<span class="cline-any cline-neutral"> </span>
|
|
420
|
+
<span class="cline-any cline-neutral"> </span>
|
|
421
|
+
<span class="cline-any cline-yes">28x</span>
|
|
422
|
+
<span class="cline-any cline-yes">28x</span>
|
|
423
|
+
<span class="cline-any cline-yes">28x</span>
|
|
424
|
+
<span class="cline-any cline-yes">28x</span>
|
|
425
|
+
<span class="cline-any cline-neutral"> </span>
|
|
426
|
+
<span class="cline-any cline-yes">28x</span>
|
|
427
|
+
<span class="cline-any cline-yes">28x</span>
|
|
428
|
+
<span class="cline-any cline-yes">28x</span>
|
|
429
|
+
<span class="cline-any cline-yes">28x</span>
|
|
430
|
+
<span class="cline-any cline-yes">1x</span>
|
|
431
|
+
<span class="cline-any cline-yes">1x</span>
|
|
432
|
+
<span class="cline-any cline-neutral"> </span>
|
|
433
|
+
<span class="cline-any cline-yes">27x</span>
|
|
434
|
+
<span class="cline-any cline-yes">27x</span>
|
|
435
|
+
<span class="cline-any cline-yes">540x</span>
|
|
436
|
+
<span class="cline-any cline-neutral"> </span>
|
|
437
|
+
<span class="cline-any cline-yes">27x</span>
|
|
438
|
+
<span class="cline-any cline-neutral"> </span>
|
|
439
|
+
<span class="cline-any cline-neutral"> </span>
|
|
440
|
+
<span class="cline-any cline-neutral"> </span>
|
|
441
|
+
<span class="cline-any cline-neutral"> </span>
|
|
442
|
+
<span class="cline-any cline-neutral"> </span>
|
|
443
|
+
<span class="cline-any cline-neutral"> </span>
|
|
444
|
+
<span class="cline-any cline-neutral"> </span>
|
|
445
|
+
<span class="cline-any cline-neutral"> </span>
|
|
446
|
+
<span class="cline-any cline-yes">6x</span>
|
|
447
|
+
<span class="cline-any cline-yes">6x</span>
|
|
448
|
+
<span class="cline-any cline-yes">5x</span>
|
|
449
|
+
<span class="cline-any cline-neutral"> </span>
|
|
450
|
+
<span class="cline-any cline-neutral"> </span>
|
|
451
|
+
<span class="cline-any cline-neutral"> </span>
|
|
452
|
+
<span class="cline-any cline-yes">4x</span>
|
|
453
|
+
<span class="cline-any cline-neutral"> </span>
|
|
454
|
+
<span class="cline-any cline-yes">4x</span>
|
|
455
|
+
<span class="cline-any cline-yes">4x</span>
|
|
456
|
+
<span class="cline-any cline-neutral"> </span>
|
|
457
|
+
<span class="cline-any cline-yes">4x</span>
|
|
458
|
+
<span class="cline-any cline-yes">4x</span>
|
|
459
|
+
<span class="cline-any cline-neutral"> </span>
|
|
460
|
+
<span class="cline-any cline-yes">4x</span>
|
|
461
|
+
<span class="cline-any cline-yes">4x</span>
|
|
462
|
+
<span class="cline-any cline-yes">4x</span>
|
|
463
|
+
<span class="cline-any cline-neutral"> </span>
|
|
464
|
+
<span class="cline-any cline-yes">4x</span>
|
|
465
|
+
<span class="cline-any cline-yes">4x</span>
|
|
466
|
+
<span class="cline-any cline-neutral"> </span>
|
|
467
|
+
<span class="cline-any cline-yes">4x</span>
|
|
468
|
+
<span class="cline-any cline-yes">3x</span>
|
|
469
|
+
<span class="cline-any cline-neutral"> </span>
|
|
470
|
+
<span class="cline-any cline-no"> </span>
|
|
471
|
+
<span class="cline-any cline-neutral"> </span>
|
|
472
|
+
<span class="cline-any cline-no"> </span>
|
|
473
|
+
<span class="cline-any cline-neutral"> </span>
|
|
474
|
+
<span class="cline-any cline-yes">4x</span>
|
|
475
|
+
<span class="cline-any cline-yes">3x</span>
|
|
476
|
+
<span class="cline-any cline-neutral"> </span>
|
|
477
|
+
<span class="cline-any cline-neutral"> </span>
|
|
478
|
+
<span class="cline-any cline-neutral"> </span>
|
|
479
|
+
<span class="cline-any cline-neutral"> </span>
|
|
480
|
+
<span class="cline-any cline-neutral"> </span>
|
|
481
|
+
<span class="cline-any cline-neutral"> </span>
|
|
482
|
+
<span class="cline-any cline-neutral"> </span>
|
|
483
|
+
<span class="cline-any cline-neutral"> </span>
|
|
484
|
+
<span class="cline-any cline-neutral"> </span>
|
|
485
|
+
<span class="cline-any cline-neutral"> </span>
|
|
486
|
+
<span class="cline-any cline-neutral"> </span>
|
|
487
|
+
<span class="cline-any cline-neutral"> </span>
|
|
488
|
+
<span class="cline-any cline-yes">23x</span>
|
|
489
|
+
<span class="cline-any cline-yes">23x</span>
|
|
490
|
+
<span class="cline-any cline-neutral"> </span>
|
|
491
|
+
<span class="cline-any cline-yes">23x</span>
|
|
492
|
+
<span class="cline-any cline-yes">23x</span>
|
|
493
|
+
<span class="cline-any cline-yes">22x</span>
|
|
494
|
+
<span class="cline-any cline-yes">21x</span>
|
|
495
|
+
<span class="cline-any cline-neutral"> </span>
|
|
496
|
+
<span class="cline-any cline-yes">23x</span>
|
|
497
|
+
<span class="cline-any cline-neutral"> </span>
|
|
498
|
+
<span class="cline-any cline-neutral"> </span>
|
|
499
|
+
<span class="cline-any cline-neutral"> </span>
|
|
500
|
+
<span class="cline-any cline-neutral"> </span>
|
|
501
|
+
<span class="cline-any cline-neutral"> </span>
|
|
502
|
+
<span class="cline-any cline-neutral"> </span>
|
|
503
|
+
<span class="cline-any cline-neutral"> </span>
|
|
504
|
+
<span class="cline-any cline-neutral"> </span>
|
|
505
|
+
<span class="cline-any cline-yes">7x</span>
|
|
506
|
+
<span class="cline-any cline-yes">7x</span>
|
|
507
|
+
<span class="cline-any cline-yes">7x</span>
|
|
508
|
+
<span class="cline-any cline-yes">7x</span>
|
|
509
|
+
<span class="cline-any cline-yes">7x</span>
|
|
510
|
+
<span class="cline-any cline-yes">7x</span>
|
|
511
|
+
<span class="cline-any cline-neutral"> </span>
|
|
206
512
|
<span class="cline-any cline-neutral"> </span>
|
|
207
513
|
<span class="cline-any cline-neutral"> </span>
|
|
208
514
|
<span class="cline-any cline-neutral"> </span>
|
|
209
515
|
<span class="cline-any cline-neutral"> </span>
|
|
210
516
|
<span class="cline-any cline-neutral"> </span>
|
|
517
|
+
<span class="cline-any cline-yes">43x</span>
|
|
518
|
+
<span class="cline-any cline-yes">18x</span>
|
|
519
|
+
<span class="cline-any cline-yes">1x</span>
|
|
520
|
+
<span class="cline-any cline-yes">1x</span>
|
|
521
|
+
<span class="cline-any cline-yes">1x</span>
|
|
211
522
|
<span class="cline-any cline-neutral"> </span>
|
|
523
|
+
<span class="cline-any cline-yes">17x</span>
|
|
524
|
+
<span class="cline-any cline-yes">17x</span>
|
|
525
|
+
<span class="cline-any cline-yes">17x</span>
|
|
526
|
+
<span class="cline-any cline-yes">17x</span>
|
|
212
527
|
<span class="cline-any cline-neutral"> </span>
|
|
213
528
|
<span class="cline-any cline-neutral"> </span>
|
|
214
|
-
<span class="cline-any cline-yes">
|
|
215
|
-
<span class="cline-any cline-yes">
|
|
216
|
-
<span class="cline-any cline-yes">51x</span>
|
|
217
|
-
<span class="cline-any cline-yes">51x</span>
|
|
218
|
-
<span class="cline-any cline-yes">51x</span>
|
|
219
|
-
<span class="cline-any cline-yes">51x</span>
|
|
220
|
-
<span class="cline-any cline-yes">51x</span>
|
|
529
|
+
<span class="cline-any cline-yes">17x</span>
|
|
530
|
+
<span class="cline-any cline-yes">17x</span>
|
|
221
531
|
<span class="cline-any cline-neutral"> </span>
|
|
532
|
+
<span class="cline-any cline-yes">25x</span>
|
|
533
|
+
<span class="cline-any cline-yes">9x</span>
|
|
534
|
+
<span class="cline-any cline-yes">9x</span>
|
|
222
535
|
<span class="cline-any cline-neutral"> </span>
|
|
223
536
|
<span class="cline-any cline-neutral"> </span>
|
|
537
|
+
<span class="cline-any cline-yes">9x</span>
|
|
538
|
+
<span class="cline-any cline-yes">9x</span>
|
|
224
539
|
<span class="cline-any cline-neutral"> </span>
|
|
540
|
+
<span class="cline-any cline-yes">16x</span>
|
|
225
541
|
<span class="cline-any cline-neutral"> </span>
|
|
226
|
-
<span class="cline-any cline-yes">32x</span>
|
|
227
542
|
<span class="cline-any cline-yes">9x</span>
|
|
228
543
|
<span class="cline-any cline-yes">1x</span>
|
|
544
|
+
<span class="cline-any cline-neutral"> </span>
|
|
545
|
+
<span class="cline-any cline-neutral"> </span>
|
|
229
546
|
<span class="cline-any cline-yes">1x</span>
|
|
230
547
|
<span class="cline-any cline-yes">1x</span>
|
|
231
548
|
<span class="cline-any cline-neutral"> </span>
|
|
232
549
|
<span class="cline-any cline-yes">8x</span>
|
|
233
550
|
<span class="cline-any cline-yes">8x</span>
|
|
234
|
-
<span class="cline-any cline-yes">
|
|
235
|
-
<span class="cline-any cline-
|
|
551
|
+
<span class="cline-any cline-yes">24x</span>
|
|
552
|
+
<span class="cline-any cline-neutral"> </span>
|
|
236
553
|
<span class="cline-any cline-neutral"> </span>
|
|
237
|
-
<span class="cline-any cline-yes">23x</span>
|
|
238
|
-
<span class="cline-any cline-yes">8x</span>
|
|
239
554
|
<span class="cline-any cline-yes">8x</span>
|
|
555
|
+
<span class="cline-any cline-neutral"> </span>
|
|
556
|
+
<span class="cline-any cline-neutral"> </span>
|
|
557
|
+
<span class="cline-any cline-neutral"> </span>
|
|
558
|
+
<span class="cline-any cline-neutral"> </span>
|
|
559
|
+
<span class="cline-any cline-neutral"> </span>
|
|
240
560
|
<span class="cline-any cline-yes">8x</span>
|
|
241
561
|
<span class="cline-any cline-yes">8x</span>
|
|
242
562
|
<span class="cline-any cline-neutral"> </span>
|
|
243
|
-
<span class="cline-any cline-yes">
|
|
563
|
+
<span class="cline-any cline-yes">3x</span>
|
|
244
564
|
<span class="cline-any cline-neutral"> </span>
|
|
245
|
-
<span class="cline-any cline-yes">8x</span>
|
|
246
|
-
<span class="cline-any cline-yes">1x</span>
|
|
247
|
-
<span class="cline-any cline-yes">1x</span>
|
|
248
|
-
<span class="cline-any cline-yes">1x</span>
|
|
249
565
|
<span class="cline-any cline-neutral"> </span>
|
|
250
|
-
<span class="cline-any cline-yes">
|
|
251
|
-
<span class="cline-any cline-yes">24x</span>
|
|
566
|
+
<span class="cline-any cline-yes">3x</span>
|
|
252
567
|
<span class="cline-any cline-neutral"> </span>
|
|
253
|
-
<span class="cline-any cline-
|
|
254
|
-
<span class="cline-any cline-yes">
|
|
255
|
-
<span class="cline-any cline-yes">7x</span>
|
|
256
|
-
<span class="cline-any cline-yes">2x</span>
|
|
257
|
-
<span class="cline-any cline-yes">2x</span>
|
|
568
|
+
<span class="cline-any cline-neutral"> </span>
|
|
569
|
+
<span class="cline-any cline-yes">3x</span>
|
|
258
570
|
<span class="cline-any cline-yes">5x</span>
|
|
571
|
+
<span class="cline-any cline-yes">1x</span>
|
|
572
|
+
<span class="cline-any cline-neutral"> </span>
|
|
573
|
+
<span class="cline-any cline-neutral"> </span>
|
|
574
|
+
<span class="cline-any cline-yes">1x</span>
|
|
575
|
+
<span class="cline-any cline-yes">4x</span>
|
|
259
576
|
<span class="cline-any cline-no"> </span>
|
|
577
|
+
<span class="cline-any cline-neutral"> </span>
|
|
578
|
+
<span class="cline-any cline-neutral"> </span>
|
|
260
579
|
<span class="cline-any cline-no"> </span>
|
|
261
580
|
<span class="cline-any cline-neutral"> </span>
|
|
262
|
-
<span class="cline-any cline-yes">
|
|
263
|
-
<span class="cline-any cline-yes">5x</span>
|
|
581
|
+
<span class="cline-any cline-yes">4x</span>
|
|
264
582
|
<span class="cline-any cline-neutral"> </span>
|
|
265
|
-
<span class="cline-any cline-
|
|
583
|
+
<span class="cline-any cline-neutral"> </span>
|
|
584
|
+
<span class="cline-any cline-yes">4x</span>
|
|
585
|
+
<span class="cline-any cline-neutral"> </span>
|
|
586
|
+
<span class="cline-any cline-yes">8x</span>
|
|
266
587
|
<span class="cline-any cline-neutral"> </span>
|
|
267
588
|
<span class="cline-any cline-yes">7x</span>
|
|
268
589
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -289,6 +610,9 @@
|
|
|
289
610
|
<span class="cline-any cline-no"> </span>
|
|
290
611
|
<span class="cline-any cline-no"> </span>
|
|
291
612
|
<span class="cline-any cline-no"> </span>
|
|
613
|
+
<span class="cline-any cline-no"> </span>
|
|
614
|
+
<span class="cline-any cline-no"> </span>
|
|
615
|
+
<span class="cline-any cline-no"> </span>
|
|
292
616
|
<span class="cline-any cline-neutral"> </span>
|
|
293
617
|
<span class="cline-any cline-neutral"> </span>
|
|
294
618
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -296,16 +620,23 @@
|
|
|
296
620
|
<span class="cline-any cline-neutral"> </span>
|
|
297
621
|
<span class="cline-any cline-neutral"> </span>
|
|
298
622
|
<span class="cline-any cline-neutral"> </span>
|
|
299
|
-
<span class="cline-any cline-
|
|
300
|
-
<span class="cline-any cline-
|
|
301
|
-
<span class="cline-any cline-
|
|
302
|
-
<span class="cline-any cline-
|
|
303
|
-
<span class="cline-any cline-
|
|
304
|
-
<span class="cline-any cline-
|
|
305
|
-
<span class="cline-any cline-
|
|
623
|
+
<span class="cline-any cline-yes">12x</span>
|
|
624
|
+
<span class="cline-any cline-yes">12x</span>
|
|
625
|
+
<span class="cline-any cline-yes">12x</span>
|
|
626
|
+
<span class="cline-any cline-yes">12x</span>
|
|
627
|
+
<span class="cline-any cline-yes">12x</span>
|
|
628
|
+
<span class="cline-any cline-yes">12x</span>
|
|
629
|
+
<span class="cline-any cline-yes">12x</span>
|
|
630
|
+
<span class="cline-any cline-yes">12x</span>
|
|
631
|
+
<span class="cline-any cline-yes">12x</span>
|
|
632
|
+
<span class="cline-any cline-yes">12x</span>
|
|
633
|
+
<span class="cline-any cline-neutral"> </span>
|
|
634
|
+
<span class="cline-any cline-neutral"> </span>
|
|
635
|
+
<span class="cline-any cline-yes">204x</span>
|
|
636
|
+
<span class="cline-any cline-neutral"> </span>
|
|
637
|
+
<span class="cline-any cline-neutral"> </span>
|
|
306
638
|
<span class="cline-any cline-neutral"> </span>
|
|
307
639
|
<span class="cline-any cline-neutral"> </span>
|
|
308
|
-
<span class="cline-any cline-yes">51x</span>
|
|
309
640
|
<span class="cline-any cline-neutral"> </span>
|
|
310
641
|
<span class="cline-any cline-neutral"> </span>
|
|
311
642
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -325,10 +656,21 @@
|
|
|
325
656
|
<span class="cline-any cline-neutral"> </span>
|
|
326
657
|
<span class="cline-any cline-neutral"> </span>
|
|
327
658
|
<span class="cline-any cline-neutral"> </span>
|
|
328
|
-
<span class="cline-any cline-neutral"> </span
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
659
|
+
<span class="cline-any cline-neutral"> </span>
|
|
660
|
+
<span class="cline-any cline-neutral"> </span>
|
|
661
|
+
<span class="cline-any cline-neutral"> </span>
|
|
662
|
+
<span class="cline-any cline-neutral"> </span>
|
|
663
|
+
<span class="cline-any cline-neutral"> </span>
|
|
664
|
+
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { useState, useRef } from 'react';
|
|
665
|
+
import {
|
|
666
|
+
validatePorts,
|
|
667
|
+
validateEnvVars,
|
|
668
|
+
} from '../../helpers/validationHelpers.js';
|
|
669
|
+
import { IMAGE_PROFILES, resolveImageTag } from '../../helpers/constants.js';
|
|
670
|
+
import { safeCall } from '../../helpers/safeCall.js';
|
|
671
|
+
import { searchDockerHub, formatHubResult } from '../../helpers/dockerHubService.js';
|
|
672
|
+
|
|
673
|
+
const MAX_VISIBLE = 6;
|
|
332
674
|
|
|
333
675
|
/**
|
|
334
676
|
* Custom hook to manage the container creation flow, step by step.
|
|
@@ -341,14 +683,131 @@ import { safeCall } from "../../helpers/safeCall.js";
|
|
|
341
683
|
* @param {Object} [params.imageProfiles] - Image profiles map for contextual validation
|
|
342
684
|
* @returns {Object} Creation state, setters, and helpers
|
|
343
685
|
*/
|
|
344
|
-
export function useContainerCreation({
|
|
686
|
+
export function useContainerCreation({
|
|
687
|
+
onCreate,
|
|
688
|
+
onCancel,
|
|
689
|
+
dbImages = <span class="branch-0 cbranch-no" title="branch not covered" >[],</span>
|
|
690
|
+
imageProfiles = IMAGE_PROFILES,
|
|
691
|
+
}) {
|
|
345
692
|
const [step, setStep] = useState(0); // 0: image, 1: name, 2: ports, 3: env
|
|
346
|
-
const [imageName, setImageName] = useState(
|
|
347
|
-
const [containerName, setContainerName] = useState(
|
|
348
|
-
const [portInput, setPortInput] = useState(
|
|
349
|
-
const [envInput, setEnvInput] = useState(
|
|
350
|
-
const [message, setMessage] = useState(
|
|
351
|
-
const [messageColor, setMessageColor] = useState(
|
|
693
|
+
const [imageName, setImageName] = useState('');
|
|
694
|
+
const [containerName, setContainerName] = useState('');
|
|
695
|
+
const [portInput, setPortInput] = useState('');
|
|
696
|
+
const [envInput, setEnvInput] = useState('');
|
|
697
|
+
const [message, setMessage] = useState('');
|
|
698
|
+
const [messageColor, setMessageColor] = useState('yellow');
|
|
699
|
+
|
|
700
|
+
// Autocomplete state
|
|
701
|
+
const [suggestions, setSuggestions] = useState([]);
|
|
702
|
+
const [selectedSuggestionIndex, setSelectedSuggestionIndex] = useState(-1);
|
|
703
|
+
const [visibleOffset, setVisibleOffset] = useState(0);
|
|
704
|
+
|
|
705
|
+
// Docker Hub search state
|
|
706
|
+
const [isSearchingHub, setIsSearchingHub] = useState(false);
|
|
707
|
+
const [hubResults, setHubResults] = useState(null);
|
|
708
|
+
// Tracks active request: { controller: AbortController|null, requestId: number }
|
|
709
|
+
const activeHubRequestRef = useRef({ controller: null, requestId: 0 });
|
|
710
|
+
|
|
711
|
+
/**
|
|
712
|
+
* Updates the image name input and recalculates autocomplete suggestions.
|
|
713
|
+
* Resets selectedSuggestionIndex to -1 on every keystroke.
|
|
714
|
+
* Also aborts any in-flight Hub search and clears Hub results.
|
|
715
|
+
*
|
|
716
|
+
* @param {string} value - New raw image name typed by user
|
|
717
|
+
*/
|
|
718
|
+
function updateImageInput(value) {
|
|
719
|
+
// Abort any in-flight Hub search and clear its state
|
|
720
|
+
activeHubRequestRef.current.controller?.abort();
|
|
721
|
+
activeHubRequestRef.current.requestId += 1;
|
|
722
|
+
setIsSearchingHub(false);
|
|
723
|
+
setHubResults(null);
|
|
724
|
+
|
|
725
|
+
setImageName(value);
|
|
726
|
+
setSelectedSuggestionIndex(-1);
|
|
727
|
+
setVisibleOffset(0);
|
|
728
|
+
if (!value.trim()) {
|
|
729
|
+
setSuggestions([]);
|
|
730
|
+
return;
|
|
731
|
+
}
|
|
732
|
+
const lower = value.toLowerCase();
|
|
733
|
+
const matches = Object.keys(imageProfiles).filter((key) =>
|
|
734
|
+
key.includes(lower)
|
|
735
|
+
);
|
|
736
|
+
setSuggestions(matches);
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
/**
|
|
740
|
+
* Triggers a Docker Hub search for the current imageName.
|
|
741
|
+
* Guards: imageName must be non-empty; no concurrent search allowed.
|
|
742
|
+
* Uses AbortController + requestId to handle race conditions.
|
|
743
|
+
*/
|
|
744
|
+
async function triggerHubSearch() {
|
|
745
|
+
const query = imageName.trim();
|
|
746
|
+
if (!query) return;
|
|
747
|
+
if (isSearchingHub) return;
|
|
748
|
+
|
|
749
|
+
// Abort previous request (should already be aborted from updateImageInput,
|
|
750
|
+
// but guard here too)
|
|
751
|
+
activeHubRequestRef.current.controller?.abort();
|
|
752
|
+
|
|
753
|
+
const requestId = activeHubRequestRef.current.requestId + 1;
|
|
754
|
+
activeHubRequestRef.current.requestId = requestId;
|
|
755
|
+
|
|
756
|
+
const controller = new AbortController();
|
|
757
|
+
activeHubRequestRef.current.controller = controller;
|
|
758
|
+
|
|
759
|
+
setIsSearchingHub(true);
|
|
760
|
+
setSelectedSuggestionIndex(-1);
|
|
761
|
+
setVisibleOffset(0);
|
|
762
|
+
|
|
763
|
+
try {
|
|
764
|
+
const results = await searchDockerHub(query, { signal: controller.signal });
|
|
765
|
+
// Ignore stale responses
|
|
766
|
+
if (activeHubRequestRef.current.requestId !== requestId) return;
|
|
767
|
+
setHubResults(results.map(formatHubResult));
|
|
768
|
+
} catch (err) {
|
|
769
|
+
<span class="cstat-no" title="statement not covered" > if (activeHubRequestRef.current.requestId !== requestId) <span class="cstat-no" title="statement not covered" >return;</span></span>
|
|
770
|
+
// Silence AbortError; for all other errors fall back to static suggestions
|
|
771
|
+
<span class="cstat-no" title="statement not covered" > setHubResults(null);</span>
|
|
772
|
+
} finally {
|
|
773
|
+
if (activeHubRequestRef.current.requestId === requestId) {
|
|
774
|
+
setIsSearchingHub(false);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
/**
|
|
780
|
+
* Moves the suggestion selection up (-1) or down (+1).
|
|
781
|
+
* Clamps index to [-1, suggestions.length - 1].
|
|
782
|
+
* Adjusts visibleOffset to keep selected item in the visible window.
|
|
783
|
+
*
|
|
784
|
+
* @param {number} direction - -1 (up) or 1 (down)
|
|
785
|
+
*/
|
|
786
|
+
function moveSuggestionSelection(direction) {
|
|
787
|
+
setSelectedSuggestionIndex((prev) => {
|
|
788
|
+
const next = Math.max(-1, Math.min(suggestions.length - 1, prev + direction));
|
|
789
|
+
// Adjust visibleOffset to keep selected in view
|
|
790
|
+
setVisibleOffset((offset) => {
|
|
791
|
+
if (next < offset) return Math.max(0, next);
|
|
792
|
+
if (next >= offset + MAX_VISIBLE) return next - MAX_VISIBLE + 1;
|
|
793
|
+
return offset;
|
|
794
|
+
});
|
|
795
|
+
return next;
|
|
796
|
+
});
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
/**
|
|
800
|
+
* Applies the currently focused suggestion to imageName.
|
|
801
|
+
* Does NOT advance the step. Clears suggestions after applying.
|
|
802
|
+
*/
|
|
803
|
+
function applyFocusedSuggestion() {
|
|
804
|
+
<span class="missing-if-branch" title="if path not taken" >I</span>if (selectedSuggestionIndex < 0 || selectedSuggestionIndex >= suggestions.length) <span class="cstat-no" title="statement not covered" >return;</span>
|
|
805
|
+
const chosen = suggestions[selectedSuggestionIndex];
|
|
806
|
+
setImageName(resolveImageTag(chosen, imageProfiles));
|
|
807
|
+
setSuggestions([]);
|
|
808
|
+
setSelectedSuggestionIndex(-1);
|
|
809
|
+
setVisibleOffset(0);
|
|
810
|
+
}
|
|
352
811
|
|
|
353
812
|
/**
|
|
354
813
|
* Advances to the next step, with validation and feedback.
|
|
@@ -356,42 +815,72 @@ export function useContainerCreation({ onCreate, onCancel, dbImages = <span clas
|
|
|
356
815
|
function nextStep() {
|
|
357
816
|
if (step === 0) {
|
|
358
817
|
if (!imageName.trim()) {
|
|
359
|
-
setMessage(
|
|
360
|
-
setMessageColor(
|
|
818
|
+
setMessage('Image name cannot be empty.');
|
|
819
|
+
setMessageColor('red');
|
|
361
820
|
return;
|
|
362
821
|
}
|
|
822
|
+
const resolved = resolveImageTag(imageName, imageProfiles);
|
|
823
|
+
setImageName(resolved);
|
|
363
824
|
setStep(1);
|
|
364
|
-
setMessage(
|
|
365
|
-
|
|
825
|
+
setMessage(
|
|
826
|
+
'Optional: Enter container name or leave empty and press Enter'
|
|
827
|
+
);
|
|
828
|
+
setMessageColor('yellow');
|
|
366
829
|
return;
|
|
367
830
|
}
|
|
368
831
|
if (step === 1) {
|
|
369
832
|
setStep(2);
|
|
370
|
-
setMessage(
|
|
371
|
-
|
|
833
|
+
setMessage(
|
|
834
|
+
'Optional: Enter ports (format 8080:80,443:443) or leave empty and press Enter'
|
|
835
|
+
);
|
|
836
|
+
setMessageColor('yellow');
|
|
372
837
|
return;
|
|
373
838
|
}
|
|
374
839
|
if (step === 2) {
|
|
375
840
|
// Ports are now optional - only validate if provided
|
|
376
841
|
if (portInput.trim() && !validatePorts(portInput)) {
|
|
377
|
-
setMessage(
|
|
378
|
-
|
|
842
|
+
setMessage(
|
|
843
|
+
'Port format must be host:container and both must be numbers (e.g. 8080:80)'
|
|
844
|
+
);
|
|
845
|
+
setMessageColor('red');
|
|
379
846
|
return;
|
|
380
847
|
}
|
|
381
848
|
setStep(3);
|
|
382
|
-
const isDb = dbImages.some(db =>
|
|
849
|
+
const isDb = dbImages.some((db) =>
|
|
850
|
+
imageName.trim().toLowerCase().includes(db)
|
|
851
|
+
);
|
|
383
852
|
// Check if the image has a profile with required env vars
|
|
384
|
-
const baseName = imageName
|
|
853
|
+
const baseName = imageName
|
|
854
|
+
.trim()
|
|
855
|
+
.toLowerCase()
|
|
856
|
+
.split(':')[0]
|
|
857
|
+
.split('/')
|
|
858
|
+
.pop();
|
|
385
859
|
const profile = imageProfiles[baseName];
|
|
386
860
|
if (profile && profile.requiredEnv && profile.requiredEnv.length) {
|
|
387
|
-
|
|
388
|
-
|
|
861
|
+
const suggestedPart =
|
|
862
|
+
profile.suggestedEnv && profile.suggestedEnv.length
|
|
863
|
+
? ` | Suggested: ${profile.suggestedEnv.join(', ')}`
|
|
864
|
+
: <span class="branch-1 cbranch-no" title="branch not covered" >'';</span>
|
|
865
|
+
setMessage(
|
|
866
|
+
`Required env vars for ${baseName}: ${profile.requiredEnv.join(', ')}. Enter as VAR=val,VAR2=val2${suggestedPart}`
|
|
867
|
+
);
|
|
868
|
+
setMessageColor('yellow');
|
|
869
|
+
} else if (profile && profile.suggestedEnv && profile.suggestedEnv.length) {
|
|
870
|
+
setMessage(
|
|
871
|
+
`Suggested env vars for ${baseName}: ${profile.suggestedEnv.join(', ')}. Enter as VAR=val,VAR2=val2 or leave empty.`
|
|
872
|
+
);
|
|
873
|
+
setMessageColor('yellow');
|
|
389
874
|
} else <span class="missing-if-branch" title="if path not taken" >I</span>if (isDb) {
|
|
390
|
-
<span class="cstat-no" title="statement not covered" > setMessage(
|
|
391
|
-
|
|
875
|
+
<span class="cstat-no" title="statement not covered" > setMessage(</span>
|
|
876
|
+
'Warning: This image usually requires environment variables (e.g. MYSQL_ROOT_PASSWORD=my-secret-pw for MySQL, POSTGRES_PASSWORD=yourpassword for Postgres). Enter them as VAR=val,VAR2=val2 or leave empty and press Enter.'
|
|
877
|
+
);
|
|
878
|
+
<span class="cstat-no" title="statement not covered" > setMessageColor('yellow');</span>
|
|
392
879
|
} else {
|
|
393
|
-
setMessage(
|
|
394
|
-
|
|
880
|
+
setMessage(
|
|
881
|
+
'Optional: Enter environment variables (format VAR1=val1,VAR2=val2) or leave empty and press Enter'
|
|
882
|
+
);
|
|
883
|
+
setMessageColor('yellow');
|
|
395
884
|
}
|
|
396
885
|
return;
|
|
397
886
|
}
|
|
@@ -399,8 +888,8 @@ export function useContainerCreation({ onCreate, onCancel, dbImages = <span clas
|
|
|
399
888
|
// Contextual env validation using image profiles
|
|
400
889
|
const result = validateEnvVars(envInput, imageName, imageProfiles);
|
|
401
890
|
if (!result.valid) {
|
|
402
|
-
setMessage(result.errors.join(
|
|
403
|
-
setMessageColor(
|
|
891
|
+
setMessage(result.errors.join(' | '));
|
|
892
|
+
setMessageColor('red');
|
|
404
893
|
return;
|
|
405
894
|
}
|
|
406
895
|
// Final step: call onCreate with all data (safely)
|
|
@@ -413,12 +902,15 @@ export function useContainerCreation({ onCreate, onCancel, dbImages = <span clas
|
|
|
413
902
|
*/
|
|
414
903
|
function <span class="fstat-no" title="function not covered" >cancelCreation(</span>) {
|
|
415
904
|
<span class="cstat-no" title="statement not covered" > setStep(0);</span>
|
|
416
|
-
<span class="cstat-no" title="statement not covered" > setImageName(
|
|
417
|
-
<span class="cstat-no" title="statement not covered" > setContainerName(
|
|
418
|
-
<span class="cstat-no" title="statement not covered" > setPortInput(
|
|
419
|
-
<span class="cstat-no" title="statement not covered" > setEnvInput(
|
|
420
|
-
<span class="cstat-no" title="statement not covered" > setMessage(
|
|
421
|
-
<span class="cstat-no" title="statement not covered" > setMessageColor(
|
|
905
|
+
<span class="cstat-no" title="statement not covered" > setImageName('');</span>
|
|
906
|
+
<span class="cstat-no" title="statement not covered" > setContainerName('');</span>
|
|
907
|
+
<span class="cstat-no" title="statement not covered" > setPortInput('');</span>
|
|
908
|
+
<span class="cstat-no" title="statement not covered" > setEnvInput('');</span>
|
|
909
|
+
<span class="cstat-no" title="statement not covered" > setMessage('');</span>
|
|
910
|
+
<span class="cstat-no" title="statement not covered" > setMessageColor('yellow');</span>
|
|
911
|
+
<span class="cstat-no" title="statement not covered" > setSuggestions([]);</span>
|
|
912
|
+
<span class="cstat-no" title="statement not covered" > setSelectedSuggestionIndex(-1);</span>
|
|
913
|
+
<span class="cstat-no" title="statement not covered" > setVisibleOffset(0);</span>
|
|
422
914
|
<span class="cstat-no" title="statement not covered" > safeCall(onCancel);</span>
|
|
423
915
|
}
|
|
424
916
|
|
|
@@ -426,14 +918,17 @@ export function useContainerCreation({ onCreate, onCancel, dbImages = <span clas
|
|
|
426
918
|
* Resets all creation state to initial values without triggering onCancel.
|
|
427
919
|
* Used by the command router when the user presses 'c' to open the creation wizard.
|
|
428
920
|
*/
|
|
429
|
-
function
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
921
|
+
function resetCreation() {
|
|
922
|
+
setStep(0);
|
|
923
|
+
setImageName('');
|
|
924
|
+
setContainerName('');
|
|
925
|
+
setPortInput('');
|
|
926
|
+
setEnvInput('');
|
|
927
|
+
setMessage('Insert the name of the image to create: ');
|
|
928
|
+
setMessageColor('yellow');
|
|
929
|
+
setSuggestions([]);
|
|
930
|
+
setSelectedSuggestionIndex(-1);
|
|
931
|
+
setVisibleOffset(0);
|
|
437
932
|
}
|
|
438
933
|
|
|
439
934
|
return {
|
|
@@ -451,6 +946,15 @@ export function useContainerCreation({ onCreate, onCancel, dbImages = <span clas
|
|
|
451
946
|
setMessage,
|
|
452
947
|
messageColor,
|
|
453
948
|
setMessageColor,
|
|
949
|
+
suggestions,
|
|
950
|
+
selectedSuggestionIndex,
|
|
951
|
+
visibleOffset,
|
|
952
|
+
isSearchingHub,
|
|
953
|
+
hubResults,
|
|
954
|
+
updateImageInput,
|
|
955
|
+
triggerHubSearch,
|
|
956
|
+
moveSuggestionSelection,
|
|
957
|
+
applyFocusedSuggestion,
|
|
454
958
|
nextStep,
|
|
455
959
|
cancelCreation,
|
|
456
960
|
resetCreation,
|
|
@@ -463,7 +967,7 @@ export function useContainerCreation({ onCreate, onCancel, dbImages = <span clas
|
|
|
463
967
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
464
968
|
Code coverage generated by
|
|
465
969
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
466
|
-
at 2026-04-
|
|
970
|
+
at 2026-04-27T22:13:21.150Z
|
|
467
971
|
</div>
|
|
468
972
|
<script src="../../prettify.js"></script>
|
|
469
973
|
<script>
|