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,11 @@
1
+ import { Ajv } from "ajv";
2
+ import addFormats from "ajv-formats";
3
+ export function createAjv() {
4
+ const ajv = new Ajv({
5
+ allErrors: true,
6
+ strict: false,
7
+ coerceTypes: false,
8
+ });
9
+ addFormats.default(ajv);
10
+ return ajv;
11
+ }
@@ -1,4 +1,3 @@
1
1
  import type { ParamType } from "../../schema-shape.js";
2
2
  export declare function coerceValue(raw: string, type: ParamType): unknown;
3
3
  export declare function coerceArrayInput(raw: string, itemType: ParamType): unknown[];
4
- //# sourceMappingURL=coerce.d.ts.map
@@ -0,0 +1,63 @@
1
+ import { InvalidArgumentError } from "commander";
2
+ export function coerceValue(raw, type) {
3
+ if (type === "string" || type === "unknown")
4
+ return raw;
5
+ if (type === "boolean") {
6
+ // Commander boolean options are handled without a value; keep for completeness.
7
+ if (raw === "true")
8
+ return true;
9
+ if (raw === "false")
10
+ return false;
11
+ throw new InvalidArgumentError(`Expected boolean, got '${raw}'`);
12
+ }
13
+ if (type === "integer") {
14
+ const n = Number.parseInt(raw, 10);
15
+ if (!Number.isFinite(n))
16
+ throw new InvalidArgumentError(`Expected integer, got '${raw}'`);
17
+ return n;
18
+ }
19
+ if (type === "number") {
20
+ const n = Number(raw);
21
+ if (!Number.isFinite(n))
22
+ throw new InvalidArgumentError(`Expected number, got '${raw}'`);
23
+ return n;
24
+ }
25
+ // For now, accept objects as JSON strings.
26
+ if (type === "object") {
27
+ try {
28
+ return JSON.parse(raw);
29
+ }
30
+ catch {
31
+ throw new InvalidArgumentError(`Expected JSON object, got '${raw}'. Use --data/--file for complex bodies.`);
32
+ }
33
+ }
34
+ // Arrays should usually be passed as repeatable flags or comma-separated,
35
+ // but allow JSON arrays too.
36
+ if (type === "array") {
37
+ return coerceArrayInput(raw, "string");
38
+ }
39
+ return raw;
40
+ }
41
+ export function coerceArrayInput(raw, itemType) {
42
+ const trimmed = raw.trim();
43
+ if (!trimmed)
44
+ return [];
45
+ if (trimmed.startsWith("[")) {
46
+ let parsed;
47
+ try {
48
+ parsed = JSON.parse(trimmed);
49
+ }
50
+ catch {
51
+ throw new InvalidArgumentError(`Expected JSON array, got '${raw}'`);
52
+ }
53
+ if (!Array.isArray(parsed)) {
54
+ throw new InvalidArgumentError(`Expected JSON array, got '${raw}'`);
55
+ }
56
+ return parsed.map((v) => coerceValue(String(v), itemType));
57
+ }
58
+ return trimmed
59
+ .split(",")
60
+ .map((s) => s.trim())
61
+ .filter(Boolean)
62
+ .map((s) => coerceValue(s, itemType));
63
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,75 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { coerceArrayInput, coerceValue } from "./coerce.js";
3
+ describe("coerceValue", () => {
4
+ test("returns string as-is for string type", () => {
5
+ expect(coerceValue("hello", "string")).toBe("hello");
6
+ });
7
+ test("returns string as-is for unknown type", () => {
8
+ expect(coerceValue("hello", "unknown")).toBe("hello");
9
+ });
10
+ test("parses integer type", () => {
11
+ expect(coerceValue("42", "integer")).toBe(42);
12
+ expect(coerceValue("-10", "integer")).toBe(-10);
13
+ expect(coerceValue("0", "integer")).toBe(0);
14
+ });
15
+ test("throws for invalid integer", () => {
16
+ expect(() => coerceValue("abc", "integer")).toThrow("Expected integer");
17
+ });
18
+ test("truncates decimal for integer type (parseInt behavior)", () => {
19
+ // parseInt("12.5", 10) returns 12 - this is expected JS behavior
20
+ expect(coerceValue("12.5", "integer")).toBe(12);
21
+ });
22
+ test("parses number type", () => {
23
+ expect(coerceValue("42", "number")).toBe(42);
24
+ expect(coerceValue("3.14", "number")).toBe(3.14);
25
+ expect(coerceValue("-0.5", "number")).toBe(-0.5);
26
+ });
27
+ test("throws for invalid number", () => {
28
+ expect(() => coerceValue("abc", "number")).toThrow("Expected number");
29
+ });
30
+ test("parses boolean type", () => {
31
+ expect(coerceValue("true", "boolean")).toBe(true);
32
+ expect(coerceValue("false", "boolean")).toBe(false);
33
+ });
34
+ test("throws for invalid boolean", () => {
35
+ expect(() => coerceValue("yes", "boolean")).toThrow("Expected boolean");
36
+ expect(() => coerceValue("1", "boolean")).toThrow("Expected boolean");
37
+ });
38
+ test("parses object type as JSON", () => {
39
+ expect(coerceValue('{"a":1}', "object")).toEqual({ a: 1 });
40
+ });
41
+ test("throws for invalid object JSON", () => {
42
+ expect(() => coerceValue("not json", "object")).toThrow("Expected JSON object");
43
+ });
44
+ });
45
+ describe("coerceArrayInput", () => {
46
+ test("parses comma-separated values", () => {
47
+ expect(coerceArrayInput("a,b,c", "string")).toEqual(["a", "b", "c"]);
48
+ });
49
+ test("trims whitespace in comma-separated values", () => {
50
+ expect(coerceArrayInput("a, b, c", "string")).toEqual(["a", "b", "c"]);
51
+ });
52
+ test("parses JSON array", () => {
53
+ expect(coerceArrayInput('["a","b","c"]', "string")).toEqual([
54
+ "a",
55
+ "b",
56
+ "c",
57
+ ]);
58
+ });
59
+ test("coerces array items to specified type", () => {
60
+ expect(coerceArrayInput("1,2,3", "integer")).toEqual([1, 2, 3]);
61
+ expect(coerceArrayInput('["1","2","3"]', "integer")).toEqual([1, 2, 3]);
62
+ });
63
+ test("returns empty array for empty string", () => {
64
+ expect(coerceArrayInput("", "string")).toEqual([]);
65
+ expect(coerceArrayInput(" ", "string")).toEqual([]);
66
+ });
67
+ test("throws for invalid JSON array", () => {
68
+ expect(() => coerceArrayInput("[invalid", "string")).toThrow("Expected JSON array");
69
+ });
70
+ test("treats non-array JSON as comma-separated string", () => {
71
+ // If it doesn't start with '[', it's treated as comma-separated
72
+ // '{"a":1}' doesn't start with '[', so it's treated as a single value
73
+ expect(coerceArrayInput('{"a":1}', "string")).toEqual(['{"a":1}']);
74
+ });
75
+ });
@@ -1,3 +1,2 @@
1
1
  import type { ErrorObject } from "ajv";
2
2
  export declare function formatAjvErrors(errors: ErrorObject[] | null | undefined): string;
3
- //# sourceMappingURL=error.d.ts.map
@@ -0,0 +1,19 @@
1
+ export function formatAjvErrors(errors) {
2
+ if (!errors?.length)
3
+ return "Invalid input";
4
+ return errors
5
+ .map((e) => {
6
+ const path = e.instancePath || e.schemaPath || "";
7
+ if (e.keyword === "required" &&
8
+ e.params &&
9
+ typeof e.params === "object" &&
10
+ "missingProperty" in e.params) {
11
+ const missing = String(e.params.missingProperty);
12
+ const where = e.instancePath || "/";
13
+ return `${where} missing required property '${missing}'`.trim();
14
+ }
15
+ const msg = e.message || "invalid";
16
+ return `${path} ${msg}`.trim();
17
+ })
18
+ .join("\n");
19
+ }
@@ -2,4 +2,3 @@ export * from "./ajv.js";
2
2
  export * from "./coerce.js";
3
3
  export * from "./error.js";
4
4
  export * from "./schema.js";
5
- //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,4 @@
1
+ export * from "./ajv.js";
2
+ export * from "./coerce.js";
3
+ export * from "./error.js";
4
+ export * from "./schema.js";
@@ -6,4 +6,3 @@ export type ValidationSchemas = {
6
6
  cookieSchema?: JsonSchema;
7
7
  };
8
8
  export declare function deriveValidationSchemas(action: CommandAction): ValidationSchemas;
9
- //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1,38 @@
1
+ export function deriveValidationSchemas(action) {
2
+ // We validate only simple containers for now.
3
+ // Deep style/encoding differences for OpenAPI params are out of scope for v1.
4
+ const query = { type: "object", properties: {}, required: [] };
5
+ const header = { type: "object", properties: {}, required: [] };
6
+ const cookie = { type: "object", properties: {}, required: [] };
7
+ for (const p of action.params) {
8
+ if (p.kind !== "flag")
9
+ continue;
10
+ const target = p.in === "query"
11
+ ? query
12
+ : p.in === "header"
13
+ ? header
14
+ : p.in === "cookie"
15
+ ? cookie
16
+ : undefined;
17
+ if (!target)
18
+ continue;
19
+ const schema = p.schema ?? (p.type === "unknown" ? {} : { type: p.type });
20
+ target.properties[p.name] = schema;
21
+ if (p.required) {
22
+ if (!target.required)
23
+ target.required = [];
24
+ target.required.push(p.name);
25
+ }
26
+ }
27
+ if (!query.required?.length)
28
+ delete query.required;
29
+ if (!header.required?.length)
30
+ delete header.required;
31
+ if (!cookie.required?.length)
32
+ delete cookie.required;
33
+ return {
34
+ querySchema: Object.keys(query.properties).length ? query : undefined,
35
+ headerSchema: Object.keys(header.properties).length ? header : undefined,
36
+ cookieSchema: Object.keys(cookie.properties).length ? cookie : undefined,
37
+ };
38
+ }
@@ -2,4 +2,3 @@ export type ParamType = "string" | "number" | "integer" | "boolean" | "array" |
2
2
  export declare function getSchemaType(schema: unknown): ParamType;
3
3
  export declare function getSchemaFormat(schema: unknown): string | undefined;
4
4
  export declare function getSchemaEnumStrings(schema: unknown): string[] | undefined;
5
- //# sourceMappingURL=schema-shape.d.ts.map
@@ -0,0 +1,34 @@
1
+ export function getSchemaType(schema) {
2
+ if (!schema || typeof schema !== "object")
3
+ return "unknown";
4
+ const t = schema.type;
5
+ if (t === "string")
6
+ return "string";
7
+ if (t === "number")
8
+ return "number";
9
+ if (t === "integer")
10
+ return "integer";
11
+ if (t === "boolean")
12
+ return "boolean";
13
+ if (t === "array")
14
+ return "array";
15
+ if (t === "object")
16
+ return "object";
17
+ return "unknown";
18
+ }
19
+ export function getSchemaFormat(schema) {
20
+ if (!schema || typeof schema !== "object")
21
+ return undefined;
22
+ const f = schema.format;
23
+ return typeof f === "string" ? f : undefined;
24
+ }
25
+ export function getSchemaEnumStrings(schema) {
26
+ if (!schema || typeof schema !== "object")
27
+ return undefined;
28
+ const e = schema.enum;
29
+ if (!Array.isArray(e))
30
+ return undefined;
31
+ // We only surface string enums for now (enough for flag docs + completion).
32
+ const values = e.filter((v) => typeof v === "string");
33
+ return values.length ? values : undefined;
34
+ }
@@ -27,4 +27,3 @@ export type SchemaOutput = {
27
27
  export type MinimalSchemaOutput = Pick<SchemaOutput, "schemaVersion" | "openapi" | "spec" | "capabilities" | "commands">;
28
28
  export declare function buildSchemaOutput(loaded: LoadedSpec, operations: NormalizedOperation[], planned: PlannedOperation[] | undefined, servers: ServerInfo[], authSchemes: AuthScheme[], commands: CommandModel | undefined, commandsIndex: import("./command-index.js").CommandsIndex | undefined, capabilities: Capabilities): SchemaOutput;
29
29
  export declare function toMinimalSchemaOutput(output: SchemaOutput): MinimalSchemaOutput;
30
- //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1,31 @@
1
+ export function buildSchemaOutput(loaded, operations, planned, servers, authSchemes, commands, commandsIndex, capabilities) {
2
+ return {
3
+ schemaVersion: 1,
4
+ openapi: {
5
+ version: loaded.doc.openapi,
6
+ title: loaded.doc.info?.title,
7
+ infoVersion: loaded.doc.info?.version,
8
+ },
9
+ spec: {
10
+ id: loaded.id,
11
+ fingerprint: loaded.fingerprint,
12
+ source: loaded.source,
13
+ },
14
+ capabilities,
15
+ servers,
16
+ authSchemes,
17
+ operations,
18
+ planned,
19
+ commands,
20
+ commandsIndex,
21
+ };
22
+ }
23
+ export function toMinimalSchemaOutput(output) {
24
+ return {
25
+ schemaVersion: output.schemaVersion,
26
+ openapi: output.openapi,
27
+ spec: output.spec,
28
+ capabilities: output.capabilities,
29
+ commands: output.commands,
30
+ };
31
+ }
@@ -13,4 +13,3 @@ export type ServerInfo = {
13
13
  };
14
14
  export declare function listServers(doc: OpenApiDoc): ServerInfo[];
15
15
  export declare function getDefaultServerUrl(doc: OpenApiDoc): string | undefined;
16
- //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1,130 @@
1
+ import { getSchemaEnumStrings } from "./schema-shape.js";
2
+ const HTTP_METHODS = [
3
+ "get",
4
+ "post",
5
+ "put",
6
+ "patch",
7
+ "delete",
8
+ "options",
9
+ "head",
10
+ "trace",
11
+ ];
12
+ function extractVariableNames(url) {
13
+ const names = [];
14
+ const re = /\{([^}]+)\}/g;
15
+ while (true) {
16
+ const match = re.exec(url);
17
+ if (!match)
18
+ break;
19
+ names.push(match[1] ?? "");
20
+ }
21
+ return names.map((n) => n.trim()).filter(Boolean);
22
+ }
23
+ function parseServer(raw) {
24
+ const s = raw;
25
+ if (!s || typeof s !== "object")
26
+ return undefined;
27
+ if (typeof s.url !== "string")
28
+ return undefined;
29
+ const variableNames = extractVariableNames(s.url);
30
+ const variables = [];
31
+ const rawVars = s.variables &&
32
+ typeof s.variables === "object" &&
33
+ !Array.isArray(s.variables)
34
+ ? s.variables
35
+ : {};
36
+ for (const name of variableNames) {
37
+ const v = rawVars[name];
38
+ const def = v?.default;
39
+ const desc = v?.description;
40
+ variables.push({
41
+ name,
42
+ default: typeof def === "string" ? def : undefined,
43
+ enum: getSchemaEnumStrings(v),
44
+ description: typeof desc === "string" ? desc : undefined,
45
+ });
46
+ }
47
+ return {
48
+ url: s.url,
49
+ description: typeof s.description === "string" ? s.description : undefined,
50
+ variables,
51
+ variableNames,
52
+ };
53
+ }
54
+ function mergeServers(a, b) {
55
+ const variableNames = [...a.variableNames];
56
+ for (const n of b.variableNames) {
57
+ if (!variableNames.includes(n))
58
+ variableNames.push(n);
59
+ }
60
+ const byName = new Map();
61
+ for (const v of a.variables)
62
+ byName.set(v.name, { ...v });
63
+ for (const v of b.variables) {
64
+ const existing = byName.get(v.name);
65
+ if (!existing) {
66
+ byName.set(v.name, { ...v });
67
+ continue;
68
+ }
69
+ byName.set(v.name, {
70
+ name: v.name,
71
+ default: existing.default ?? v.default,
72
+ enum: existing.enum ?? v.enum,
73
+ description: existing.description ?? v.description,
74
+ });
75
+ }
76
+ return {
77
+ url: a.url,
78
+ description: a.description ?? b.description,
79
+ variableNames,
80
+ variables: variableNames
81
+ .map((n) => byName.get(n))
82
+ .filter(Boolean),
83
+ };
84
+ }
85
+ export function listServers(doc) {
86
+ const rawServers = [];
87
+ // OpenAPI 3.x allows servers at the root, per-path-item, and per-operation.
88
+ if (Array.isArray(doc.servers))
89
+ rawServers.push(...doc.servers);
90
+ const paths = doc.paths;
91
+ if (paths && typeof paths === "object" && !Array.isArray(paths)) {
92
+ for (const rawPathItem of Object.values(paths)) {
93
+ if (!rawPathItem || typeof rawPathItem !== "object")
94
+ continue;
95
+ const pathItem = rawPathItem;
96
+ if (Array.isArray(pathItem.servers))
97
+ rawServers.push(...pathItem.servers);
98
+ for (const method of HTTP_METHODS) {
99
+ const op = pathItem[method];
100
+ if (!op || typeof op !== "object")
101
+ continue;
102
+ const opObj = op;
103
+ if (Array.isArray(opObj.servers))
104
+ rawServers.push(...opObj.servers);
105
+ }
106
+ }
107
+ }
108
+ const out = [];
109
+ const byUrl = new Map();
110
+ for (const raw of rawServers) {
111
+ const parsed = parseServer(raw);
112
+ if (!parsed)
113
+ continue;
114
+ const existing = byUrl.get(parsed.url);
115
+ if (!existing) {
116
+ byUrl.set(parsed.url, parsed);
117
+ out.push(parsed);
118
+ continue;
119
+ }
120
+ const merged = mergeServers(existing, parsed);
121
+ byUrl.set(parsed.url, merged);
122
+ const idx = out.findIndex((s) => s.url === parsed.url);
123
+ if (idx !== -1)
124
+ out[idx] = merged;
125
+ }
126
+ return out;
127
+ }
128
+ export function getDefaultServerUrl(doc) {
129
+ return listServers(doc)[0]?.url;
130
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,49 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { listServers } from "./server.js";
3
+ describe("listServers", () => {
4
+ test("extracts server variables from template", () => {
5
+ const doc = {
6
+ openapi: "3.0.3",
7
+ servers: [
8
+ {
9
+ url: "https://{region}.api.example.com/{basePath}",
10
+ variables: {
11
+ region: {
12
+ default: "us",
13
+ enum: ["us", "eu"],
14
+ },
15
+ basePath: {
16
+ default: "v1",
17
+ },
18
+ },
19
+ },
20
+ ],
21
+ };
22
+ const servers = listServers(doc);
23
+ expect(servers).toHaveLength(1);
24
+ expect(servers[0]?.variableNames).toEqual(["region", "basePath"]);
25
+ expect(servers[0]?.variables.map((v) => v.name)).toEqual([
26
+ "region",
27
+ "basePath",
28
+ ]);
29
+ expect(servers[0]?.variables[0]?.enum).toEqual(["us", "eu"]);
30
+ });
31
+ test("includes servers defined on paths and operations", () => {
32
+ const doc = {
33
+ openapi: "3.0.3",
34
+ paths: {
35
+ "/v1/forecast": {
36
+ servers: [{ url: "https://api.a.example.com" }],
37
+ get: {
38
+ servers: [{ url: "https://api.b.example.com" }],
39
+ },
40
+ },
41
+ },
42
+ };
43
+ const servers = listServers(doc);
44
+ expect(servers.map((s) => s.url)).toEqual([
45
+ "https://api.a.example.com",
46
+ "https://api.b.example.com",
47
+ ]);
48
+ });
49
+ });
@@ -1,3 +1,2 @@
1
1
  import type { LoadedSpec } from "./types.js";
2
2
  export declare function getSpecId(loaded: Pick<LoadedSpec, "doc" | "fingerprint">): string;
3
- //# sourceMappingURL=spec-id.d.ts.map
@@ -0,0 +1,8 @@
1
+ import { kebabCase } from "./strings.js";
2
+ export function getSpecId(loaded) {
3
+ const title = loaded.doc.info?.title;
4
+ const fromTitle = title ? kebabCase(title) : "";
5
+ if (fromTitle)
6
+ return fromTitle;
7
+ return loaded.fingerprint.slice(0, 12);
8
+ }
@@ -4,4 +4,3 @@ export type LoadSpecOptions = {
4
4
  embeddedSpecText?: string;
5
5
  };
6
6
  export declare function loadSpec(options: LoadSpecOptions): Promise<LoadedSpec>;
7
- //# sourceMappingURL=spec-loader.d.ts.map
@@ -0,0 +1,40 @@
1
+ import SwaggerParser from "@apidevtools/swagger-parser";
2
+ import { sha256Hex } from "./crypto.js";
3
+ import { parseYamlContent } from "./runtime/compat.js";
4
+ import { getSpecId } from "./spec-id.js";
5
+ import { stableStringify } from "./stable-json.js";
6
+ function isProbablyUrl(input) {
7
+ return /^https?:\/\//i.test(input);
8
+ }
9
+ function parseSpecText(text) {
10
+ const trimmed = text.trimStart();
11
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
12
+ return JSON.parse(text);
13
+ }
14
+ return parseYamlContent(text);
15
+ }
16
+ export async function loadSpec(options) {
17
+ const { spec, embeddedSpecText } = options;
18
+ let source;
19
+ let inputForParser;
20
+ if (typeof embeddedSpecText === "string") {
21
+ source = "embedded";
22
+ inputForParser = parseSpecText(embeddedSpecText);
23
+ }
24
+ else if (spec) {
25
+ source = isProbablyUrl(spec) ? "url" : "file";
26
+ inputForParser = spec;
27
+ }
28
+ else {
29
+ throw new Error("Missing spec. Provide --spec <url|path> or build with an embedded spec.");
30
+ }
31
+ const doc = (await SwaggerParser.dereference(
32
+ // biome-ignore lint/suspicious/noExplicitAny: unknown
33
+ inputForParser));
34
+ if (!doc || typeof doc !== "object" || typeof doc.openapi !== "string") {
35
+ throw new Error("Loaded spec is not a valid OpenAPI document");
36
+ }
37
+ const fingerprint = await sha256Hex(stableStringify(doc));
38
+ const id = getSpecId({ doc, fingerprint });
39
+ return { source, id, fingerprint, doc };
40
+ }
@@ -1,4 +1,3 @@
1
1
  export declare function stableStringify(value: unknown, options?: {
2
2
  space?: number;
3
3
  }): string;
4
- //# sourceMappingURL=stable-json.d.ts.map
@@ -0,0 +1,29 @@
1
+ export function stableStringify(value, options) {
2
+ const visiting = new WeakSet();
3
+ return JSON.stringify(sort(value, visiting), null, options?.space);
4
+ }
5
+ function sort(value, visiting) {
6
+ if (value === null)
7
+ return null;
8
+ if (Array.isArray(value)) {
9
+ if (visiting.has(value))
10
+ return { __specli_circular: true };
11
+ visiting.add(value);
12
+ const out = value.map((v) => sort(v, visiting));
13
+ visiting.delete(value);
14
+ return out;
15
+ }
16
+ if (typeof value === "object") {
17
+ if (visiting.has(value))
18
+ return { __specli_circular: true };
19
+ visiting.add(value);
20
+ const obj = value;
21
+ const out = {};
22
+ for (const key of Object.keys(obj).sort()) {
23
+ out[key] = sort(obj[key], visiting);
24
+ }
25
+ visiting.delete(value);
26
+ return out;
27
+ }
28
+ return value;
29
+ }
@@ -1,3 +1,2 @@
1
1
  export declare function kebabCase(input: string): string;
2
2
  export declare function titleCase(input: string): string;
3
- //# sourceMappingURL=strings.d.ts.map
@@ -0,0 +1,20 @@
1
+ export function kebabCase(input) {
2
+ const trimmed = input.trim();
3
+ if (!trimmed)
4
+ return "";
5
+ // Convert spaces/underscores/dots to dashes, split camelCase.
6
+ return trimmed
7
+ .replace(/([a-z0-9])([A-Z])/g, "$1-$2")
8
+ .replace(/[\s_.:/]+/g, "-")
9
+ .replace(/[^a-zA-Z0-9-]/g, "-")
10
+ .replace(/-+/g, "-")
11
+ .replace(/^-|-$/g, "")
12
+ .toLowerCase();
13
+ }
14
+ export function titleCase(input) {
15
+ return input
16
+ .split(/\s+/g)
17
+ .filter(Boolean)
18
+ .map((w) => w[0]?.toUpperCase() + w.slice(1))
19
+ .join(" ");
20
+ }
@@ -50,4 +50,3 @@ export type LoadedSpec = {
50
50
  fingerprint: string;
51
51
  doc: OpenApiDoc;
52
52
  };
53
- //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,3 @@
1
+ export function isJsonSchema(value) {
2
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
3
+ }
package/dist/cli.d.ts CHANGED
@@ -1,3 +1,2 @@
1
1
  #!/usr/bin/env node
2
2
  export {};
3
- //# sourceMappingURL=cli.d.ts.map