@ttctl/cli 0.0.0 → 0.1.0-rc.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 (395) hide show
  1. package/README.md +44 -9
  2. package/dist/commands/applications/index.d.ts +21 -0
  3. package/dist/commands/applications/index.d.ts.map +1 -0
  4. package/dist/commands/applications/index.js +87 -0
  5. package/dist/commands/applications/index.js.map +1 -0
  6. package/dist/commands/applications/list.d.ts +55 -0
  7. package/dist/commands/applications/list.d.ts.map +1 -0
  8. package/dist/commands/applications/list.js +106 -0
  9. package/dist/commands/applications/list.js.map +1 -0
  10. package/dist/commands/applications/shared.d.ts +14 -0
  11. package/dist/commands/applications/shared.d.ts.map +1 -0
  12. package/dist/commands/applications/shared.js +19 -0
  13. package/dist/commands/applications/shared.js.map +1 -0
  14. package/dist/commands/applications/show.d.ts +51 -0
  15. package/dist/commands/applications/show.d.ts.map +1 -0
  16. package/dist/commands/applications/show.js +154 -0
  17. package/dist/commands/applications/show.js.map +1 -0
  18. package/dist/commands/applications/stats.d.ts +42 -0
  19. package/dist/commands/applications/stats.d.ts.map +1 -0
  20. package/dist/commands/applications/stats.js +69 -0
  21. package/dist/commands/applications/stats.js.map +1 -0
  22. package/dist/commands/auth/index.d.ts +17 -0
  23. package/dist/commands/auth/index.d.ts.map +1 -0
  24. package/dist/commands/auth/index.js +69 -0
  25. package/dist/commands/auth/index.js.map +1 -0
  26. package/dist/commands/auth/init.d.ts +98 -0
  27. package/dist/commands/auth/init.d.ts.map +1 -0
  28. package/dist/commands/auth/init.js +387 -0
  29. package/dist/commands/auth/init.js.map +1 -0
  30. package/dist/commands/auth/signin.d.ts +81 -0
  31. package/dist/commands/auth/signin.d.ts.map +1 -0
  32. package/dist/commands/auth/signin.js +145 -0
  33. package/dist/commands/auth/signin.js.map +1 -0
  34. package/dist/commands/auth/signout.d.ts +133 -0
  35. package/dist/commands/auth/signout.d.ts.map +1 -0
  36. package/dist/commands/auth/signout.js +172 -0
  37. package/dist/commands/auth/signout.js.map +1 -0
  38. package/dist/commands/auth/status.d.ts +62 -0
  39. package/dist/commands/auth/status.d.ts.map +1 -0
  40. package/dist/commands/auth/status.js +98 -0
  41. package/dist/commands/auth/status.js.map +1 -0
  42. package/dist/commands/availability/allocated-hours.d.ts +27 -0
  43. package/dist/commands/availability/allocated-hours.d.ts.map +1 -0
  44. package/dist/commands/availability/allocated-hours.js +61 -0
  45. package/dist/commands/availability/allocated-hours.js.map +1 -0
  46. package/dist/commands/availability/index.d.ts +30 -0
  47. package/dist/commands/availability/index.d.ts.map +1 -0
  48. package/dist/commands/availability/index.js +124 -0
  49. package/dist/commands/availability/index.js.map +1 -0
  50. package/dist/commands/availability/shared.d.ts +11 -0
  51. package/dist/commands/availability/shared.d.ts.map +1 -0
  52. package/dist/commands/availability/shared.js +30 -0
  53. package/dist/commands/availability/shared.js.map +1 -0
  54. package/dist/commands/availability/show.d.ts +32 -0
  55. package/dist/commands/availability/show.d.ts.map +1 -0
  56. package/dist/commands/availability/show.js +86 -0
  57. package/dist/commands/availability/show.js.map +1 -0
  58. package/dist/commands/availability/working-hours.d.ts +53 -0
  59. package/dist/commands/availability/working-hours.d.ts.map +1 -0
  60. package/dist/commands/availability/working-hours.js +151 -0
  61. package/dist/commands/availability/working-hours.js.map +1 -0
  62. package/dist/commands/contracts/index.d.ts +69 -0
  63. package/dist/commands/contracts/index.d.ts.map +1 -0
  64. package/dist/commands/contracts/index.js +198 -0
  65. package/dist/commands/contracts/index.js.map +1 -0
  66. package/dist/commands/engagements/breaks.d.ts +81 -0
  67. package/dist/commands/engagements/breaks.d.ts.map +1 -0
  68. package/dist/commands/engagements/breaks.js +229 -0
  69. package/dist/commands/engagements/breaks.js.map +1 -0
  70. package/dist/commands/engagements/index.d.ts +29 -0
  71. package/dist/commands/engagements/index.d.ts.map +1 -0
  72. package/dist/commands/engagements/index.js +172 -0
  73. package/dist/commands/engagements/index.js.map +1 -0
  74. package/dist/commands/engagements/list.d.ts +49 -0
  75. package/dist/commands/engagements/list.d.ts.map +1 -0
  76. package/dist/commands/engagements/list.js +95 -0
  77. package/dist/commands/engagements/list.js.map +1 -0
  78. package/dist/commands/engagements/shared.d.ts +10 -0
  79. package/dist/commands/engagements/shared.d.ts.map +1 -0
  80. package/dist/commands/engagements/shared.js +31 -0
  81. package/dist/commands/engagements/shared.js.map +1 -0
  82. package/dist/commands/engagements/show.d.ts +19 -0
  83. package/dist/commands/engagements/show.d.ts.map +1 -0
  84. package/dist/commands/engagements/show.js +150 -0
  85. package/dist/commands/engagements/show.js.map +1 -0
  86. package/dist/commands/engagements/stats.d.ts +24 -0
  87. package/dist/commands/engagements/stats.d.ts.map +1 -0
  88. package/dist/commands/engagements/stats.js +51 -0
  89. package/dist/commands/engagements/stats.js.map +1 -0
  90. package/dist/commands/jobs/index.d.ts +49 -0
  91. package/dist/commands/jobs/index.d.ts.map +1 -0
  92. package/dist/commands/jobs/index.js +304 -0
  93. package/dist/commands/jobs/index.js.map +1 -0
  94. package/dist/commands/jobs/interest.d.ts +65 -0
  95. package/dist/commands/jobs/interest.d.ts.map +1 -0
  96. package/dist/commands/jobs/interest.js +172 -0
  97. package/dist/commands/jobs/interest.js.map +1 -0
  98. package/dist/commands/jobs/list.d.ts +81 -0
  99. package/dist/commands/jobs/list.d.ts.map +1 -0
  100. package/dist/commands/jobs/list.js +157 -0
  101. package/dist/commands/jobs/list.js.map +1 -0
  102. package/dist/commands/jobs/search.d.ts +71 -0
  103. package/dist/commands/jobs/search.d.ts.map +1 -0
  104. package/dist/commands/jobs/search.js +163 -0
  105. package/dist/commands/jobs/search.js.map +1 -0
  106. package/dist/commands/jobs/shared.d.ts +79 -0
  107. package/dist/commands/jobs/shared.d.ts.map +1 -0
  108. package/dist/commands/jobs/shared.js +133 -0
  109. package/dist/commands/jobs/shared.js.map +1 -0
  110. package/dist/commands/jobs/show.d.ts +20 -0
  111. package/dist/commands/jobs/show.d.ts.map +1 -0
  112. package/dist/commands/jobs/show.js +135 -0
  113. package/dist/commands/jobs/show.js.map +1 -0
  114. package/dist/commands/payments/index.d.ts +34 -0
  115. package/dist/commands/payments/index.d.ts.map +1 -0
  116. package/dist/commands/payments/index.js +160 -0
  117. package/dist/commands/payments/index.js.map +1 -0
  118. package/dist/commands/payments/methods.d.ts +17 -0
  119. package/dist/commands/payments/methods.d.ts.map +1 -0
  120. package/dist/commands/payments/methods.js +79 -0
  121. package/dist/commands/payments/methods.js.map +1 -0
  122. package/dist/commands/payments/payouts.d.ts +44 -0
  123. package/dist/commands/payments/payouts.d.ts.map +1 -0
  124. package/dist/commands/payments/payouts.js +147 -0
  125. package/dist/commands/payments/payouts.js.map +1 -0
  126. package/dist/commands/payments/rate.d.ts +48 -0
  127. package/dist/commands/payments/rate.d.ts.map +1 -0
  128. package/dist/commands/payments/rate.js +229 -0
  129. package/dist/commands/payments/rate.js.map +1 -0
  130. package/dist/commands/payments/shared.d.ts +10 -0
  131. package/dist/commands/payments/shared.d.ts.map +1 -0
  132. package/dist/commands/payments/shared.js +27 -0
  133. package/dist/commands/payments/shared.js.map +1 -0
  134. package/dist/commands/profile/basic/index.d.ts +18 -0
  135. package/dist/commands/profile/basic/index.d.ts.map +1 -0
  136. package/dist/commands/profile/basic/index.js +79 -0
  137. package/dist/commands/profile/basic/index.js.map +1 -0
  138. package/dist/commands/profile/basic/photo-show.d.ts +28 -0
  139. package/dist/commands/profile/basic/photo-show.d.ts.map +1 -0
  140. package/dist/commands/profile/basic/photo-show.js +112 -0
  141. package/dist/commands/profile/basic/photo-show.js.map +1 -0
  142. package/dist/commands/profile/basic/photo-upload.d.ts +10 -0
  143. package/dist/commands/profile/basic/photo-upload.d.ts.map +1 -0
  144. package/dist/commands/profile/basic/photo-upload.js +61 -0
  145. package/dist/commands/profile/basic/photo-upload.js.map +1 -0
  146. package/dist/commands/profile/basic/set.d.ts +54 -0
  147. package/dist/commands/profile/basic/set.d.ts.map +1 -0
  148. package/dist/commands/profile/basic/set.js +174 -0
  149. package/dist/commands/profile/basic/set.js.map +1 -0
  150. package/dist/commands/profile/basic/show.d.ts +95 -0
  151. package/dist/commands/profile/basic/show.d.ts.map +1 -0
  152. package/dist/commands/profile/basic/show.js +310 -0
  153. package/dist/commands/profile/basic/show.js.map +1 -0
  154. package/dist/commands/profile/certifications/index.d.ts +40 -0
  155. package/dist/commands/profile/certifications/index.d.ts.map +1 -0
  156. package/dist/commands/profile/certifications/index.js +350 -0
  157. package/dist/commands/profile/certifications/index.js.map +1 -0
  158. package/dist/commands/profile/education/index.d.ts +37 -0
  159. package/dist/commands/profile/education/index.d.ts.map +1 -0
  160. package/dist/commands/profile/education/index.js +331 -0
  161. package/dist/commands/profile/education/index.js.map +1 -0
  162. package/dist/commands/profile/employment/index.d.ts +49 -0
  163. package/dist/commands/profile/employment/index.d.ts.map +1 -0
  164. package/dist/commands/profile/employment/index.js +425 -0
  165. package/dist/commands/profile/employment/index.js.map +1 -0
  166. package/dist/commands/profile/external/_shared.d.ts +35 -0
  167. package/dist/commands/profile/external/_shared.d.ts.map +1 -0
  168. package/dist/commands/profile/external/_shared.js +59 -0
  169. package/dist/commands/profile/external/_shared.js.map +1 -0
  170. package/dist/commands/profile/external/advanced-wizard-show.d.ts +15 -0
  171. package/dist/commands/profile/external/advanced-wizard-show.d.ts.map +1 -0
  172. package/dist/commands/profile/external/advanced-wizard-show.js +82 -0
  173. package/dist/commands/profile/external/advanced-wizard-show.js.map +1 -0
  174. package/dist/commands/profile/external/custom-requirements-set.d.ts +32 -0
  175. package/dist/commands/profile/external/custom-requirements-set.d.ts.map +1 -0
  176. package/dist/commands/profile/external/custom-requirements-set.js +116 -0
  177. package/dist/commands/profile/external/custom-requirements-set.js.map +1 -0
  178. package/dist/commands/profile/external/custom-requirements-show.d.ts +16 -0
  179. package/dist/commands/profile/external/custom-requirements-show.d.ts.map +1 -0
  180. package/dist/commands/profile/external/custom-requirements-show.js +84 -0
  181. package/dist/commands/profile/external/custom-requirements-show.js.map +1 -0
  182. package/dist/commands/profile/external/index.d.ts +21 -0
  183. package/dist/commands/profile/external/index.d.ts.map +1 -0
  184. package/dist/commands/profile/external/index.js +113 -0
  185. package/dist/commands/profile/external/index.js.map +1 -0
  186. package/dist/commands/profile/external/readiness.d.ts +15 -0
  187. package/dist/commands/profile/external/readiness.d.ts.map +1 -0
  188. package/dist/commands/profile/external/readiness.js +104 -0
  189. package/dist/commands/profile/external/readiness.js.map +1 -0
  190. package/dist/commands/profile/external/recommendations.d.ts +17 -0
  191. package/dist/commands/profile/external/recommendations.d.ts.map +1 -0
  192. package/dist/commands/profile/external/recommendations.js +97 -0
  193. package/dist/commands/profile/external/recommendations.js.map +1 -0
  194. package/dist/commands/profile/external/show.d.ts +22 -0
  195. package/dist/commands/profile/external/show.d.ts.map +1 -0
  196. package/dist/commands/profile/external/show.js +83 -0
  197. package/dist/commands/profile/external/show.js.map +1 -0
  198. package/dist/commands/profile/external/update.d.ts +37 -0
  199. package/dist/commands/profile/external/update.d.ts.map +1 -0
  200. package/dist/commands/profile/external/update.js +125 -0
  201. package/dist/commands/profile/external/update.js.map +1 -0
  202. package/dist/commands/profile/index.d.ts +16 -0
  203. package/dist/commands/profile/index.d.ts.map +1 -0
  204. package/dist/commands/profile/index.js +81 -0
  205. package/dist/commands/profile/index.js.map +1 -0
  206. package/dist/commands/profile/industries/index.d.ts +43 -0
  207. package/dist/commands/profile/industries/index.d.ts.map +1 -0
  208. package/dist/commands/profile/industries/index.js +258 -0
  209. package/dist/commands/profile/industries/index.js.map +1 -0
  210. package/dist/commands/profile/portfolio/add.d.ts +43 -0
  211. package/dist/commands/profile/portfolio/add.d.ts.map +1 -0
  212. package/dist/commands/profile/portfolio/add.js +181 -0
  213. package/dist/commands/profile/portfolio/add.js.map +1 -0
  214. package/dist/commands/profile/portfolio/highlight.d.ts +11 -0
  215. package/dist/commands/profile/portfolio/highlight.d.ts.map +1 -0
  216. package/dist/commands/profile/portfolio/highlight.js +31 -0
  217. package/dist/commands/profile/portfolio/highlight.js.map +1 -0
  218. package/dist/commands/profile/portfolio/index.d.ts +16 -0
  219. package/dist/commands/profile/portfolio/index.d.ts.map +1 -0
  220. package/dist/commands/profile/portfolio/index.js +121 -0
  221. package/dist/commands/profile/portfolio/index.js.map +1 -0
  222. package/dist/commands/profile/portfolio/list.d.ts +83 -0
  223. package/dist/commands/profile/portfolio/list.d.ts.map +1 -0
  224. package/dist/commands/profile/portfolio/list.js +189 -0
  225. package/dist/commands/profile/portfolio/list.js.map +1 -0
  226. package/dist/commands/profile/portfolio/remove.d.ts +9 -0
  227. package/dist/commands/profile/portfolio/remove.d.ts.map +1 -0
  228. package/dist/commands/profile/portfolio/remove.js +24 -0
  229. package/dist/commands/profile/portfolio/remove.js.map +1 -0
  230. package/dist/commands/profile/portfolio/reorder.d.ts +17 -0
  231. package/dist/commands/profile/portfolio/reorder.d.ts.map +1 -0
  232. package/dist/commands/profile/portfolio/reorder.js +135 -0
  233. package/dist/commands/profile/portfolio/reorder.js.map +1 -0
  234. package/dist/commands/profile/portfolio/shared.d.ts +8 -0
  235. package/dist/commands/profile/portfolio/shared.d.ts.map +1 -0
  236. package/dist/commands/profile/portfolio/shared.js +10 -0
  237. package/dist/commands/profile/portfolio/shared.js.map +1 -0
  238. package/dist/commands/profile/portfolio/update.d.ts +18 -0
  239. package/dist/commands/profile/portfolio/update.d.ts.map +1 -0
  240. package/dist/commands/profile/portfolio/update.js +77 -0
  241. package/dist/commands/profile/portfolio/update.js.map +1 -0
  242. package/dist/commands/profile/portfolio/upload.d.ts +8 -0
  243. package/dist/commands/profile/portfolio/upload.d.ts.map +1 -0
  244. package/dist/commands/profile/portfolio/upload.js +131 -0
  245. package/dist/commands/profile/portfolio/upload.js.map +1 -0
  246. package/dist/commands/profile/resume/cancel-upload.d.ts +9 -0
  247. package/dist/commands/profile/resume/cancel-upload.d.ts.map +1 -0
  248. package/dist/commands/profile/resume/cancel-upload.js +30 -0
  249. package/dist/commands/profile/resume/cancel-upload.js.map +1 -0
  250. package/dist/commands/profile/resume/index.d.ts +15 -0
  251. package/dist/commands/profile/resume/index.d.ts.map +1 -0
  252. package/dist/commands/profile/resume/index.js +42 -0
  253. package/dist/commands/profile/resume/index.js.map +1 -0
  254. package/dist/commands/profile/resume/upload.d.ts +16 -0
  255. package/dist/commands/profile/resume/upload.d.ts.map +1 -0
  256. package/dist/commands/profile/resume/upload.js +65 -0
  257. package/dist/commands/profile/resume/upload.js.map +1 -0
  258. package/dist/commands/profile/reviews/_shared.d.ts +9 -0
  259. package/dist/commands/profile/reviews/_shared.d.ts.map +1 -0
  260. package/dist/commands/profile/reviews/_shared.js +15 -0
  261. package/dist/commands/profile/reviews/_shared.js.map +1 -0
  262. package/dist/commands/profile/reviews/approve-item.d.ts +30 -0
  263. package/dist/commands/profile/reviews/approve-item.d.ts.map +1 -0
  264. package/dist/commands/profile/reviews/approve-item.js +82 -0
  265. package/dist/commands/profile/reviews/approve-item.js.map +1 -0
  266. package/dist/commands/profile/reviews/approve-section.d.ts +15 -0
  267. package/dist/commands/profile/reviews/approve-section.d.ts.map +1 -0
  268. package/dist/commands/profile/reviews/approve-section.js +67 -0
  269. package/dist/commands/profile/reviews/approve-section.js.map +1 -0
  270. package/dist/commands/profile/reviews/index.d.ts +19 -0
  271. package/dist/commands/profile/reviews/index.d.ts.map +1 -0
  272. package/dist/commands/profile/reviews/index.js +71 -0
  273. package/dist/commands/profile/reviews/index.js.map +1 -0
  274. package/dist/commands/profile/reviews/list.d.ts +17 -0
  275. package/dist/commands/profile/reviews/list.d.ts.map +1 -0
  276. package/dist/commands/profile/reviews/list.js +96 -0
  277. package/dist/commands/profile/reviews/list.js.map +1 -0
  278. package/dist/commands/profile/reviews/submit-for-review.d.ts +16 -0
  279. package/dist/commands/profile/reviews/submit-for-review.d.ts.map +1 -0
  280. package/dist/commands/profile/reviews/submit-for-review.js +65 -0
  281. package/dist/commands/profile/reviews/submit-for-review.js.map +1 -0
  282. package/dist/commands/profile/shared.d.ts +46 -0
  283. package/dist/commands/profile/shared.d.ts.map +1 -0
  284. package/dist/commands/profile/shared.js +111 -0
  285. package/dist/commands/profile/shared.js.map +1 -0
  286. package/dist/commands/profile/skills/index.d.ts +29 -0
  287. package/dist/commands/profile/skills/index.d.ts.map +1 -0
  288. package/dist/commands/profile/skills/index.js +475 -0
  289. package/dist/commands/profile/skills/index.js.map +1 -0
  290. package/dist/commands/profile/visas/add.d.ts +19 -0
  291. package/dist/commands/profile/visas/add.d.ts.map +1 -0
  292. package/dist/commands/profile/visas/add.js +37 -0
  293. package/dist/commands/profile/visas/add.js.map +1 -0
  294. package/dist/commands/profile/visas/index.d.ts +13 -0
  295. package/dist/commands/profile/visas/index.d.ts.map +1 -0
  296. package/dist/commands/profile/visas/index.js +69 -0
  297. package/dist/commands/profile/visas/index.js.map +1 -0
  298. package/dist/commands/profile/visas/list.d.ts +40 -0
  299. package/dist/commands/profile/visas/list.d.ts.map +1 -0
  300. package/dist/commands/profile/visas/list.js +115 -0
  301. package/dist/commands/profile/visas/list.js.map +1 -0
  302. package/dist/commands/profile/visas/remove.d.ts +8 -0
  303. package/dist/commands/profile/visas/remove.d.ts.map +1 -0
  304. package/dist/commands/profile/visas/remove.js +23 -0
  305. package/dist/commands/profile/visas/remove.js.map +1 -0
  306. package/dist/commands/profile/visas/shared.d.ts +11 -0
  307. package/dist/commands/profile/visas/shared.d.ts.map +1 -0
  308. package/dist/commands/profile/visas/shared.js +16 -0
  309. package/dist/commands/profile/visas/shared.js.map +1 -0
  310. package/dist/commands/profile/visas/update.d.ts +13 -0
  311. package/dist/commands/profile/visas/update.d.ts.map +1 -0
  312. package/dist/commands/profile/visas/update.js +44 -0
  313. package/dist/commands/profile/visas/update.js.map +1 -0
  314. package/dist/commands/timesheet/index.d.ts +24 -0
  315. package/dist/commands/timesheet/index.d.ts.map +1 -0
  316. package/dist/commands/timesheet/index.js +98 -0
  317. package/dist/commands/timesheet/index.js.map +1 -0
  318. package/dist/commands/timesheet/list.d.ts +40 -0
  319. package/dist/commands/timesheet/list.d.ts.map +1 -0
  320. package/dist/commands/timesheet/list.js +79 -0
  321. package/dist/commands/timesheet/list.js.map +1 -0
  322. package/dist/commands/timesheet/shared.d.ts +10 -0
  323. package/dist/commands/timesheet/shared.d.ts.map +1 -0
  324. package/dist/commands/timesheet/shared.js +35 -0
  325. package/dist/commands/timesheet/shared.js.map +1 -0
  326. package/dist/commands/timesheet/show.d.ts +19 -0
  327. package/dist/commands/timesheet/show.d.ts.map +1 -0
  328. package/dist/commands/timesheet/show.js +109 -0
  329. package/dist/commands/timesheet/show.js.map +1 -0
  330. package/dist/commands/timesheet/submit.d.ts +50 -0
  331. package/dist/commands/timesheet/submit.d.ts.map +1 -0
  332. package/dist/commands/timesheet/submit.js +151 -0
  333. package/dist/commands/timesheet/submit.js.map +1 -0
  334. package/dist/crash-handlers.d.ts +67 -0
  335. package/dist/crash-handlers.d.ts.map +1 -0
  336. package/dist/crash-handlers.js +78 -0
  337. package/dist/crash-handlers.js.map +1 -0
  338. package/dist/errors.d.ts +45 -0
  339. package/dist/errors.d.ts.map +1 -0
  340. package/dist/errors.js +57 -0
  341. package/dist/errors.js.map +1 -0
  342. package/dist/index.d.ts +8 -0
  343. package/dist/index.d.ts.map +1 -0
  344. package/dist/index.js +15 -0
  345. package/dist/index.js.map +1 -0
  346. package/dist/lib/config-context.d.ts +41 -0
  347. package/dist/lib/config-context.d.ts.map +1 -0
  348. package/dist/lib/config-context.js +74 -0
  349. package/dist/lib/config-context.js.map +1 -0
  350. package/dist/lib/dry-run.d.ts +70 -0
  351. package/dist/lib/dry-run.d.ts.map +1 -0
  352. package/dist/lib/dry-run.js +114 -0
  353. package/dist/lib/dry-run.js.map +1 -0
  354. package/dist/lib/empty-state-cta.d.ts +63 -0
  355. package/dist/lib/empty-state-cta.d.ts.map +1 -0
  356. package/dist/lib/empty-state-cta.js +88 -0
  357. package/dist/lib/empty-state-cta.js.map +1 -0
  358. package/dist/lib/envelopes.d.ts +540 -0
  359. package/dist/lib/envelopes.d.ts.map +1 -0
  360. package/dist/lib/envelopes.js +598 -0
  361. package/dist/lib/envelopes.js.map +1 -0
  362. package/dist/lib/error-routing.d.ts +49 -0
  363. package/dist/lib/error-routing.d.ts.map +1 -0
  364. package/dist/lib/error-routing.js +72 -0
  365. package/dist/lib/error-routing.js.map +1 -0
  366. package/dist/lib/format-helpers.d.ts +65 -0
  367. package/dist/lib/format-helpers.d.ts.map +1 -0
  368. package/dist/lib/format-helpers.js +79 -0
  369. package/dist/lib/format-helpers.js.map +1 -0
  370. package/dist/lib/format-overrides.d.ts +81 -0
  371. package/dist/lib/format-overrides.d.ts.map +1 -0
  372. package/dist/lib/format-overrides.js +55 -0
  373. package/dist/lib/format-overrides.js.map +1 -0
  374. package/dist/lib/freetext.d.ts +83 -0
  375. package/dist/lib/freetext.d.ts.map +1 -0
  376. package/dist/lib/freetext.js +182 -0
  377. package/dist/lib/freetext.js.map +1 -0
  378. package/dist/lib/kill-switch-hook.d.ts +49 -0
  379. package/dist/lib/kill-switch-hook.d.ts.map +1 -0
  380. package/dist/lib/kill-switch-hook.js +34 -0
  381. package/dist/lib/kill-switch-hook.js.map +1 -0
  382. package/dist/lib/output.d.ts +173 -0
  383. package/dist/lib/output.d.ts.map +1 -0
  384. package/dist/lib/output.js +177 -0
  385. package/dist/lib/output.js.map +1 -0
  386. package/dist/lib/pagination.d.ts +49 -0
  387. package/dist/lib/pagination.d.ts.map +1 -0
  388. package/dist/lib/pagination.js +36 -0
  389. package/dist/lib/pagination.js.map +1 -0
  390. package/dist/program.d.ts +80 -0
  391. package/dist/program.d.ts.map +1 -0
  392. package/dist/program.js +273 -0
  393. package/dist/program.js.map +1 -0
  394. package/package.json +35 -13
  395. package/index.js +0 -7
@@ -0,0 +1,121 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { Command, Option } from "commander";
4
+ import { OUTPUT_FORMATS } from "../../../lib/output.js";
5
+ import { runProfilePortfolioAdd } from "./add.js";
6
+ import { runProfilePortfolioHighlight } from "./highlight.js";
7
+ import { runProfilePortfolioList } from "./list.js";
8
+ import { runProfilePortfolioRemove } from "./remove.js";
9
+ import { runProfilePortfolioReorder } from "./reorder.js";
10
+ import { runProfilePortfolioUpdate } from "./update.js";
11
+ import { runProfilePortfolioUpload } from "./upload.js";
12
+ /**
13
+ * Build the `ttctl profile portfolio` command tree.
14
+ *
15
+ * The canonical sub-domain name is `portfolio`; the CLI registers
16
+ * `projects` as a Commander.js alias so users can type either form. Per
17
+ * project policy (see issue #72), aliases are CLI-only — MCP tool names
18
+ * use ONLY the canonical name.
19
+ *
20
+ * The seven leaves follow the verb economy from the #68 epic:
21
+ * `add / update / remove / list / reorder / highlight / upload`. The
22
+ * `update` verb name is the user-facing CLI form; the core function is
23
+ * `update()` (no rename — verbs match between CLI and core for portfolio).
24
+ */
25
+ export function buildProfilePortfolioCommand() {
26
+ const portfolio = new Command("portfolio")
27
+ .alias("projects")
28
+ .description("View and update the portfolio section of your profile");
29
+ portfolio
30
+ .command("add")
31
+ .description("Create a new portfolio item")
32
+ .requiredOption("--title <text>", "portfolio item title")
33
+ .option("--description <text>", 'item description (inline text, "-" for stdin, or "@path" to read from file)')
34
+ .option("--edit", "open $EDITOR to compose the description interactively")
35
+ .option("--url <url>", "primary URL for the item (alias for --link)")
36
+ .option("--link <url>", "primary URL for the item (canonical flag, equivalent to --url)")
37
+ .option("--cover <file>", "path to a cover-image file to upload alongside the item")
38
+ .option("--industry-id <id>", 'catalog Industry id (repeatable; required — at least one). Discover via `ttctl profile industries autocomplete "<query>"`.', (value, prev) => (prev ? [...prev, value] : [value]))
39
+ .addOption(new Option("-o, --output <format>", "output format")
40
+ .choices(OUTPUT_FORMATS)
41
+ .default("pretty"))
42
+ .action(async (options) => {
43
+ await runProfilePortfolioAdd(options);
44
+ });
45
+ portfolio
46
+ .command("update")
47
+ .description("Update fields on a portfolio item")
48
+ .argument("<id>", "id of the portfolio item to update")
49
+ .option("--title <text>", "portfolio item title")
50
+ .option("--description <text>", 'item description (inline text, "-" for stdin, or "@path" to read from file)')
51
+ .option("--edit", "open $EDITOR to compose the description interactively")
52
+ .option("--url <url>", "primary URL for the item (alias for --link)")
53
+ .option("--link <url>", "primary URL for the item (canonical flag, equivalent to --url)")
54
+ .option("--client <name>", "client/company name")
55
+ .option("--accomplishment <text>", "accomplishment summary")
56
+ .addOption(new Option("-o, --output <format>", "output format")
57
+ .choices(OUTPUT_FORMATS)
58
+ .default("pretty"))
59
+ .action(async (id, options) => {
60
+ await runProfilePortfolioUpdate(id, options);
61
+ });
62
+ portfolio
63
+ .command("remove")
64
+ .alias("rm")
65
+ .description("Remove a portfolio item")
66
+ .argument("<id>", "id of the portfolio item to remove")
67
+ .addOption(new Option("-o, --output <format>", "output format")
68
+ .choices(OUTPUT_FORMATS)
69
+ .default("pretty"))
70
+ .action(async (id, options) => {
71
+ await runProfilePortfolioRemove(id, options.output);
72
+ });
73
+ portfolio
74
+ .command("list")
75
+ .description("List portfolio items")
76
+ .addOption(new Option("-o, --output <format>", "output format")
77
+ .choices(OUTPUT_FORMATS)
78
+ .default("pretty"))
79
+ .action(async (options) => {
80
+ await runProfilePortfolioList(options.output);
81
+ });
82
+ portfolio
83
+ .command("reorder")
84
+ .description("Reorder a portfolio item")
85
+ .argument("<id>", "id of the portfolio item to move")
86
+ .option("--before <id>", "place the item immediately before this neighbour id")
87
+ .option("--after <id>", "place the item immediately after this neighbour id")
88
+ .option("--to <position>", "place the item at this absolute 0-based position")
89
+ .addOption(new Option("-o, --output <format>", "output format")
90
+ .choices(OUTPUT_FORMATS)
91
+ .default("pretty"))
92
+ .action(async (id, options) => {
93
+ await runProfilePortfolioReorder(id, options);
94
+ });
95
+ portfolio
96
+ .command("highlight")
97
+ .description("Toggle the highlight flag on a portfolio item (default: enable)")
98
+ .argument("<id>", "id of the portfolio item to highlight")
99
+ .option("--off", "clear the highlight flag instead of setting it")
100
+ .addOption(new Option("-o, --output <format>", "output format")
101
+ .choices(OUTPUT_FORMATS)
102
+ .default("pretty"))
103
+ .action(async (id, options) => {
104
+ await runProfilePortfolioHighlight(id, options);
105
+ });
106
+ portfolio
107
+ .command("upload")
108
+ .description("Upload a cover image (--cover) or attachment file (--file) for the user's portfolio")
109
+ .argument("[id]", "(unused; reserved for future per-item upload routing)")
110
+ .option("--cover <file>", "path to a cover-image file to upload")
111
+ .option("--file <file>", "path to a portfolio-attachment file to upload")
112
+ .option("--crop <x,y,w,h>", "cover crop (px), comma-separated x,y,w,h; default: whole image (PNG) or sentinel oversize")
113
+ .addOption(new Option("-o, --output <format>", "output format")
114
+ .choices(OUTPUT_FORMATS)
115
+ .default("pretty"))
116
+ .action(async (id, options) => {
117
+ await runProfilePortfolioUpload(id, options);
118
+ });
119
+ return portfolio;
120
+ }
121
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/commands/profile/portfolio/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ import { profile } from "@ttctl/core";
2
+ import type { OutputFormat } from "../../../lib/output.js";
3
+ /**
4
+ * Action handler for `ttctl profile portfolio list`. Reads the user's
5
+ * portfolio collection and emits it via the cross-CLI output helper
6
+ * (`packages/cli/src/lib/output.ts` from #71), wrapped in the v0.4
7
+ * list envelope (`{version, items, pageInfo?}` from #128) for
8
+ * json/yaml.
9
+ *
10
+ * Per #129, the `pretty` slot is registered with `emitResult` and
11
+ * unwraps the envelope's `items` field for the curated multi-line
12
+ * layout that surfaces `description`, `accomplishment`, `coverImage`,
13
+ * and `clientOrCompanyName` (the audit-confirmed dropped fields from
14
+ * #124). The `table` slot is also wired (also unwrapping `items`) —
15
+ * `formatResult`'s shape dispatcher prefers `table` for list-shape
16
+ * data when present, but the audit's Override Registry Decisions
17
+ * endorse routing portfolio list to multi-line because
18
+ * `description`/`accomplishment` are paragraph-length and the
19
+ * row-based table layout collapses them. {@link formatPortfolioTable}
20
+ * stays exported for direct test use and future override-dispatch
21
+ * wiring.
22
+ *
23
+ * Empty case is handled by the shared empty-state wrapper (#122) via
24
+ * `empty: { command: "profile.portfolio.list" }`. The wrapper detects
25
+ * both `[]` and `{items: []}` shapes (per #122's `isEmptyCollection`),
26
+ * so the post-#128 envelope wrapping continues to short-circuit
27
+ * BEFORE per-format dispatch — emitting `"No portfolio items found.
28
+ * Add one with: ttctl profile portfolio add"` for `pretty`, `[]` for
29
+ * `json`. The formatters keep a defensive empty-list branch for
30
+ * direct callers (tests, future programmatic use) that bypass the
31
+ * action handler.
32
+ */
33
+ export declare function runProfilePortfolioList(format: OutputFormat): Promise<void>;
34
+ /**
35
+ * Format the portfolio list as the post-#129 `pretty` summary. Pure —
36
+ * no I/O — directly unit-testable.
37
+ *
38
+ * Per-item layout, indented two spaces from the count header:
39
+ *
40
+ * <id>[ ★] <title>
41
+ * Client: <clientOrCompanyName> // skip-if-null
42
+ * URL: <link> // skip-if-null
43
+ * Cover: <coverImage> // skip-if-null
44
+ * Description: // always (renders (unset) on null)
45
+ * <body, paragraph breaks preserved>
46
+ * Accomplishment: // skip-if-null (multi-paragraph)
47
+ * <body>
48
+ *
49
+ * Items are separated by a single blank line. Field ordering for each
50
+ * item: identity (id, highlight star, title) first, then user-edited
51
+ * narrative (client, url, cover, description, accomplishment) — most
52
+ * user-edited last because they're the multi-line block fields that
53
+ * benefit from sticking to the bottom of the item.
54
+ *
55
+ * Closes the audit-confirmed formatter-root-cause defect from #124:
56
+ * `description`, `accomplishment`, `coverImage`, and
57
+ * `clientOrCompanyName` are now visible in the default output (the
58
+ * pre-#129 formatter dropped 7 of 12 entity fields).
59
+ *
60
+ * `tags` and `media` are NOT on the wire `PortfolioItem` — neither the
61
+ * mobile-gateway nor the talent-profile schema declares them. The audit
62
+ * flagged them as suspect; #127 verified absence empirically. They are
63
+ * deliberately omitted here.
64
+ *
65
+ * Pretty does NOT truncate (per the issue AC: "For long URLs / IDs:
66
+ * don't truncate (this is `pretty`, not `table`)"); the terminal wraps
67
+ * if the user's window is narrow.
68
+ */
69
+ export declare function formatPortfolioPretty(items: profile.portfolio.PortfolioItem[]): string;
70
+ /**
71
+ * Format the portfolio list as a `cli-table3`-rendered table sized to
72
+ * the current terminal width. Restores the `clientOrCompanyName` column
73
+ * dropped by the pre-#129 formatter (audit-confirmed asymmetric drop:
74
+ * `text` had it, `table` didn't).
75
+ *
76
+ * Long-form fields (`description`, `accomplishment`) are NOT in the
77
+ * table — paragraph-length text doesn't fit a row layout. The override
78
+ * registry in `lib/format-overrides.ts` flags `profile portfolio list`
79
+ * as a candidate for the `multi-line` strategy; users wanting the full
80
+ * detail land on `pretty` (the post-#126 default).
81
+ */
82
+ export declare function formatPortfolioTable(items: profile.portfolio.PortfolioItem[], terminalWidth?: number): string;
83
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../../src/commands/profile/portfolio/list.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAKtC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAI3D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBjF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,aAAa,EAAE,GAAG,MAAM,CAMtF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,aAAa,EAAE,EACxC,aAAa,GAAE,MAAqC,GACnD,MAAM,CAsBR"}
@@ -0,0 +1,189 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import Table from "cli-table3";
4
+ import { profile } from "@ttctl/core";
5
+ import { wrapListEnvelope } from "../../../lib/envelopes.js";
6
+ import { renderMultiParagraph, unsetOr } from "../../../lib/format-helpers.js";
7
+ import { emitResult } from "../../../lib/output.js";
8
+ import { handlePortfolioError } from "./add.js";
9
+ import { loadAuthTokenOrExit } from "./shared.js";
10
+ /**
11
+ * Action handler for `ttctl profile portfolio list`. Reads the user's
12
+ * portfolio collection and emits it via the cross-CLI output helper
13
+ * (`packages/cli/src/lib/output.ts` from #71), wrapped in the v0.4
14
+ * list envelope (`{version, items, pageInfo?}` from #128) for
15
+ * json/yaml.
16
+ *
17
+ * Per #129, the `pretty` slot is registered with `emitResult` and
18
+ * unwraps the envelope's `items` field for the curated multi-line
19
+ * layout that surfaces `description`, `accomplishment`, `coverImage`,
20
+ * and `clientOrCompanyName` (the audit-confirmed dropped fields from
21
+ * #124). The `table` slot is also wired (also unwrapping `items`) —
22
+ * `formatResult`'s shape dispatcher prefers `table` for list-shape
23
+ * data when present, but the audit's Override Registry Decisions
24
+ * endorse routing portfolio list to multi-line because
25
+ * `description`/`accomplishment` are paragraph-length and the
26
+ * row-based table layout collapses them. {@link formatPortfolioTable}
27
+ * stays exported for direct test use and future override-dispatch
28
+ * wiring.
29
+ *
30
+ * Empty case is handled by the shared empty-state wrapper (#122) via
31
+ * `empty: { command: "profile.portfolio.list" }`. The wrapper detects
32
+ * both `[]` and `{items: []}` shapes (per #122's `isEmptyCollection`),
33
+ * so the post-#128 envelope wrapping continues to short-circuit
34
+ * BEFORE per-format dispatch — emitting `"No portfolio items found.
35
+ * Add one with: ttctl profile portfolio add"` for `pretty`, `[]` for
36
+ * `json`. The formatters keep a defensive empty-list branch for
37
+ * direct callers (tests, future programmatic use) that bypass the
38
+ * action handler.
39
+ */
40
+ export async function runProfilePortfolioList(format) {
41
+ const token = await loadAuthTokenOrExit("portfolio list", format);
42
+ let items;
43
+ try {
44
+ items = await profile.portfolio.list(token);
45
+ }
46
+ catch (err) {
47
+ handlePortfolioError("portfolio list", err, format);
48
+ return;
49
+ }
50
+ emitResult(wrapListEnvelope(items), format, {
51
+ pretty: (data) => formatPortfolioPretty(data.items),
52
+ table: (data) => formatPortfolioTable(data.items),
53
+ empty: { command: "profile.portfolio.list" },
54
+ });
55
+ }
56
+ /**
57
+ * Format the portfolio list as the post-#129 `pretty` summary. Pure —
58
+ * no I/O — directly unit-testable.
59
+ *
60
+ * Per-item layout, indented two spaces from the count header:
61
+ *
62
+ * <id>[ ★] <title>
63
+ * Client: <clientOrCompanyName> // skip-if-null
64
+ * URL: <link> // skip-if-null
65
+ * Cover: <coverImage> // skip-if-null
66
+ * Description: // always (renders (unset) on null)
67
+ * <body, paragraph breaks preserved>
68
+ * Accomplishment: // skip-if-null (multi-paragraph)
69
+ * <body>
70
+ *
71
+ * Items are separated by a single blank line. Field ordering for each
72
+ * item: identity (id, highlight star, title) first, then user-edited
73
+ * narrative (client, url, cover, description, accomplishment) — most
74
+ * user-edited last because they're the multi-line block fields that
75
+ * benefit from sticking to the bottom of the item.
76
+ *
77
+ * Closes the audit-confirmed formatter-root-cause defect from #124:
78
+ * `description`, `accomplishment`, `coverImage`, and
79
+ * `clientOrCompanyName` are now visible in the default output (the
80
+ * pre-#129 formatter dropped 7 of 12 entity fields).
81
+ *
82
+ * `tags` and `media` are NOT on the wire `PortfolioItem` — neither the
83
+ * mobile-gateway nor the talent-profile schema declares them. The audit
84
+ * flagged them as suspect; #127 verified absence empirically. They are
85
+ * deliberately omitted here.
86
+ *
87
+ * Pretty does NOT truncate (per the issue AC: "For long URLs / IDs:
88
+ * don't truncate (this is `pretty`, not `table`)"); the terminal wraps
89
+ * if the user's window is narrow.
90
+ */
91
+ export function formatPortfolioPretty(items) {
92
+ if (items.length === 0)
93
+ return "(no portfolio items)";
94
+ const headerLine = `${items.length.toString()} portfolio item${items.length === 1 ? "" : "s"}:`;
95
+ const itemBlocks = items.map((it) => renderPortfolioItem(it));
96
+ return [headerLine, "", ...joinWithSeparator(itemBlocks, "")].join("\n");
97
+ }
98
+ /**
99
+ * Format the portfolio list as a `cli-table3`-rendered table sized to
100
+ * the current terminal width. Restores the `clientOrCompanyName` column
101
+ * dropped by the pre-#129 formatter (audit-confirmed asymmetric drop:
102
+ * `text` had it, `table` didn't).
103
+ *
104
+ * Long-form fields (`description`, `accomplishment`) are NOT in the
105
+ * table — paragraph-length text doesn't fit a row layout. The override
106
+ * registry in `lib/format-overrides.ts` flags `profile portfolio list`
107
+ * as a candidate for the `multi-line` strategy; users wanting the full
108
+ * detail land on `pretty` (the post-#126 default).
109
+ */
110
+ export function formatPortfolioTable(items, terminalWidth = process.stdout.columns || 80) {
111
+ if (items.length === 0) {
112
+ const empty = new Table({ head: ["id", "title", "highlight", "client", "link"] });
113
+ return empty.toString();
114
+ }
115
+ const idWidth = 14;
116
+ const highlightWidth = 12;
117
+ // Three text columns share the remaining width: title, client, link.
118
+ // Borders + outer padding consume ~7 chars total.
119
+ const remaining = Math.max(60, terminalWidth - idWidth - highlightWidth - 7);
120
+ const titleWidth = Math.max(15, Math.floor(remaining / 3));
121
+ const clientWidth = Math.max(15, Math.floor(remaining / 3));
122
+ const linkWidth = Math.max(15, remaining - titleWidth - clientWidth);
123
+ const table = new Table({
124
+ head: ["id", "title", "highlight", "client", "link"],
125
+ colWidths: [idWidth, titleWidth, highlightWidth, clientWidth, linkWidth],
126
+ wordWrap: true,
127
+ });
128
+ for (const it of items) {
129
+ table.push([it.id, it.title ?? "", it.highlight ? "★" : "", it.clientOrCompanyName ?? "", it.link ?? ""]);
130
+ }
131
+ return table.toString();
132
+ }
133
+ /**
134
+ * Render one portfolio item as a multi-line block. The block is indented
135
+ * two spaces from the count header; the per-field detail is indented
136
+ * four spaces total (block indent + nested indent).
137
+ */
138
+ function renderPortfolioItem(it) {
139
+ const blockIndent = " ";
140
+ const detailIndent = " ";
141
+ const star = it.highlight ? " ★" : "";
142
+ const title = it.title ?? "(untitled)";
143
+ const lines = [`${blockIndent}${it.id}${star} ${title}`];
144
+ if (it.clientOrCompanyName !== null) {
145
+ lines.push(`${detailIndent}Client: ${it.clientOrCompanyName}`);
146
+ }
147
+ if (it.link !== null) {
148
+ lines.push(`${detailIndent}URL: ${it.link}`);
149
+ }
150
+ if (it.coverImage !== null) {
151
+ lines.push(`${detailIndent}Cover: ${it.coverImage}`);
152
+ }
153
+ // Description always emits — it's the primary user-edited field, so
154
+ // the (unset) marker is itself the "you can edit this" signal. Multi-
155
+ // paragraph rendering preserves `\n\n` as actual blank lines.
156
+ if (it.description !== null && it.description !== "") {
157
+ lines.push(renderMultiParagraph("Description", it.description, detailIndent));
158
+ }
159
+ else {
160
+ lines.push(`${detailIndent}Description: ${unsetOr(null)}`);
161
+ }
162
+ // Accomplishment is skip-if-null per the AC's "if present" qualifier
163
+ // — it's secondary narrative content; rendering (unset) for every
164
+ // item without one would clutter long lists.
165
+ if (it.accomplishment !== null && it.accomplishment !== "") {
166
+ lines.push(renderMultiParagraph("Accomplishment", it.accomplishment, detailIndent));
167
+ }
168
+ return lines.join("\n");
169
+ }
170
+ /**
171
+ * Interleave `parts` with `separator` between every adjacent pair, like
172
+ * `parts.join(separator)` but yielding a string array suitable for
173
+ * splicing into a larger `lines` array via the spread operator.
174
+ *
175
+ * Used to produce the visible blank-line delimiter between portfolio
176
+ * items without a trailing separator after the last item.
177
+ */
178
+ function joinWithSeparator(parts, separator) {
179
+ const out = [];
180
+ for (let i = 0; i < parts.length; i++) {
181
+ if (i > 0)
182
+ out.push(separator);
183
+ const part = parts[i];
184
+ if (part !== undefined)
185
+ out.push(part);
186
+ }
187
+ return out;
188
+ }
189
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../../src/commands/profile/portfolio/list.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { OutputFormat } from "../../../lib/output.js";
2
+ /**
3
+ * Action handler for `ttctl profile portfolio remove <id>` (alias `rm`).
4
+ * Removes the portfolio item by id; emits the v0.4 envelope (#128) with
5
+ * `removed: {id}` and renders the post-removal list under the success
6
+ * line in pretty mode.
7
+ */
8
+ export declare function runProfilePortfolioRemove(id: string, format: OutputFormat): Promise<void>;
9
+ //# sourceMappingURL=remove.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove.d.ts","sourceRoot":"","sources":["../../../../src/commands/profile/portfolio/remove.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAI3D;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAY/F"}
@@ -0,0 +1,24 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { profile } from "@ttctl/core";
4
+ import { emitMutationResult, handlePortfolioError } from "./add.js";
5
+ import { loadAuthTokenOrExit } from "./shared.js";
6
+ /**
7
+ * Action handler for `ttctl profile portfolio remove <id>` (alias `rm`).
8
+ * Removes the portfolio item by id; emits the v0.4 envelope (#128) with
9
+ * `removed: {id}` and renders the post-removal list under the success
10
+ * line in pretty mode.
11
+ */
12
+ export async function runProfilePortfolioRemove(id, format) {
13
+ const token = await loadAuthTokenOrExit("portfolio remove", format);
14
+ let items;
15
+ try {
16
+ items = await profile.portfolio.remove(token, id);
17
+ }
18
+ catch (err) {
19
+ handlePortfolioError("portfolio remove", err, format);
20
+ return;
21
+ }
22
+ emitMutationResult(items, format, "remove", { id, prettyHeader: id });
23
+ }
24
+ //# sourceMappingURL=remove.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove.js","sourceRoot":"","sources":["../../../../src/commands/profile/portfolio/remove.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,EAAU,EAAE,MAAoB;IAC9E,MAAM,KAAK,GAAG,MAAM,mBAAmB,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC;IAEpE,IAAI,KAAwC,CAAC;IAC7C,IAAI,CAAC;QACH,KAAK,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,oBAAoB,CAAC,kBAAkB,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QACtD,OAAO;IACT,CAAC;IAED,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,CAAC;AACxE,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { OutputFormat } from "../../../lib/output.js";
2
+ /**
3
+ * Action handler for `ttctl profile portfolio reorder <id>`. The user
4
+ * supplies exactly one of `--before <id>` / `--after <id>` / `--to <pos>`;
5
+ * the helper translates `--before`/`--after` to an absolute position by
6
+ * fetching the current list, then issues `changePortfolioItemPosition`.
7
+ *
8
+ * Mutually-exclusive enforcement is at the CLI layer — the service-side
9
+ * `reorder()` only accepts an absolute integer position.
10
+ */
11
+ export declare function runProfilePortfolioReorder(id: string, options: {
12
+ before?: string;
13
+ after?: string;
14
+ to?: string;
15
+ output: OutputFormat;
16
+ }): Promise<void>;
17
+ //# sourceMappingURL=reorder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reorder.d.ts","sourceRoot":"","sources":["../../../../src/commands/profile/portfolio/reorder.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAI3D;;;;;;;;GAQG;AACH,wBAAsB,0BAA0B,CAC9C,EAAE,EAAE,MAAM,EACV,OAAO,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GAC9E,OAAO,CAAC,IAAI,CAAC,CAsHf"}
@@ -0,0 +1,135 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { profile } from "@ttctl/core";
4
+ import { emitErrorAndExit } from "../../../lib/envelopes.js";
5
+ import { emitMutationResult, handlePortfolioError } from "./add.js";
6
+ import { loadAuthTokenOrExit } from "./shared.js";
7
+ /**
8
+ * Action handler for `ttctl profile portfolio reorder <id>`. The user
9
+ * supplies exactly one of `--before <id>` / `--after <id>` / `--to <pos>`;
10
+ * the helper translates `--before`/`--after` to an absolute position by
11
+ * fetching the current list, then issues `changePortfolioItemPosition`.
12
+ *
13
+ * Mutually-exclusive enforcement is at the CLI layer — the service-side
14
+ * `reorder()` only accepts an absolute integer position.
15
+ */
16
+ export async function runProfilePortfolioReorder(id, options) {
17
+ const modes = [options.before !== undefined, options.after !== undefined, options.to !== undefined];
18
+ const modeCount = modes.filter(Boolean).length;
19
+ if (modeCount === 0) {
20
+ emitErrorAndExit({
21
+ operation: "profile.portfolio.reorder",
22
+ format: options.output,
23
+ errors: [
24
+ {
25
+ code: "VALIDATION_ERROR",
26
+ message: "supply exactly one of --before <id>, --after <id>, or --to <position>.",
27
+ },
28
+ ],
29
+ prettySummary: "portfolio reorder failed (VALIDATION_ERROR): supply exactly one of --before <id>, --after <id>, or --to <position>.",
30
+ });
31
+ }
32
+ if (modeCount > 1) {
33
+ emitErrorAndExit({
34
+ operation: "profile.portfolio.reorder",
35
+ format: options.output,
36
+ errors: [
37
+ {
38
+ code: "VALIDATION_ERROR",
39
+ message: "--before, --after, and --to are mutually exclusive.",
40
+ },
41
+ ],
42
+ prettySummary: "portfolio reorder failed (VALIDATION_ERROR): --before, --after, and --to are mutually exclusive.",
43
+ });
44
+ }
45
+ const token = await loadAuthTokenOrExit("portfolio reorder", options.output);
46
+ let position;
47
+ if (options.to !== undefined) {
48
+ const parsed = Number.parseInt(options.to, 10);
49
+ if (!Number.isInteger(parsed) || parsed < 0) {
50
+ emitErrorAndExit({
51
+ operation: "profile.portfolio.reorder",
52
+ format: options.output,
53
+ errors: [
54
+ {
55
+ code: "VALIDATION_ERROR",
56
+ field: "to",
57
+ message: "--to must be a non-negative integer position.",
58
+ },
59
+ ],
60
+ prettySummary: "portfolio reorder failed (VALIDATION_ERROR): --to must be a non-negative integer position.",
61
+ });
62
+ }
63
+ position = parsed;
64
+ }
65
+ else {
66
+ // Need the current list to translate neighbour-anchored flags into
67
+ // an absolute index. The read is a separate round-trip; the cost
68
+ // is acceptable because reorder is a low-frequency operation.
69
+ let current;
70
+ try {
71
+ current = await profile.portfolio.list(token);
72
+ }
73
+ catch (err) {
74
+ handlePortfolioError("portfolio reorder", err, options.output);
75
+ return;
76
+ }
77
+ if (options.before !== undefined) {
78
+ // Pass `id` (the moving item) so the helper filters it out before
79
+ // computing the target's index. Without it, the helper would
80
+ // return a position that's one off in the common "A before B (A
81
+ // is before B in the list)" case and the server would either
82
+ // reject or move the item to the wrong slot. See service-layer
83
+ // doc comment on `positionBefore` for the post-removal semantics.
84
+ const result = profile.portfolio.positionBefore(current, options.before, id);
85
+ if (result === null) {
86
+ emitErrorAndExit({
87
+ operation: "profile.portfolio.reorder",
88
+ format: options.output,
89
+ errors: [
90
+ {
91
+ code: "VALIDATION_ERROR",
92
+ field: "before",
93
+ message: `--before id '${options.before}' is not in the portfolio.`,
94
+ },
95
+ ],
96
+ prettySummary: `portfolio reorder failed (VALIDATION_ERROR): --before id '${options.before}' is not in the portfolio.`,
97
+ });
98
+ }
99
+ position = result;
100
+ }
101
+ else {
102
+ const after = options.after;
103
+ // See positionBefore comment above — `id` (moving item) is
104
+ // filtered out before computing the target's index.
105
+ const result = profile.portfolio.positionAfter(current, after, id);
106
+ if (result === null) {
107
+ emitErrorAndExit({
108
+ operation: "profile.portfolio.reorder",
109
+ format: options.output,
110
+ errors: [
111
+ {
112
+ code: "VALIDATION_ERROR",
113
+ field: "after",
114
+ message: `--after id '${after}' is not in the portfolio.`,
115
+ },
116
+ ],
117
+ prettySummary: `portfolio reorder failed (VALIDATION_ERROR): --after id '${after}' is not in the portfolio.`,
118
+ });
119
+ }
120
+ position = result;
121
+ }
122
+ }
123
+ let items;
124
+ try {
125
+ items = await profile.portfolio.reorder(token, id, position);
126
+ }
127
+ catch (err) {
128
+ handlePortfolioError("portfolio reorder", err, options.output);
129
+ return;
130
+ }
131
+ emitMutationResult(items, options.output, "update", {
132
+ prettyHeader: `Portfolio item ${id} moved to position ${position.toString()}.`,
133
+ });
134
+ }
135
+ //# sourceMappingURL=reorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reorder.js","sourceRoot":"","sources":["../../../../src/commands/profile/portfolio/reorder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Shared helpers for `ttctl profile portfolio` leaves. Re-exports
3
+ * `loadAuthTokenOrExit` from `../shared.ts` (post-#107 unification — the
4
+ * separate token file is gone; auth-token resolution is centralised on
5
+ * the in-memory `config.auth.token`).
6
+ */
7
+ export { loadAuthTokenOrExit } from "../shared.js";
8
+ //# sourceMappingURL=shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../../src/commands/profile/portfolio/shared.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC"}