@seamapi/cli 0.18.1 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (364) hide show
  1. package/README.md +55 -1
  2. package/bin/cli.js +73 -249
  3. package/bin/cli.js.map +1 -1
  4. package/lib/args/coerce.d.ts +28 -0
  5. package/lib/args/coerce.js +131 -0
  6. package/lib/args/coerce.js.map +1 -0
  7. package/lib/{util/cli-args.d.ts → args/parse.d.ts} +12 -15
  8. package/lib/{util/cli-args.js → args/parse.js} +21 -24
  9. package/lib/args/parse.js.map +1 -0
  10. package/lib/args/validate.d.ts +23 -0
  11. package/lib/args/validate.js +42 -0
  12. package/lib/args/validate.js.map +1 -0
  13. package/lib/auth/operations.d.ts +54 -0
  14. package/lib/auth/operations.js +115 -0
  15. package/lib/auth/operations.js.map +1 -0
  16. package/lib/{validate-token.js → auth/validate-token.js} +2 -2
  17. package/lib/auth/validate-token.js.map +1 -0
  18. package/lib/blueprint/cache.d.ts +16 -0
  19. package/lib/blueprint/cache.js +73 -0
  20. package/lib/blueprint/cache.js.map +1 -0
  21. package/lib/blueprint/endpoint.d.ts +14 -0
  22. package/lib/{get-response-key.js → blueprint/endpoint.js} +11 -2
  23. package/lib/blueprint/endpoint.js.map +1 -0
  24. package/lib/blueprint/index.d.ts +12 -0
  25. package/lib/blueprint/index.js +10 -0
  26. package/lib/blueprint/index.js.map +1 -0
  27. package/lib/blueprint/source-npm.d.ts +10 -0
  28. package/lib/{blueprint.js → blueprint/source-npm.js} +20 -74
  29. package/lib/blueprint/source-npm.js.map +1 -0
  30. package/lib/blueprint/source-remote.d.ts +6 -0
  31. package/lib/blueprint/source-remote.js +14 -0
  32. package/lib/blueprint/source-remote.js.map +1 -0
  33. package/lib/commands/api-command.d.ts +8 -0
  34. package/lib/commands/api-command.js +71 -0
  35. package/lib/commands/api-command.js.map +1 -0
  36. package/lib/commands/local/completion.d.ts +18 -0
  37. package/lib/commands/local/completion.js +35 -0
  38. package/lib/commands/local/completion.js.map +1 -0
  39. package/lib/commands/local/config-reveal-location.d.ts +2 -0
  40. package/lib/commands/local/config-reveal-location.js +15 -0
  41. package/lib/commands/local/config-reveal-location.js.map +1 -0
  42. package/lib/commands/local/config-set-fake-server.d.ts +3 -0
  43. package/lib/commands/local/config-set-fake-server.js +20 -0
  44. package/lib/commands/local/config-set-fake-server.js.map +1 -0
  45. package/lib/commands/local/config-use-remote-api-defs.d.ts +2 -0
  46. package/lib/commands/local/config-use-remote-api-defs.js +20 -0
  47. package/lib/commands/local/config-use-remote-api-defs.js.map +1 -0
  48. package/lib/commands/local/health.d.ts +2 -0
  49. package/lib/commands/local/health.js +18 -0
  50. package/lib/commands/local/health.js.map +1 -0
  51. package/lib/commands/local/login.d.ts +2 -0
  52. package/lib/commands/local/login.js +35 -0
  53. package/lib/commands/local/login.js.map +1 -0
  54. package/lib/commands/local/logout.d.ts +2 -0
  55. package/lib/commands/local/logout.js +17 -0
  56. package/lib/commands/local/logout.js.map +1 -0
  57. package/lib/commands/local/select-server.d.ts +2 -0
  58. package/lib/commands/local/select-server.js +27 -0
  59. package/lib/commands/local/select-server.js.map +1 -0
  60. package/lib/commands/local/select-workspace.d.ts +2 -0
  61. package/lib/commands/local/select-workspace.js +22 -0
  62. package/lib/commands/local/select-workspace.js.map +1 -0
  63. package/lib/commands/local/wizard.d.ts +9 -0
  64. package/lib/commands/local/wizard.js +28 -0
  65. package/lib/commands/local/wizard.js.map +1 -0
  66. package/lib/commands/registry.d.ts +54 -0
  67. package/lib/commands/registry.js +64 -0
  68. package/lib/commands/registry.js.map +1 -0
  69. package/lib/{command-spec.d.ts → commands/spec.d.ts} +8 -12
  70. package/lib/{command-spec.js → commands/spec.js} +27 -120
  71. package/lib/commands/spec.js.map +1 -0
  72. package/lib/config/config-store.d.ts +23 -8
  73. package/lib/config/config-store.js +16 -42
  74. package/lib/config/config-store.js.map +1 -1
  75. package/lib/config/index.d.ts +2 -1
  76. package/lib/config/index.js +2 -1
  77. package/lib/config/index.js.map +1 -1
  78. package/lib/config/memory-config-store.d.ts +21 -0
  79. package/lib/config/memory-config-store.js +48 -0
  80. package/lib/config/memory-config-store.js.map +1 -0
  81. package/lib/config/migrate.js +1 -1
  82. package/lib/config/migrate.js.map +1 -1
  83. package/lib/config/values.d.ts +12 -0
  84. package/lib/config/values.js +50 -0
  85. package/lib/config/values.js.map +1 -0
  86. package/lib/context.d.ts +37 -0
  87. package/lib/context.js +31 -0
  88. package/lib/context.js.map +1 -0
  89. package/lib/env.d.ts +5 -0
  90. package/lib/env.js +5 -0
  91. package/lib/env.js.map +1 -1
  92. package/lib/errors.d.ts +31 -0
  93. package/lib/errors.js +58 -0
  94. package/lib/errors.js.map +1 -0
  95. package/lib/http/api.d.ts +37 -0
  96. package/lib/http/api.js +20 -0
  97. package/lib/http/api.js.map +1 -0
  98. package/lib/http/client.d.ts +4 -0
  99. package/lib/{get-seam.js → http/client.js} +16 -17
  100. package/lib/http/client.js.map +1 -0
  101. package/lib/http/follow-ups.d.ts +6 -0
  102. package/lib/http/follow-ups.js +30 -0
  103. package/lib/http/follow-ups.js.map +1 -0
  104. package/lib/http/memory-seam-api.d.ts +22 -0
  105. package/lib/http/memory-seam-api.js +41 -0
  106. package/lib/http/memory-seam-api.js.map +1 -0
  107. package/lib/http/request.d.ts +19 -0
  108. package/lib/http/request.js +39 -0
  109. package/lib/http/request.js.map +1 -0
  110. package/lib/{interact-for-access-code.js → interactions/access-code.js} +4 -4
  111. package/lib/interactions/access-code.js.map +1 -0
  112. package/lib/{interact-for-acs-entrance.js → interactions/acs-entrance.js} +3 -3
  113. package/lib/interactions/acs-entrance.js.map +1 -0
  114. package/lib/{interact-for-acs-system.js → interactions/acs-system.js} +3 -3
  115. package/lib/interactions/acs-system.js.map +1 -0
  116. package/lib/{interact-for-acs-user.js → interactions/acs-user.js} +4 -4
  117. package/lib/interactions/acs-user.js.map +1 -0
  118. package/lib/{interact-for-action-attempt-poll.js → interactions/action-attempt-poll.js} +5 -5
  119. package/lib/interactions/action-attempt-poll.js.map +1 -0
  120. package/lib/{interact-for-array.js → interactions/array.js} +4 -3
  121. package/lib/interactions/array.js.map +1 -0
  122. package/lib/{interact-for-blueprint-object.d.ts → interactions/blueprint-object.d.ts} +3 -2
  123. package/lib/{interact-for-blueprint-object.js → interactions/blueprint-object.js} +49 -20
  124. package/lib/interactions/blueprint-object.js.map +1 -0
  125. package/lib/{interact-for-command-params.d.ts → interactions/command-params.d.ts} +2 -2
  126. package/lib/{interact-for-command-params.js → interactions/command-params.js} +4 -3
  127. package/lib/interactions/command-params.js.map +1 -0
  128. package/lib/interactions/command-selection.d.ts +10 -0
  129. package/lib/{interact-for-command-selection.js → interactions/command-selection.js} +9 -15
  130. package/lib/interactions/command-selection.js.map +1 -0
  131. package/lib/{interact-for-connected-account.js → interactions/connected-account.js} +3 -3
  132. package/lib/interactions/connected-account.js.map +1 -0
  133. package/lib/{interact-for-custom-metadata.js → interactions/custom-metadata.js} +4 -3
  134. package/lib/interactions/custom-metadata.js.map +1 -0
  135. package/lib/{interact-for-device.js → interactions/device.js} +3 -3
  136. package/lib/interactions/device.js.map +1 -0
  137. package/lib/interactions/index.d.ts +19 -0
  138. package/lib/interactions/index.js +20 -0
  139. package/lib/interactions/index.js.map +1 -0
  140. package/lib/{interact-for-login.js → interactions/login.js} +16 -14
  141. package/lib/interactions/login.js.map +1 -0
  142. package/lib/{interact-for-resource.js → interactions/resource.js} +3 -3
  143. package/lib/interactions/resource.js.map +1 -0
  144. package/lib/{interact-for-server-selection.js → interactions/server-selection.js} +10 -13
  145. package/lib/interactions/server-selection.js.map +1 -0
  146. package/lib/{interact-for-timestamp.js → interactions/timestamp.js} +2 -2
  147. package/lib/interactions/timestamp.js.map +1 -0
  148. package/lib/{interact-for-use-remote-api-defs.js → interactions/use-remote-api-defs.js} +5 -6
  149. package/lib/interactions/use-remote-api-defs.js.map +1 -0
  150. package/lib/{interact-for-user-identity.js → interactions/user-identity.js} +3 -3
  151. package/lib/interactions/user-identity.js.map +1 -0
  152. package/lib/{interact-for-workspace-id.js → interactions/workspace-id.js} +11 -10
  153. package/lib/interactions/workspace-id.js.map +1 -0
  154. package/lib/memory-prompt.d.ts +32 -0
  155. package/lib/memory-prompt.js +41 -0
  156. package/lib/memory-prompt.js.map +1 -0
  157. package/lib/output/get-output.d.ts +1 -1
  158. package/lib/output/get-output.js +1 -1
  159. package/lib/output/get-output.js.map +1 -1
  160. package/lib/output/{create-memory-output.d.ts → memory-output.d.ts} +1 -1
  161. package/lib/output/{create-memory-output.js → memory-output.js} +2 -2
  162. package/lib/output/memory-output.js.map +1 -0
  163. package/lib/output/{create-output.d.ts → output.d.ts} +18 -1
  164. package/lib/output/output.js +46 -0
  165. package/lib/output/output.js.map +1 -0
  166. package/lib/output/read-stdin-json.js.map +1 -0
  167. package/lib/output/resolve-output-format.d.ts +1 -1
  168. package/lib/{util → output}/with-loading.js +1 -1
  169. package/lib/output/with-loading.js.map +1 -0
  170. package/lib/prompt.d.ts +101 -0
  171. package/lib/{util/prompt.js → prompt.js} +83 -56
  172. package/lib/prompt.js.map +1 -0
  173. package/lib/{completion → render/completion}/describe.js +1 -2
  174. package/lib/render/completion/describe.js.map +1 -0
  175. package/lib/{completion → render/completion}/index.d.ts +2 -2
  176. package/lib/{completion → render/completion}/index.js +1 -2
  177. package/lib/render/completion/index.js.map +1 -0
  178. package/lib/{completion → render/completion}/render-bash.d.ts +1 -1
  179. package/lib/{completion → render/completion}/render-bash.js +1 -1
  180. package/lib/render/completion/render-bash.js.map +1 -0
  181. package/lib/{completion → render/completion}/render-fish.d.ts +1 -1
  182. package/lib/render/completion/render-fish.js.map +1 -0
  183. package/lib/{completion → render/completion}/render-zsh.d.ts +1 -1
  184. package/lib/{completion → render/completion}/render-zsh.js +1 -1
  185. package/lib/render/completion/render-zsh.js.map +1 -0
  186. package/lib/{render-help.d.ts → render/help.d.ts} +1 -1
  187. package/lib/{render-help.js → render/help.js} +2 -2
  188. package/lib/render/help.js.map +1 -0
  189. package/lib/render/text.d.ts +4 -0
  190. package/lib/render/text.js +16 -0
  191. package/lib/render/text.js.map +1 -0
  192. package/lib/version.d.ts +2 -2
  193. package/lib/version.js +2 -2
  194. package/package.json +4 -3
  195. package/src/bin/cli.ts +91 -332
  196. package/src/lib/args/coerce.ts +164 -0
  197. package/src/lib/{util/cli-args.ts → args/parse.ts} +30 -25
  198. package/src/lib/args/validate.ts +73 -0
  199. package/src/lib/auth/operations.ts +169 -0
  200. package/src/lib/{validate-token.ts → auth/validate-token.ts} +2 -2
  201. package/src/lib/blueprint/cache.ts +97 -0
  202. package/src/lib/{get-response-key.ts → blueprint/endpoint.ts} +17 -3
  203. package/src/lib/blueprint/index.ts +27 -0
  204. package/src/lib/{blueprint.ts → blueprint/source-npm.ts} +27 -99
  205. package/src/lib/blueprint/source-remote.ts +17 -0
  206. package/src/lib/commands/api-command.ts +109 -0
  207. package/src/lib/commands/local/completion.ts +51 -0
  208. package/src/lib/commands/local/config-reveal-location.ts +16 -0
  209. package/src/lib/commands/local/config-set-fake-server.ts +21 -0
  210. package/src/lib/commands/local/config-use-remote-api-defs.ts +23 -0
  211. package/src/lib/commands/local/health.ts +22 -0
  212. package/src/lib/commands/local/login.ts +42 -0
  213. package/src/lib/commands/local/logout.ts +18 -0
  214. package/src/lib/commands/local/select-server.ts +30 -0
  215. package/src/lib/commands/local/select-workspace.ts +25 -0
  216. package/src/lib/commands/local/wizard.ts +31 -0
  217. package/src/lib/commands/registry.ts +127 -0
  218. package/src/lib/{command-spec.ts → commands/spec.ts} +30 -131
  219. package/src/lib/config/config-store.ts +39 -64
  220. package/src/lib/config/index.ts +8 -1
  221. package/src/lib/config/memory-config-store.ts +62 -0
  222. package/src/lib/config/migrate.ts +1 -1
  223. package/src/lib/config/values.ts +72 -0
  224. package/src/lib/context.ts +84 -0
  225. package/src/lib/env.ts +9 -2
  226. package/src/lib/errors.ts +67 -0
  227. package/src/lib/http/api.ts +61 -0
  228. package/src/lib/{get-seam.ts → http/client.ts} +19 -18
  229. package/src/lib/http/follow-ups.ts +42 -0
  230. package/src/lib/http/memory-seam-api.ts +57 -0
  231. package/src/lib/http/request.ts +69 -0
  232. package/src/lib/{interact-for-access-code.ts → interactions/access-code.ts} +4 -3
  233. package/src/lib/{interact-for-acs-entrance.ts → interactions/acs-entrance.ts} +3 -2
  234. package/src/lib/{interact-for-acs-system.ts → interactions/acs-system.ts} +3 -2
  235. package/src/lib/{interact-for-acs-user.ts → interactions/acs-user.ts} +4 -3
  236. package/src/lib/{interact-for-action-attempt-poll.ts → interactions/action-attempt-poll.ts} +4 -4
  237. package/src/lib/{interact-for-array.ts → interactions/array.ts} +3 -3
  238. package/src/lib/{interact-for-blueprint-object.ts → interactions/blueprint-object.ts} +57 -24
  239. package/src/lib/{interact-for-command-params.ts → interactions/command-params.ts} +6 -4
  240. package/src/lib/{interact-for-command-selection.ts → interactions/command-selection.ts} +11 -23
  241. package/src/lib/{interact-for-connected-account.ts → interactions/connected-account.ts} +3 -2
  242. package/src/lib/{interact-for-custom-metadata.ts → interactions/custom-metadata.ts} +3 -7
  243. package/src/lib/{interact-for-device.ts → interactions/device.ts} +3 -2
  244. package/src/lib/interactions/index.ts +19 -0
  245. package/src/lib/{interact-for-login.ts → interactions/login.ts} +16 -13
  246. package/src/lib/{interact-for-resource.ts → interactions/resource.ts} +2 -2
  247. package/src/lib/{interact-for-server-selection.ts → interactions/server-selection.ts} +12 -17
  248. package/src/lib/{interact-for-timestamp.ts → interactions/timestamp.ts} +1 -1
  249. package/src/lib/{interact-for-use-remote-api-defs.ts → interactions/use-remote-api-defs.ts} +4 -5
  250. package/src/lib/{interact-for-user-identity.ts → interactions/user-identity.ts} +3 -2
  251. package/src/lib/{interact-for-workspace-id.ts → interactions/workspace-id.ts} +10 -17
  252. package/src/lib/memory-prompt.ts +89 -0
  253. package/src/lib/output/get-output.ts +1 -1
  254. package/src/lib/output/{create-memory-output.ts → memory-output.ts} +1 -1
  255. package/src/lib/output/{create-output.ts → output.ts} +47 -32
  256. package/src/lib/output/resolve-output-format.ts +1 -1
  257. package/src/lib/{util → output}/with-loading.ts +1 -1
  258. package/src/lib/prompt.ts +306 -0
  259. package/src/lib/{completion → render/completion}/describe.ts +1 -2
  260. package/src/lib/{completion → render/completion}/index.ts +3 -4
  261. package/src/lib/{completion → render/completion}/render-bash.ts +1 -1
  262. package/src/lib/{completion → render/completion}/render-fish.ts +2 -1
  263. package/src/lib/{completion → render/completion}/render-zsh.ts +2 -1
  264. package/src/lib/{render-help.ts → render/help.ts} +1 -1
  265. package/src/lib/render/text.ts +17 -0
  266. package/src/lib/version.ts +2 -2
  267. package/lib/blueprint.d.ts +0 -7
  268. package/lib/blueprint.js.map +0 -1
  269. package/lib/command-spec.js.map +0 -1
  270. package/lib/completion/describe.js.map +0 -1
  271. package/lib/completion/index.js.map +0 -1
  272. package/lib/completion/render-bash.js.map +0 -1
  273. package/lib/completion/render-fish.js.map +0 -1
  274. package/lib/completion/render-zsh.js.map +0 -1
  275. package/lib/get-api-blueprint.d.ts +0 -6
  276. package/lib/get-api-blueprint.js +0 -18
  277. package/lib/get-api-blueprint.js.map +0 -1
  278. package/lib/get-command-blueprint-def.d.ts +0 -2
  279. package/lib/get-command-blueprint-def.js +0 -11
  280. package/lib/get-command-blueprint-def.js.map +0 -1
  281. package/lib/get-credentials.d.ts +0 -15
  282. package/lib/get-credentials.js +0 -35
  283. package/lib/get-credentials.js.map +0 -1
  284. package/lib/get-current-workspace-id.d.ts +0 -1
  285. package/lib/get-current-workspace-id.js +0 -9
  286. package/lib/get-current-workspace-id.js.map +0 -1
  287. package/lib/get-response-key.d.ts +0 -9
  288. package/lib/get-response-key.js.map +0 -1
  289. package/lib/get-seam.d.ts +0 -3
  290. package/lib/get-seam.js.map +0 -1
  291. package/lib/get-server.d.ts +0 -6
  292. package/lib/get-server.js +0 -17
  293. package/lib/get-server.js.map +0 -1
  294. package/lib/interact-for-access-code.js.map +0 -1
  295. package/lib/interact-for-acs-entrance.js.map +0 -1
  296. package/lib/interact-for-acs-system.js.map +0 -1
  297. package/lib/interact-for-acs-user.js.map +0 -1
  298. package/lib/interact-for-action-attempt-poll.js.map +0 -1
  299. package/lib/interact-for-array.js.map +0 -1
  300. package/lib/interact-for-blueprint-object.js.map +0 -1
  301. package/lib/interact-for-command-params.js.map +0 -1
  302. package/lib/interact-for-command-selection.d.ts +0 -2
  303. package/lib/interact-for-command-selection.js.map +0 -1
  304. package/lib/interact-for-connected-account.js.map +0 -1
  305. package/lib/interact-for-custom-metadata.js.map +0 -1
  306. package/lib/interact-for-device.js.map +0 -1
  307. package/lib/interact-for-login.js.map +0 -1
  308. package/lib/interact-for-resource.js.map +0 -1
  309. package/lib/interact-for-server-selection.js.map +0 -1
  310. package/lib/interact-for-timestamp.js.map +0 -1
  311. package/lib/interact-for-use-remote-api-defs.js.map +0 -1
  312. package/lib/interact-for-user-identity.js.map +0 -1
  313. package/lib/interact-for-workspace-id.js.map +0 -1
  314. package/lib/output/create-memory-output.js.map +0 -1
  315. package/lib/output/create-output.js +0 -34
  316. package/lib/output/create-output.js.map +0 -1
  317. package/lib/render-help.js.map +0 -1
  318. package/lib/types.d.ts +0 -6
  319. package/lib/types.js +0 -2
  320. package/lib/types.js.map +0 -1
  321. package/lib/util/cli-args.js.map +0 -1
  322. package/lib/util/ellipsis.d.ts +0 -1
  323. package/lib/util/ellipsis.js +0 -6
  324. package/lib/util/ellipsis.js.map +0 -1
  325. package/lib/util/prompt.d.ts +0 -80
  326. package/lib/util/prompt.js.map +0 -1
  327. package/lib/util/read-stdin-json.js.map +0 -1
  328. package/lib/util/request-seam-api.d.ts +0 -7
  329. package/lib/util/request-seam-api.js +0 -26
  330. package/lib/util/request-seam-api.js.map +0 -1
  331. package/lib/util/with-loading.js.map +0 -1
  332. package/lib/validate-token.js.map +0 -1
  333. package/src/lib/get-api-blueprint.ts +0 -31
  334. package/src/lib/get-command-blueprint-def.ts +0 -15
  335. package/src/lib/get-credentials.ts +0 -38
  336. package/src/lib/get-current-workspace-id.ts +0 -9
  337. package/src/lib/get-server.ts +0 -20
  338. package/src/lib/types.ts +0 -7
  339. package/src/lib/util/ellipsis.ts +0 -4
  340. package/src/lib/util/prompt.ts +0 -229
  341. package/src/lib/util/request-seam-api.ts +0 -47
  342. /package/lib/{validate-token.d.ts → auth/validate-token.d.ts} +0 -0
  343. /package/lib/{interact-for-access-code.d.ts → interactions/access-code.d.ts} +0 -0
  344. /package/lib/{interact-for-acs-entrance.d.ts → interactions/acs-entrance.d.ts} +0 -0
  345. /package/lib/{interact-for-acs-system.d.ts → interactions/acs-system.d.ts} +0 -0
  346. /package/lib/{interact-for-acs-user.d.ts → interactions/acs-user.d.ts} +0 -0
  347. /package/lib/{interact-for-action-attempt-poll.d.ts → interactions/action-attempt-poll.d.ts} +0 -0
  348. /package/lib/{interact-for-array.d.ts → interactions/array.d.ts} +0 -0
  349. /package/lib/{interact-for-connected-account.d.ts → interactions/connected-account.d.ts} +0 -0
  350. /package/lib/{interact-for-custom-metadata.d.ts → interactions/custom-metadata.d.ts} +0 -0
  351. /package/lib/{interact-for-device.d.ts → interactions/device.d.ts} +0 -0
  352. /package/lib/{interact-for-login.d.ts → interactions/login.d.ts} +0 -0
  353. /package/lib/{interact-for-resource.d.ts → interactions/resource.d.ts} +0 -0
  354. /package/lib/{interact-for-server-selection.d.ts → interactions/server-selection.d.ts} +0 -0
  355. /package/lib/{interact-for-timestamp.d.ts → interactions/timestamp.d.ts} +0 -0
  356. /package/lib/{interact-for-use-remote-api-defs.d.ts → interactions/use-remote-api-defs.d.ts} +0 -0
  357. /package/lib/{interact-for-user-identity.d.ts → interactions/user-identity.d.ts} +0 -0
  358. /package/lib/{interact-for-workspace-id.d.ts → interactions/workspace-id.d.ts} +0 -0
  359. /package/lib/{util → output}/read-stdin-json.d.ts +0 -0
  360. /package/lib/{util → output}/read-stdin-json.js +0 -0
  361. /package/lib/{util → output}/with-loading.d.ts +0 -0
  362. /package/lib/{completion → render/completion}/describe.d.ts +0 -0
  363. /package/lib/{completion → render/completion}/render-fish.js +0 -0
  364. /package/src/lib/{util → output}/read-stdin-json.ts +0 -0
@@ -1,29 +1,30 @@
1
1
  import type { Parameter } from '@seamapi/blueprint'
2
2
 
3
- import { interactForAccessCode } from './interact-for-access-code.js'
4
- import { interactForAcsEntrance } from './interact-for-acs-entrance.js'
5
- import { interactForAcsSystem } from './interact-for-acs-system.js'
6
- import { interactForAcsUser } from './interact-for-acs-user.js'
7
- import { interactForArray } from './interact-for-array.js'
8
- import { interactForConnectedAccount } from './interact-for-connected-account.js'
9
- import { interactForCustomMetadata } from './interact-for-custom-metadata.js'
10
- import { interactForDevice } from './interact-for-device.js'
11
- import { interactForTimestamp } from './interact-for-timestamp.js'
12
- import { interactForUserIdentity } from './interact-for-user-identity.js'
13
- import { getOutput } from './output/get-output.js'
14
- import type { ContextHelpers } from './types.js'
15
- import { NonInteractiveError, toArgName } from './util/cli-args.js'
16
- import { ellipsis } from './util/ellipsis.js'
3
+ import { assertRequiredParams } from 'lib/args/validate.js'
4
+ import type { CliContext } from 'lib/context.js'
5
+ import { NonInteractiveError, PromptCancelledError } from 'lib/errors.js'
6
+ import { getOutput } from 'lib/output/get-output.js'
17
7
  import {
18
8
  promptAutocomplete,
19
9
  promptAutocompleteMultiselect,
20
- PromptCancelledError,
21
10
  promptConfirm,
22
11
  promptNumber,
23
12
  promptSelect,
24
13
  promptText,
25
14
  withBackHint,
26
- } from './util/prompt.js'
15
+ } from 'lib/prompt.js'
16
+ import { ellipsis } from 'lib/render/text.js'
17
+
18
+ import { interactForAccessCode } from './access-code.js'
19
+ import { interactForAcsEntrance } from './acs-entrance.js'
20
+ import { interactForAcsSystem } from './acs-system.js'
21
+ import { interactForAcsUser } from './acs-user.js'
22
+ import { interactForArray } from './array.js'
23
+ import { interactForConnectedAccount } from './connected-account.js'
24
+ import { interactForCustomMetadata } from './custom-metadata.js'
25
+ import { interactForDevice } from './device.js'
26
+ import { interactForTimestamp } from './timestamp.js'
27
+ import { interactForUserIdentity } from './user-identity.js'
27
28
 
28
29
  const ergonomicPropOrder = [
29
30
  'name',
@@ -41,10 +42,11 @@ export const interactForBlueprintObject = async (
41
42
  command: string[]
42
43
  parameters: Parameter[]
43
44
  params: Record<string, any>
45
+ hasRequiredParameters?: boolean
44
46
  isSubProperty?: boolean
45
47
  subPropertyPath?: string
46
48
  },
47
- ctx: ContextHelpers,
49
+ ctx: CliContext,
48
50
  ): Promise<any> => {
49
51
  // Clone args and args params so that we can mutate it
50
52
  args = { ...args, params: { ...args.params } }
@@ -59,26 +61,31 @@ export const interactForBlueprintObject = async (
59
61
  const isSupplied = (k: string): boolean => args.params[k] !== undefined
60
62
 
61
63
  const haveAllRequiredParams = required.every(isSupplied)
64
+ // Some request schemas require one of several parameters without marking
65
+ // any individual parameter as required. The request-level signal tells us
66
+ // that an entirely empty request still needs interaction.
67
+ const hasAnyParams = Object.values(args.params).some(
68
+ (value) => value !== undefined,
69
+ )
70
+ const satisfiesRequestRequirement =
71
+ args.hasRequiredParameters !== true || hasAnyParams
62
72
 
63
73
  const cmdPath = `/${args.command.join('/').replace(/-/g, '_')}`
64
74
 
65
75
  const shouldAutoSubmit =
66
76
  ctx.interactivity !== 'interactive' &&
67
77
  haveAllRequiredParams &&
78
+ satisfiesRequestRequirement &&
68
79
  !args.isSubProperty
69
80
  if (shouldAutoSubmit) {
70
81
  return args.params
71
82
  }
72
83
 
73
84
  if (ctx.interactivity === 'non-interactive') {
74
- const missing = required.filter((k) => !isSupplied(k))
75
85
  const target = args.isSubProperty ? `"${args.subPropertyPath}"` : cmdPath
86
+ assertRequiredParams(args.parameters, args.params, target)
76
87
  throw new NonInteractiveError(
77
- missing.length > 0
78
- ? `Missing required ${
79
- missing.length === 1 ? 'parameter' : 'parameters'
80
- } for ${target}: ${missing.map(toArgName).join(' ')}`
81
- : `Cannot prompt for ${target} in non-interactive mode`,
88
+ `Cannot prompt for ${target} in non-interactive mode`,
82
89
  )
83
90
  }
84
91
 
@@ -102,7 +109,9 @@ export const interactForBlueprintObject = async (
102
109
  paramToEdit = await promptAutocomplete({
103
110
  message: parameterSelectionMessage,
104
111
  choices: [
105
- ...(haveAllRequiredParams && !args.isSubProperty
112
+ ...(haveAllRequiredParams &&
113
+ satisfiesRequestRequirement &&
114
+ !args.isSubProperty
106
115
  ? [
107
116
  {
108
117
  value: 'done',
@@ -174,6 +183,30 @@ export const interactForBlueprintObject = async (
174
183
  // Dismissing any prompt below returns to the parameter menu with the
175
184
  // parameter left as it was, rather than ending the whole command.
176
185
  try {
186
+ if (prop != null && (prop.isNullable || isSupplied(paramToEdit))) {
187
+ const action = await promptSelect({
188
+ message: withBackHint(`${paramToEdit}:`),
189
+ choices: [
190
+ { label: 'Enter a value', value: 'value' },
191
+ ...(prop.isNullable
192
+ ? [{ label: 'Set to null', value: 'null' as const }]
193
+ : []),
194
+ ...(isSupplied(paramToEdit)
195
+ ? [{ label: 'Unset', value: 'unset' as const }]
196
+ : []),
197
+ ],
198
+ })
199
+
200
+ if (action === 'null') {
201
+ args.params[paramToEdit] = null
202
+ return interactForBlueprintObject(args, ctx)
203
+ }
204
+ if (action === 'unset') {
205
+ delete args.params[paramToEdit]
206
+ return interactForBlueprintObject(args, ctx)
207
+ }
208
+ }
209
+
177
210
  if (paramToEdit === 'device_id') {
178
211
  args.params[paramToEdit] = await interactForDevice()
179
212
  return interactForBlueprintObject(args, ctx)
@@ -1,13 +1,14 @@
1
- import { getCommandBlueprintDef } from './get-command-blueprint-def.js'
2
- import { interactForBlueprintObject } from './interact-for-blueprint-object.js'
3
- import type { ContextHelpers } from './types.js'
1
+ import { getCommandBlueprintDef } from 'lib/blueprint/endpoint.js'
2
+ import type { CliContext } from 'lib/context.js'
3
+
4
+ import { interactForBlueprintObject } from './blueprint-object.js'
4
5
 
5
6
  export const interactForCommandParams = async (
6
7
  args: {
7
8
  command: string[]
8
9
  params: Record<string, any>
9
10
  },
10
- ctx: ContextHelpers,
11
+ ctx: CliContext,
11
12
  ): Promise<any> => {
12
13
  const endpoint = getCommandBlueprintDef(args.command, ctx)
13
14
 
@@ -16,6 +17,7 @@ export const interactForCommandParams = async (
16
17
  command: args.command,
17
18
  params: args.params,
18
19
  parameters: endpoint.request.parameters,
20
+ hasRequiredParameters: endpoint.request.hasRequiredParameters,
19
21
  },
20
22
  ctx,
21
23
  )
@@ -1,12 +1,8 @@
1
1
  import { isDeepStrictEqual as isEqual } from 'node:util'
2
2
 
3
- import type { ContextHelpers } from './types.js'
4
- import { NonInteractiveError } from './util/cli-args.js'
5
- import {
6
- promptAutocomplete,
7
- PromptCancelledError,
8
- withBackHint,
9
- } from './util/prompt.js'
3
+ import type { Interactivity } from 'lib/args/parse.js'
4
+ import { NonInteractiveError, PromptCancelledError } from 'lib/errors.js'
5
+ import { promptAutocomplete, withBackHint } from 'lib/prompt.js'
10
6
 
11
7
  const uniqBy = <T>(items: T[], keyOf: (item: T) => unknown): T[] => {
12
8
  const seen = new Set<unknown>()
@@ -29,24 +25,16 @@ function ergonomicSort(aStr: string, bStr: string) {
29
25
  return a > b ? 1 : a < b ? -1 : 0
30
26
  }
31
27
 
28
+ /**
29
+ * Resolve a command path to a full command, prompting to complete it when
30
+ * interactive. `commands` is every selectable command path, from the
31
+ * registry's spec.
32
+ */
32
33
  export async function interactForCommandSelection(
33
34
  commandPath: string[],
34
- helpers: ContextHelpers,
35
- ) {
36
- const commands = helpers.blueprint.routes
37
- .flatMap((route) => route.endpoints)
38
- .map((endpoint) =>
39
- endpoint.path.replace(/_/g, '-').replace(/^\//, '').split('/'),
40
- )
41
- .concat([
42
- ['login'],
43
- ['logout'],
44
- ['config', 'reveal-location'],
45
- ['config', 'use-remote-api-defs'],
46
- ['select', 'workspace'],
47
- ['select', 'server'],
48
- ['health', 'get-health'],
49
- ])
35
+ helpers: { commands: string[][]; interactivity: Interactivity },
36
+ ): Promise<string[]> {
37
+ const commands = helpers.commands
50
38
 
51
39
  const possibleCommands = uniqBy(
52
40
  commandPath.length === 0
@@ -1,5 +1,6 @@
1
- import { getSeam } from './get-seam.js'
2
- import { interactForResource } from './interact-for-resource.js'
1
+ import { getSeam } from 'lib/http/client.js'
2
+
3
+ import { interactForResource } from './resource.js'
3
4
  export const interactForConnectedAccount = async () => {
4
5
  const seam = await getSeam()
5
6
 
@@ -1,10 +1,6 @@
1
- import { getOutput } from './output/get-output.js'
2
- import {
3
- PromptCancelledError,
4
- promptSelect,
5
- promptText,
6
- withBackHint,
7
- } from './util/prompt.js'
1
+ import { PromptCancelledError } from 'lib/errors.js'
2
+ import { getOutput } from 'lib/output/get-output.js'
3
+ import { promptSelect, promptText, withBackHint } from 'lib/prompt.js'
8
4
 
9
5
  // Structurally the CustomMetadata of @seamapi/types, spelled out here so the
10
6
  // published declarations do not depend on a development-only package.
@@ -1,5 +1,6 @@
1
- import { getSeam } from './get-seam.js'
2
- import { interactForResource } from './interact-for-resource.js'
1
+ import { getSeam } from 'lib/http/client.js'
2
+
3
+ import { interactForResource } from './resource.js'
3
4
  export const interactForDevice = async () => {
4
5
  const seam = await getSeam()
5
6
 
@@ -0,0 +1,19 @@
1
+ export * from './access-code.js'
2
+ export * from './acs-entrance.js'
3
+ export * from './acs-system.js'
4
+ export * from './acs-user.js'
5
+ export * from './action-attempt-poll.js'
6
+ export * from './array.js'
7
+ export * from './blueprint-object.js'
8
+ export * from './command-params.js'
9
+ export * from './command-selection.js'
10
+ export * from './connected-account.js'
11
+ export * from './custom-metadata.js'
12
+ export * from './device.js'
13
+ export * from './login.js'
14
+ export * from './resource.js'
15
+ export * from './server-selection.js'
16
+ export * from './timestamp.js'
17
+ export * from './use-remote-api-defs.js'
18
+ export * from './user-identity.js'
19
+ export * from './workspace-id.js'
@@ -1,24 +1,27 @@
1
1
  import { isApiKey, isPersonalAccessToken } from '@seamapi/http/connect'
2
2
  import chalk from 'chalk'
3
3
 
4
- import { getConfigStore } from './config/index.js'
5
- import { assertEnvVarUnset, getTokenFromEnv, tokenEnvVar } from './env.js'
6
- import { getServer } from './get-server.js'
7
- import { interactForWorkspaceId } from './interact-for-workspace-id.js'
8
- import { getOutput } from './output/get-output.js'
9
- import { promptText } from './util/prompt.js'
10
- import { withLoading } from './util/with-loading.js'
11
- import { validateToken } from './validate-token.js'
4
+ import { assertMutable, storeToken } from 'lib/auth/operations.js'
5
+ import { validateToken } from 'lib/auth/validate-token.js'
6
+ import { getConfigStore } from 'lib/config/index.js'
7
+ import { resolveAuth } from 'lib/context.js'
8
+ import { getOutput } from 'lib/output/get-output.js'
9
+ import { withLoading } from 'lib/output/with-loading.js'
10
+ import { promptText } from 'lib/prompt.js'
11
+
12
+ import { interactForWorkspaceId } from './workspace-id.js'
12
13
 
13
14
  export const interactForLogin = async () => {
14
- const config = await getConfigStore()
15
+ const config = getConfigStore()
15
16
  const output = getOutput()
17
+ const auth = resolveAuth(config)
16
18
 
17
- assertEnvVarUnset(tokenEnvVar, getTokenFromEnv(), 'log in')
19
+ // Refuse before prompting: nothing typed here could be stored.
20
+ assertMutable(auth, 'token', 'log in')
18
21
 
19
- if (getServer().includes('localhost')) {
22
+ if (auth.server.includes('localhost')) {
20
23
  output.info(
21
- `You're using a local Seam Connect instance, you can enter the API Key to your local user, you can create a new user from:\n\n${getServer()}/admin/create_user_with_api_key`,
24
+ `You're using a local Seam Connect instance, you can enter the API Key to your local user, you can create a new user from:\n\n${auth.server}/admin/create_user_with_api_key`,
22
25
  )
23
26
  } else {
24
27
  output.info(
@@ -51,6 +54,6 @@ export const interactForLogin = async () => {
51
54
  )
52
55
  }
53
56
 
54
- config.set(`${getServer()}.pat`, token)
57
+ storeToken(token, config)
55
58
  output.info(`Token saved! You may begin using the CLI!`)
56
59
  }
@@ -1,5 +1,5 @@
1
- import { promptAutocomplete, withBackHint } from './util/prompt.js'
2
- import { withLoading } from './util/with-loading.js'
1
+ import { withLoading } from 'lib/output/with-loading.js'
2
+ import { promptAutocomplete, withBackHint } from 'lib/prompt.js'
3
3
 
4
4
  export interface ResourceChoice {
5
5
  title: string
@@ -1,19 +1,18 @@
1
1
  import { randomBytes } from 'node:crypto'
2
2
 
3
- import { getConfigStore } from './config/index.js'
4
3
  import {
5
- assertEnvVarUnset,
6
- endpointEnvVar,
7
- getEndpointFromEnv,
8
- getTokenFromEnv,
9
- tokenEnvVar,
10
- } from './env.js'
11
- import { getServer } from './get-server.js'
12
- import { getOutput } from './output/get-output.js'
13
- import { promptAutocomplete, promptText } from './util/prompt.js'
4
+ assertMutable,
5
+ selectFakeServer,
6
+ selectServer,
7
+ } from 'lib/auth/operations.js'
8
+ import { getConfigStore } from 'lib/config/index.js'
9
+ import { resolveAuth } from 'lib/context.js'
10
+ import { getOutput } from 'lib/output/get-output.js'
11
+ import { promptAutocomplete, promptText } from 'lib/prompt.js'
14
12
 
15
13
  export async function interactForServerSelection() {
16
- assertEnvVarUnset(endpointEnvVar, getEndpointFromEnv(), 'select a server')
14
+ const config = getConfigStore()
15
+ assertMutable(resolveAuth(config), 'server', 'select a server')
17
16
 
18
17
  const servers = [
19
18
  'http://localhost:3020',
@@ -27,7 +26,6 @@ export async function interactForServerSelection() {
27
26
  choices: servers.map((server) => ({ label: server, value: server })),
28
27
  })
29
28
 
30
- const config = getConfigStore()
31
29
  const output = getOutput()
32
30
  if (server === servers[2]) {
33
31
  let userUrlSeed = await promptText({
@@ -38,13 +36,10 @@ export async function interactForServerSelection() {
38
36
  if (userUrlSeed.trim().length === 0) {
39
37
  userUrlSeed = randomBytes(5).toString('hex')
40
38
  }
41
- assertEnvVarUnset(tokenEnvVar, getTokenFromEnv(), 'log in')
42
- config.set('server', `https://${userUrlSeed}.fakeseamconnect.seam.vc`)
43
- config.set(`${getServer()}.pat`, `seam_apikey1_token`)
39
+ selectFakeServer({ urlSeed: userUrlSeed, config })
44
40
  output.info(`PAT set to use fakeseamconnect with "seam_apikey1_token"`)
45
41
  } else {
46
- config.set('server', server)
42
+ selectServer(server, config)
47
43
  }
48
- config.delete('current_workspace_id')
49
44
  output.info(`Server set to ${server}`)
50
45
  }
@@ -1,4 +1,4 @@
1
- import { promptText, withBackHint } from './util/prompt.js'
1
+ import { promptText, withBackHint } from 'lib/prompt.js'
2
2
 
3
3
  export const interactForTimestamp = async () => {
4
4
  const now = new Date().toISOString()
@@ -1,6 +1,6 @@
1
- import { getConfigStore } from './config/index.js'
2
- import { getOutput } from './output/get-output.js'
3
- import { promptSelect } from './util/prompt.js'
1
+ import { setUseRemoteApiDefs } from 'lib/auth/operations.js'
2
+ import { getOutput } from 'lib/output/get-output.js'
3
+ import { promptSelect } from 'lib/prompt.js'
4
4
 
5
5
  export async function interactForUseRemoteApiDefs() {
6
6
  const useRemoteApiDefs = await promptSelect({
@@ -17,7 +17,6 @@ export async function interactForUseRemoteApiDefs() {
17
17
  ],
18
18
  })
19
19
 
20
- const config = getConfigStore()
21
- config.set('use_remote_api_defs', useRemoteApiDefs)
20
+ setUseRemoteApiDefs(useRemoteApiDefs)
22
21
  getOutput().info(`Use remote API Definitions: ${useRemoteApiDefs}`)
23
22
  }
@@ -1,5 +1,6 @@
1
- import { getSeam } from './get-seam.js'
2
- import { interactForResource } from './interact-for-resource.js'
1
+ import { getSeam } from 'lib/http/client.js'
2
+
3
+ import { interactForResource } from './resource.js'
3
4
 
4
5
  export const interactForUserIdentity = async () => {
5
6
  const seam = await getSeam()
@@ -1,28 +1,21 @@
1
1
  import { SeamHttpWithoutWorkspace } from '@seamapi/http/connect'
2
2
 
3
- import { getConfigStore } from './config/index.js'
4
- import {
5
- assertEnvVarUnset,
6
- getWorkspaceIdFromEnv,
7
- workspaceIdEnvVar,
8
- } from './env.js'
9
- import { getSeamMultiWorkspace } from './get-seam.js'
10
- import { getServer } from './get-server.js'
11
- import { promptAutocomplete } from './util/prompt.js'
12
- import { withLoading } from './util/with-loading.js'
3
+ import { assertMutable, selectWorkspace } from 'lib/auth/operations.js'
4
+ import { getConfigStore } from 'lib/config/index.js'
5
+ import { resolveAuth } from 'lib/context.js'
6
+ import { getSeamMultiWorkspace } from 'lib/http/client.js'
7
+ import { withLoading } from 'lib/output/with-loading.js'
8
+ import { promptAutocomplete } from 'lib/prompt.js'
13
9
 
14
10
  export const interactForWorkspaceId = async (personalAccessToken?: string) => {
15
11
  const config = getConfigStore()
16
12
 
17
- assertEnvVarUnset(
18
- workspaceIdEnvVar,
19
- getWorkspaceIdFromEnv(),
20
- 'select a workspace',
21
- )
13
+ // Refuse before prompting: nothing selected here could be stored.
14
+ assertMutable(resolveAuth(config), 'workspaceId', 'select a workspace')
22
15
 
23
16
  const seam = personalAccessToken
24
17
  ? SeamHttpWithoutWorkspace.fromPersonalAccessToken(personalAccessToken, {
25
- endpoint: getServer(),
18
+ endpoint: resolveAuth(config).server,
26
19
  })
27
20
  : await getSeamMultiWorkspace()
28
21
 
@@ -40,6 +33,6 @@ export const interactForWorkspaceId = async (personalAccessToken?: string) => {
40
33
  })),
41
34
  })
42
35
 
43
- config.set('current_workspace_id', workspaceId)
36
+ selectWorkspace(workspaceId, config)
44
37
  return workspaceId
45
38
  }
@@ -0,0 +1,89 @@
1
+ import { PromptCancelledError } from 'lib/errors.js'
2
+ import type {
3
+ PromptChoice,
4
+ PromptClient,
5
+ PromptConfirmOptions,
6
+ PromptNumberOptions,
7
+ PromptSelectOptions,
8
+ PromptTextOptions,
9
+ } from 'lib/prompt.js'
10
+
11
+ /** A question a {@link PromptClient} was asked, as a test sees it. */
12
+ export interface PromptQuestion {
13
+ kind:
14
+ | 'text'
15
+ | 'number'
16
+ | 'confirm'
17
+ | 'select'
18
+ | 'autocomplete'
19
+ | 'autocompleteMultiselect'
20
+ message: string
21
+ choices?: Array<PromptChoice<unknown>>
22
+ }
23
+
24
+ /** Scripted in place of an answer to dismiss that prompt. */
25
+ export const cancelPrompt = Symbol('cancel-prompt')
26
+
27
+ /**
28
+ * A real {@link PromptClient} that answers from a script instead of a
29
+ * terminal, and records every question it was asked.
30
+ *
31
+ * Each ask consumes the next scripted answer in turn. Scripting
32
+ * {@link cancelPrompt} dismisses that prompt, and an exhausted script
33
+ * dismisses every prompt after it, exactly as a user cancelling would.
34
+ */
35
+ export class MemoryPromptClient implements PromptClient {
36
+ /** Every question asked, in order — assert on what the user was offered. */
37
+ readonly questions: PromptQuestion[] = []
38
+
39
+ private readonly answers: unknown[]
40
+
41
+ constructor(script: unknown[] = []) {
42
+ this.answers = [...script]
43
+ }
44
+
45
+ canPrompt = (): boolean => true
46
+
47
+ text = async ({ message }: PromptTextOptions): Promise<string> =>
48
+ this.answer({ kind: 'text', message }) as string
49
+
50
+ number = async ({ message }: PromptNumberOptions): Promise<number> =>
51
+ this.answer({ kind: 'number', message }) as number
52
+
53
+ confirm = async ({ message }: PromptConfirmOptions): Promise<boolean> =>
54
+ this.answer({ kind: 'confirm', message }) as boolean
55
+
56
+ select = async <Value>({
57
+ message,
58
+ choices,
59
+ }: PromptSelectOptions<Value>): Promise<Value> =>
60
+ this.answer({ kind: 'select', message, choices }) as Value
61
+
62
+ autocomplete = async <Value>({
63
+ message,
64
+ choices,
65
+ }: PromptSelectOptions<Value>): Promise<Value> =>
66
+ this.answer({ kind: 'autocomplete', message, choices }) as Value
67
+
68
+ autocompleteMultiselect = async <Value>({
69
+ message,
70
+ choices,
71
+ }: PromptSelectOptions<Value>): Promise<Value[]> =>
72
+ this.answer({
73
+ kind: 'autocompleteMultiselect',
74
+ message,
75
+ choices,
76
+ }) as Value[]
77
+
78
+ private answer(question: PromptQuestion): unknown {
79
+ this.questions.push(question)
80
+ if (this.answers.length === 0) throw new PromptCancelledError()
81
+ const value = this.answers.shift()
82
+ if (value === cancelPrompt) throw new PromptCancelledError()
83
+ return value
84
+ }
85
+ }
86
+
87
+ export const createMemoryPrompt = (
88
+ script: unknown[] = [],
89
+ ): MemoryPromptClient => new MemoryPromptClient(script)
@@ -1,4 +1,4 @@
1
- import { createOutput, type Output } from './create-output.js'
1
+ import { createOutput, type Output } from './output.js'
2
2
 
3
3
  let output: Output | null = null
4
4
 
@@ -3,7 +3,7 @@ import {
3
3
  type CreateOutputOptions,
4
4
  type Output,
5
5
  type OutputStream,
6
- } from './create-output.js'
6
+ } from './output.js'
7
7
 
8
8
  export interface MemoryOutput {
9
9
  output: Output
@@ -58,41 +58,56 @@ export interface CreateOutputOptions {
58
58
  colors?: boolean
59
59
  }
60
60
 
61
- export const createOutput = ({
62
- format = 'text',
63
- stdout = process.stdout,
64
- stderr = process.stderr,
65
- colors = false,
66
- }: CreateOutputOptions = {}): Output => {
67
- const isJson = format === 'json'
68
-
69
- return {
70
- format,
71
-
72
- data: (value: unknown): void => {
73
- if (value === undefined) return
74
- stdout.write(`${formatData(value, format, colors)}\n`)
75
- },
76
-
77
- text: (value: string): void => {
78
- stdout.write(`${value}\n`)
79
- },
80
-
81
- info: (message = ''): void => {
82
- if (isJson) return
83
- stderr.write(`${message}\n`)
84
- },
85
-
86
- warn: (message: string): void => {
87
- stderr.write(`${message}\n`)
88
- },
89
-
90
- error: (message: string): void => {
91
- stderr.write(`${message}\n`)
92
- },
61
+ /**
62
+ * The one {@link Output} implementation: writes to a pair of streams. The
63
+ * process streams make it the real output; in-memory streams make it the
64
+ * test capture (see `create-memory-output.ts`).
65
+ */
66
+ export class StreamOutput implements Output {
67
+ readonly format: OutputFormat
68
+
69
+ private readonly stdout: OutputStream
70
+ private readonly stderr: OutputStream
71
+ private readonly colors: boolean
72
+
73
+ constructor({
74
+ format = 'text',
75
+ stdout = process.stdout,
76
+ stderr = process.stderr,
77
+ colors = false,
78
+ }: CreateOutputOptions = {}) {
79
+ this.format = format
80
+ this.stdout = stdout
81
+ this.stderr = stderr
82
+ this.colors = colors
83
+ }
84
+
85
+ data = (value: unknown): void => {
86
+ if (value === undefined) return
87
+ this.stdout.write(`${formatData(value, this.format, this.colors)}\n`)
88
+ }
89
+
90
+ text = (value: string): void => {
91
+ this.stdout.write(`${value}\n`)
92
+ }
93
+
94
+ info = (message = ''): void => {
95
+ if (this.format === 'json') return
96
+ this.stderr.write(`${message}\n`)
97
+ }
98
+
99
+ warn = (message: string): void => {
100
+ this.stderr.write(`${message}\n`)
101
+ }
102
+
103
+ error = (message: string): void => {
104
+ this.stderr.write(`${message}\n`)
93
105
  }
94
106
  }
95
107
 
108
+ export const createOutput = (options: CreateOutputOptions = {}): Output =>
109
+ new StreamOutput(options)
110
+
96
111
  const formatData = (
97
112
  value: unknown,
98
113
  format: OutputFormat,