@synteq/cli 0.2.0 → 1.1.2

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 (433) hide show
  1. package/dist/api/client.d.ts +362 -5
  2. package/dist/api/client.js +559 -44
  3. package/dist/api/client.js.map +1 -1
  4. package/dist/api/factory.js +5 -2
  5. package/dist/api/factory.js.map +1 -1
  6. package/dist/api/types.d.ts +892 -3
  7. package/dist/apps-support/deploy.d.ts +197 -0
  8. package/dist/apps-support/deploy.js +639 -0
  9. package/dist/apps-support/deploy.js.map +1 -0
  10. package/dist/apps-support/dotenv.d.ts +67 -0
  11. package/dist/apps-support/dotenv.js +136 -0
  12. package/dist/apps-support/dotenv.js.map +1 -0
  13. package/dist/apps-support/env-rollout.d.ts +18 -0
  14. package/dist/apps-support/env-rollout.js +52 -0
  15. package/dist/apps-support/env-rollout.js.map +1 -0
  16. package/dist/apps-support/git.d.ts +14 -0
  17. package/dist/apps-support/git.js +25 -0
  18. package/dist/apps-support/git.js.map +1 -0
  19. package/dist/apps-support/link.d.ts +25 -0
  20. package/dist/apps-support/link.js +39 -0
  21. package/dist/apps-support/link.js.map +1 -0
  22. package/dist/apps-support/log-stream.d.ts +25 -0
  23. package/dist/apps-support/log-stream.js +85 -0
  24. package/dist/apps-support/log-stream.js.map +1 -0
  25. package/dist/apps-support/paid-app.d.ts +64 -0
  26. package/dist/apps-support/paid-app.js +195 -0
  27. package/dist/apps-support/paid-app.js.map +1 -0
  28. package/dist/apps-support/plans.d.ts +44 -0
  29. package/dist/apps-support/plans.js +43 -0
  30. package/dist/apps-support/plans.js.map +1 -0
  31. package/dist/apps-support/resolve.d.ts +10 -0
  32. package/dist/apps-support/resolve.js +53 -0
  33. package/dist/apps-support/resolve.js.map +1 -0
  34. package/dist/apps-support/time.d.ts +20 -0
  35. package/dist/apps-support/time.js +82 -0
  36. package/dist/apps-support/time.js.map +1 -0
  37. package/dist/auth/scope.js +4 -0
  38. package/dist/auth/scope.js.map +1 -1
  39. package/dist/auth/tokens.d.ts +3 -0
  40. package/dist/auth/tokens.js +6 -4
  41. package/dist/auth/tokens.js.map +1 -1
  42. package/dist/base/command.d.ts +35 -0
  43. package/dist/base/command.js +87 -4
  44. package/dist/base/command.js.map +1 -1
  45. package/dist/commands/agents.d.ts +10 -0
  46. package/dist/commands/agents.js +53 -0
  47. package/dist/commands/agents.js.map +1 -0
  48. package/dist/commands/api.d.ts +0 -1
  49. package/dist/commands/api.js +6 -5
  50. package/dist/commands/api.js.map +1 -1
  51. package/dist/commands/app/deployment/list.d.ts +14 -0
  52. package/dist/commands/app/deployment/list.js +45 -0
  53. package/dist/commands/app/deployment/list.js.map +1 -0
  54. package/dist/commands/app/deployment/rollback.d.ts +18 -0
  55. package/dist/commands/app/deployment/rollback.js +57 -0
  56. package/dist/commands/app/deployment/rollback.js.map +1 -0
  57. package/dist/commands/app/deployment/show.d.ts +26 -0
  58. package/dist/commands/app/deployment/show.js +98 -0
  59. package/dist/commands/app/deployment/show.js.map +1 -0
  60. package/dist/commands/app/domain/add.d.ts +17 -0
  61. package/dist/commands/app/domain/add.js +59 -0
  62. package/dist/commands/app/domain/add.js.map +1 -0
  63. package/dist/commands/app/domain/list.d.ts +14 -0
  64. package/dist/commands/app/domain/list.js +42 -0
  65. package/dist/commands/app/domain/list.js.map +1 -0
  66. package/dist/commands/app/domain/remove.d.ts +16 -0
  67. package/dist/commands/app/domain/remove.js +51 -0
  68. package/dist/commands/app/domain/remove.js.map +1 -0
  69. package/dist/commands/app/domain/verify.d.ts +15 -0
  70. package/dist/commands/app/domain/verify.js +39 -0
  71. package/dist/commands/app/domain/verify.js.map +1 -0
  72. package/dist/commands/app/env/add.d.ts +22 -0
  73. package/dist/commands/app/env/add.js +103 -0
  74. package/dist/commands/app/env/add.js.map +1 -0
  75. package/dist/commands/app/env/list.d.ts +17 -0
  76. package/dist/commands/app/env/list.js +40 -0
  77. package/dist/commands/app/env/list.js.map +1 -0
  78. package/dist/commands/app/env/reveal.d.ts +17 -0
  79. package/dist/commands/app/env/reveal.js +40 -0
  80. package/dist/commands/app/env/reveal.js.map +1 -0
  81. package/dist/commands/app/env/rm.d.ts +16 -0
  82. package/dist/commands/app/env/rm.js +48 -0
  83. package/dist/commands/app/env/rm.js.map +1 -0
  84. package/dist/commands/app/health.d.ts +14 -0
  85. package/dist/commands/app/health.js +40 -0
  86. package/dist/commands/app/health.js.map +1 -0
  87. package/dist/commands/app/index.d.ts +6 -0
  88. package/dist/commands/app/index.js +7 -0
  89. package/dist/commands/app/index.js.map +1 -0
  90. package/dist/commands/app/link.d.ts +22 -0
  91. package/dist/commands/app/link.js +31 -0
  92. package/dist/commands/app/link.js.map +1 -0
  93. package/dist/commands/app/logs.d.ts +25 -0
  94. package/dist/commands/app/logs.js +121 -0
  95. package/dist/commands/app/logs.js.map +1 -0
  96. package/dist/commands/app/metrics.d.ts +21 -0
  97. package/dist/commands/app/metrics.js +123 -0
  98. package/dist/commands/app/metrics.js.map +1 -0
  99. package/dist/commands/app/plan/change.d.ts +18 -0
  100. package/dist/commands/app/plan/change.js +79 -0
  101. package/dist/commands/app/plan/change.js.map +1 -0
  102. package/dist/commands/app/plan/show.d.ts +14 -0
  103. package/dist/commands/app/plan/show.js +40 -0
  104. package/dist/commands/app/plan/show.js.map +1 -0
  105. package/dist/commands/app/settings/set.d.ts +25 -0
  106. package/dist/commands/app/settings/set.js +96 -0
  107. package/dist/commands/app/settings/set.js.map +1 -0
  108. package/dist/commands/app/settings/show.d.ts +14 -0
  109. package/dist/commands/app/settings/show.js +48 -0
  110. package/dist/commands/app/settings/show.js.map +1 -0
  111. package/dist/commands/app/unlink.d.ts +8 -0
  112. package/dist/commands/app/unlink.js +25 -0
  113. package/dist/commands/app/unlink.js.map +1 -0
  114. package/dist/commands/apps/create.d.ts +26 -0
  115. package/dist/commands/apps/create.js +91 -0
  116. package/dist/commands/apps/create.js.map +1 -0
  117. package/dist/commands/apps/list.d.ts +17 -0
  118. package/dist/commands/apps/list.js +56 -0
  119. package/dist/commands/apps/list.js.map +1 -0
  120. package/dist/commands/baremetal/activity.d.ts +14 -0
  121. package/dist/commands/baremetal/activity.js +53 -0
  122. package/dist/commands/baremetal/activity.js.map +1 -0
  123. package/dist/commands/baremetal/bandwidth.d.ts +10 -0
  124. package/dist/commands/baremetal/bandwidth.js +86 -0
  125. package/dist/commands/baremetal/bandwidth.js.map +1 -0
  126. package/dist/commands/baremetal/console.d.ts +20 -0
  127. package/dist/commands/baremetal/console.js +72 -0
  128. package/dist/commands/baremetal/console.js.map +1 -0
  129. package/dist/commands/baremetal/details.d.ts +11 -0
  130. package/dist/commands/baremetal/details.js +116 -0
  131. package/dist/commands/baremetal/details.js.map +1 -0
  132. package/dist/commands/baremetal/index.d.ts +5 -0
  133. package/dist/commands/baremetal/index.js +6 -0
  134. package/dist/commands/baremetal/index.js.map +1 -0
  135. package/dist/commands/baremetal/install-password.d.ts +14 -0
  136. package/dist/commands/baremetal/install-password.js +80 -0
  137. package/dist/commands/baremetal/install-password.js.map +1 -0
  138. package/dist/commands/baremetal/list.d.ts +11 -0
  139. package/dist/commands/baremetal/list.js +59 -0
  140. package/dist/commands/baremetal/list.js.map +1 -0
  141. package/dist/commands/baremetal/order.d.ts +34 -0
  142. package/dist/commands/baremetal/order.js +394 -0
  143. package/dist/commands/baremetal/order.js.map +1 -0
  144. package/dist/commands/baremetal/power.d.ts +18 -0
  145. package/dist/commands/baremetal/power.js +168 -0
  146. package/dist/commands/baremetal/power.js.map +1 -0
  147. package/dist/commands/baremetal/reinstall.d.ts +21 -0
  148. package/dist/commands/baremetal/reinstall.js +168 -0
  149. package/dist/commands/baremetal/reinstall.js.map +1 -0
  150. package/dist/commands/config/profile/add.d.ts +11 -0
  151. package/dist/commands/config/profile/add.js +51 -0
  152. package/dist/commands/config/profile/add.js.map +1 -0
  153. package/dist/commands/config/profile/list.d.ts +7 -0
  154. package/dist/commands/config/profile/list.js +29 -0
  155. package/dist/commands/config/profile/list.js.map +1 -0
  156. package/dist/commands/config/profile/remove.d.ts +11 -0
  157. package/dist/commands/config/profile/remove.js +35 -0
  158. package/dist/commands/config/profile/remove.js.map +1 -0
  159. package/dist/commands/config/profile/use.d.ts +10 -0
  160. package/dist/commands/config/profile/use.js +44 -0
  161. package/dist/commands/config/profile/use.js.map +1 -0
  162. package/dist/commands/config/show.js +4 -1
  163. package/dist/commands/config/show.js.map +1 -1
  164. package/dist/commands/credits/add.js +2 -2
  165. package/dist/commands/credits/add.js.map +1 -1
  166. package/dist/commands/credits/index.js +5 -1
  167. package/dist/commands/credits/index.js.map +1 -1
  168. package/dist/commands/deploy.d.ts +51 -0
  169. package/dist/commands/deploy.js +515 -0
  170. package/dist/commands/deploy.js.map +1 -0
  171. package/dist/commands/function/create.d.ts +29 -0
  172. package/dist/commands/function/create.js +113 -0
  173. package/dist/commands/function/create.js.map +1 -0
  174. package/dist/commands/function/credits/add.d.ts +29 -0
  175. package/dist/commands/function/credits/add.js +209 -0
  176. package/dist/commands/function/credits/add.js.map +1 -0
  177. package/dist/commands/function/credits/auto-reload.d.ts +27 -0
  178. package/dist/commands/function/credits/auto-reload.js +107 -0
  179. package/dist/commands/function/credits/auto-reload.js.map +1 -0
  180. package/dist/commands/function/credits/index.d.ts +22 -0
  181. package/dist/commands/function/credits/index.js +80 -0
  182. package/dist/commands/function/credits/index.js.map +1 -0
  183. package/dist/commands/function/cron/add.d.ts +19 -0
  184. package/dist/commands/function/cron/add.js +74 -0
  185. package/dist/commands/function/cron/add.js.map +1 -0
  186. package/dist/commands/function/cron/list.d.ts +12 -0
  187. package/dist/commands/function/cron/list.js +55 -0
  188. package/dist/commands/function/cron/list.js.map +1 -0
  189. package/dist/commands/function/cron/rm.d.ts +17 -0
  190. package/dist/commands/function/cron/rm.js +73 -0
  191. package/dist/commands/function/cron/rm.js.map +1 -0
  192. package/dist/commands/function/cron/run.d.ts +16 -0
  193. package/dist/commands/function/cron/run.js +59 -0
  194. package/dist/commands/function/cron/run.js.map +1 -0
  195. package/dist/commands/function/cron/update.d.ts +21 -0
  196. package/dist/commands/function/cron/update.js +87 -0
  197. package/dist/commands/function/cron/update.js.map +1 -0
  198. package/dist/commands/function/delete.d.ts +23 -0
  199. package/dist/commands/function/delete.js +90 -0
  200. package/dist/commands/function/delete.js.map +1 -0
  201. package/dist/commands/function/deploy.d.ts +64 -0
  202. package/dist/commands/function/deploy.js +616 -0
  203. package/dist/commands/function/deploy.js.map +1 -0
  204. package/dist/commands/function/env/list.d.ts +12 -0
  205. package/dist/commands/function/env/list.js +46 -0
  206. package/dist/commands/function/env/list.js.map +1 -0
  207. package/dist/commands/function/env/reveal.d.ts +21 -0
  208. package/dist/commands/function/env/reveal.js +54 -0
  209. package/dist/commands/function/env/reveal.js.map +1 -0
  210. package/dist/commands/function/env/rm.d.ts +17 -0
  211. package/dist/commands/function/env/rm.js +62 -0
  212. package/dist/commands/function/env/rm.js.map +1 -0
  213. package/dist/commands/function/env/set.d.ts +28 -0
  214. package/dist/commands/function/env/set.js +124 -0
  215. package/dist/commands/function/env/set.js.map +1 -0
  216. package/dist/commands/function/index.d.ts +14 -0
  217. package/dist/commands/function/index.js +11 -0
  218. package/dist/commands/function/index.js.map +1 -0
  219. package/dist/commands/function/init.d.ts +48 -0
  220. package/dist/commands/function/init.js +277 -0
  221. package/dist/commands/function/init.js.map +1 -0
  222. package/dist/commands/function/invoke.d.ts +29 -0
  223. package/dist/commands/function/invoke.js +138 -0
  224. package/dist/commands/function/invoke.js.map +1 -0
  225. package/dist/commands/function/link.d.ts +23 -0
  226. package/dist/commands/function/link.js +80 -0
  227. package/dist/commands/function/link.js.map +1 -0
  228. package/dist/commands/function/list.d.ts +16 -0
  229. package/dist/commands/function/list.js +55 -0
  230. package/dist/commands/function/list.js.map +1 -0
  231. package/dist/commands/function/logs.d.ts +29 -0
  232. package/dist/commands/function/logs.js +171 -0
  233. package/dist/commands/function/logs.js.map +1 -0
  234. package/dist/commands/function/pause.d.ts +19 -0
  235. package/dist/commands/function/pause.js +50 -0
  236. package/dist/commands/function/pause.js.map +1 -0
  237. package/dist/commands/function/releases.d.ts +15 -0
  238. package/dist/commands/function/releases.js +62 -0
  239. package/dist/commands/function/releases.js.map +1 -0
  240. package/dist/commands/function/resume.d.ts +16 -0
  241. package/dist/commands/function/resume.js +47 -0
  242. package/dist/commands/function/resume.js.map +1 -0
  243. package/dist/commands/function/rollback.d.ts +18 -0
  244. package/dist/commands/function/rollback.js +69 -0
  245. package/dist/commands/function/rollback.js.map +1 -0
  246. package/dist/commands/function/settings/set.d.ts +23 -0
  247. package/dist/commands/function/settings/set.js +119 -0
  248. package/dist/commands/function/settings/set.js.map +1 -0
  249. package/dist/commands/function/show.d.ts +15 -0
  250. package/dist/commands/function/show.js +80 -0
  251. package/dist/commands/function/show.js.map +1 -0
  252. package/dist/commands/function/unlink.d.ts +9 -0
  253. package/dist/commands/function/unlink.js +34 -0
  254. package/dist/commands/function/unlink.js.map +1 -0
  255. package/dist/commands/link.d.ts +82 -0
  256. package/dist/commands/link.js +532 -0
  257. package/dist/commands/link.js.map +1 -0
  258. package/dist/commands/login.js +9 -0
  259. package/dist/commands/login.js.map +1 -1
  260. package/dist/commands/order.js +3 -1
  261. package/dist/commands/order.js.map +1 -1
  262. package/dist/commands/payments/methods/delete.js +2 -2
  263. package/dist/commands/payments/methods/delete.js.map +1 -1
  264. package/dist/commands/resources.js +50 -7
  265. package/dist/commands/resources.js.map +1 -1
  266. package/dist/commands/status.d.ts +12 -0
  267. package/dist/commands/status.js +71 -0
  268. package/dist/commands/status.js.map +1 -0
  269. package/dist/commands/storage/detach.js +1 -1
  270. package/dist/commands/storage/detach.js.map +1 -1
  271. package/dist/commands/storage/list.js +6 -2
  272. package/dist/commands/storage/list.js.map +1 -1
  273. package/dist/commands/storage/order.d.ts +2 -0
  274. package/dist/commands/storage/order.js +100 -18
  275. package/dist/commands/storage/order.js.map +1 -1
  276. package/dist/commands/storage/resize.js +19 -6
  277. package/dist/commands/storage/resize.js.map +1 -1
  278. package/dist/commands/tickets/create.d.ts +2 -0
  279. package/dist/commands/tickets/create.js +40 -1
  280. package/dist/commands/tickets/create.js.map +1 -1
  281. package/dist/commands/tickets/download.d.ts +18 -0
  282. package/dist/commands/tickets/download.js +138 -0
  283. package/dist/commands/tickets/download.js.map +1 -0
  284. package/dist/commands/tickets/list.js +13 -7
  285. package/dist/commands/tickets/list.js.map +1 -1
  286. package/dist/commands/tickets/reply.d.ts +2 -0
  287. package/dist/commands/tickets/reply.js +33 -4
  288. package/dist/commands/tickets/reply.js.map +1 -1
  289. package/dist/commands/vds/order.js +72 -7
  290. package/dist/commands/vds/order.js.map +1 -1
  291. package/dist/commands/vps/console.js +14 -6
  292. package/dist/commands/vps/console.js.map +1 -1
  293. package/dist/commands/vps/details.js +7 -1
  294. package/dist/commands/vps/details.js.map +1 -1
  295. package/dist/commands/vps/ip/add.js +76 -9
  296. package/dist/commands/vps/ip/add.js.map +1 -1
  297. package/dist/commands/vps/list.js +13 -4
  298. package/dist/commands/vps/list.js.map +1 -1
  299. package/dist/commands/vps/order.d.ts +19 -0
  300. package/dist/commands/vps/order.js +179 -23
  301. package/dist/commands/vps/order.js.map +1 -1
  302. package/dist/commands/vps/power.js +2 -2
  303. package/dist/commands/vps/power.js.map +1 -1
  304. package/dist/commands/vps/reinstall.js +2 -2
  305. package/dist/commands/vps/reinstall.js.map +1 -1
  306. package/dist/commands/vps/resize.js +36 -13
  307. package/dist/commands/vps/resize.js.map +1 -1
  308. package/dist/commands/whoami.d.ts +5 -0
  309. package/dist/commands/whoami.js +8 -3
  310. package/dist/commands/whoami.js.map +1 -1
  311. package/dist/config/paths.d.ts +1 -1
  312. package/dist/config/paths.js +6 -1
  313. package/dist/config/paths.js.map +1 -1
  314. package/dist/config/store.d.ts +58 -0
  315. package/dist/config/store.js +84 -2
  316. package/dist/config/store.js.map +1 -1
  317. package/dist/functions-support/credits.d.ts +64 -0
  318. package/dist/functions-support/credits.js +181 -0
  319. package/dist/functions-support/credits.js.map +1 -0
  320. package/dist/functions-support/cron.d.ts +17 -0
  321. package/dist/functions-support/cron.js +99 -0
  322. package/dist/functions-support/cron.js.map +1 -0
  323. package/dist/functions-support/env.d.ts +23 -0
  324. package/dist/functions-support/env.js +44 -0
  325. package/dist/functions-support/env.js.map +1 -0
  326. package/dist/functions-support/link.d.ts +25 -0
  327. package/dist/functions-support/link.js +51 -0
  328. package/dist/functions-support/link.js.map +1 -0
  329. package/dist/functions-support/poll.d.ts +40 -0
  330. package/dist/functions-support/poll.js +109 -0
  331. package/dist/functions-support/poll.js.map +1 -0
  332. package/dist/functions-support/resolve.d.ts +3 -0
  333. package/dist/functions-support/resolve.js +31 -0
  334. package/dist/functions-support/resolve.js.map +1 -0
  335. package/dist/functions-support/runtime.d.ts +30 -0
  336. package/dist/functions-support/runtime.js +52 -0
  337. package/dist/functions-support/runtime.js.map +1 -0
  338. package/dist/functions-support/source.d.ts +92 -0
  339. package/dist/functions-support/source.js +343 -0
  340. package/dist/functions-support/source.js.map +1 -0
  341. package/dist/help/scope-aware-help.js +10 -1
  342. package/dist/help/scope-aware-help.js.map +1 -1
  343. package/dist/tui/App.js +10 -25
  344. package/dist/tui/App.js.map +1 -1
  345. package/dist/tui/components/Menu.d.ts +3 -1
  346. package/dist/tui/components/Menu.js +7 -3
  347. package/dist/tui/components/Menu.js.map +1 -1
  348. package/dist/tui/router.d.ts +1 -1
  349. package/dist/tui/router.js.map +1 -1
  350. package/dist/tui/screens/Billing.js +56 -4
  351. package/dist/tui/screens/Billing.js.map +1 -1
  352. package/dist/tui/screens/Dashboard.js +8 -7
  353. package/dist/tui/screens/Dashboard.js.map +1 -1
  354. package/dist/tui/screens/Deploy.d.ts +2 -0
  355. package/dist/tui/screens/Deploy.js +912 -0
  356. package/dist/tui/screens/Deploy.js.map +1 -0
  357. package/dist/tui/screens/Order.js +359 -26
  358. package/dist/tui/screens/Order.js.map +1 -1
  359. package/dist/tui/screens/Resources.js +273 -31
  360. package/dist/tui/screens/Resources.js.map +1 -1
  361. package/dist/tui/screens/Tickets.js +18 -6
  362. package/dist/tui/screens/Tickets.js.map +1 -1
  363. package/dist/tui/screens/deployPreset.d.ts +20 -0
  364. package/dist/tui/screens/deployPreset.js +11 -0
  365. package/dist/tui/screens/deployPreset.js.map +1 -0
  366. package/dist/tui/screens/resources/AppDetail.d.ts +7 -0
  367. package/dist/tui/screens/resources/AppDetail.js +810 -0
  368. package/dist/tui/screens/resources/AppDetail.js.map +1 -0
  369. package/dist/tui/screens/resources/FunctionDetail.d.ts +7 -0
  370. package/dist/tui/screens/resources/FunctionDetail.js +751 -0
  371. package/dist/tui/screens/resources/FunctionDetail.js.map +1 -0
  372. package/dist/ui/attach.d.ts +15 -0
  373. package/dist/ui/attach.js +63 -0
  374. package/dist/ui/attach.js.map +1 -0
  375. package/dist/ui/baremetal-resolve.d.ts +10 -0
  376. package/dist/ui/baremetal-resolve.js +50 -0
  377. package/dist/ui/baremetal-resolve.js.map +1 -0
  378. package/dist/ui/confirm.js +1 -1
  379. package/dist/ui/confirm.js.map +1 -1
  380. package/dist/ui/cycle.d.ts +66 -0
  381. package/dist/ui/cycle.js +96 -0
  382. package/dist/ui/cycle.js.map +1 -0
  383. package/dist/ui/deploy-ui.d.ts +75 -0
  384. package/dist/ui/deploy-ui.js +243 -0
  385. package/dist/ui/deploy-ui.js.map +1 -0
  386. package/dist/ui/order-result.d.ts +4 -0
  387. package/dist/ui/order-result.js +32 -0
  388. package/dist/ui/order-result.js.map +1 -0
  389. package/dist/ui/payment-gate.d.ts +26 -0
  390. package/dist/ui/payment-gate.js +70 -0
  391. package/dist/ui/payment-gate.js.map +1 -0
  392. package/dist/ui/payment.js +10 -3
  393. package/dist/ui/payment.js.map +1 -1
  394. package/dist/ui/portal.d.ts +1 -1
  395. package/dist/ui/portal.js +7 -2
  396. package/dist/ui/portal.js.map +1 -1
  397. package/dist/ui/project-resolve.d.ts +25 -0
  398. package/dist/ui/project-resolve.js +31 -0
  399. package/dist/ui/project-resolve.js.map +1 -0
  400. package/dist/ui/render-mode.d.ts +5 -0
  401. package/dist/ui/render-mode.js +1 -1
  402. package/dist/ui/render-mode.js.map +1 -1
  403. package/dist/ui/resource-detail.js +0 -3
  404. package/dist/ui/resource-detail.js.map +1 -1
  405. package/dist/ui/resource-resolve.d.ts +9 -2
  406. package/dist/ui/resource-resolve.js +11 -4
  407. package/dist/ui/resource-resolve.js.map +1 -1
  408. package/dist/ui/spinner.d.ts +10 -1
  409. package/dist/ui/spinner.js +12 -3
  410. package/dist/ui/spinner.js.map +1 -1
  411. package/dist/ui/table.d.ts +7 -0
  412. package/dist/ui/table.js +11 -0
  413. package/dist/ui/table.js.map +1 -1
  414. package/dist/ui/tax.d.ts +10 -0
  415. package/dist/ui/tax.js +31 -0
  416. package/dist/ui/tax.js.map +1 -0
  417. package/dist/ui/ticket-resolve.d.ts +9 -1
  418. package/dist/ui/ticket-resolve.js +13 -2
  419. package/dist/ui/ticket-resolve.js.map +1 -1
  420. package/dist/ui/volume-resolve.js +4 -1
  421. package/dist/ui/volume-resolve.js.map +1 -1
  422. package/dist/ui/wait.d.ts +4 -0
  423. package/dist/ui/wait.js +7 -2
  424. package/dist/ui/wait.js.map +1 -1
  425. package/dist/ui/wizard.d.ts +2 -1
  426. package/dist/ui/wizard.js +1 -1
  427. package/dist/ui/wizard.js.map +1 -1
  428. package/dist/version-check-bin.js +2 -2
  429. package/dist/version-check-bin.js.map +1 -1
  430. package/dist/version-check.d.ts +5 -0
  431. package/dist/version-check.js +6 -1
  432. package/dist/version-check.js.map +1 -1
  433. package/package.json +53 -6
@@ -0,0 +1,810 @@
1
+ import React, { useCallback, useEffect, useMemo, useState } from "react";
2
+ import { Box, Text, useInput } from "ink";
3
+ import { Spinner } from "../../components/Spinner.js";
4
+ import { InputBar } from "../../components/InputBar.js";
5
+ import { ConfirmModal } from "../../components/ConfirmModal.js";
6
+ import { Sparkline } from "../../components/Sparkline.js";
7
+ import { useApi } from "../../hooks/useApi.js";
8
+ import { useRouter } from "../../router.js";
9
+ import { colors, statusColor } from "../../theme/colors.js";
10
+ import { glyphs } from "../../theme/glyphs.js";
11
+ import { deployPresetRef } from "../deployPreset.js";
12
+ import { parseTimeBound, fmtClock, fmtWhen } from "../../../apps-support/time.js";
13
+ const TABS = [
14
+ { key: "overview", label: "Overview", hotkey: "1" },
15
+ { key: "logs", label: "Logs", hotkey: "2" },
16
+ { key: "deployments", label: "Deployments", hotkey: "3" },
17
+ { key: "metrics", label: "Metrics", hotkey: "4" },
18
+ { key: "env", label: "Env", hotkey: "5" },
19
+ { key: "settings", label: "Settings", hotkey: "6" },
20
+ ];
21
+ export function AppDetailView({ app: initial, onClose, onLock, }) {
22
+ const [tab, setTab] = useState("overview");
23
+ const [app, setApp] = useState(initial);
24
+ // A tab that is mid-prompt or mid-modal owns the keyboard; the tab bar
25
+ // and Esc-to-close step aside until it releases.
26
+ const [busy, setBusy] = useState(false);
27
+ useEffect(() => {
28
+ onLock(true);
29
+ return () => onLock(false);
30
+ }, [onLock]);
31
+ useInput((input, key) => {
32
+ if (busy)
33
+ return;
34
+ if (key.escape) {
35
+ onClose();
36
+ return;
37
+ }
38
+ const hit = TABS.find((t) => t.hotkey === input);
39
+ if (hit) {
40
+ setTab(hit.key);
41
+ return;
42
+ }
43
+ if (input === "]" || key.rightArrow) {
44
+ setTab((t) => TABS[(TABS.findIndex((x) => x.key === t) + 1) % TABS.length].key);
45
+ }
46
+ else if (input === "[" || key.leftArrow) {
47
+ setTab((t) => TABS[(TABS.findIndex((x) => x.key === t) - 1 + TABS.length) % TABS.length].key);
48
+ }
49
+ }, { isActive: true });
50
+ return (React.createElement(Box, { flexDirection: "column", width: "100%" },
51
+ React.createElement(Box, { marginBottom: 1 }, TABS.map((t, i) => (React.createElement(Box, { key: t.key, marginRight: i === TABS.length - 1 ? 0 : 2 },
52
+ React.createElement(Text, { color: t.key === tab ? colors.accent : colors.dim, bold: t.key === tab },
53
+ t.hotkey,
54
+ " ",
55
+ t.label))))),
56
+ tab === "overview" && React.createElement(OverviewTab, { app: app, onApp: setApp }),
57
+ tab === "logs" && React.createElement(LogsTab, { app: app, onBusy: setBusy }),
58
+ tab === "deployments" && React.createElement(DeploymentsTab, { app: app, onBusy: setBusy }),
59
+ tab === "metrics" && React.createElement(MetricsTab, { app: app }),
60
+ tab === "env" && React.createElement(EnvTab, { app: app, onBusy: setBusy }),
61
+ tab === "settings" && React.createElement(SettingsTab, { app: app, onBusy: setBusy })));
62
+ }
63
+ // ─── Overview ────────────────────────────────────────────────────────────────
64
+ function OverviewTab({ app, onApp }) {
65
+ const api = useApi();
66
+ const { navigate } = useRouter();
67
+ const [health, setHealth] = useState(null);
68
+ const [tick, setTick] = useState(0);
69
+ useEffect(() => {
70
+ let cancelled = false;
71
+ api.apps.get(app.id).then((a) => !cancelled && onApp(a)).catch(() => { });
72
+ api.apps.health(app.id).then((h) => !cancelled && setHealth(h)).catch(() => setHealth(null));
73
+ return () => {
74
+ cancelled = true;
75
+ };
76
+ // eslint-disable-next-line react-hooks/exhaustive-deps
77
+ }, [api, app.id, tick]);
78
+ useInput((input) => {
79
+ if (input === "r")
80
+ setTick((t) => t + 1);
81
+ else if (input === "d") {
82
+ deployPresetRef.current = { appId: app.id };
83
+ navigate("deploy");
84
+ }
85
+ });
86
+ return (React.createElement(Box, { flexDirection: "column" },
87
+ React.createElement(DetailRow, { label: "Id", value: app.id }),
88
+ React.createElement(DetailRow, { label: "Status", value: React.createElement(Text, { color: statusColor(app.status) ?? colors.text }, app.status) }),
89
+ React.createElement(DetailRow, { label: "URL", value: `https://${app.hostname}` }),
90
+ React.createElement(DetailRow, { label: "Plan", value: `${app.planTier} · ${app.replicas} replica${app.replicas === 1 ? "" : "s"}` }),
91
+ React.createElement(DetailRow, { label: "Region", value: app.region }),
92
+ React.createElement(DetailRow, { label: "Release", value: app.activeRelease ? `#${app.activeRelease}` : "none yet" }),
93
+ app.githubRepoFullName ? React.createElement(DetailRow, { label: "GitHub", value: app.githubRepoFullName }) : null,
94
+ React.createElement(DetailRow, { label: "Created", value: fmtWhen(app.createdAt) }),
95
+ React.createElement(DetailRow, { label: "Health", value: health === null ? (React.createElement(Text, { color: colors.dim }, "checking\u2026")) : (React.createElement(Text, { color: health.ok ? colors.success : colors.error },
96
+ health.ok ? "healthy" : "unhealthy",
97
+ health.status != null ? ` · HTTP ${health.status}` : "",
98
+ health.latencyMs != null ? ` · ${health.latencyMs} ms` : "",
99
+ health.detail ? ` · ${health.detail}` : "")) }),
100
+ React.createElement(Box, { marginTop: 1 },
101
+ React.createElement(Text, { color: colors.dim }, "d deploy a directory here \u00B7 r refresh \u00B7 1-6 or [ ] switch tabs \u00B7 Esc back"))));
102
+ }
103
+ // ─── Logs ────────────────────────────────────────────────────────────────────
104
+ const WINDOWS = ["15m", "1h", "6h", "24h", "72h", "168h"];
105
+ function LogsTab({ app, onBusy }) {
106
+ const api = useApi();
107
+ const [windowIdx, setWindowIdx] = useState(1);
108
+ const [from, setFrom] = useState(null);
109
+ const [until, setUntil] = useState(null);
110
+ const [search, setSearch] = useState("");
111
+ const [editing, setEditing] = useState(null);
112
+ const [draft, setDraft] = useState("");
113
+ const [promptError, setPromptError] = useState(null);
114
+ const [lines, setLines] = useState([]);
115
+ const [loading, setLoading] = useState(true);
116
+ const [error, setError] = useState(null);
117
+ const [offset, setOffset] = useState(0); // lines scrolled up from the tail
118
+ const [tick, setTick] = useState(0);
119
+ useEffect(() => {
120
+ onBusy(editing !== null);
121
+ }, [editing, onBusy]);
122
+ useEffect(() => {
123
+ let cancelled = false;
124
+ setLoading(true);
125
+ setError(null);
126
+ api.apps
127
+ .logHistory(app.id, {
128
+ since: WINDOWS[windowIdx],
129
+ from: from ?? undefined,
130
+ until: until ?? undefined,
131
+ limit: 2000,
132
+ })
133
+ .then((res) => {
134
+ if (cancelled)
135
+ return;
136
+ setLines(res.lines ?? res.entries ?? []);
137
+ setOffset(0);
138
+ })
139
+ .catch((e) => !cancelled && setError(e instanceof Error ? e.message : String(e)))
140
+ .finally(() => !cancelled && setLoading(false));
141
+ return () => {
142
+ cancelled = true;
143
+ };
144
+ }, [api, app.id, windowIdx, from, until, tick]);
145
+ const visibleLines = useMemo(() => {
146
+ const needle = search.trim().toLowerCase();
147
+ return needle ? lines.filter((l) => (l.message ?? "").toLowerCase().includes(needle)) : lines;
148
+ }, [lines, search]);
149
+ const rows = Math.max(6, (process.stdout.rows ?? 24) - 14);
150
+ const end = Math.max(0, visibleLines.length - offset);
151
+ const start = Math.max(0, end - rows);
152
+ const shown = visibleLines.slice(start, end);
153
+ useInput((input, key) => {
154
+ if (editing)
155
+ return;
156
+ if (input === "w") {
157
+ setFrom(null);
158
+ setUntil(null);
159
+ setWindowIdx((i) => (i + 1) % WINDOWS.length);
160
+ }
161
+ else if (input === "f") {
162
+ setDraft("");
163
+ setPromptError(null);
164
+ setEditing("from");
165
+ }
166
+ else if (input === "t") {
167
+ setDraft("");
168
+ setPromptError(null);
169
+ setEditing("until");
170
+ }
171
+ else if (input === "/") {
172
+ setDraft(search);
173
+ setEditing("search");
174
+ }
175
+ else if (input === "c") {
176
+ setFrom(null);
177
+ setUntil(null);
178
+ setSearch("");
179
+ }
180
+ else if (input === "r") {
181
+ setTick((t) => t + 1);
182
+ }
183
+ else if (key.upArrow || input === "k") {
184
+ setOffset((o) => Math.min(Math.max(0, visibleLines.length - rows), o + 1));
185
+ }
186
+ else if (key.downArrow || input === "j") {
187
+ setOffset((o) => Math.max(0, o - 1));
188
+ }
189
+ else if (key.pageUp) {
190
+ setOffset((o) => Math.min(Math.max(0, visibleLines.length - rows), o + rows));
191
+ }
192
+ else if (key.pageDown) {
193
+ setOffset((o) => Math.max(0, o - rows));
194
+ }
195
+ else if (input === "G") {
196
+ setOffset(0);
197
+ }
198
+ }, { isActive: true });
199
+ const windowLabel = from
200
+ ? `${fmtWhen(from)} → ${until ? fmtWhen(until) : "now"}`
201
+ : `last ${WINDOWS[windowIdx]}${until ? ` until ${fmtWhen(until)}` : ""}`;
202
+ const submitPrompt = (v) => {
203
+ if (editing === "search") {
204
+ setSearch(v);
205
+ setEditing(null);
206
+ return;
207
+ }
208
+ const text = v.trim();
209
+ if (!text) {
210
+ if (editing === "from")
211
+ setFrom(null);
212
+ else
213
+ setUntil(null);
214
+ setEditing(null);
215
+ return;
216
+ }
217
+ const d = parseTimeBound(text);
218
+ if (!d) {
219
+ setPromptError("Not a timestamp (2026-09-12 16:00) or an age (90m, 2h, 3d).");
220
+ return;
221
+ }
222
+ if (editing === "from") {
223
+ if (until && d >= new Date(until)) {
224
+ setPromptError("from must be before until.");
225
+ return;
226
+ }
227
+ setFrom(d.toISOString());
228
+ }
229
+ else {
230
+ if (from && d <= new Date(from)) {
231
+ setPromptError("until must be after from.");
232
+ return;
233
+ }
234
+ setUntil(d.toISOString());
235
+ }
236
+ setEditing(null);
237
+ };
238
+ return (React.createElement(Box, { flexDirection: "column" },
239
+ React.createElement(Box, null,
240
+ React.createElement(Text, { color: colors.dim }, "Window "),
241
+ React.createElement(Text, { color: colors.text }, windowLabel),
242
+ search ? (React.createElement(Text, { color: colors.dim },
243
+ " · filter ",
244
+ React.createElement(Text, { color: colors.text }, search))) : null,
245
+ React.createElement(Text, { color: colors.dim }, ` · ${visibleLines.length} line${visibleLines.length === 1 ? "" : "s"}`)),
246
+ React.createElement(Box, { marginTop: 1, flexDirection: "column" },
247
+ loading ? (React.createElement(Spinner, { label: "Fetching logs\u2026" })) : error ? (React.createElement(Text, { color: colors.error },
248
+ "Error: ",
249
+ error)) : shown.length === 0 ? (React.createElement(Text, { color: colors.dim }, "No log lines in this window.")) : (shown.map((l, i) => (React.createElement(Box, { key: `${l.ts ?? ""}-${start + i}` },
250
+ React.createElement(Text, { color: colors.dim }, fmtClock(l.ts).padEnd(9)),
251
+ l.build ? React.createElement(Text, { color: colors.dim }, `${l.build} `) : null,
252
+ React.createElement(Text, { color: levelColor(l.level), wrap: "truncate-end" }, l.message ?? ""))))),
253
+ !loading && offset > 0 ? React.createElement(Text, { color: colors.dim }, `… ${offset} newer line${offset === 1 ? "" : "s"} below (G to jump to the end)`) : null),
254
+ React.createElement(Box, { marginTop: 1, flexDirection: "column" }, editing ? (React.createElement(Box, { flexDirection: "column" },
255
+ React.createElement(Text, { color: colors.dim }, editing === "from"
256
+ ? "From — a timestamp (2026-09-12 16:00) or an age (2h, 3d). Empty clears it."
257
+ : editing === "until"
258
+ ? "Until — a timestamp or an age (30m). Empty = now."
259
+ : "Filter — substring to match, case-insensitive. Empty clears it."),
260
+ promptError ? React.createElement(Text, { color: colors.error }, promptError) : null,
261
+ React.createElement(InputBar, { value: draft, onChange: setDraft, onSubmit: submitPrompt, focused: true, placeholder: editing === "search" ? "error" : "2h" }),
262
+ React.createElement(Text, { color: colors.dim }, "Enter to apply \u00B7 Esc to cancel"))) : (React.createElement(Text, { color: colors.dim }, "w window \u00B7 f from \u00B7 t until \u00B7 / filter \u00B7 c clear \u00B7 r refresh \u00B7 \u2191\u2193 PgUp PgDn scroll \u00B7 G end"))),
263
+ React.createElement(EscListener, { active: editing !== null, onEscape: () => setEditing(null) })));
264
+ }
265
+ function levelColor(level) {
266
+ const l = (level ?? "").toLowerCase();
267
+ if (l === "error" || l === "fatal")
268
+ return colors.error;
269
+ if (l === "warn" || l === "warning")
270
+ return colors.warning;
271
+ return colors.text;
272
+ }
273
+ /** Esc inside a text prompt: ink-text-input does not consume it, so the
274
+ * owning tab listens while a prompt is open. */
275
+ function EscListener({ active, onEscape }) {
276
+ useInput((_input, key) => {
277
+ if (key.escape)
278
+ onEscape();
279
+ }, { isActive: active });
280
+ return null;
281
+ }
282
+ // ─── Deployments ─────────────────────────────────────────────────────────────
283
+ function DeploymentsTab({ app, onBusy }) {
284
+ const api = useApi();
285
+ const [releases, setReleases] = useState(null);
286
+ const [error, setError] = useState(null);
287
+ const [cursor, setCursor] = useState(0);
288
+ const [open, setOpen] = useState(null);
289
+ const [build, setBuild] = useState(null);
290
+ const [confirm, setConfirm] = useState(null);
291
+ const [notice, setNotice] = useState(null);
292
+ const [tick, setTick] = useState(0);
293
+ useEffect(() => {
294
+ onBusy(confirm !== null);
295
+ }, [confirm, onBusy]);
296
+ useEffect(() => {
297
+ let cancelled = false;
298
+ api.apps
299
+ .releases(app.id)
300
+ .then((rs) => {
301
+ if (cancelled)
302
+ return;
303
+ setReleases([...rs].sort((a, b) => b.number - a.number));
304
+ setError(null);
305
+ })
306
+ .catch((e) => !cancelled && setError(e instanceof Error ? e.message : String(e)));
307
+ return () => {
308
+ cancelled = true;
309
+ };
310
+ }, [api, app.id, tick]);
311
+ useEffect(() => {
312
+ if (!open?.buildId) {
313
+ setBuild(null);
314
+ return;
315
+ }
316
+ let cancelled = false;
317
+ api.apps.buildDetail(app.id, open.buildId).then((b) => !cancelled && setBuild(b)).catch(() => { });
318
+ return () => {
319
+ cancelled = true;
320
+ };
321
+ }, [api, app.id, open]);
322
+ const rows = releases ?? [];
323
+ const selected = rows[cursor];
324
+ useInput((input, key) => {
325
+ if (confirm)
326
+ return;
327
+ if (open) {
328
+ if (key.escape || key.leftArrow)
329
+ setOpen(null);
330
+ else if (input === "b" && !open.isCurrent)
331
+ setConfirm(open);
332
+ return;
333
+ }
334
+ if (key.upArrow || input === "k")
335
+ setCursor((c) => Math.max(0, c - 1));
336
+ else if (key.downArrow || input === "j")
337
+ setCursor((c) => Math.min(rows.length - 1, c + 1));
338
+ else if (key.return && selected)
339
+ setOpen(selected);
340
+ else if (input === "b" && selected && !selected.isCurrent)
341
+ setConfirm(selected);
342
+ else if (input === "r")
343
+ setTick((t) => t + 1);
344
+ }, { isActive: true });
345
+ const rollback = useCallback(async (r) => {
346
+ setNotice({ text: `Rolling back to #${r.number}…`, color: colors.warning });
347
+ try {
348
+ await api.apps.rollback(app.id, r.number);
349
+ setNotice({ text: `Rollback to #${r.number} started — a new release with that image is rolling out.`, color: colors.success });
350
+ setOpen(null);
351
+ setTick((t) => t + 1);
352
+ }
353
+ catch (e) {
354
+ setNotice({ text: e instanceof Error ? e.message : String(e), color: colors.error });
355
+ }
356
+ }, [api, app.id]);
357
+ if (confirm) {
358
+ return (React.createElement(ConfirmModal, { title: `Roll ${app.slug} back to release #${confirm.number}?`, hint: "Re-deploys that release's image as a new release. The current release stays in history.", onConfirm: () => {
359
+ const r = confirm;
360
+ setConfirm(null);
361
+ void rollback(r);
362
+ }, onCancel: () => setConfirm(null) }));
363
+ }
364
+ if (open) {
365
+ return (React.createElement(Box, { flexDirection: "column" },
366
+ React.createElement(DetailRow, { label: "Release", value: `#${open.number}${open.isCurrent ? " (current)" : ""}` }),
367
+ React.createElement(DetailRow, { label: "Status", value: React.createElement(Text, { color: statusColor(open.status) ?? colors.text }, open.status) }),
368
+ React.createElement(DetailRow, { label: "Deployed", value: fmtWhen(open.deployedAt) }),
369
+ React.createElement(DetailRow, { label: "Image", value: open.imageDigest.slice(0, 24) }),
370
+ open.commitSha ? React.createElement(DetailRow, { label: "Commit", value: `${open.commitSha.slice(0, 7)}${open.commitMessage ? ` ${open.commitMessage}` : ""}` }) : null,
371
+ build ? (React.createElement(Box, { marginTop: 1, flexDirection: "column" },
372
+ React.createElement(Text, { color: colors.dim, bold: true },
373
+ "Build ",
374
+ build.id.slice(0, 8),
375
+ " \u00B7 ",
376
+ build.frontend,
377
+ " \u00B7 ",
378
+ build.status,
379
+ build.cacheHit ? " · cache hit" : ""),
380
+ (build.steps ?? []).map((s) => (React.createElement(Box, { key: s.id },
381
+ React.createElement(Box, { width: 3 },
382
+ React.createElement(Text, { color: statusColor(s.status) ?? colors.dim }, s.status === "succeeded" ? glyphs.check : s.status === "failed" ? "✗" : "·")),
383
+ React.createElement(Box, { width: 28 },
384
+ React.createElement(Text, { color: colors.text }, s.label)),
385
+ React.createElement(Text, { color: colors.dim }, s.durationMs != null ? `${(s.durationMs / 1000).toFixed(1)}s` : s.status)))))) : open.buildId ? (React.createElement(Box, { marginTop: 1 },
386
+ React.createElement(Spinner, { label: "Loading build\u2026" }))) : (React.createElement(Box, { marginTop: 1 },
387
+ React.createElement(Text, { color: colors.dim }, "No source build (image deploy or rollback)."))),
388
+ notice ? (React.createElement(Box, { marginTop: 1 },
389
+ React.createElement(Text, { color: notice.color }, notice.text))) : null,
390
+ React.createElement(Box, { marginTop: 1 },
391
+ React.createElement(Text, { color: colors.dim }, open.isCurrent ? "Esc back" : "b roll back to this release · Esc back"))));
392
+ }
393
+ return (React.createElement(Box, { flexDirection: "column" },
394
+ releases === null ? (React.createElement(Spinner, { label: "Loading deployments\u2026" })) : error ? (React.createElement(Text, { color: colors.error },
395
+ "Error: ",
396
+ error)) : rows.length === 0 ? (React.createElement(Text, { color: colors.dim }, "No deployments yet \u2014 press d on Overview to deploy.")) : (rows.slice(0, Math.max(5, (process.stdout.rows ?? 24) - 14)).map((r, i) => {
397
+ const focused = i === cursor;
398
+ return (React.createElement(Box, { key: r.id },
399
+ React.createElement(Text, { color: focused ? colors.accent : colors.dim }, focused ? `${glyphs.chevronRight} ` : " "),
400
+ React.createElement(Box, { width: 7 },
401
+ React.createElement(Text, { color: focused ? colors.accent : colors.text, bold: focused }, `#${r.number}`)),
402
+ React.createElement(Box, { width: 16 },
403
+ React.createElement(Text, { color: statusColor(r.status) ?? colors.dim }, r.status)),
404
+ React.createElement(Box, { width: 14 },
405
+ React.createElement(Text, { color: colors.dim }, fmtWhen(r.deployedAt))),
406
+ React.createElement(Text, { color: colors.dim, wrap: "truncate-end" },
407
+ r.isCurrent ? "current " : "",
408
+ r.commitSha ? `${r.commitSha.slice(0, 7)} ` : "",
409
+ r.commitMessage ?? "")));
410
+ })),
411
+ notice ? (React.createElement(Box, { marginTop: 1 },
412
+ React.createElement(Text, { color: notice.color }, notice.text))) : null,
413
+ React.createElement(Box, { marginTop: 1 },
414
+ React.createElement(Text, { color: colors.dim }, "\u2191\u2193 select \u00B7 Enter details \u00B7 b roll back to selected \u00B7 r refresh"))));
415
+ }
416
+ // ─── Metrics ─────────────────────────────────────────────────────────────────
417
+ const RANGES = ["15m", "1h", "6h", "24h"];
418
+ function MetricsTab({ app }) {
419
+ const api = useApi();
420
+ const [rangeIdx, setRangeIdx] = useState(1);
421
+ const [usage, setUsage] = useState(null);
422
+ const [error, setError] = useState(null);
423
+ const [tick, setTick] = useState(0);
424
+ useEffect(() => {
425
+ let cancelled = false;
426
+ const load = () => api.apps
427
+ .usage(app.id, { range: RANGES[rangeIdx] })
428
+ .then((u) => {
429
+ if (cancelled)
430
+ return;
431
+ setUsage(u);
432
+ setError(null);
433
+ })
434
+ .catch((e) => !cancelled && setError(e instanceof Error ? e.message : String(e)));
435
+ void load();
436
+ const id = setInterval(load, 15_000);
437
+ return () => {
438
+ cancelled = true;
439
+ clearInterval(id);
440
+ };
441
+ }, [api, app.id, rangeIdx, tick]);
442
+ useInput((input) => {
443
+ if (input === "w")
444
+ setRangeIdx((i) => (i + 1) % RANGES.length);
445
+ else if (input === "r")
446
+ setTick((t) => t + 1);
447
+ });
448
+ if (error)
449
+ return React.createElement(Text, { color: colors.error },
450
+ "Error: ",
451
+ error);
452
+ if (!usage)
453
+ return React.createElement(Spinner, { label: "Loading usage\u2026" });
454
+ const env = usage.envelope;
455
+ const cur = usage.current;
456
+ const cpuNow = cur?.cpu?.current ?? null;
457
+ const memNow = cur?.memory?.current ?? null;
458
+ const cpuPct = cpuNow !== null && env && env.cpuMillicores > 0 ? (cpuNow / env.cpuMillicores) * 100 : null;
459
+ const memPct = memNow !== null && env && env.memoryMib > 0 ? (memNow / (env.memoryMib * 1024 * 1024)) * 100 : null;
460
+ const cpuSeries = seriesOf(usage, "cpu");
461
+ const memSeries = seriesOf(usage, "memory");
462
+ const rx = cur?.networkRx?.current ?? null;
463
+ const tx = cur?.networkTx?.current ?? null;
464
+ return (React.createElement(Box, { flexDirection: "column" },
465
+ React.createElement(Box, null,
466
+ React.createElement(Text, { color: colors.dim }, "Window "),
467
+ React.createElement(Text, { color: colors.text }, RANGES[rangeIdx]),
468
+ React.createElement(Text, { color: colors.dim }, cur ? " · live" : " · latest snapshot (orchestrator unreachable)")),
469
+ React.createElement(Box, { marginTop: 1, flexDirection: "column" },
470
+ React.createElement(UsageRow, { label: "CPU", pct: cpuPct, rightText: cpuNow !== null ? `${(cpuNow / 1000).toFixed(2)}${env ? ` / ${(env.cpuMillicores / 1000).toFixed(2)}` : ""} cores` : undefined }),
471
+ React.createElement(UsageRow, { label: "RAM", pct: memPct, rightText: memNow !== null ? `${Math.round(memNow / (1024 * 1024))}${env ? ` / ${env.memoryMib}` : ""} MB` : undefined }),
472
+ env?.bandwidthGbMonth != null || env?.bandwidthUsedGb != null ? (React.createElement(UsageRow, { label: "Net", pct: env.bandwidthGbMonth ? ((env.bandwidthUsedGb ?? 0) / env.bandwidthGbMonth) * 100 : null, rightText: `${(env.bandwidthUsedGb ?? 0).toFixed(2)} GB${env.bandwidthGbMonth != null ? ` / ${env.bandwidthGbMonth} GB this period` : " this period"}` })) : null),
473
+ React.createElement(Box, { marginTop: 1, flexDirection: "column" },
474
+ React.createElement(Text, { color: colors.dim, bold: true }, "Over the window"),
475
+ React.createElement(Sparkline, { data: cpuSeries, width: 28, label: "cpu ", color: colors.accent }),
476
+ React.createElement(Sparkline, { data: memSeries, width: 28, label: "ram ", color: colors.accentSoft }),
477
+ rx !== null || tx !== null ? (React.createElement(Text, { color: colors.dim }, `net ↓ ${fmtRate(rx ?? 0)} ↑ ${fmtRate(tx ?? 0)}`)) : null),
478
+ React.createElement(Box, { marginTop: 1 },
479
+ React.createElement(Text, { color: colors.dim }, "w window \u00B7 r refresh \u00B7 refreshes every 15 s"))));
480
+ }
481
+ function seriesOf(usage, key) {
482
+ const live = usage.current?.[key]?.series?.map((p) => p.value) ?? [];
483
+ if (live.length)
484
+ return live;
485
+ return (usage.series ?? []).map((s) => s.payload?.[key]?.current ?? 0);
486
+ }
487
+ function fmtRate(bytesPerSec) {
488
+ if (bytesPerSec < 1024)
489
+ return `${bytesPerSec.toFixed(0)} B/s`;
490
+ if (bytesPerSec < 1024 * 1024)
491
+ return `${(bytesPerSec / 1024).toFixed(1)} KB/s`;
492
+ return `${(bytesPerSec / (1024 * 1024)).toFixed(2)} MB/s`;
493
+ }
494
+ // ─── Env ─────────────────────────────────────────────────────────────────────
495
+ function EnvTab({ app, onBusy }) {
496
+ const api = useApi();
497
+ const [vars, setVars] = useState(null);
498
+ const [error, setError] = useState(null);
499
+ const [cursor, setCursor] = useState(0);
500
+ const [editing, setEditing] = useState(null);
501
+ const [draft, setDraft] = useState("");
502
+ const [promptError, setPromptError] = useState(null);
503
+ const [revealed, setRevealed] = useState({});
504
+ const [confirmDelete, setConfirmDelete] = useState(null);
505
+ const [notice, setNotice] = useState(null);
506
+ const [tick, setTick] = useState(0);
507
+ useEffect(() => {
508
+ onBusy(editing !== null || confirmDelete !== null);
509
+ }, [editing, confirmDelete, onBusy]);
510
+ useEffect(() => {
511
+ let cancelled = false;
512
+ api.apps
513
+ .env(app.id)
514
+ .then((vs) => {
515
+ if (cancelled)
516
+ return;
517
+ setVars([...vs].sort((a, b) => a.key.localeCompare(b.key)));
518
+ setError(null);
519
+ })
520
+ .catch((e) => !cancelled && setError(e instanceof Error ? e.message : String(e)));
521
+ return () => {
522
+ cancelled = true;
523
+ };
524
+ }, [api, app.id, tick]);
525
+ const rows = vars ?? [];
526
+ const selected = rows[cursor];
527
+ useInput((input, key) => {
528
+ if (editing || confirmDelete)
529
+ return;
530
+ if (key.upArrow || input === "k")
531
+ setCursor((c) => Math.max(0, c - 1));
532
+ else if (key.downArrow || input === "j")
533
+ setCursor((c) => Math.min(rows.length - 1, c + 1));
534
+ else if (input === "a") {
535
+ setDraft("");
536
+ setPromptError(null);
537
+ setEditing("add");
538
+ }
539
+ else if ((input === "e" || key.return) && selected) {
540
+ setDraft("");
541
+ setPromptError(null);
542
+ setEditing("edit");
543
+ }
544
+ else if (input === "v" && selected) {
545
+ void reveal(selected);
546
+ }
547
+ else if (input === "x" && selected)
548
+ setConfirmDelete(selected);
549
+ else if (input === "r")
550
+ setTick((t) => t + 1);
551
+ }, { isActive: true });
552
+ const reveal = async (v) => {
553
+ if (revealed[v.key] !== undefined) {
554
+ setRevealed((r) => {
555
+ const next = { ...r };
556
+ delete next[v.key];
557
+ return next;
558
+ });
559
+ return;
560
+ }
561
+ try {
562
+ const out = await api.apps.revealEnv(app.id, v.key);
563
+ setRevealed((r) => ({ ...r, [v.key]: out.value }));
564
+ }
565
+ catch (e) {
566
+ setNotice({ text: e instanceof Error ? e.message : String(e), color: colors.error });
567
+ }
568
+ };
569
+ const submit = async (raw) => {
570
+ let key;
571
+ let value;
572
+ if (editing === "add") {
573
+ const eq = raw.indexOf("=");
574
+ if (eq <= 0) {
575
+ setPromptError("Type KEY=VALUE.");
576
+ return;
577
+ }
578
+ key = raw.slice(0, eq).trim();
579
+ value = raw.slice(eq + 1);
580
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {
581
+ setPromptError("Keys are letters, digits and underscores, not starting with a digit.");
582
+ return;
583
+ }
584
+ }
585
+ else {
586
+ if (!selected)
587
+ return;
588
+ key = selected.key;
589
+ value = raw;
590
+ }
591
+ setEditing(null);
592
+ setNotice({ text: `Saving ${key}…`, color: colors.warning });
593
+ try {
594
+ await api.apps.setEnv(app.id, {
595
+ key,
596
+ value,
597
+ scope: editing === "edit" ? selected?.scope : undefined,
598
+ kind: editing === "edit" ? selected?.kind : undefined,
599
+ });
600
+ setNotice({ text: `Saved ${key}. Redeploy to apply it at runtime.`, color: colors.success });
601
+ setRevealed((r) => {
602
+ const next = { ...r };
603
+ delete next[key];
604
+ return next;
605
+ });
606
+ setTick((t) => t + 1);
607
+ }
608
+ catch (e) {
609
+ setNotice({ text: e instanceof Error ? e.message : String(e), color: colors.error });
610
+ }
611
+ };
612
+ const remove = async (v) => {
613
+ setNotice({ text: `Removing ${v.key}…`, color: colors.warning });
614
+ try {
615
+ await api.apps.deleteEnv(app.id, v.key);
616
+ setNotice({ text: `Removed ${v.key}.`, color: colors.success });
617
+ setCursor((c) => Math.max(0, c - 1));
618
+ setTick((t) => t + 1);
619
+ }
620
+ catch (e) {
621
+ setNotice({ text: e instanceof Error ? e.message : String(e), color: colors.error });
622
+ }
623
+ };
624
+ if (confirmDelete) {
625
+ return (React.createElement(ConfirmModal, { title: `Remove ${confirmDelete.key} from ${app.slug}?`, hint: "The value is gone for good; a redeploy no longer sees it.", onConfirm: () => {
626
+ const v = confirmDelete;
627
+ setConfirmDelete(null);
628
+ void remove(v);
629
+ }, onCancel: () => setConfirmDelete(null) }));
630
+ }
631
+ return (React.createElement(Box, { flexDirection: "column" },
632
+ vars === null ? (React.createElement(Spinner, { label: "Loading env\u2026" })) : error ? (React.createElement(Text, { color: colors.error },
633
+ "Error: ",
634
+ error)) : rows.length === 0 ? (React.createElement(Text, { color: colors.dim }, "No environment variables. Press a to add one.")) : (rows.map((v, i) => {
635
+ const focused = i === cursor;
636
+ const shown = revealed[v.key];
637
+ return (React.createElement(Box, { key: v.id, flexDirection: "column" },
638
+ React.createElement(Box, null,
639
+ React.createElement(Text, { color: focused ? colors.accent : colors.dim }, focused ? `${glyphs.chevronRight} ` : " "),
640
+ React.createElement(Box, { width: 28 },
641
+ React.createElement(Text, { color: focused ? colors.accent : colors.text, bold: focused, wrap: "truncate-end" }, v.key)),
642
+ React.createElement(Box, { width: 9 },
643
+ React.createElement(Text, { color: colors.dim }, v.scope)),
644
+ React.createElement(Box, { width: 8 },
645
+ React.createElement(Text, { color: colors.dim }, v.kind ?? "secret")),
646
+ React.createElement(Text, { color: colors.dim }, shown !== undefined ? `= ${shown}` : v.hasValue ? "••••••" : "(empty)"),
647
+ React.createElement(Text, { color: colors.dim }, ` ${fmtWhen(v.updatedAt)}`))));
648
+ })),
649
+ notice ? (React.createElement(Box, { marginTop: 1 },
650
+ React.createElement(Text, { color: notice.color }, notice.text))) : null,
651
+ React.createElement(Box, { marginTop: 1, flexDirection: "column" }, editing ? (React.createElement(Box, { flexDirection: "column" },
652
+ React.createElement(Text, { color: colors.dim }, editing === "add"
653
+ ? "New variable as KEY=VALUE (stored as a runtime secret; change scope or kind with `synteq app env add`)."
654
+ : `New value for ${selected?.key}.`),
655
+ promptError ? React.createElement(Text, { color: colors.error }, promptError) : null,
656
+ React.createElement(InputBar, { value: draft, onChange: setDraft, onSubmit: (v) => void submit(v), focused: true, placeholder: editing === "add" ? "DATABASE_URL=postgres://…" : "" }),
657
+ React.createElement(Text, { color: colors.dim }, "Enter to save \u00B7 Esc to cancel"))) : (React.createElement(Text, { color: colors.dim }, "a add \u00B7 e / Enter edit \u00B7 v reveal / hide \u00B7 x remove \u00B7 r refresh"))),
658
+ React.createElement(EscListener, { active: editing !== null, onEscape: () => setEditing(null) })));
659
+ }
660
+ const SETTING_FIELDS = [
661
+ { key: "rootDirectory", label: "Root directory", hint: "Subdirectory to build from (empty = repo root).", kind: "text" },
662
+ { key: "dockerfilePath", label: "Dockerfile path", hint: "Relative to the root directory.", kind: "text" },
663
+ { key: "buildContext", label: "Build context", hint: "Docker build context directory.", kind: "text" },
664
+ { key: "dockerCommand", label: "Start command", hint: "Overrides the container's start command.", kind: "text" },
665
+ { key: "preDeployCommand", label: "Pre-deploy command", hint: "Runs once before each deploy (migrations).", kind: "text" },
666
+ { key: "autoDeploy", label: "Auto-deploy", hint: "on_commit deploys every push; off deploys only by hand.", kind: "toggle" },
667
+ { key: "healthCheckPath", label: "Health check path", hint: "HTTP path polled to gate a deploy healthy (/healthz).", kind: "text" },
668
+ { key: "port", label: "Port", hint: "1-65535; empty lets the runtime detect it.", kind: "int" },
669
+ { key: "buildFilterIncluded", label: "Build paths (include)", hint: "Comma-separated; a push touching none of them skips the build.", kind: "list" },
670
+ { key: "buildFilterIgnored", label: "Build paths (ignore)", hint: "Comma-separated; pushes touching only these skip the build.", kind: "list" },
671
+ ];
672
+ function SettingsTab({ app, onBusy }) {
673
+ const api = useApi();
674
+ const [settings, setSettings] = useState(null);
675
+ const [error, setError] = useState(null);
676
+ const [cursor, setCursor] = useState(0);
677
+ const [editing, setEditing] = useState(false);
678
+ const [draft, setDraft] = useState("");
679
+ const [promptError, setPromptError] = useState(null);
680
+ const [notice, setNotice] = useState(null);
681
+ useEffect(() => {
682
+ onBusy(editing);
683
+ }, [editing, onBusy]);
684
+ useEffect(() => {
685
+ let cancelled = false;
686
+ api.apps
687
+ .settings(app.id)
688
+ .then((s) => !cancelled && setSettings(s))
689
+ .catch((e) => !cancelled && setError(e instanceof Error ? e.message : String(e)));
690
+ return () => {
691
+ cancelled = true;
692
+ };
693
+ }, [api, app.id]);
694
+ const field = SETTING_FIELDS[cursor];
695
+ const currentText = (key) => {
696
+ if (!settings)
697
+ return "";
698
+ const v = settings[key];
699
+ if (v == null)
700
+ return "";
701
+ if (Array.isArray(v))
702
+ return v.join(", ");
703
+ return String(v);
704
+ };
705
+ const save = useCallback(async (patch, label) => {
706
+ setNotice({ text: `Saving ${label}…`, color: colors.warning });
707
+ try {
708
+ const s = await api.apps.patchSettings(app.id, patch);
709
+ setSettings(s);
710
+ setNotice({ text: `Saved ${label}.`, color: colors.success });
711
+ }
712
+ catch (e) {
713
+ setNotice({ text: e instanceof Error ? e.message : String(e), color: colors.error });
714
+ }
715
+ }, [api, app.id]);
716
+ useInput((input, key) => {
717
+ if (editing || !settings)
718
+ return;
719
+ if (key.upArrow || input === "k")
720
+ setCursor((c) => Math.max(0, c - 1));
721
+ else if (key.downArrow || input === "j")
722
+ setCursor((c) => Math.min(SETTING_FIELDS.length - 1, c + 1));
723
+ else if (key.return || input === "e") {
724
+ if (field.kind === "toggle") {
725
+ const next = settings.autoDeploy === "off" ? "on_commit" : "off";
726
+ void save({ autoDeploy: next }, `${field.label} → ${next}`);
727
+ return;
728
+ }
729
+ setDraft(currentText(field.key));
730
+ setPromptError(null);
731
+ setEditing(true);
732
+ }
733
+ }, { isActive: true });
734
+ const submit = (raw) => {
735
+ const text = raw.trim();
736
+ const patch = {};
737
+ if (field.kind === "int") {
738
+ if (text === "")
739
+ patch.port = null;
740
+ else {
741
+ const n = Number(text);
742
+ if (!Number.isInteger(n) || n < 1 || n > 65535) {
743
+ setPromptError("Port must be a whole number 1-65535, or empty to clear it.");
744
+ return;
745
+ }
746
+ patch.port = n;
747
+ }
748
+ }
749
+ else if (field.kind === "list") {
750
+ const items = text ? text.split(",").map((s) => s.trim()).filter(Boolean) : [];
751
+ patch[field.key] = items.length ? items : null;
752
+ }
753
+ else {
754
+ patch[field.key] = text === "" ? null : text;
755
+ }
756
+ setEditing(false);
757
+ void save(patch, field.label);
758
+ };
759
+ if (error)
760
+ return React.createElement(Text, { color: colors.error },
761
+ "Error: ",
762
+ error);
763
+ if (!settings)
764
+ return React.createElement(Spinner, { label: "Loading settings\u2026" });
765
+ return (React.createElement(Box, { flexDirection: "column" },
766
+ SETTING_FIELDS.map((f, i) => {
767
+ const focused = i === cursor;
768
+ const text = currentText(f.key);
769
+ const placeholder = f.key === "port" ? `detect (${settings.effectivePort})` : f.key === "autoDeploy" ? "" : "—";
770
+ return (React.createElement(Box, { key: f.key },
771
+ React.createElement(Text, { color: focused ? colors.accent : colors.dim }, focused ? `${glyphs.chevronRight} ` : " "),
772
+ React.createElement(Box, { width: 24 },
773
+ React.createElement(Text, { color: focused ? colors.accent : colors.text, bold: focused }, f.label)),
774
+ React.createElement(Text, { color: text ? colors.text : colors.dim, wrap: "truncate-end" }, text || placeholder)));
775
+ }),
776
+ notice ? (React.createElement(Box, { marginTop: 1 },
777
+ React.createElement(Text, { color: notice.color }, notice.text))) : null,
778
+ React.createElement(Box, { marginTop: 1, flexDirection: "column" }, editing ? (React.createElement(Box, { flexDirection: "column" },
779
+ React.createElement(Text, { color: colors.dim },
780
+ field.label,
781
+ " \u2014 ",
782
+ field.hint,
783
+ " Empty clears it."),
784
+ promptError ? React.createElement(Text, { color: colors.error }, promptError) : null,
785
+ React.createElement(InputBar, { value: draft, onChange: setDraft, onSubmit: submit, focused: true }),
786
+ React.createElement(Text, { color: colors.dim }, "Enter to save \u00B7 Esc to cancel"))) : (React.createElement(Text, { color: colors.dim },
787
+ field.hint,
788
+ " · ",
789
+ field.kind === "toggle" ? "Enter toggles" : "Enter / e edits"))),
790
+ React.createElement(EscListener, { active: editing, onEscape: () => setEditing(false) })));
791
+ }
792
+ // ─── shared bits ─────────────────────────────────────────────────────────────
793
+ function DetailRow({ label, value }) {
794
+ return (React.createElement(Box, null,
795
+ React.createElement(Box, { width: 16 },
796
+ React.createElement(Text, { color: colors.dim }, label)),
797
+ typeof value === "string" ? React.createElement(Text, { color: colors.text }, value) : value));
798
+ }
799
+ function UsageRow({ label, pct, rightText }) {
800
+ const barWidth = 16;
801
+ const filled = pct !== null && Number.isFinite(pct) ? Math.min(barWidth, Math.max(0, Math.round((pct / 100) * barWidth))) : 0;
802
+ const bar = pct !== null ? "█".repeat(filled) + "░".repeat(barWidth - filled) : "─".repeat(barWidth);
803
+ const tone = pct === null ? colors.dim : pct >= 100 ? colors.error : pct >= 80 ? colors.warning : colors.accent;
804
+ return (React.createElement(Box, null,
805
+ React.createElement(Box, { width: 8 },
806
+ React.createElement(Text, { color: colors.dim }, label)),
807
+ React.createElement(Text, { color: tone }, bar),
808
+ rightText ? React.createElement(Text, { color: colors.dim }, ` ${rightText}`) : null));
809
+ }
810
+ //# sourceMappingURL=AppDetail.js.map