@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,616 @@
1
+ import { Args, Flags } from "@oclif/core";
2
+ import { existsSync, statSync } from "node:fs";
3
+ import { resolve, basename } from "node:path";
4
+ import { BaseCommand } from "../../base/command.js";
5
+ import { resolveLinkedFunction, notLinkedFunctionError } from "../../functions-support/link.js";
6
+ import FunctionInit from "./init.js";
7
+ import { slugify, pickTeamId, pickProjectId } from "../link.js";
8
+ import { makeClients } from "../../api/factory.js";
9
+ import { RUNTIMES } from "../../functions-support/runtime.js";
10
+ import { ensurePaymentMethod, PaymentMethodRequired } from "../../ui/payment-gate.js";
11
+ import { collectSourceFiles, tarballFromFiles, EDITOR_MAX_FILES, MAX_TOTAL_BYTES, SourceTooLargeError, SourceTooManyFilesError, } from "../../functions-support/source.js";
12
+ import { waitForBuild, waitForRelease, DeployTimeoutError } from "../../functions-support/poll.js";
13
+ import { inferRuntime } from "../../functions-support/runtime.js";
14
+ import { buildProgress, deployedCard, failedCard, deploymentUrl } from "../../ui/deploy-ui.js";
15
+ import { withSpinner } from "../../ui/spinner.js";
16
+ import { importDotenv, offerDotenv } from "../../apps-support/dotenv.js";
17
+ import { ApiError } from "../../api/errors.js";
18
+ import { portalUrl } from "../../ui/portal.js";
19
+ import { dim, ok, statusColor, G } from "../../ui/glyphs.js";
20
+ import { parseEnvAssignment } from "../../functions-support/env.js";
21
+ const ENV_KEY_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
22
+ import { normalizeSchedule, shortTriggerId } from "../../functions-support/cron.js";
23
+ import { isInteractive, confirmAction, pickFromCatalog, promptString } from "../../ui/wizard.js";
24
+ /** One-line function plan description: resources + the metered prices. */
25
+ function fnPlanLine(p) {
26
+ const cpu = p.cpuMillicores ? `${(p.cpuMillicores / 1000).toFixed(p.cpuMillicores % 1000 ? 1 : 0)} vCPU` : "";
27
+ const mem = p.memoryMib ? `${p.memoryMib} MiB` : "";
28
+ const inv = p.pricePerMillionInvocationsUsd != null ? `$${p.pricePerMillionInvocationsUsd}/M runs` : "";
29
+ const gbs = p.pricePerGbSecondUsd != null ? `$${p.pricePerGbSecondUsd}/GB·s` : "";
30
+ return [cpu, mem, inv, gbs].filter(Boolean).join(" · ");
31
+ }
32
+ /** Sentinel picker value for the "create a new function" row. */
33
+ const CREATE = "__create__";
34
+ /** Human wording for each reason collectSourceFiles reports a skip. */
35
+ const SKIP_REASON = {
36
+ binary: "binary file",
37
+ "too-large": "larger than the source limit on its own",
38
+ ignored: "excluded",
39
+ dotenv: "never packed — set variables with `synteq function env set`, `--env-file`, or the Environment tab",
40
+ symlink: "symlink (not followed)",
41
+ "bad-path": "path the backend won't accept",
42
+ };
43
+ /**
44
+ * `synteq function deploy` — upload this directory's source and roll it out,
45
+ * or roll out a pre-built image with `--image <ref>`.
46
+ *
47
+ * Backend: POST /functions/{id}/deploys/source — the files inline when the
48
+ * tree fits the editor's 32-file shape (so the portal editor can reopen it),
49
+ * else a gzipped tarball (`sourceB64`) bounded only by the function's source
50
+ * caps (`maxSourceBytes` / `maxSourceFiles` on the row). The server decides the build path (Dockerfile / bundle) itself and
51
+ * returns the build row. The deploy then has two phases the CLI follows: the
52
+ * BUILD reaches succeeded/failed, then the status cron mints a RELEASE and
53
+ * flips it current once the function is live. `--image` is the apps
54
+ * `deploy --image` route, function-owned (POST /functions/{id}/deploys): no
55
+ * source, a pull Build the same two phases follow.
56
+ */
57
+ export default class FunctionDeploy extends BaseCommand {
58
+ static apiKeyScope = "none";
59
+ static description = [
60
+ "Deploy a function from a local source directory or a pre-built image.",
61
+ "",
62
+ "Uploads the directory's text files (node_modules, .git, build output, .env",
63
+ "files and anything a .synteqignore excludes are left out), then follows the build",
64
+ "and the release it produces, printing each status transition. Ctrl-C stops",
65
+ "watching; the deploy keeps running server-side. `--image <ref>` skips the",
66
+ "upload: the platform pulls the image and rolls it out the same way.",
67
+ "",
68
+ "First run (an unlinked directory on a TTY): pick one of the project's",
69
+ "functions to link, or create one — name, plan, location, then optional env",
70
+ "vars and a cron trigger. --env/--secret/--cron do the same from the command",
71
+ "line, with --create, --name or a linked directory; they are applied before",
72
+ "the build starts, so the release carries them. If one of those fails, the",
73
+ "deploy stops before the build; whatever was already set stays set.",
74
+ "",
75
+ "On a function that already has a release, --env/--secret reach the server",
76
+ "before the build, and the server rolls env changes out after 120 s. A build",
77
+ "that takes longer can first mint an \"Environment change\" release of the",
78
+ "old image, then the new release: two releases, two restarts. The first",
79
+ "deploy of a new function is unaffected.",
80
+ ].join("\n");
81
+ static examples = [
82
+ "<%= config.bin %> function deploy # first run on a TTY: pick a function, or create one (name → plan → location → env → cron), then deploy",
83
+ "<%= config.bin %> function deploy --create my-fn --runtime node22 --plan nano --location dfw # scripted first run, no prompts",
84
+ '<%= config.bin %> function deploy --create my-fn --env LOG_LEVEL=info --secret API_KEY=sk-abc --cron "*/15 * * * *"',
85
+ "<%= config.bin %> function deploy # bare: this directory's linked function",
86
+ "<%= config.bin %> function deploy --name my-fn",
87
+ "<%= config.bin %> function deploy --name my-fn --dir ./api",
88
+ "<%= config.bin %> function deploy --env-file .env.production # import that file's variables onto the function first, no prompt",
89
+ "<%= config.bin %> function deploy --name my-fn --image docker.io/library/nginx:1.27-alpine # pre-built image, no upload",
90
+ "<%= config.bin %> function deploy --name my-fn --no-wait # fire-and-forget; returns the build row",
91
+ "<%= config.bin %> function deploy --name my-fn -o json",
92
+ ];
93
+ static args = {
94
+ target: Args.string({ required: false, description: "Function slug or id (optional; default: the directory's linked function or --name)." }),
95
+ };
96
+ static flags = {
97
+ name: Flags.string({
98
+ description: "Function slug (or uuid) to deploy (default: the function this directory is linked to via `synteq function init`).",
99
+ }),
100
+ create: Flags.string({
101
+ description: "Create a function with this name (or reuse one of that name), link this directory to it, and deploy — the scripted first run. Pair with --runtime, --plan and --location.",
102
+ }),
103
+ runtime: Flags.string({
104
+ options: [...RUNTIMES],
105
+ description: `Runtime for --create: ${RUNTIMES.join(" or ")} (default: what the directory's files imply, else node22).`,
106
+ }),
107
+ plan: Flags.string({
108
+ description: "Plan tier for --create (default: the first tier in the catalog).",
109
+ }),
110
+ location: Flags.string({
111
+ description: "Location code for --create, e.g. dfw (default: the first location).",
112
+ }),
113
+ project: Flags.string({
114
+ description: "Project id for --create, and the project whose functions the first-run picker lists (default: the active project).",
115
+ }),
116
+ dir: Flags.string({
117
+ description: "Directory to upload as the function's source (default: the current directory).",
118
+ }),
119
+ image: Flags.string({
120
+ description: "Pre-built image reference to roll out, registry host included (mutually exclusive with --dir; no source is uploaded).",
121
+ }),
122
+ "no-wait": Flags.boolean({
123
+ description: "Return as soon as the build is triggered; don't follow it to completion.",
124
+ }),
125
+ "poll-interval": Flags.integer({
126
+ default: 3,
127
+ description: "Seconds between build/release polls (default: 3, min: 2).",
128
+ }),
129
+ timeout: Flags.integer({
130
+ default: 600,
131
+ description: "Max seconds to wait for the build and release (default: 600).",
132
+ }),
133
+ env: Flags.string({
134
+ multiple: true,
135
+ description: "Config env var KEY=VALUE to set before the build (repeatable). Works with --create, --name or a linked directory.",
136
+ }),
137
+ secret: Flags.string({
138
+ multiple: true,
139
+ description: "Secret env var KEY=VALUE to set before the build (repeatable; reveal is masked). Works with --create, --name or a linked directory.",
140
+ }),
141
+ cron: Flags.string({
142
+ description: 'Cron trigger to add before the build: a quoted 5-field expression in UTC, e.g. "*/15 * * * *".',
143
+ }),
144
+ yes: Flags.boolean({
145
+ char: "y",
146
+ description: "Deploy without confirming when the directory looks like a different runtime than the function is configured for (non-interactive runs never pause).",
147
+ }),
148
+ "env-file": Flags.string({
149
+ description: "Import this .env's KEY=VALUE lines as variables on the function before the build (runtime secrets unless a `# scope=… kind=…` comment above a line says otherwise); no question asked. A .env is never packed, and a plain deploy never asks about it.",
150
+ }),
151
+ };
152
+ /** The argv `function init` runs with on a first deploy: --create's values
153
+ * verbatim, else what the user picks. Runtime comes from the directory's
154
+ * files when they say (init infers it too; passing it keeps the two in
155
+ * step when the user overrides). */
156
+ async firstRunArgs(dir, flags, interactive) {
157
+ let name = flags.create ? slugify(flags.create) : "";
158
+ let plan = flags.plan;
159
+ let location = flags.location;
160
+ const runtime = flags.runtime;
161
+ if (!flags.create) {
162
+ name = slugify(await promptString("Function name", {
163
+ default: slugify(basename(dir)),
164
+ validate: (s) => (slugify(s).length >= 1 ? true : "Give it a name."),
165
+ }));
166
+ }
167
+ if (interactive && !plan) {
168
+ const plans = await this.clients.api.functions.plans().catch(() => []);
169
+ if (plans.length > 1) {
170
+ const items = plans.map((p) => ({
171
+ value: p.name,
172
+ name: p.displayName ?? p.name,
173
+ description: fnPlanLine(p),
174
+ }));
175
+ plan = await pickFromCatalog("Plan", items, { defaultValue: plans[0].name });
176
+ }
177
+ }
178
+ if (interactive && !location) {
179
+ const locations = await this.clients.api.functions.locations().catch(() => []);
180
+ if (locations.length > 1) {
181
+ location = await pickFromCatalog("Primary location", locations.map((l) => ({ value: l.code, name: l.city, description: l.code })));
182
+ }
183
+ else if (locations.length === 1) {
184
+ this.log(dim(`Primary location: ${locations[0].city} (${locations[0].code})`));
185
+ }
186
+ }
187
+ const argv = [name, "--dir", dir, "--from-deploy"];
188
+ if (flags.image)
189
+ argv.push("--no-scaffold");
190
+ if (runtime)
191
+ argv.push("--runtime", runtime);
192
+ if (plan)
193
+ argv.push("--plan", plan);
194
+ if (location)
195
+ argv.push("--location", location);
196
+ if (flags.project)
197
+ argv.push("--project", flags.project);
198
+ if (this.outputFormat === "json")
199
+ argv.push("-o", "json");
200
+ return argv;
201
+ }
202
+ /** Step 0 of the first run — the apps `pickOrCreateApp` shape: link one of
203
+ * the project's functions, or null for "Create a new function…". No
204
+ * functions at all goes straight to create. */
205
+ async pickExistingFunction(projectId) {
206
+ const fns = await withSpinner("Loading functions", () => this.clients.api.functions.list(projectId));
207
+ if (fns.length === 0)
208
+ return null;
209
+ const items = [
210
+ ...fns.map((f) => ({
211
+ value: f.id,
212
+ name: f.slug,
213
+ description: `${f.status} · ${f.runtime} · ${f.region}`,
214
+ })),
215
+ {
216
+ value: CREATE,
217
+ name: "Create a new function…",
218
+ description: "Name, plan and location; optional env vars and a cron trigger.",
219
+ },
220
+ ];
221
+ const choice = await pickFromCatalog("Which function should this directory deploy?", items);
222
+ return choice === CREATE ? null : fns.find((f) => f.id === choice);
223
+ }
224
+ /** The two optional steps after location on a created function: env vars
225
+ * (the apps walkthrough's shape — confirm, then name → value → secret?
226
+ * until a blank name) and a cron trigger (blank for none). Each is
227
+ * skipped when its flags already answered it. */
228
+ async promptFirstRunExtras(dir, have) {
229
+ const env = [];
230
+ // A .env in the directory first — this is the one place it is offered.
231
+ // Scope is runtime (what applySetup saves); kind follows the file.
232
+ if (!have.env) {
233
+ const rows = await offerDotenv({ dir, target: "the new function", log: (l) => this.log(l) });
234
+ env.push(...rows.map((r) => ({ key: r.key, value: r.value, kind: r.kind ?? "secret" })));
235
+ }
236
+ if (!have.env && (await confirmAction(env.length ? "Add more variables?" : "Set environment variables now?"))) {
237
+ this.log(dim("Secrets are masked after saving; config values can be revealed in full."));
238
+ for (;;) {
239
+ const key = await promptString("Variable name (blank to finish)", {
240
+ allowEmpty: true,
241
+ validate: (s) => ENV_KEY_RE.test(s.trim()) ? true : "Letters, digits and underscores; can't start with a digit.",
242
+ });
243
+ if (!key.trim())
244
+ break;
245
+ const value = await promptString(`Value for ${key.trim()}`, { allowEmpty: true });
246
+ const secret = await confirmAction(`Is ${key.trim()} a secret?`, false);
247
+ env.push({ key: key.trim(), value, kind: secret ? "secret" : "config" });
248
+ }
249
+ }
250
+ let cron;
251
+ if (!have.cron) {
252
+ const raw = await promptString("Cron trigger (5-field UTC, blank for none)", {
253
+ allowEmpty: true,
254
+ validate: (s) => {
255
+ try {
256
+ normalizeSchedule(s);
257
+ return true;
258
+ }
259
+ catch (e) {
260
+ return e.message;
261
+ }
262
+ },
263
+ });
264
+ if (raw.trim())
265
+ cron = normalizeSchedule(raw);
266
+ }
267
+ return { env, cron };
268
+ }
269
+ /** Set the env vars (same call `function env set` makes) and add the cron
270
+ * trigger (same call `function cron add` makes) — before the build, so
271
+ * the release it produces carries them. */
272
+ async applySetup(fn, env, cron) {
273
+ const table = this.outputFormat === "table";
274
+ for (const v of env) {
275
+ const saved = await withSpinner(`Setting ${v.key}`, () => this.clients.api.functions.setEnv(fn.id, { key: v.key, value: v.value, kind: v.kind, scope: "runtime" }));
276
+ if (table)
277
+ this.log(ok(`Set ${saved.key} on ${fn.slug} ${dim(`(${saved.kind} · ${saved.scope})`)}`));
278
+ }
279
+ if (cron) {
280
+ // Idempotent: a scripted deploy re-run on every push (or a linked dir
281
+ // deployed with --cron again) must not stack a second trigger on the
282
+ // same schedule — the backend doesn't dedupe, so each copy would fire
283
+ // (and bill) every tick until the per-function cap 422s the deploy.
284
+ const existing = await this.clients.api.functions.cronTriggers(fn.id);
285
+ const same = existing.find((t) => t.schedule.trim().replace(/\s+/g, " ") === cron);
286
+ if (same) {
287
+ if (table) {
288
+ this.log(dim(`Cron ${cron} (UTC) is already scheduled on ${fn.slug} (trigger ${shortTriggerId(same.id)}).`));
289
+ }
290
+ return;
291
+ }
292
+ const trigger = await withSpinner("Adding cron trigger", () => this.clients.api.functions.createCronTrigger(fn.id, {
293
+ schedule: cron,
294
+ enabled: true,
295
+ retries: 0,
296
+ description: null,
297
+ }));
298
+ if (table) {
299
+ this.log(ok(`Added cron trigger ${shortTriggerId(trigger.id)} to ${fn.slug}: ${trigger.schedule} (UTC).`));
300
+ }
301
+ }
302
+ }
303
+ async run() {
304
+ await this.initClients();
305
+ const { args, flags: rawFlags } = await this.parse(FunctionDeploy);
306
+ const flags = { ...rawFlags, name: args.target ?? rawFlags.name };
307
+ try {
308
+ const dir = resolve(flags.dir && flags.dir !== "" ? flags.dir : ".");
309
+ if (!existsSync(dir) || !statSync(dir).isDirectory()) {
310
+ this.error(`Not a directory: ${dir}`, { exit: 1 });
311
+ }
312
+ if (flags.create && flags.name) {
313
+ this.error("Pass either --create <name> or --name <slug>, not both.", { exit: 1 });
314
+ }
315
+ if (flags.image && flags.dir) {
316
+ this.error("Pass either --image or --dir, not both.", { exit: 1 });
317
+ }
318
+ // --env / --secret / --cron are checked before anything is created, so
319
+ // a typo never leaves a half-set-up function behind.
320
+ let env = [];
321
+ let cron;
322
+ const parseFlag = (flag, raw, kind) => {
323
+ try {
324
+ return parseEnvAssignment(raw, kind);
325
+ }
326
+ catch (e) {
327
+ this.error(`--${flag}: ${e.message}`, { exit: 1 });
328
+ }
329
+ };
330
+ env = [
331
+ ...(flags.env ?? []).map((a) => parseFlag("env", a, "config")),
332
+ ...(flags.secret ?? []).map((a) => parseFlag("secret", a, "secret")),
333
+ ];
334
+ try {
335
+ cron = flags.cron !== undefined ? normalizeSchedule(flags.cron) : undefined;
336
+ }
337
+ catch (e) {
338
+ this.error(`--cron: ${e.message}`, { exit: 1 });
339
+ }
340
+ // First run: nothing linked and no --name. On a TTY, pick one of the
341
+ // project's functions to link, or set a new one up right here (name →
342
+ // plan → location → env → cron; runtime from the files) and carry on
343
+ // into the deploy — one command. --create is the same thing with every
344
+ // answer on the command line, so scripts never prompt.
345
+ const interactive = isInteractive() && this.outputFormat === "table";
346
+ const linked = this.clients.config.linkFor(dir);
347
+ const firstRun = !flags.create && !flags.name && !linked && interactive;
348
+ let existing = null;
349
+ let teamId;
350
+ if (firstRun) {
351
+ this.log(dim("No function is linked to this directory yet — set it up, then the deploy runs."));
352
+ // Team → project → function, as `synteq deploy` asks for an app.
353
+ const log = (l) => this.log(l);
354
+ teamId = await pickTeamId(this.clients, log);
355
+ this.clients = { ...makeClients(teamId, { insecure: flags.insecure }), authMode: this.clients.authMode, apiKeyScopes: this.clients.apiKeyScopes };
356
+ flags.project = flags.project ?? (await pickProjectId(this.clients, log));
357
+ existing = await this.pickExistingFunction(flags.project);
358
+ }
359
+ const teamArgv = teamId ? ["--team", teamId] : [];
360
+ if (existing) {
361
+ // Link it exactly as `function init <slug>` would (init reuses an
362
+ // existing function and writes the same link record) — no scaffold:
363
+ // this directory's files are what gets deployed.
364
+ const argv = [existing.id, "--dir", dir, "--from-deploy", "--no-scaffold", ...teamArgv];
365
+ if (flags.project)
366
+ argv.push("--project", flags.project);
367
+ await FunctionInit.run(argv, this.config);
368
+ this.clients.config.reload();
369
+ this.log("");
370
+ }
371
+ else if (flags.create || firstRun) {
372
+ const argv = await this.firstRunArgs(dir, flags, interactive);
373
+ if (firstRun) {
374
+ const extras = await this.promptFirstRunExtras(dir, {
375
+ env: env.length > 0,
376
+ cron: cron !== undefined,
377
+ });
378
+ env = [...env, ...extras.env];
379
+ cron = cron ?? extras.cron;
380
+ }
381
+ await FunctionInit.run([...argv, ...teamArgv], this.config);
382
+ // init wrote the link through its own ConfigStore; pick it up here.
383
+ this.clients.config.reload();
384
+ if (interactive)
385
+ this.log("");
386
+ }
387
+ const { fn, clients } = await resolveLinkedFunction(this.clients, flags, dir).catch((e) => {
388
+ if (e instanceof Error && !("status" in e)) {
389
+ this.error(flags.create || interactive ? e.message : notLinkedFunctionError("--name <slug>, or --create <name>"), { exit: 1 });
390
+ }
391
+ throw e;
392
+ });
393
+ this.clients = clients;
394
+ // Every deploy needs a payment method on the team, free tier included.
395
+ // (A just-created function was gated at create; this is the cheap
396
+ // re-check for a directory linked long ago.)
397
+ await ensurePaymentMethod({
398
+ api: this.clients.api,
399
+ apiBaseUrl: this.clients.config.get().api_base_url,
400
+ interactive,
401
+ log: (l) => this.log(l),
402
+ }).catch((e) => {
403
+ if (e instanceof PaymentMethodRequired)
404
+ this.error(e.message, { exit: 1 });
405
+ throw e;
406
+ });
407
+ // --image: no tree to collect or check; the env/cron setup and the
408
+ // follow below are the same as for a source deploy.
409
+ if (flags.image) {
410
+ await this.applySetup(fn, env, cron);
411
+ const build = await withSpinner("Triggering deploy", () => this.clients.api.functions.deployImage(fn.id, flags.image));
412
+ await this.follow(fn, build, [], flags);
413
+ return;
414
+ }
415
+ // 1. Collect the tree against the backend's LIVE caps (the row carries
416
+ // them; older backends don't, and the collector's fallbacks are the
417
+ // backend's defaults). A too-large tree is a user error with a
418
+ // message that already names the offenders.
419
+ let collected;
420
+ try {
421
+ collected = await withSpinner("Collecting source", () => collectSourceFiles(dir, {
422
+ maxTotalBytes: fn.maxSourceBytes ?? undefined,
423
+ maxFiles: fn.maxSourceFiles ?? undefined,
424
+ }));
425
+ }
426
+ catch (e) {
427
+ if (e instanceof SourceTooLargeError || e instanceof SourceTooManyFilesError) {
428
+ this.error(e.message, { exit: 1 });
429
+ }
430
+ throw e;
431
+ }
432
+ if (collected.files.length === 0) {
433
+ this.error(`No deployable files in ${dir}. Add a handler (\`synteq function init ${fn.slug}\` writes one).`, { exit: 1 });
434
+ }
435
+ // A skipped file is reported in EVERY output mode. In JSON mode the
436
+ // lines go to stderr so the JSON body stays parseable, and the body
437
+ // itself carries `skipped` (below) — a 6 MB data.json silently left out
438
+ // of a deploy is exactly the surprise -o json callers cannot see
439
+ // otherwise (2026-09-25).
440
+ const skipLines = collected.skipped.map((s) => `skipped ${s.path} — ${SKIP_REASON[s.reason] ?? s.reason}`);
441
+ if (this.outputFormat === "table") {
442
+ for (const line of skipLines)
443
+ this.log(dim(` ${line}`));
444
+ this.log(dim(`Uploading ${collected.files.length} file${collected.files.length === 1 ? "" : "s"} (${(collected.totalBytes / 1024).toFixed(0)} KiB) to ${fn.slug}.`));
445
+ }
446
+ // 2. A tree that looks like a different runtime than the function is
447
+ // configured for is the mismatch that fails LATE (the build uses the
448
+ // FUNCTION's runtime and finds no entry), so surface it now. On a
449
+ // TTY it is a confirm the user can decline; --yes and non-interactive
450
+ // runs get the warning and proceed, since a script cannot answer.
451
+ const inferred = inferRuntime(collected.files.map((f) => f.path));
452
+ const hasDockerfile = collected.files.some((f) => f.path === "Dockerfile");
453
+ if (inferred && !hasDockerfile && inferred !== fn.runtime && this.outputFormat === "table") {
454
+ this.log("");
455
+ // Advisory only; route to stderr so -o json stdout stays clean, and
456
+ // only prompt in table mode (json/non-TTY proceeds — the build uses
457
+ // fn.runtime either way).
458
+ this.info(`${G.dot} This directory looks like ${inferred}, but ${fn.slug} is configured for ${fn.runtime}.`);
459
+ this.info(dim(` The build will use ${fn.runtime}. Change the runtime in the portal (function → Settings) if that's wrong.`));
460
+ this.info("");
461
+ if (!flags.yes && interactive) {
462
+ const go = await confirmAction(`Deploy to ${fn.slug} as ${fn.runtime} anyway?`, false);
463
+ if (!go)
464
+ this.error("Deploy cancelled.", { exit: 1 });
465
+ }
466
+ }
467
+ // 3. The first release carries the env vars and the cron trigger:
468
+ // apply them now, after the function exists and before the build.
469
+ // --env-file lands the same way (a .env is never packed; a plain
470
+ // deploy never asks about it — the first-run create did).
471
+ await this.applySetup(fn, env, cron);
472
+ try {
473
+ await importDotenv({
474
+ dir,
475
+ envFile: flags["env-file"],
476
+ interactive: false,
477
+ target: `function ${fn.slug}`,
478
+ log: (l) => this.log(l),
479
+ save: (r) => this.clients.api.functions
480
+ .setEnv(fn.id, {
481
+ key: r.key,
482
+ value: r.value,
483
+ scope: r.scope ?? "runtime",
484
+ kind: r.kind ?? "secret",
485
+ ...(r.note ? { note: r.note } : {}),
486
+ rollout: false,
487
+ })
488
+ .then(() => undefined),
489
+ });
490
+ }
491
+ catch (e) {
492
+ if (e instanceof ApiError)
493
+ throw e;
494
+ this.error(e.message, { exit: 1 });
495
+ }
496
+ // 4. Trigger. Past the editor's 32 files the tree goes up as a tarball,
497
+ // which the API bounds by the compressed size; refuse here rather
498
+ // than after the upload in the rare case tar overhead tips it over.
499
+ let tarball;
500
+ if (collected.files.length > EDITOR_MAX_FILES) {
501
+ tarball = tarballFromFiles(collected.files);
502
+ const limit = fn.maxSourceBytes ?? MAX_TOTAL_BYTES;
503
+ if (tarball.length > limit) {
504
+ this.error(`Source archive is ${(tarball.length / 1024).toFixed(0)} KiB; the limit is ${(limit / 1024).toFixed(0)} KiB. ` +
505
+ "Exclude files with a .synteqignore, or add a Dockerfile and deploy as a container.", { exit: 1 });
506
+ }
507
+ }
508
+ const build = await withSpinner("Uploading source", () => tarball
509
+ ? this.clients.api.functions.deployTarball(fn.id, tarball)
510
+ : this.clients.api.functions.deployFiles(fn.id, collected.files));
511
+ await this.follow(fn, build, collected.skipped, flags);
512
+ }
513
+ catch (err) {
514
+ this.fail(err);
515
+ }
516
+ }
517
+ /** Steps 5+: print the build row (--no-wait) or follow the build and the
518
+ * release it produces — in JSON mode too, with progress on stderr. Shared
519
+ * by the source and image paths. */
520
+ async follow(fn, build, skipped, flags) {
521
+ const skipLines = skipped.map((s) => `skipped ${s.path} — ${SKIP_REASON[s.reason] ?? s.reason}`);
522
+ const json = this.outputFormat === "json";
523
+ // Every emitted document carries the skip list; in JSON mode the lines go
524
+ // to stderr too, since a scripted caller never sees them otherwise (the
525
+ // skip report in run(), 2026-09-25).
526
+ const withSkipped = (doc) => (skipped.length ? { ...doc, skipped } : doc);
527
+ if (json)
528
+ for (const line of skipLines)
529
+ process.stderr.write(`${line}\n`);
530
+ if (flags["no-wait"]) {
531
+ this.emit(withSkipped(build), () => this.log(`${statusColor(build.status)} build ${build.id.slice(0, 8)} ${build.frontend}`));
532
+ return;
533
+ }
534
+ // JSON mode follows the build like table mode — a CI job must see exit 1
535
+ // for a failed build or a release that never goes live (until 1.2.2 JSON
536
+ // returned the triggered build and exit 0, so the failure was invisible).
537
+ // The checklist takes an `out` stream and goes to stderr; stdout carries
538
+ // the final document only.
539
+ const out = json ? process.stderr : process.stdout;
540
+ // 5. Follow it. Ctrl-C stops watching, not the deploy.
541
+ const controller = new AbortController();
542
+ const onSigint = () => {
543
+ controller.abort();
544
+ };
545
+ process.on("SIGINT", onSigint);
546
+ const apiBaseUrl = this.clients.config.get().api_base_url;
547
+ const panelUrl = portalUrl(apiBaseUrl, `/functions/${fn.id}`);
548
+ const intervalMs = Math.max(2, flags["poll-interval"]) * 1000;
549
+ const deadline = Date.now() + flags.timeout * 1000;
550
+ const progress = buildProgress(`Deploying ${fn.slug}`, { out });
551
+ progress.update(build.status);
552
+ try {
553
+ const finalBuild = await waitForBuild(this.clients.api, fn.id, build.id, {
554
+ intervalMs,
555
+ timeoutMs: Math.max(0, deadline - Date.now()),
556
+ signal: controller.signal,
557
+ onStatus: (status) => progress.update(status),
558
+ });
559
+ if (finalBuild.status !== "succeeded") {
560
+ progress.failed();
561
+ this.emit(withSkipped(finalBuild), () => this.log(failedCard({ appSlug: fn.slug, buildId: finalBuild.id, panelUrl })));
562
+ this.exit(1);
563
+ }
564
+ const release = await waitForRelease(this.clients.api, fn.id, build.id, {
565
+ intervalMs,
566
+ timeoutMs: Math.max(0, deadline - Date.now()),
567
+ signal: controller.signal,
568
+ });
569
+ progress.done("succeeded");
570
+ const durationMs = finalBuild.startedAt && finalBuild.finishedAt
571
+ ? new Date(finalBuild.finishedAt).getTime() - new Date(finalBuild.startedAt).getTime()
572
+ : null;
573
+ if (release.isCurrent) {
574
+ this.emit(withSkipped({ build: finalBuild, release }), () => this.log(deployedCard({
575
+ appSlug: fn.slug,
576
+ url: deploymentUrl(fn.hostname),
577
+ release: release.number,
578
+ digest: release.imageDigest,
579
+ durationMs,
580
+ panelUrl,
581
+ })));
582
+ }
583
+ else {
584
+ // The build produced a release that never went current — the image
585
+ // is fine, the rollout is not. Say so rather than claiming success.
586
+ this.emit(withSkipped({ build: finalBuild, release }), () => this.log(failedCard({ appSlug: fn.slug, buildId: finalBuild.id, panelUrl }) +
587
+ `\n${dim(` Release #${release.number} is ${statusColor(release.status)}.`)}`));
588
+ this.exit(1);
589
+ }
590
+ }
591
+ catch (e) {
592
+ if (controller.signal.aborted) {
593
+ progress.failed("Stopped watching");
594
+ // JSON stdout stays empty on an interrupt (nothing parseable to emit);
595
+ // the hint is for a human at a terminal only.
596
+ if (!json) {
597
+ this.log("");
598
+ this.log(`${G.dot} The deploy continues server-side. Watch it: ${panelUrl}, or run \`synteq function releases --name ${fn.slug}\`.`);
599
+ }
600
+ return;
601
+ }
602
+ if (e instanceof DeployTimeoutError) {
603
+ progress.failed(e.message);
604
+ // A timeout is "unknown", not a failure (exit 0). JSON still owes the
605
+ // caller a parseable document — the build row plus `timedOut`.
606
+ this.emit(withSkipped({ ...build, timedOut: true }), () => this.log(`${G.dot} Stopped waiting after ${flags.timeout}s — the deploy may still finish. Watch it: ${panelUrl}`));
607
+ return;
608
+ }
609
+ throw e;
610
+ }
611
+ finally {
612
+ process.removeListener("SIGINT", onSigint);
613
+ }
614
+ }
615
+ }
616
+ //# sourceMappingURL=deploy.js.map