specli 0.0.11 → 0.0.13

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 (335) hide show
  1. package/README.md +216 -325
  2. package/bin/cli.sh +27 -0
  3. package/dist/{src/ai → ai}/tools.d.ts +0 -1
  4. package/dist/ai/tools.js +161 -0
  5. package/dist/ai/tools.test.d.ts +1 -0
  6. package/dist/ai/tools.test.js +56 -0
  7. package/dist/{src/cli → cli}/auth-requirements.d.ts +0 -1
  8. package/dist/cli/auth-requirements.js +65 -0
  9. package/dist/cli/auth-requirements.test.d.ts +1 -0
  10. package/dist/cli/auth-requirements.test.js +16 -0
  11. package/dist/{src/cli → cli}/auth-schemes.d.ts +0 -1
  12. package/dist/cli/auth-schemes.js +112 -0
  13. package/dist/cli/auth-schemes.test.d.ts +1 -0
  14. package/dist/cli/auth-schemes.test.js +56 -0
  15. package/dist/{src/cli → cli}/capabilities.d.ts +0 -1
  16. package/dist/cli/capabilities.js +41 -0
  17. package/dist/cli/capabilities.test.d.ts +1 -0
  18. package/dist/cli/capabilities.test.js +84 -0
  19. package/dist/{src/cli → cli}/command-id.d.ts +0 -1
  20. package/dist/cli/command-id.js +8 -0
  21. package/dist/cli/command-id.test.d.ts +1 -0
  22. package/dist/cli/command-id.test.js +27 -0
  23. package/dist/{src/cli → cli}/command-index.d.ts +0 -1
  24. package/dist/cli/command-index.js +9 -0
  25. package/dist/{src/cli → cli}/command-model.d.ts +0 -1
  26. package/dist/cli/command-model.js +53 -0
  27. package/dist/cli/command-model.test.d.ts +1 -0
  28. package/dist/cli/command-model.test.js +40 -0
  29. package/dist/{src/cli → cli}/compile.d.ts +0 -1
  30. package/dist/cli/compile.js +79 -0
  31. package/dist/{src/cli → cli}/crypto.d.ts +0 -1
  32. package/dist/cli/crypto.js +9 -0
  33. package/dist/{src/cli → cli}/derive-name.d.ts +0 -1
  34. package/dist/cli/derive-name.js +96 -0
  35. package/dist/{src/cli → cli}/exec.d.ts +0 -1
  36. package/dist/cli/exec.js +50 -0
  37. package/dist/{src/cli → cli}/main.d.ts +0 -1
  38. package/dist/cli/main.js +177 -0
  39. package/dist/{src/cli → cli}/naming.d.ts +0 -1
  40. package/dist/cli/naming.js +191 -0
  41. package/dist/cli/naming.test.d.ts +1 -0
  42. package/dist/cli/naming.test.js +75 -0
  43. package/dist/{src/cli → cli}/operations.d.ts +0 -1
  44. package/dist/cli/operations.js +100 -0
  45. package/dist/cli/operations.test.d.ts +1 -0
  46. package/dist/cli/operations.test.js +51 -0
  47. package/dist/{src/cli → cli}/params.d.ts +0 -1
  48. package/dist/cli/params.js +36 -0
  49. package/dist/cli/params.test.d.ts +1 -0
  50. package/dist/cli/params.test.js +62 -0
  51. package/dist/{src/cli → cli}/pluralize.d.ts +0 -1
  52. package/dist/cli/pluralize.js +38 -0
  53. package/dist/{src/cli → cli}/positional.d.ts +0 -1
  54. package/dist/cli/positional.js +35 -0
  55. package/dist/cli/positional.test.d.ts +1 -0
  56. package/dist/cli/positional.test.js +60 -0
  57. package/dist/{src/cli → cli}/request-body.d.ts +0 -1
  58. package/dist/cli/request-body.js +44 -0
  59. package/dist/cli/request-body.test.d.ts +1 -0
  60. package/dist/cli/request-body.test.js +31 -0
  61. package/dist/{src/cli → cli}/runtime/argv.d.ts +0 -1
  62. package/dist/cli/runtime/argv.js +15 -0
  63. package/dist/{src/cli → cli}/runtime/auth/resolve.d.ts +0 -1
  64. package/dist/cli/runtime/auth/resolve.js +39 -0
  65. package/dist/{src/cli → cli}/runtime/body-flags.d.ts +0 -1
  66. package/dist/cli/runtime/body-flags.js +117 -0
  67. package/dist/cli/runtime/body-flags.test.d.ts +1 -0
  68. package/dist/cli/runtime/body-flags.test.js +192 -0
  69. package/dist/{src/cli → cli}/runtime/body.d.ts +0 -1
  70. package/dist/cli/runtime/body.js +16 -0
  71. package/dist/{src/cli → cli}/runtime/collect.d.ts +0 -1
  72. package/dist/cli/runtime/collect.js +3 -0
  73. package/dist/{src/cli → cli}/runtime/compat.d.ts +0 -1
  74. package/dist/cli/runtime/compat.js +78 -0
  75. package/dist/{src/cli → cli}/runtime/context.d.ts +0 -1
  76. package/dist/cli/runtime/context.js +44 -0
  77. package/dist/{src/cli → cli}/runtime/execute.d.ts +0 -1
  78. package/dist/cli/runtime/execute.js +106 -0
  79. package/dist/{src/cli → cli}/runtime/generated.d.ts +0 -1
  80. package/dist/cli/runtime/generated.js +168 -0
  81. package/dist/{src/cli → cli}/runtime/headers.d.ts +0 -1
  82. package/dist/cli/runtime/headers.js +30 -0
  83. package/dist/{src/cli → cli}/runtime/index.d.ts +0 -1
  84. package/dist/cli/runtime/index.js +3 -0
  85. package/dist/{src/cli → cli}/runtime/profile/secrets.d.ts +0 -1
  86. package/dist/cli/runtime/profile/secrets.js +53 -0
  87. package/dist/{src/cli → cli}/runtime/profile/store.d.ts +0 -1
  88. package/dist/cli/runtime/profile/store.js +63 -0
  89. package/dist/{src/cli → cli}/runtime/request.d.ts +0 -1
  90. package/dist/cli/runtime/request.js +283 -0
  91. package/dist/cli/runtime/request.test.d.ts +1 -0
  92. package/dist/cli/runtime/request.test.js +332 -0
  93. package/dist/{src/cli → cli}/runtime/server-url.d.ts +0 -1
  94. package/dist/cli/runtime/server-url.js +28 -0
  95. package/dist/{src/cli → cli}/runtime/template.d.ts +0 -1
  96. package/dist/cli/runtime/template.js +22 -0
  97. package/dist/cli/runtime/validate/ajv.d.ts +2 -0
  98. package/dist/cli/runtime/validate/ajv.js +11 -0
  99. package/dist/{src/cli → cli}/runtime/validate/coerce.d.ts +0 -1
  100. package/dist/cli/runtime/validate/coerce.js +63 -0
  101. package/dist/cli/runtime/validate/coerce.test.d.ts +1 -0
  102. package/dist/cli/runtime/validate/coerce.test.js +75 -0
  103. package/dist/{src/cli → cli}/runtime/validate/error.d.ts +0 -1
  104. package/dist/cli/runtime/validate/error.js +19 -0
  105. package/dist/{src/cli → cli}/runtime/validate/index.d.ts +0 -1
  106. package/dist/cli/runtime/validate/index.js +4 -0
  107. package/dist/{src/cli → cli}/runtime/validate/schema.d.ts +0 -1
  108. package/dist/cli/runtime/validate/schema.js +38 -0
  109. package/dist/{src/cli → cli}/schema-shape.d.ts +0 -1
  110. package/dist/cli/schema-shape.js +34 -0
  111. package/dist/{src/cli → cli}/schema.d.ts +0 -1
  112. package/dist/cli/schema.js +31 -0
  113. package/dist/{src/cli → cli}/server.d.ts +0 -1
  114. package/dist/cli/server.js +130 -0
  115. package/dist/cli/server.test.d.ts +1 -0
  116. package/dist/cli/server.test.js +49 -0
  117. package/dist/{src/cli → cli}/spec-id.d.ts +0 -1
  118. package/dist/cli/spec-id.js +8 -0
  119. package/dist/{src/cli → cli}/spec-loader.d.ts +0 -1
  120. package/dist/cli/spec-loader.js +40 -0
  121. package/dist/{src/cli → cli}/stable-json.d.ts +0 -1
  122. package/dist/cli/stable-json.js +29 -0
  123. package/dist/{src/cli → cli}/strings.d.ts +0 -1
  124. package/dist/cli/strings.js +20 -0
  125. package/dist/{src/cli → cli}/types.d.ts +0 -1
  126. package/dist/cli/types.js +3 -0
  127. package/dist/cli.d.ts +0 -1
  128. package/dist/cli.js +51 -2324
  129. package/dist/compiled.d.ts +2 -0
  130. package/{src/compiled.ts → dist/compiled.js} +8 -11
  131. package/dist/macros/env.d.ts +10 -0
  132. package/dist/macros/env.js +22 -0
  133. package/dist/macros/spec.d.ts +5 -0
  134. package/dist/macros/spec.js +16 -0
  135. package/package.json +17 -25
  136. package/bin/specli.js +0 -26
  137. package/cli.ts +0 -77
  138. package/dist/cli.d.ts.map +0 -1
  139. package/dist/cli.js.map +0 -53
  140. package/dist/index.d.ts +0 -2
  141. package/dist/index.d.ts.map +0 -1
  142. package/dist/index.js +0 -2032
  143. package/dist/index.js.map +0 -48
  144. package/dist/src/ai/tools.d.ts.map +0 -1
  145. package/dist/src/ai/tools.js +0 -1656
  146. package/dist/src/ai/tools.js.map +0 -45
  147. package/dist/src/cli/auth-requirements.d.ts.map +0 -1
  148. package/dist/src/cli/auth-requirements.js +0 -66
  149. package/dist/src/cli/auth-requirements.js.map +0 -10
  150. package/dist/src/cli/auth-schemes.d.ts.map +0 -1
  151. package/dist/src/cli/auth-schemes.js +0 -116
  152. package/dist/src/cli/auth-schemes.js.map +0 -11
  153. package/dist/src/cli/capabilities.d.ts.map +0 -1
  154. package/dist/src/cli/capabilities.js +0 -45
  155. package/dist/src/cli/capabilities.js.map +0 -10
  156. package/dist/src/cli/command-id.d.ts.map +0 -1
  157. package/dist/src/cli/command-id.js +0 -18
  158. package/dist/src/cli/command-id.js.map +0 -11
  159. package/dist/src/cli/command-index.d.ts.map +0 -1
  160. package/dist/src/cli/command-index.js +0 -15
  161. package/dist/src/cli/command-index.js.map +0 -10
  162. package/dist/src/cli/command-model.d.ts.map +0 -1
  163. package/dist/src/cli/command-model.js +0 -274
  164. package/dist/src/cli/command-model.js.map +0 -18
  165. package/dist/src/cli/compile.d.ts.map +0 -1
  166. package/dist/src/cli/compile.js +0 -146
  167. package/dist/src/cli/compile.js.map +0 -11
  168. package/dist/src/cli/crypto.d.ts.map +0 -1
  169. package/dist/src/cli/crypto.js +0 -15
  170. package/dist/src/cli/crypto.js.map +0 -10
  171. package/dist/src/cli/derive-name.d.ts.map +0 -1
  172. package/dist/src/cli/derive-name.js +0 -70
  173. package/dist/src/cli/derive-name.js.map +0 -10
  174. package/dist/src/cli/exec.d.ts.map +0 -1
  175. package/dist/src/cli/exec.js +0 -2077
  176. package/dist/src/cli/exec.js.map +0 -49
  177. package/dist/src/cli/main.d.ts.map +0 -1
  178. package/dist/src/cli/main.js +0 -2032
  179. package/dist/src/cli/main.js.map +0 -48
  180. package/dist/src/cli/naming.d.ts.map +0 -1
  181. package/dist/src/cli/naming.js +0 -216
  182. package/dist/src/cli/naming.js.map +0 -12
  183. package/dist/src/cli/operations.d.ts.map +0 -1
  184. package/dist/src/cli/operations.js +0 -103
  185. package/dist/src/cli/operations.js.map +0 -10
  186. package/dist/src/cli/params.d.ts.map +0 -1
  187. package/dist/src/cli/params.js +0 -79
  188. package/dist/src/cli/params.js.map +0 -12
  189. package/dist/src/cli/pluralize.d.ts.map +0 -1
  190. package/dist/src/cli/pluralize.js +0 -43
  191. package/dist/src/cli/pluralize.js.map +0 -10
  192. package/dist/src/cli/positional.d.ts.map +0 -1
  193. package/dist/src/cli/positional.js +0 -39
  194. package/dist/src/cli/positional.js.map +0 -10
  195. package/dist/src/cli/request-body.d.ts.map +0 -1
  196. package/dist/src/cli/request-body.js +0 -82
  197. package/dist/src/cli/request-body.js.map +0 -12
  198. package/dist/src/cli/runtime/argv.d.ts.map +0 -1
  199. package/dist/src/cli/runtime/argv.js +0 -22
  200. package/dist/src/cli/runtime/argv.js.map +0 -10
  201. package/dist/src/cli/runtime/auth/resolve.d.ts.map +0 -1
  202. package/dist/src/cli/runtime/auth/resolve.js +0 -38
  203. package/dist/src/cli/runtime/auth/resolve.js.map +0 -10
  204. package/dist/src/cli/runtime/body-flags.d.ts.map +0 -1
  205. package/dist/src/cli/runtime/body-flags.js +0 -86
  206. package/dist/src/cli/runtime/body-flags.js.map +0 -10
  207. package/dist/src/cli/runtime/body.d.ts.map +0 -1
  208. package/dist/src/cli/runtime/body.js +0 -40
  209. package/dist/src/cli/runtime/body.js.map +0 -11
  210. package/dist/src/cli/runtime/collect.d.ts.map +0 -1
  211. package/dist/src/cli/runtime/collect.js +0 -9
  212. package/dist/src/cli/runtime/collect.js.map +0 -10
  213. package/dist/src/cli/runtime/compat.d.ts.map +0 -1
  214. package/dist/src/cli/runtime/compat.js +0 -62
  215. package/dist/src/cli/runtime/compat.js.map +0 -10
  216. package/dist/src/cli/runtime/context.d.ts.map +0 -1
  217. package/dist/src/cli/runtime/context.js +0 -936
  218. package/dist/src/cli/runtime/context.js.map +0 -32
  219. package/dist/src/cli/runtime/execute.d.ts.map +0 -1
  220. package/dist/src/cli/runtime/execute.js +0 -670
  221. package/dist/src/cli/runtime/execute.js.map +0 -22
  222. package/dist/src/cli/runtime/generated.d.ts.map +0 -1
  223. package/dist/src/cli/runtime/generated.js +0 -869
  224. package/dist/src/cli/runtime/generated.js.map +0 -23
  225. package/dist/src/cli/runtime/headers.d.ts.map +0 -1
  226. package/dist/src/cli/runtime/headers.js +0 -36
  227. package/dist/src/cli/runtime/headers.js.map +0 -10
  228. package/dist/src/cli/runtime/index.d.ts.map +0 -1
  229. package/dist/src/cli/runtime/index.js +0 -1808
  230. package/dist/src/cli/runtime/index.js.map +0 -46
  231. package/dist/src/cli/runtime/profile/secrets.d.ts.map +0 -1
  232. package/dist/src/cli/runtime/profile/secrets.js +0 -51
  233. package/dist/src/cli/runtime/profile/secrets.js.map +0 -11
  234. package/dist/src/cli/runtime/profile/store.d.ts.map +0 -1
  235. package/dist/src/cli/runtime/profile/store.js +0 -102
  236. package/dist/src/cli/runtime/profile/store.js.map +0 -11
  237. package/dist/src/cli/runtime/request.d.ts.map +0 -1
  238. package/dist/src/cli/runtime/request.js +0 -571
  239. package/dist/src/cli/runtime/request.js.map +0 -21
  240. package/dist/src/cli/runtime/server-url.d.ts.map +0 -1
  241. package/dist/src/cli/runtime/server-url.js +0 -55
  242. package/dist/src/cli/runtime/server-url.js.map +0 -11
  243. package/dist/src/cli/runtime/template.d.ts.map +0 -1
  244. package/dist/src/cli/runtime/template.js +0 -29
  245. package/dist/src/cli/runtime/template.js.map +0 -10
  246. package/dist/src/cli/runtime/validate/ajv.d.ts +0 -3
  247. package/dist/src/cli/runtime/validate/ajv.d.ts.map +0 -1
  248. package/dist/src/cli/runtime/validate/ajv.js +0 -17
  249. package/dist/src/cli/runtime/validate/ajv.js.map +0 -10
  250. package/dist/src/cli/runtime/validate/coerce.d.ts.map +0 -1
  251. package/dist/src/cli/runtime/validate/coerce.js +0 -60
  252. package/dist/src/cli/runtime/validate/coerce.js.map +0 -10
  253. package/dist/src/cli/runtime/validate/error.d.ts.map +0 -1
  254. package/dist/src/cli/runtime/validate/error.js +0 -21
  255. package/dist/src/cli/runtime/validate/error.js.map +0 -10
  256. package/dist/src/cli/runtime/validate/index.d.ts.map +0 -1
  257. package/dist/src/cli/runtime/validate/index.js +0 -122
  258. package/dist/src/cli/runtime/validate/index.js.map +0 -13
  259. package/dist/src/cli/runtime/validate/schema.d.ts.map +0 -1
  260. package/dist/src/cli/runtime/validate/schema.js +0 -36
  261. package/dist/src/cli/runtime/validate/schema.js.map +0 -10
  262. package/dist/src/cli/schema-shape.d.ts.map +0 -1
  263. package/dist/src/cli/schema-shape.js +0 -41
  264. package/dist/src/cli/schema-shape.js.map +0 -10
  265. package/dist/src/cli/schema.d.ts.map +0 -1
  266. package/dist/src/cli/schema.js +0 -38
  267. package/dist/src/cli/schema.js.map +0 -10
  268. package/dist/src/cli/server.d.ts.map +0 -1
  269. package/dist/src/cli/server.js +0 -64
  270. package/dist/src/cli/server.js.map +0 -11
  271. package/dist/src/cli/spec-id.d.ts.map +0 -1
  272. package/dist/src/cli/spec-id.js +0 -21
  273. package/dist/src/cli/spec-id.js.map +0 -11
  274. package/dist/src/cli/spec-loader.d.ts.map +0 -1
  275. package/dist/src/cli/spec-loader.js +0 -110
  276. package/dist/src/cli/spec-loader.js.map +0 -15
  277. package/dist/src/cli/stable-json.d.ts.map +0 -1
  278. package/dist/src/cli/stable-json.js +0 -35
  279. package/dist/src/cli/stable-json.js.map +0 -10
  280. package/dist/src/cli/strings.d.ts.map +0 -1
  281. package/dist/src/cli/strings.js +0 -16
  282. package/dist/src/cli/strings.js.map +0 -10
  283. package/dist/src/cli/types.d.ts.map +0 -1
  284. package/dist/src/cli/types.js +0 -9
  285. package/dist/src/cli/types.js.map +0 -10
  286. package/index.ts +0 -1
  287. package/src/ai/tools.ts +0 -211
  288. package/src/cli/auth-requirements.ts +0 -91
  289. package/src/cli/auth-schemes.ts +0 -187
  290. package/src/cli/capabilities.ts +0 -88
  291. package/src/cli/command-id.ts +0 -16
  292. package/src/cli/command-index.ts +0 -19
  293. package/src/cli/command-model.ts +0 -128
  294. package/src/cli/compile.ts +0 -101
  295. package/src/cli/crypto.ts +0 -9
  296. package/src/cli/derive-name.ts +0 -101
  297. package/src/cli/exec.ts +0 -72
  298. package/src/cli/main.ts +0 -231
  299. package/src/cli/naming.ts +0 -224
  300. package/src/cli/operations.ts +0 -152
  301. package/src/cli/params.ts +0 -71
  302. package/src/cli/pluralize.ts +0 -41
  303. package/src/cli/positional.ts +0 -75
  304. package/src/cli/request-body.ts +0 -94
  305. package/src/cli/runtime/argv.ts +0 -14
  306. package/src/cli/runtime/auth/resolve.ts +0 -59
  307. package/src/cli/runtime/body-flags.ts +0 -176
  308. package/src/cli/runtime/body.ts +0 -24
  309. package/src/cli/runtime/collect.ts +0 -6
  310. package/src/cli/runtime/compat.ts +0 -89
  311. package/src/cli/runtime/context.ts +0 -62
  312. package/src/cli/runtime/execute.ts +0 -147
  313. package/src/cli/runtime/generated.ts +0 -242
  314. package/src/cli/runtime/headers.ts +0 -37
  315. package/src/cli/runtime/index.ts +0 -3
  316. package/src/cli/runtime/profile/secrets.ts +0 -83
  317. package/src/cli/runtime/profile/store.ts +0 -100
  318. package/src/cli/runtime/request.ts +0 -390
  319. package/src/cli/runtime/server-url.ts +0 -45
  320. package/src/cli/runtime/template.ts +0 -26
  321. package/src/cli/runtime/validate/ajv.ts +0 -13
  322. package/src/cli/runtime/validate/coerce.ts +0 -71
  323. package/src/cli/runtime/validate/error.ts +0 -29
  324. package/src/cli/runtime/validate/index.ts +0 -4
  325. package/src/cli/runtime/validate/schema.ts +0 -54
  326. package/src/cli/schema-shape.ts +0 -36
  327. package/src/cli/schema.ts +0 -76
  328. package/src/cli/server.ts +0 -88
  329. package/src/cli/spec-id.ts +0 -12
  330. package/src/cli/spec-loader.ts +0 -58
  331. package/src/cli/stable-json.ts +0 -35
  332. package/src/cli/strings.ts +0 -21
  333. package/src/cli/types.ts +0 -59
  334. package/src/macros/env.ts +0 -21
  335. package/src/macros/spec.ts +0 -17
@@ -0,0 +1,106 @@
1
+ import { buildRequest } from "./request.js";
2
+ /**
3
+ * Format an error message with a help hint.
4
+ */
5
+ function formatError(message, resourceName, actionName) {
6
+ const helpCmd = resourceName
7
+ ? `${resourceName} ${actionName} --help`
8
+ : `${actionName} --help`;
9
+ return `${message}\n\nRun '${helpCmd}' to see available options.`;
10
+ }
11
+ /**
12
+ * Execute an action and return the result as data.
13
+ * This is the core execution function used by both CLI and programmatic API.
14
+ */
15
+ export async function execute(input) {
16
+ const { request, curl } = await buildRequest({
17
+ specId: input.specId,
18
+ action: input.action,
19
+ positionalValues: input.positionalValues,
20
+ flagValues: input.flagValues,
21
+ globals: input.globals,
22
+ servers: input.servers,
23
+ authSchemes: input.authSchemes,
24
+ embeddedDefaults: input.embeddedDefaults,
25
+ bodyFlagDefs: input.bodyFlagDefs,
26
+ });
27
+ const res = await fetch(request);
28
+ const contentType = res.headers.get("content-type") ?? "";
29
+ const text = await res.text();
30
+ let body = text;
31
+ if (contentType.includes("json") && text) {
32
+ try {
33
+ body = JSON.parse(text);
34
+ }
35
+ catch {
36
+ // keep as text
37
+ }
38
+ }
39
+ return {
40
+ ok: res.ok,
41
+ status: res.status,
42
+ body,
43
+ curl,
44
+ };
45
+ }
46
+ /**
47
+ * Execute an action and write output to stdout/stderr.
48
+ * This is the CLI-facing wrapper around execute().
49
+ */
50
+ export async function executeAction(input) {
51
+ const actionName = input.action.action;
52
+ const resourceName = input.resourceName;
53
+ try {
54
+ if (input.globals.curl) {
55
+ const { curl } = await buildRequest({
56
+ specId: input.specId,
57
+ action: input.action,
58
+ positionalValues: input.positionalValues,
59
+ flagValues: input.flagValues,
60
+ globals: input.globals,
61
+ servers: input.servers,
62
+ authSchemes: input.authSchemes,
63
+ embeddedDefaults: input.embeddedDefaults,
64
+ bodyFlagDefs: input.bodyFlagDefs,
65
+ });
66
+ process.stdout.write(`${curl}\n`);
67
+ return;
68
+ }
69
+ const result = await execute(input);
70
+ if (!result.ok) {
71
+ if (input.globals.json) {
72
+ process.stdout.write(`${JSON.stringify({ status: result.status, body: result.body })}\n`);
73
+ }
74
+ else {
75
+ process.stderr.write(`HTTP ${result.status}\n`);
76
+ process.stderr.write(`${typeof result.body === "string" ? result.body : JSON.stringify(result.body, null, 2)}\n`);
77
+ }
78
+ process.exitCode = 1;
79
+ return;
80
+ }
81
+ if (input.globals.json) {
82
+ process.stdout.write(`${JSON.stringify(result.body)}\n`);
83
+ return;
84
+ }
85
+ // default (human + agent readable)
86
+ if (typeof result.body === "string") {
87
+ process.stdout.write(result.body);
88
+ if (!result.body.endsWith("\n"))
89
+ process.stdout.write("\n");
90
+ }
91
+ else {
92
+ process.stdout.write(`${JSON.stringify(result.body, null, 2)}\n`);
93
+ }
94
+ }
95
+ catch (err) {
96
+ const rawMessage = err instanceof Error ? err.message : String(err);
97
+ const message = formatError(rawMessage, resourceName, actionName);
98
+ if (input.globals.json) {
99
+ process.stdout.write(`${JSON.stringify({ error: rawMessage })}\n`);
100
+ }
101
+ else {
102
+ process.stderr.write(`error: ${message}\n`);
103
+ }
104
+ process.exitCode = 1;
105
+ }
106
+ }
@@ -11,4 +11,3 @@ export type GeneratedCliContext = {
11
11
  embeddedDefaults?: EmbeddedDefaults;
12
12
  };
13
13
  export declare function addGeneratedCommands(program: Command, context: GeneratedCliContext): void;
14
- //# sourceMappingURL=generated.d.ts.map
@@ -0,0 +1,168 @@
1
+ import { Command } from "commander";
2
+ import { generateBodyFlags } from "./body-flags.js";
3
+ import { executeAction } from "./execute.js";
4
+ import { coerceArrayInput, coerceValue } from "./validate/index.js";
5
+ /**
6
+ * Format help output that is clear for both humans and AI agents.
7
+ * Groups options into Required, Optional, and Global sections.
8
+ */
9
+ function formatCustomHelp(cmd, action, operationFlags, bodyFlagDefs) {
10
+ const lines = [];
11
+ const cmdName = cmd.name();
12
+ const parentName = cmd.parent?.name() ?? "";
13
+ const fullCmd = parentName ? `${parentName} ${cmdName}` : cmdName;
14
+ // Usage line
15
+ const positionals = action.positionals.map((p) => `<${p.name}>`).join(" ");
16
+ const usageSuffix = positionals ? ` ${positionals}` : "";
17
+ lines.push(`Usage: ${fullCmd}${usageSuffix} [options]`);
18
+ lines.push("");
19
+ // Description
20
+ const desc = action.summary ?? action.description ?? `${action.method} ${action.path}`;
21
+ lines.push(desc);
22
+ lines.push("");
23
+ // Collect all options into categories
24
+ const requiredOpts = [];
25
+ const optionalOpts = [];
26
+ // Format a single option line
27
+ const formatOpt = (flag, type, desc, required) => {
28
+ const typeStr = type === "boolean" ? "" : ` <${type}>`;
29
+ const reqMarker = required ? " (required)" : "";
30
+ return ` ${flag}${typeStr}${reqMarker}\n ${desc}`;
31
+ };
32
+ // Operation flags (query/header/path params)
33
+ for (const f of operationFlags) {
34
+ const type = f.type === "array" ? `${f.itemType ?? "string"}[]` : f.type;
35
+ const line = formatOpt(f.flag, type, f.description ?? `${f.in} parameter`, f.required);
36
+ if (f.required) {
37
+ requiredOpts.push(line);
38
+ }
39
+ else {
40
+ optionalOpts.push(line);
41
+ }
42
+ }
43
+ // Body flags
44
+ for (const def of bodyFlagDefs) {
45
+ const line = formatOpt(def.flag, def.type, def.description, def.required);
46
+ if (def.required) {
47
+ requiredOpts.push(line);
48
+ }
49
+ else {
50
+ optionalOpts.push(line);
51
+ }
52
+ }
53
+ // Required options section
54
+ if (requiredOpts.length > 0) {
55
+ lines.push("Required:");
56
+ lines.push(...requiredOpts);
57
+ lines.push("");
58
+ }
59
+ // Optional options section
60
+ if (optionalOpts.length > 0) {
61
+ lines.push("Options:");
62
+ lines.push(...optionalOpts);
63
+ lines.push("");
64
+ }
65
+ // Global options (always available)
66
+ lines.push("Global:");
67
+ lines.push(" --curl\n Print curl command instead of executing");
68
+ lines.push(" --json\n Output response as JSON");
69
+ lines.push(" --server <url>\n Override the API server URL");
70
+ lines.push(" --bearer-token <token>\n Provide auth token (or use 'login' command)");
71
+ lines.push(" -h, --help\n Show this help message");
72
+ lines.push("");
73
+ return lines.join("\n");
74
+ }
75
+ export function addGeneratedCommands(program, context) {
76
+ for (const resource of context.commands.resources) {
77
+ const resourceCmd = program
78
+ .command(resource.resource)
79
+ .description(`Operations for ${resource.resource}`);
80
+ for (const action of resource.actions) {
81
+ const cmd = resourceCmd.command(action.action);
82
+ cmd.description(action.summary ??
83
+ action.description ??
84
+ `${action.method} ${action.path}`);
85
+ for (const pos of action.positionals) {
86
+ cmd.argument(`<${pos.name}>`, pos.description);
87
+ }
88
+ for (const flag of action.flags) {
89
+ const opt = flag.flag;
90
+ const desc = flag.description ?? `${flag.in} parameter`;
91
+ if (flag.type === "boolean") {
92
+ cmd.option(opt, desc);
93
+ continue;
94
+ }
95
+ const isArray = flag.type === "array";
96
+ const itemType = flag.itemType ?? "string";
97
+ const flagType = isArray ? itemType : flag.type;
98
+ const parser = (raw) => coerceValue(raw, flagType);
99
+ if (isArray) {
100
+ const key = `${opt} <value>`;
101
+ cmd.option(key, desc, (value, prev) => {
102
+ const next = [...(prev ?? [])];
103
+ // Allow `--tags a,b` and `--tags '["a","b"]'` to expand.
104
+ const items = coerceArrayInput(value, itemType);
105
+ for (const item of items) {
106
+ next.push(item);
107
+ }
108
+ return next;
109
+ });
110
+ continue;
111
+ }
112
+ const key = `${opt} <value>`;
113
+ if (flag.required)
114
+ cmd.requiredOption(key, desc, parser);
115
+ else
116
+ cmd.option(key, desc, parser);
117
+ }
118
+ // Collect reserved flags: operation params + --curl
119
+ const operationFlagSet = new Set(action.flags.map((f) => f.flag));
120
+ const reservedFlags = new Set([...operationFlagSet, "--curl"]);
121
+ // Only --curl is a built-in flag (for debugging)
122
+ if (!operationFlagSet.has("--curl")) {
123
+ cmd.option("--curl", "Print curl command without sending");
124
+ }
125
+ // Track body flag definitions for this action
126
+ let bodyFlagDefs = [];
127
+ if (action.requestBody) {
128
+ // Generate body flags from schema (recursive with dot notation)
129
+ // Pass reserved flags to avoid conflicts with operation params and --curl
130
+ bodyFlagDefs = generateBodyFlags(action.requestBodySchema, reservedFlags);
131
+ for (const def of bodyFlagDefs) {
132
+ if (def.type === "boolean") {
133
+ cmd.option(def.flag, def.description);
134
+ }
135
+ else {
136
+ cmd.option(`${def.flag} <value>`, def.description);
137
+ }
138
+ }
139
+ }
140
+ // Custom help output for better agent/human readability
141
+ cmd.configureHelp({
142
+ formatHelp: () => formatCustomHelp(cmd, action, action.flags, bodyFlagDefs),
143
+ });
144
+ // Commander passes positional args and then the Command instance as last arg.
145
+ cmd.action(async (...args) => {
146
+ const command = args[args.length - 1];
147
+ const positionalValues = args.slice(0, -1).map((v) => String(v));
148
+ if (!(command instanceof Command)) {
149
+ throw new Error("Unexpected commander action signature");
150
+ }
151
+ const globals = command.optsWithGlobals();
152
+ const local = command.opts();
153
+ await executeAction({
154
+ action,
155
+ positionalValues,
156
+ flagValues: local,
157
+ globals,
158
+ servers: context.servers,
159
+ authSchemes: context.authSchemes,
160
+ specId: context.specId,
161
+ embeddedDefaults: context.embeddedDefaults,
162
+ bodyFlagDefs,
163
+ resourceName: resource.resource,
164
+ });
165
+ });
166
+ }
167
+ }
168
+ }
@@ -6,4 +6,3 @@ export declare function mergeHeaders(base: Headers, entries: Array<{
6
6
  name: string;
7
7
  value: string;
8
8
  }>): Headers;
9
- //# sourceMappingURL=headers.d.ts.map
@@ -0,0 +1,30 @@
1
+ export function parseHeaderInput(input) {
2
+ const trimmed = input.trim();
3
+ if (!trimmed)
4
+ throw new Error("Empty header");
5
+ // Support either "Name: Value" or "Name=Value".
6
+ const colon = trimmed.indexOf(":");
7
+ if (colon !== -1) {
8
+ const name = trimmed.slice(0, colon).trim();
9
+ const value = trimmed.slice(colon + 1).trim();
10
+ if (!name)
11
+ throw new Error("Invalid header name");
12
+ return { name, value };
13
+ }
14
+ const eq = trimmed.indexOf("=");
15
+ if (eq !== -1) {
16
+ const name = trimmed.slice(0, eq).trim();
17
+ const value = trimmed.slice(eq + 1).trim();
18
+ if (!name)
19
+ throw new Error("Invalid header name");
20
+ return { name, value };
21
+ }
22
+ throw new Error("Invalid header format. Use 'Name: Value' or 'Name=Value'.");
23
+ }
24
+ export function mergeHeaders(base, entries) {
25
+ const h = new Headers(base);
26
+ for (const { name, value } of entries) {
27
+ h.set(name, value);
28
+ }
29
+ return h;
30
+ }
@@ -1,4 +1,3 @@
1
1
  export * from "./argv.js";
2
2
  export * from "./context.js";
3
3
  export * from "./generated.js";
4
- //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,3 @@
1
+ export * from "./argv.js";
2
+ export * from "./context.js";
3
+ export * from "./generated.js";
@@ -22,4 +22,3 @@ export declare function getToken(specId: string, profile: string): Promise<strin
22
22
  * In Node.js: returns false (secrets not supported)
23
23
  */
24
24
  export declare function deleteToken(specId: string, profile: string): Promise<boolean>;
25
- //# sourceMappingURL=secrets.d.ts.map
@@ -0,0 +1,53 @@
1
+ import { isBun } from "../compat.js";
2
+ const bunLiteral = "bun";
3
+ export function secretServiceForSpec(specId) {
4
+ return `specli:${specId}`;
5
+ }
6
+ export function tokenSecretKey(specId, profile) {
7
+ return {
8
+ service: secretServiceForSpec(specId),
9
+ name: `profile:${profile}:token`,
10
+ };
11
+ }
12
+ /**
13
+ * Store a token securely.
14
+ * In Bun: uses the native secrets store (system keychain)
15
+ * In Node.js: secrets are not supported, warns user
16
+ */
17
+ export async function setToken(specId, profile, token) {
18
+ if (!isBun) {
19
+ console.warn("Warning: Secure token storage requires Bun. Token will not be persisted.");
20
+ console.warn("Use --bearer-token <token> flag instead when running with Node.js.");
21
+ return;
22
+ }
23
+ const { secrets } = await import(bunLiteral);
24
+ const key = tokenSecretKey(specId, profile);
25
+ await secrets.set({ service: key.service, name: key.name, value: token });
26
+ }
27
+ /**
28
+ * Retrieve a stored token.
29
+ * In Bun: retrieves from the native secrets store
30
+ * In Node.js: returns null (secrets not supported)
31
+ */
32
+ export async function getToken(specId, profile) {
33
+ if (!isBun) {
34
+ return null;
35
+ }
36
+ const { secrets } = await import(bunLiteral);
37
+ const key = tokenSecretKey(specId, profile);
38
+ return await secrets.get({ service: key.service, name: key.name });
39
+ }
40
+ /**
41
+ * Delete a stored token.
42
+ * In Bun: removes from the native secrets store
43
+ * In Node.js: returns false (secrets not supported)
44
+ */
45
+ export async function deleteToken(specId, profile) {
46
+ if (!isBun) {
47
+ console.warn("Warning: Secure token storage requires Bun. No token to delete.");
48
+ return false;
49
+ }
50
+ const { secrets } = await import(bunLiteral);
51
+ const key = tokenSecretKey(specId, profile);
52
+ return await secrets.delete({ service: key.service, name: key.name });
53
+ }
@@ -12,4 +12,3 @@ export declare function writeProfiles(data: ProfilesFile): Promise<void>;
12
12
  export declare function getProfile(data: ProfilesFile, name: string | undefined): Profile | undefined;
13
13
  export declare function upsertProfile(data: ProfilesFile, profile: Profile): ProfilesFile;
14
14
  export declare function removeProfile(data: ProfilesFile, name: string): ProfilesFile;
15
- //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1,63 @@
1
+ import { fileExists, mkdirp, parseYamlContent, readFileText, writeFileText, } from "../compat.js";
2
+ function configDir() {
3
+ // Keep it simple (v1). We can move to env-paths later.
4
+ const home = process.env.HOME;
5
+ if (!home)
6
+ throw new Error("Missing HOME env var");
7
+ return `${home}/.config/specli`;
8
+ }
9
+ function configPathJson() {
10
+ return `${configDir()}/profiles.json`;
11
+ }
12
+ function configPathYaml() {
13
+ return `${configDir()}/profiles.yaml`;
14
+ }
15
+ export async function readProfiles() {
16
+ const jsonPath = configPathJson();
17
+ const yamlPath = configPathYaml();
18
+ const jsonExists = await fileExists(jsonPath);
19
+ const yamlExists = await fileExists(yamlPath);
20
+ const filePath = jsonExists ? jsonPath : yamlExists ? yamlPath : null;
21
+ if (!filePath)
22
+ return { profiles: [] };
23
+ const text = await readFileText(filePath);
24
+ let parsed;
25
+ try {
26
+ parsed = parseYamlContent(text);
27
+ }
28
+ catch {
29
+ parsed = JSON.parse(text);
30
+ }
31
+ const obj = parsed && typeof parsed === "object"
32
+ ? parsed
33
+ : {};
34
+ const profiles = Array.isArray(obj.profiles)
35
+ ? obj.profiles
36
+ : [];
37
+ return {
38
+ profiles: profiles.filter(Boolean),
39
+ defaultProfile: typeof obj.defaultProfile === "string"
40
+ ? obj.defaultProfile
41
+ : undefined,
42
+ };
43
+ }
44
+ export async function writeProfiles(data) {
45
+ const dir = configDir();
46
+ await mkdirp(dir);
47
+ await writeFileText(configPathJson(), JSON.stringify(data, null, 2));
48
+ }
49
+ export function getProfile(data, name) {
50
+ const wanted = name ?? data.defaultProfile;
51
+ if (!wanted)
52
+ return undefined;
53
+ return data.profiles.find((p) => p?.name === wanted);
54
+ }
55
+ export function upsertProfile(data, profile) {
56
+ const profiles = data.profiles.filter((p) => p.name !== profile.name);
57
+ profiles.push(profile);
58
+ profiles.sort((a, b) => a.name.localeCompare(b.name));
59
+ return { ...data, profiles };
60
+ }
61
+ export function removeProfile(data, name) {
62
+ return { ...data, profiles: data.profiles.filter((p) => p.name !== name) };
63
+ }
@@ -33,4 +33,3 @@ export declare function buildRequest(input: BuildRequestInput): Promise<{
33
33
  request: Request;
34
34
  curl: string;
35
35
  }>;
36
- //# sourceMappingURL=request.d.ts.map