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
@@ -1,242 +0,0 @@
1
- import { Command } from "commander";
2
-
3
- import type { AuthScheme } from "../auth-schemes.ts";
4
- import type { CommandAction, CommandModel } from "../command-model.ts";
5
- import type { ServerInfo } from "../server.ts";
6
-
7
- import { type BodyFlagDef, generateBodyFlags } from "./body-flags.ts";
8
- import { executeAction } from "./execute.ts";
9
- import type { EmbeddedDefaults } from "./request.ts";
10
- import { coerceArrayInput, coerceValue } from "./validate/index.ts";
11
-
12
- // Flag type from CommandAction
13
- type CommandFlag = CommandAction["flags"][number];
14
-
15
- /**
16
- * Format help output that is clear for both humans and AI agents.
17
- * Groups options into Required, Optional, and Global sections.
18
- */
19
- function formatCustomHelp(
20
- cmd: Command,
21
- action: CommandAction,
22
- operationFlags: CommandFlag[],
23
- bodyFlagDefs: BodyFlagDef[],
24
- ): string {
25
- const lines: string[] = [];
26
- const cmdName = cmd.name();
27
- const parentName = cmd.parent?.name() ?? "";
28
- const fullCmd = parentName ? `${parentName} ${cmdName}` : cmdName;
29
-
30
- // Usage line
31
- const positionals = action.positionals.map((p) => `<${p.name}>`).join(" ");
32
- const usageSuffix = positionals ? ` ${positionals}` : "";
33
- lines.push(`Usage: ${fullCmd}${usageSuffix} [options]`);
34
- lines.push("");
35
-
36
- // Description
37
- const desc =
38
- action.summary ?? action.description ?? `${action.method} ${action.path}`;
39
- lines.push(desc);
40
- lines.push("");
41
-
42
- // Collect all options into categories
43
- const requiredOpts: string[] = [];
44
- const optionalOpts: string[] = [];
45
-
46
- // Format a single option line
47
- const formatOpt = (
48
- flag: string,
49
- type: string,
50
- desc: string,
51
- required: boolean,
52
- ): string => {
53
- const typeStr = type === "boolean" ? "" : ` <${type}>`;
54
- const reqMarker = required ? " (required)" : "";
55
- return ` ${flag}${typeStr}${reqMarker}\n ${desc}`;
56
- };
57
-
58
- // Operation flags (query/header/path params)
59
- for (const f of operationFlags) {
60
- const type = f.type === "array" ? `${f.itemType ?? "string"}[]` : f.type;
61
- const line = formatOpt(
62
- f.flag,
63
- type,
64
- f.description ?? `${f.in} parameter`,
65
- f.required,
66
- );
67
- if (f.required) {
68
- requiredOpts.push(line);
69
- } else {
70
- optionalOpts.push(line);
71
- }
72
- }
73
-
74
- // Body flags
75
- for (const def of bodyFlagDefs) {
76
- const line = formatOpt(def.flag, def.type, def.description, def.required);
77
- if (def.required) {
78
- requiredOpts.push(line);
79
- } else {
80
- optionalOpts.push(line);
81
- }
82
- }
83
-
84
- // Required options section
85
- if (requiredOpts.length > 0) {
86
- lines.push("Required:");
87
- lines.push(...requiredOpts);
88
- lines.push("");
89
- }
90
-
91
- // Optional options section
92
- if (optionalOpts.length > 0) {
93
- lines.push("Options:");
94
- lines.push(...optionalOpts);
95
- lines.push("");
96
- }
97
-
98
- // Global options (always available)
99
- lines.push("Global:");
100
- lines.push(" --curl\n Print curl command instead of executing");
101
- lines.push(" --json\n Output response as JSON");
102
- lines.push(" --server <url>\n Override the API server URL");
103
- lines.push(
104
- " --bearer-token <token>\n Provide auth token (or use 'login' command)",
105
- );
106
- lines.push(" -h, --help\n Show this help message");
107
- lines.push("");
108
-
109
- return lines.join("\n");
110
- }
111
-
112
- export type GeneratedCliContext = {
113
- servers: ServerInfo[];
114
- authSchemes: AuthScheme[];
115
- commands: CommandModel;
116
- specId: string;
117
- embeddedDefaults?: EmbeddedDefaults;
118
- };
119
-
120
- export function addGeneratedCommands(
121
- program: Command,
122
- context: GeneratedCliContext,
123
- ): void {
124
- for (const resource of context.commands.resources) {
125
- const resourceCmd = program
126
- .command(resource.resource)
127
- .description(`Operations for ${resource.resource}`);
128
-
129
- for (const action of resource.actions) {
130
- const cmd = resourceCmd.command(action.action);
131
- cmd.description(
132
- action.summary ??
133
- action.description ??
134
- `${action.method} ${action.path}`,
135
- );
136
-
137
- for (const pos of action.positionals) {
138
- cmd.argument(`<${pos.name}>`, pos.description);
139
- }
140
-
141
- for (const flag of action.flags) {
142
- const opt = flag.flag;
143
- const desc = flag.description ?? `${flag.in} parameter`;
144
-
145
- if (flag.type === "boolean") {
146
- cmd.option(opt, desc);
147
- continue;
148
- }
149
-
150
- const isArray = flag.type === "array";
151
- const itemType = flag.itemType ?? "string";
152
- const flagType = isArray ? itemType : flag.type;
153
- const parser = (raw: string) => coerceValue(raw, flagType);
154
-
155
- if (isArray) {
156
- const key = `${opt} <value>`;
157
- cmd.option(
158
- key,
159
- desc,
160
- (value: string, prev: unknown[] | undefined) => {
161
- const next: unknown[] = [...(prev ?? [])];
162
-
163
- // Allow `--tags a,b` and `--tags '["a","b"]'` to expand.
164
- const items = coerceArrayInput(value, itemType);
165
- for (const item of items) {
166
- next.push(item);
167
- }
168
-
169
- return next;
170
- },
171
- );
172
- continue;
173
- }
174
-
175
- const key = `${opt} <value>`;
176
- if (flag.required) cmd.requiredOption(key, desc, parser);
177
- else cmd.option(key, desc, parser);
178
- }
179
-
180
- // Collect reserved flags: operation params + --curl
181
- const operationFlagSet = new Set(action.flags.map((f) => f.flag));
182
- const reservedFlags = new Set([...operationFlagSet, "--curl"]);
183
-
184
- // Only --curl is a built-in flag (for debugging)
185
- if (!operationFlagSet.has("--curl")) {
186
- cmd.option("--curl", "Print curl command without sending");
187
- }
188
-
189
- // Track body flag definitions for this action
190
- let bodyFlagDefs: BodyFlagDef[] = [];
191
-
192
- if (action.requestBody) {
193
- // Generate body flags from schema (recursive with dot notation)
194
- // Pass reserved flags to avoid conflicts with operation params and --curl
195
- bodyFlagDefs = generateBodyFlags(
196
- action.requestBodySchema,
197
- reservedFlags,
198
- );
199
-
200
- for (const def of bodyFlagDefs) {
201
- if (def.type === "boolean") {
202
- cmd.option(def.flag, def.description);
203
- } else {
204
- cmd.option(`${def.flag} <value>`, def.description);
205
- }
206
- }
207
- }
208
-
209
- // Custom help output for better agent/human readability
210
- cmd.configureHelp({
211
- formatHelp: () =>
212
- formatCustomHelp(cmd, action, action.flags, bodyFlagDefs),
213
- });
214
-
215
- // Commander passes positional args and then the Command instance as last arg.
216
- cmd.action(async (...args) => {
217
- const command = args[args.length - 1];
218
- const positionalValues = args.slice(0, -1).map((v) => String(v));
219
-
220
- if (!(command instanceof Command)) {
221
- throw new Error("Unexpected commander action signature");
222
- }
223
-
224
- const globals = command.optsWithGlobals();
225
- const local = command.opts();
226
-
227
- await executeAction({
228
- action,
229
- positionalValues,
230
- flagValues: local,
231
- globals,
232
- servers: context.servers,
233
- authSchemes: context.authSchemes,
234
- specId: context.specId,
235
- embeddedDefaults: context.embeddedDefaults,
236
- bodyFlagDefs,
237
- resourceName: resource.resource,
238
- });
239
- });
240
- }
241
- }
242
- }
@@ -1,37 +0,0 @@
1
- export function parseHeaderInput(input: string): {
2
- name: string;
3
- value: string;
4
- } {
5
- const trimmed = input.trim();
6
- if (!trimmed) throw new Error("Empty header");
7
-
8
- // Support either "Name: Value" or "Name=Value".
9
- const colon = trimmed.indexOf(":");
10
- if (colon !== -1) {
11
- const name = trimmed.slice(0, colon).trim();
12
- const value = trimmed.slice(colon + 1).trim();
13
- if (!name) throw new Error("Invalid header name");
14
- return { name, value };
15
- }
16
-
17
- const eq = trimmed.indexOf("=");
18
- if (eq !== -1) {
19
- const name = trimmed.slice(0, eq).trim();
20
- const value = trimmed.slice(eq + 1).trim();
21
- if (!name) throw new Error("Invalid header name");
22
- return { name, value };
23
- }
24
-
25
- throw new Error("Invalid header format. Use 'Name: Value' or 'Name=Value'.");
26
- }
27
-
28
- export function mergeHeaders(
29
- base: Headers,
30
- entries: Array<{ name: string; value: string }>,
31
- ): Headers {
32
- const h = new Headers(base);
33
- for (const { name, value } of entries) {
34
- h.set(name, value);
35
- }
36
- return h;
37
- }
@@ -1,3 +0,0 @@
1
- export * from "./argv.ts";
2
- export * from "./context.ts";
3
- export * from "./generated.ts";
@@ -1,83 +0,0 @@
1
- import { isBun } from "../compat.ts";
2
-
3
- const bunLiteral = "bun" as const;
4
-
5
- export type SecretKey = {
6
- service: string;
7
- name: string;
8
- };
9
-
10
- export function secretServiceForSpec(specId: string): string {
11
- return `specli:${specId}`;
12
- }
13
-
14
- export function tokenSecretKey(specId: string, profile: string): SecretKey {
15
- return {
16
- service: secretServiceForSpec(specId),
17
- name: `profile:${profile}:token`,
18
- };
19
- }
20
-
21
- /**
22
- * Store a token securely.
23
- * In Bun: uses the native secrets store (system keychain)
24
- * In Node.js: secrets are not supported, warns user
25
- */
26
- export async function setToken(
27
- specId: string,
28
- profile: string,
29
- token: string,
30
- ): Promise<void> {
31
- if (!isBun) {
32
- console.warn(
33
- "Warning: Secure token storage requires Bun. Token will not be persisted.",
34
- );
35
- console.warn(
36
- "Use --bearer-token <token> flag instead when running with Node.js.",
37
- );
38
- return;
39
- }
40
-
41
- const { secrets } = await import(bunLiteral);
42
- const key = tokenSecretKey(specId, profile);
43
- await secrets.set({ service: key.service, name: key.name, value: token });
44
- }
45
-
46
- /**
47
- * Retrieve a stored token.
48
- * In Bun: retrieves from the native secrets store
49
- * In Node.js: returns null (secrets not supported)
50
- */
51
- export async function getToken(
52
- specId: string,
53
- profile: string,
54
- ): Promise<string | null> {
55
- if (!isBun) {
56
- return null;
57
- }
58
-
59
- const { secrets } = await import(bunLiteral);
60
- const key = tokenSecretKey(specId, profile);
61
- return await secrets.get({ service: key.service, name: key.name });
62
- }
63
-
64
- /**
65
- * Delete a stored token.
66
- * In Bun: removes from the native secrets store
67
- * In Node.js: returns false (secrets not supported)
68
- */
69
- export async function deleteToken(
70
- specId: string,
71
- profile: string,
72
- ): Promise<boolean> {
73
- if (!isBun) {
74
- console.warn(
75
- "Warning: Secure token storage requires Bun. No token to delete.",
76
- );
77
- return false;
78
- }
79
-
80
- const { secrets } = await import(bunLiteral);
81
- const key = tokenSecretKey(specId, profile);
82
- return await secrets.delete({ service: key.service, name: key.name });
83
- }
@@ -1,100 +0,0 @@
1
- import {
2
- fileExists,
3
- mkdirp,
4
- parseYamlContent,
5
- readFileText,
6
- writeFileText,
7
- } from "../compat.ts";
8
-
9
- export type Profile = {
10
- name: string;
11
- server?: string;
12
- authScheme?: string;
13
- // For apiKey schemes we also need the apiKey name/in from spec to inject,
14
- // but that is discoverable from the spec at runtime.
15
- };
16
-
17
- export type ProfilesFile = {
18
- profiles: Profile[];
19
- defaultProfile?: string;
20
- };
21
-
22
- function configDir(): string {
23
- // Keep it simple (v1). We can move to env-paths later.
24
- const home = process.env.HOME;
25
- if (!home) throw new Error("Missing HOME env var");
26
- return `${home}/.config/specli`;
27
- }
28
-
29
- function configPathJson(): string {
30
- return `${configDir()}/profiles.json`;
31
- }
32
-
33
- function configPathYaml(): string {
34
- return `${configDir()}/profiles.yaml`;
35
- }
36
-
37
- export async function readProfiles(): Promise<ProfilesFile> {
38
- const jsonPath = configPathJson();
39
- const yamlPath = configPathYaml();
40
-
41
- const jsonExists = await fileExists(jsonPath);
42
- const yamlExists = await fileExists(yamlPath);
43
-
44
- const filePath = jsonExists ? jsonPath : yamlExists ? yamlPath : null;
45
-
46
- if (!filePath) return { profiles: [] };
47
-
48
- const text = await readFileText(filePath);
49
- let parsed: unknown;
50
- try {
51
- parsed = parseYamlContent(text) as unknown;
52
- } catch {
53
- parsed = JSON.parse(text) as unknown;
54
- }
55
-
56
- const obj =
57
- parsed && typeof parsed === "object"
58
- ? (parsed as Record<string, unknown>)
59
- : {};
60
- const profiles = Array.isArray(obj.profiles)
61
- ? (obj.profiles as Profile[])
62
- : [];
63
-
64
- return {
65
- profiles: profiles.filter(Boolean),
66
- defaultProfile:
67
- typeof obj.defaultProfile === "string"
68
- ? (obj.defaultProfile as string)
69
- : undefined,
70
- };
71
- }
72
-
73
- export async function writeProfiles(data: ProfilesFile): Promise<void> {
74
- const dir = configDir();
75
- await mkdirp(dir);
76
- await writeFileText(configPathJson(), JSON.stringify(data, null, 2));
77
- }
78
-
79
- export function getProfile(
80
- data: ProfilesFile,
81
- name: string | undefined,
82
- ): Profile | undefined {
83
- const wanted = name ?? data.defaultProfile;
84
- if (!wanted) return undefined;
85
- return data.profiles.find((p) => p?.name === wanted);
86
- }
87
-
88
- export function upsertProfile(
89
- data: ProfilesFile,
90
- profile: Profile,
91
- ): ProfilesFile {
92
- const profiles = data.profiles.filter((p) => p.name !== profile.name);
93
- profiles.push(profile);
94
- profiles.sort((a, b) => a.name.localeCompare(b.name));
95
- return { ...data, profiles };
96
- }
97
-
98
- export function removeProfile(data: ProfilesFile, name: string): ProfilesFile {
99
- return { ...data, profiles: data.profiles.filter((p) => p.name !== name) };
100
- }