specli 0.0.10 → 0.0.12

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 (334) hide show
  1. package/bin/cli.sh +27 -0
  2. package/dist/{src/ai → ai}/tools.d.ts +0 -1
  3. package/dist/ai/tools.js +161 -0
  4. package/dist/ai/tools.test.d.ts +1 -0
  5. package/dist/ai/tools.test.js +56 -0
  6. package/dist/{src/cli → cli}/auth-requirements.d.ts +0 -1
  7. package/dist/cli/auth-requirements.js +65 -0
  8. package/dist/cli/auth-requirements.test.d.ts +1 -0
  9. package/dist/cli/auth-requirements.test.js +16 -0
  10. package/dist/{src/cli → cli}/auth-schemes.d.ts +0 -1
  11. package/dist/cli/auth-schemes.js +112 -0
  12. package/dist/cli/auth-schemes.test.d.ts +1 -0
  13. package/dist/cli/auth-schemes.test.js +56 -0
  14. package/dist/{src/cli → cli}/capabilities.d.ts +0 -1
  15. package/dist/cli/capabilities.js +41 -0
  16. package/dist/cli/capabilities.test.d.ts +1 -0
  17. package/dist/cli/capabilities.test.js +84 -0
  18. package/dist/{src/cli → cli}/command-id.d.ts +0 -1
  19. package/dist/cli/command-id.js +8 -0
  20. package/dist/cli/command-id.test.d.ts +1 -0
  21. package/dist/cli/command-id.test.js +27 -0
  22. package/dist/{src/cli → cli}/command-index.d.ts +0 -1
  23. package/dist/cli/command-index.js +9 -0
  24. package/dist/{src/cli → cli}/command-model.d.ts +0 -1
  25. package/dist/cli/command-model.js +53 -0
  26. package/dist/cli/command-model.test.d.ts +1 -0
  27. package/dist/cli/command-model.test.js +40 -0
  28. package/dist/{src/cli → cli}/compile.d.ts +0 -1
  29. package/dist/cli/compile.js +79 -0
  30. package/dist/{src/cli → cli}/crypto.d.ts +0 -1
  31. package/dist/cli/crypto.js +9 -0
  32. package/dist/{src/cli → cli}/derive-name.d.ts +0 -1
  33. package/dist/cli/derive-name.js +96 -0
  34. package/dist/{src/cli → cli}/exec.d.ts +0 -1
  35. package/dist/cli/exec.js +50 -0
  36. package/dist/{src/cli → cli}/main.d.ts +0 -1
  37. package/dist/cli/main.js +177 -0
  38. package/dist/{src/cli → cli}/naming.d.ts +0 -1
  39. package/dist/cli/naming.js +191 -0
  40. package/dist/cli/naming.test.d.ts +1 -0
  41. package/dist/cli/naming.test.js +75 -0
  42. package/dist/{src/cli → cli}/operations.d.ts +0 -1
  43. package/dist/cli/operations.js +100 -0
  44. package/dist/cli/operations.test.d.ts +1 -0
  45. package/dist/cli/operations.test.js +51 -0
  46. package/dist/{src/cli → cli}/params.d.ts +0 -1
  47. package/dist/cli/params.js +36 -0
  48. package/dist/cli/params.test.d.ts +1 -0
  49. package/dist/cli/params.test.js +62 -0
  50. package/dist/{src/cli → cli}/pluralize.d.ts +0 -1
  51. package/dist/cli/pluralize.js +38 -0
  52. package/dist/{src/cli → cli}/positional.d.ts +0 -1
  53. package/dist/cli/positional.js +35 -0
  54. package/dist/cli/positional.test.d.ts +1 -0
  55. package/dist/cli/positional.test.js +60 -0
  56. package/dist/{src/cli → cli}/request-body.d.ts +0 -1
  57. package/dist/cli/request-body.js +44 -0
  58. package/dist/cli/request-body.test.d.ts +1 -0
  59. package/dist/cli/request-body.test.js +31 -0
  60. package/dist/{src/cli → cli}/runtime/argv.d.ts +0 -1
  61. package/dist/cli/runtime/argv.js +15 -0
  62. package/dist/{src/cli → cli}/runtime/auth/resolve.d.ts +0 -1
  63. package/dist/cli/runtime/auth/resolve.js +39 -0
  64. package/dist/{src/cli → cli}/runtime/body-flags.d.ts +0 -1
  65. package/dist/cli/runtime/body-flags.js +117 -0
  66. package/dist/cli/runtime/body-flags.test.d.ts +1 -0
  67. package/dist/cli/runtime/body-flags.test.js +192 -0
  68. package/dist/{src/cli → cli}/runtime/body.d.ts +0 -1
  69. package/dist/cli/runtime/body.js +16 -0
  70. package/dist/{src/cli → cli}/runtime/collect.d.ts +0 -1
  71. package/dist/cli/runtime/collect.js +3 -0
  72. package/dist/{src/cli → cli}/runtime/compat.d.ts +0 -1
  73. package/dist/cli/runtime/compat.js +78 -0
  74. package/dist/{src/cli → cli}/runtime/context.d.ts +0 -1
  75. package/dist/cli/runtime/context.js +44 -0
  76. package/dist/{src/cli → cli}/runtime/execute.d.ts +0 -1
  77. package/dist/cli/runtime/execute.js +106 -0
  78. package/dist/{src/cli → cli}/runtime/generated.d.ts +0 -1
  79. package/dist/cli/runtime/generated.js +168 -0
  80. package/dist/{src/cli → cli}/runtime/headers.d.ts +0 -1
  81. package/dist/cli/runtime/headers.js +30 -0
  82. package/dist/{src/cli → cli}/runtime/index.d.ts +0 -1
  83. package/dist/cli/runtime/index.js +3 -0
  84. package/dist/{src/cli → cli}/runtime/profile/secrets.d.ts +0 -1
  85. package/dist/cli/runtime/profile/secrets.js +53 -0
  86. package/dist/{src/cli → cli}/runtime/profile/store.d.ts +0 -1
  87. package/dist/cli/runtime/profile/store.js +63 -0
  88. package/dist/{src/cli → cli}/runtime/request.d.ts +0 -1
  89. package/dist/cli/runtime/request.js +283 -0
  90. package/dist/cli/runtime/request.test.d.ts +1 -0
  91. package/dist/cli/runtime/request.test.js +332 -0
  92. package/dist/{src/cli → cli}/runtime/server-url.d.ts +0 -1
  93. package/dist/cli/runtime/server-url.js +28 -0
  94. package/dist/{src/cli → cli}/runtime/template.d.ts +0 -1
  95. package/dist/cli/runtime/template.js +22 -0
  96. package/dist/cli/runtime/validate/ajv.d.ts +2 -0
  97. package/dist/cli/runtime/validate/ajv.js +11 -0
  98. package/dist/{src/cli → cli}/runtime/validate/coerce.d.ts +0 -1
  99. package/dist/cli/runtime/validate/coerce.js +63 -0
  100. package/dist/cli/runtime/validate/coerce.test.d.ts +1 -0
  101. package/dist/cli/runtime/validate/coerce.test.js +75 -0
  102. package/dist/{src/cli → cli}/runtime/validate/error.d.ts +0 -1
  103. package/dist/cli/runtime/validate/error.js +19 -0
  104. package/dist/{src/cli → cli}/runtime/validate/index.d.ts +0 -1
  105. package/dist/cli/runtime/validate/index.js +4 -0
  106. package/dist/{src/cli → cli}/runtime/validate/schema.d.ts +0 -1
  107. package/dist/cli/runtime/validate/schema.js +38 -0
  108. package/dist/{src/cli → cli}/schema-shape.d.ts +0 -1
  109. package/dist/cli/schema-shape.js +34 -0
  110. package/dist/{src/cli → cli}/schema.d.ts +0 -1
  111. package/dist/cli/schema.js +31 -0
  112. package/dist/{src/cli → cli}/server.d.ts +0 -1
  113. package/dist/cli/server.js +130 -0
  114. package/dist/cli/server.test.d.ts +1 -0
  115. package/dist/cli/server.test.js +49 -0
  116. package/dist/{src/cli → cli}/spec-id.d.ts +0 -1
  117. package/dist/cli/spec-id.js +8 -0
  118. package/dist/{src/cli → cli}/spec-loader.d.ts +0 -1
  119. package/dist/cli/spec-loader.js +40 -0
  120. package/dist/{src/cli → cli}/stable-json.d.ts +0 -1
  121. package/dist/cli/stable-json.js +29 -0
  122. package/dist/{src/cli → cli}/strings.d.ts +0 -1
  123. package/dist/cli/strings.js +20 -0
  124. package/dist/{src/cli → cli}/types.d.ts +0 -1
  125. package/dist/cli/types.js +3 -0
  126. package/dist/cli.d.ts +0 -1
  127. package/dist/cli.js +52 -2325
  128. package/dist/compiled.d.ts +2 -0
  129. package/{src/compiled.ts → dist/compiled.js} +8 -11
  130. package/dist/macros/env.d.ts +10 -0
  131. package/dist/macros/env.js +22 -0
  132. package/dist/macros/spec.d.ts +5 -0
  133. package/dist/macros/spec.js +16 -0
  134. package/dist/weather +0 -0
  135. package/package.json +12 -25
  136. package/cli.ts +0 -77
  137. package/dist/cli.d.ts.map +0 -1
  138. package/dist/cli.js.map +0 -53
  139. package/dist/index.d.ts +0 -2
  140. package/dist/index.d.ts.map +0 -1
  141. package/dist/index.js +0 -2032
  142. package/dist/index.js.map +0 -48
  143. package/dist/src/ai/tools.d.ts.map +0 -1
  144. package/dist/src/ai/tools.js +0 -1656
  145. package/dist/src/ai/tools.js.map +0 -45
  146. package/dist/src/cli/auth-requirements.d.ts.map +0 -1
  147. package/dist/src/cli/auth-requirements.js +0 -66
  148. package/dist/src/cli/auth-requirements.js.map +0 -10
  149. package/dist/src/cli/auth-schemes.d.ts.map +0 -1
  150. package/dist/src/cli/auth-schemes.js +0 -116
  151. package/dist/src/cli/auth-schemes.js.map +0 -11
  152. package/dist/src/cli/capabilities.d.ts.map +0 -1
  153. package/dist/src/cli/capabilities.js +0 -45
  154. package/dist/src/cli/capabilities.js.map +0 -10
  155. package/dist/src/cli/command-id.d.ts.map +0 -1
  156. package/dist/src/cli/command-id.js +0 -18
  157. package/dist/src/cli/command-id.js.map +0 -11
  158. package/dist/src/cli/command-index.d.ts.map +0 -1
  159. package/dist/src/cli/command-index.js +0 -15
  160. package/dist/src/cli/command-index.js.map +0 -10
  161. package/dist/src/cli/command-model.d.ts.map +0 -1
  162. package/dist/src/cli/command-model.js +0 -274
  163. package/dist/src/cli/command-model.js.map +0 -18
  164. package/dist/src/cli/compile.d.ts.map +0 -1
  165. package/dist/src/cli/compile.js +0 -146
  166. package/dist/src/cli/compile.js.map +0 -11
  167. package/dist/src/cli/crypto.d.ts.map +0 -1
  168. package/dist/src/cli/crypto.js +0 -15
  169. package/dist/src/cli/crypto.js.map +0 -10
  170. package/dist/src/cli/derive-name.d.ts.map +0 -1
  171. package/dist/src/cli/derive-name.js +0 -70
  172. package/dist/src/cli/derive-name.js.map +0 -10
  173. package/dist/src/cli/exec.d.ts.map +0 -1
  174. package/dist/src/cli/exec.js +0 -2077
  175. package/dist/src/cli/exec.js.map +0 -49
  176. package/dist/src/cli/main.d.ts.map +0 -1
  177. package/dist/src/cli/main.js +0 -2032
  178. package/dist/src/cli/main.js.map +0 -48
  179. package/dist/src/cli/naming.d.ts.map +0 -1
  180. package/dist/src/cli/naming.js +0 -216
  181. package/dist/src/cli/naming.js.map +0 -12
  182. package/dist/src/cli/operations.d.ts.map +0 -1
  183. package/dist/src/cli/operations.js +0 -103
  184. package/dist/src/cli/operations.js.map +0 -10
  185. package/dist/src/cli/params.d.ts.map +0 -1
  186. package/dist/src/cli/params.js +0 -79
  187. package/dist/src/cli/params.js.map +0 -12
  188. package/dist/src/cli/pluralize.d.ts.map +0 -1
  189. package/dist/src/cli/pluralize.js +0 -43
  190. package/dist/src/cli/pluralize.js.map +0 -10
  191. package/dist/src/cli/positional.d.ts.map +0 -1
  192. package/dist/src/cli/positional.js +0 -39
  193. package/dist/src/cli/positional.js.map +0 -10
  194. package/dist/src/cli/request-body.d.ts.map +0 -1
  195. package/dist/src/cli/request-body.js +0 -82
  196. package/dist/src/cli/request-body.js.map +0 -12
  197. package/dist/src/cli/runtime/argv.d.ts.map +0 -1
  198. package/dist/src/cli/runtime/argv.js +0 -22
  199. package/dist/src/cli/runtime/argv.js.map +0 -10
  200. package/dist/src/cli/runtime/auth/resolve.d.ts.map +0 -1
  201. package/dist/src/cli/runtime/auth/resolve.js +0 -38
  202. package/dist/src/cli/runtime/auth/resolve.js.map +0 -10
  203. package/dist/src/cli/runtime/body-flags.d.ts.map +0 -1
  204. package/dist/src/cli/runtime/body-flags.js +0 -86
  205. package/dist/src/cli/runtime/body-flags.js.map +0 -10
  206. package/dist/src/cli/runtime/body.d.ts.map +0 -1
  207. package/dist/src/cli/runtime/body.js +0 -40
  208. package/dist/src/cli/runtime/body.js.map +0 -11
  209. package/dist/src/cli/runtime/collect.d.ts.map +0 -1
  210. package/dist/src/cli/runtime/collect.js +0 -9
  211. package/dist/src/cli/runtime/collect.js.map +0 -10
  212. package/dist/src/cli/runtime/compat.d.ts.map +0 -1
  213. package/dist/src/cli/runtime/compat.js +0 -62
  214. package/dist/src/cli/runtime/compat.js.map +0 -10
  215. package/dist/src/cli/runtime/context.d.ts.map +0 -1
  216. package/dist/src/cli/runtime/context.js +0 -936
  217. package/dist/src/cli/runtime/context.js.map +0 -32
  218. package/dist/src/cli/runtime/execute.d.ts.map +0 -1
  219. package/dist/src/cli/runtime/execute.js +0 -670
  220. package/dist/src/cli/runtime/execute.js.map +0 -22
  221. package/dist/src/cli/runtime/generated.d.ts.map +0 -1
  222. package/dist/src/cli/runtime/generated.js +0 -869
  223. package/dist/src/cli/runtime/generated.js.map +0 -23
  224. package/dist/src/cli/runtime/headers.d.ts.map +0 -1
  225. package/dist/src/cli/runtime/headers.js +0 -36
  226. package/dist/src/cli/runtime/headers.js.map +0 -10
  227. package/dist/src/cli/runtime/index.d.ts.map +0 -1
  228. package/dist/src/cli/runtime/index.js +0 -1808
  229. package/dist/src/cli/runtime/index.js.map +0 -46
  230. package/dist/src/cli/runtime/profile/secrets.d.ts.map +0 -1
  231. package/dist/src/cli/runtime/profile/secrets.js +0 -51
  232. package/dist/src/cli/runtime/profile/secrets.js.map +0 -11
  233. package/dist/src/cli/runtime/profile/store.d.ts.map +0 -1
  234. package/dist/src/cli/runtime/profile/store.js +0 -102
  235. package/dist/src/cli/runtime/profile/store.js.map +0 -11
  236. package/dist/src/cli/runtime/request.d.ts.map +0 -1
  237. package/dist/src/cli/runtime/request.js +0 -571
  238. package/dist/src/cli/runtime/request.js.map +0 -21
  239. package/dist/src/cli/runtime/server-url.d.ts.map +0 -1
  240. package/dist/src/cli/runtime/server-url.js +0 -55
  241. package/dist/src/cli/runtime/server-url.js.map +0 -11
  242. package/dist/src/cli/runtime/template.d.ts.map +0 -1
  243. package/dist/src/cli/runtime/template.js +0 -29
  244. package/dist/src/cli/runtime/template.js.map +0 -10
  245. package/dist/src/cli/runtime/validate/ajv.d.ts +0 -3
  246. package/dist/src/cli/runtime/validate/ajv.d.ts.map +0 -1
  247. package/dist/src/cli/runtime/validate/ajv.js +0 -17
  248. package/dist/src/cli/runtime/validate/ajv.js.map +0 -10
  249. package/dist/src/cli/runtime/validate/coerce.d.ts.map +0 -1
  250. package/dist/src/cli/runtime/validate/coerce.js +0 -60
  251. package/dist/src/cli/runtime/validate/coerce.js.map +0 -10
  252. package/dist/src/cli/runtime/validate/error.d.ts.map +0 -1
  253. package/dist/src/cli/runtime/validate/error.js +0 -21
  254. package/dist/src/cli/runtime/validate/error.js.map +0 -10
  255. package/dist/src/cli/runtime/validate/index.d.ts.map +0 -1
  256. package/dist/src/cli/runtime/validate/index.js +0 -122
  257. package/dist/src/cli/runtime/validate/index.js.map +0 -13
  258. package/dist/src/cli/runtime/validate/schema.d.ts.map +0 -1
  259. package/dist/src/cli/runtime/validate/schema.js +0 -36
  260. package/dist/src/cli/runtime/validate/schema.js.map +0 -10
  261. package/dist/src/cli/schema-shape.d.ts.map +0 -1
  262. package/dist/src/cli/schema-shape.js +0 -41
  263. package/dist/src/cli/schema-shape.js.map +0 -10
  264. package/dist/src/cli/schema.d.ts.map +0 -1
  265. package/dist/src/cli/schema.js +0 -38
  266. package/dist/src/cli/schema.js.map +0 -10
  267. package/dist/src/cli/server.d.ts.map +0 -1
  268. package/dist/src/cli/server.js +0 -64
  269. package/dist/src/cli/server.js.map +0 -11
  270. package/dist/src/cli/spec-id.d.ts.map +0 -1
  271. package/dist/src/cli/spec-id.js +0 -21
  272. package/dist/src/cli/spec-id.js.map +0 -11
  273. package/dist/src/cli/spec-loader.d.ts.map +0 -1
  274. package/dist/src/cli/spec-loader.js +0 -110
  275. package/dist/src/cli/spec-loader.js.map +0 -15
  276. package/dist/src/cli/stable-json.d.ts.map +0 -1
  277. package/dist/src/cli/stable-json.js +0 -35
  278. package/dist/src/cli/stable-json.js.map +0 -10
  279. package/dist/src/cli/strings.d.ts.map +0 -1
  280. package/dist/src/cli/strings.js +0 -16
  281. package/dist/src/cli/strings.js.map +0 -10
  282. package/dist/src/cli/types.d.ts.map +0 -1
  283. package/dist/src/cli/types.js +0 -9
  284. package/dist/src/cli/types.js.map +0 -10
  285. package/index.ts +0 -1
  286. package/src/ai/tools.ts +0 -211
  287. package/src/cli/auth-requirements.ts +0 -91
  288. package/src/cli/auth-schemes.ts +0 -187
  289. package/src/cli/capabilities.ts +0 -88
  290. package/src/cli/command-id.ts +0 -16
  291. package/src/cli/command-index.ts +0 -19
  292. package/src/cli/command-model.ts +0 -128
  293. package/src/cli/compile.ts +0 -101
  294. package/src/cli/crypto.ts +0 -9
  295. package/src/cli/derive-name.ts +0 -101
  296. package/src/cli/exec.ts +0 -72
  297. package/src/cli/main.ts +0 -231
  298. package/src/cli/naming.ts +0 -224
  299. package/src/cli/operations.ts +0 -152
  300. package/src/cli/params.ts +0 -71
  301. package/src/cli/pluralize.ts +0 -41
  302. package/src/cli/positional.ts +0 -75
  303. package/src/cli/request-body.ts +0 -94
  304. package/src/cli/runtime/argv.ts +0 -14
  305. package/src/cli/runtime/auth/resolve.ts +0 -59
  306. package/src/cli/runtime/body-flags.ts +0 -176
  307. package/src/cli/runtime/body.ts +0 -24
  308. package/src/cli/runtime/collect.ts +0 -6
  309. package/src/cli/runtime/compat.ts +0 -89
  310. package/src/cli/runtime/context.ts +0 -62
  311. package/src/cli/runtime/execute.ts +0 -147
  312. package/src/cli/runtime/generated.ts +0 -242
  313. package/src/cli/runtime/headers.ts +0 -37
  314. package/src/cli/runtime/index.ts +0 -3
  315. package/src/cli/runtime/profile/secrets.ts +0 -83
  316. package/src/cli/runtime/profile/store.ts +0 -100
  317. package/src/cli/runtime/request.ts +0 -390
  318. package/src/cli/runtime/server-url.ts +0 -45
  319. package/src/cli/runtime/template.ts +0 -26
  320. package/src/cli/runtime/validate/ajv.ts +0 -13
  321. package/src/cli/runtime/validate/coerce.ts +0 -71
  322. package/src/cli/runtime/validate/error.ts +0 -29
  323. package/src/cli/runtime/validate/index.ts +0 -4
  324. package/src/cli/runtime/validate/schema.ts +0 -54
  325. package/src/cli/schema-shape.ts +0 -36
  326. package/src/cli/schema.ts +0 -76
  327. package/src/cli/server.ts +0 -88
  328. package/src/cli/spec-id.ts +0 -12
  329. package/src/cli/spec-loader.ts +0 -58
  330. package/src/cli/stable-json.ts +0 -35
  331. package/src/cli/strings.ts +0 -21
  332. package/src/cli/types.ts +0 -59
  333. package/src/macros/env.ts +0 -21
  334. package/src/macros/spec.ts +0 -17
package/src/cli/naming.ts DELETED
@@ -1,224 +0,0 @@
1
- import { pluralize } from "./pluralize.ts";
2
- import { kebabCase } from "./strings.ts";
3
- import type { NormalizedOperation } from "./types.ts";
4
-
5
- export type PlannedOperation = NormalizedOperation & {
6
- resource: string;
7
- action: string;
8
- pathArgs: string[];
9
- style: "rest" | "rpc";
10
- canonicalAction: string;
11
- aliasOf?: string;
12
- };
13
-
14
- const GENERIC_TAGS = new Set(["default", "defaults", "api"]);
15
-
16
- function getPathSegments(path: string): string[] {
17
- return path
18
- .split("/")
19
- .map((s) => s.trim())
20
- .filter(Boolean);
21
- }
22
-
23
- function getPathArgs(path: string): string[] {
24
- const args: string[] = [];
25
- const re = /\{([^}]+)\}/g;
26
-
27
- while (true) {
28
- const match = re.exec(path);
29
- if (!match) break;
30
- // biome-ignore lint/style/noNonNullAssertion: unknown
31
- args.push(match[1]!);
32
- }
33
-
34
- return args;
35
- }
36
-
37
- function pickResourceFromTags(tags: string[]): string | undefined {
38
- if (!tags.length) return undefined;
39
- const first = tags[0]?.trim();
40
- if (!first) return undefined;
41
- if (GENERIC_TAGS.has(first.toLowerCase())) return undefined;
42
- return first;
43
- }
44
-
45
- function splitOperationId(operationId: string): {
46
- prefix?: string;
47
- suffix?: string;
48
- } {
49
- const trimmed = operationId.trim();
50
- if (!trimmed) return {};
51
-
52
- // Prefer dot-notation when present: Contacts.List
53
- if (trimmed.includes(".")) {
54
- const [prefix, ...rest] = trimmed.split(".");
55
- return { prefix, suffix: rest.join(".") };
56
- }
57
-
58
- // Try separators: Contacts_List, Contacts__List
59
- if (trimmed.includes("__")) {
60
- const [prefix, ...rest] = trimmed.split("__");
61
- return { prefix, suffix: rest.join("__") };
62
- }
63
-
64
- if (trimmed.includes("_")) {
65
- const [prefix, ...rest] = trimmed.split("_");
66
- return { prefix, suffix: rest.join("_") };
67
- }
68
-
69
- return { suffix: trimmed };
70
- }
71
-
72
- function inferStyle(op: NormalizedOperation): "rest" | "rpc" {
73
- // Path-based RPC convention (common in gRPC-ish HTTP gateways)
74
- // - POST /Contacts.List
75
- // - POST /Contacts/Service.List
76
- if (op.path.includes(".")) return "rpc";
77
-
78
- // operationId dot-notation alone is not enough to call it RPC; many REST APIs
79
- // have dotted ids. We treat dotted operationId as a weak signal.
80
- if (op.operationId?.includes(".") && op.method === "POST") return "rpc";
81
-
82
- return "rest";
83
- }
84
-
85
- function inferResource(op: NormalizedOperation): string {
86
- const tag = pickResourceFromTags(op.tags);
87
- if (tag) return pluralize(kebabCase(tag));
88
-
89
- if (op.operationId) {
90
- const { prefix } = splitOperationId(op.operationId);
91
- if (prefix) {
92
- const fromId = kebabCase(prefix);
93
- if (fromId === "ping") return "ping";
94
- return pluralize(fromId);
95
- }
96
- }
97
-
98
- const segments = getPathSegments(op.path);
99
- let first = segments[0] ?? "api";
100
-
101
- // If first segment is rpc-ish, like Contacts.List, split it.
102
- // biome-ignore lint/style/noNonNullAssertion: split always returns at least one element
103
- first = first.includes(".") ? first.split(".")[0]! : first;
104
-
105
- // Singletons like /ping generally shouldn't become `pings`.
106
- if (first.toLowerCase() === "ping") return "ping";
107
-
108
- // Strip path params if they appear in first segment (rare)
109
- const cleaned = first.replace(/^\{.+\}$/, "");
110
- return pluralize(kebabCase(cleaned || "api"));
111
- }
112
-
113
- function canonicalizeAction(action: string): string {
114
- const a = kebabCase(action);
115
-
116
- // Common RPC verbs -> REST canonical verbs
117
- if (a === "retrieve" || a === "read") return "get";
118
- if (a === "list" || a === "search") return "list";
119
- if (a === "create") return "create";
120
- if (a === "update" || a === "patch") return "update";
121
- if (a === "delete" || a === "remove") return "delete";
122
-
123
- return a;
124
- }
125
-
126
- function inferRestAction(op: NormalizedOperation): string {
127
- // If operationId is present and looks intentional, prefer it.
128
- // This helps with singleton endpoints like GET /ping (Ping.Get) vs collections.
129
- if (op.operationId) {
130
- const { suffix } = splitOperationId(op.operationId);
131
- if (suffix) {
132
- const fromId = canonicalizeAction(suffix);
133
- if (
134
- fromId === "get" ||
135
- fromId === "list" ||
136
- fromId === "create" ||
137
- fromId === "update" ||
138
- fromId === "delete"
139
- ) {
140
- return fromId;
141
- }
142
- }
143
- }
144
-
145
- const method = op.method.toUpperCase();
146
- const args = getPathArgs(op.path);
147
- const hasId = args.length > 0;
148
-
149
- if (method === "GET" && !hasId) return "list";
150
- if (method === "POST" && !hasId) return "create";
151
-
152
- if (method === "GET" && hasId) return "get";
153
- if ((method === "PUT" || method === "PATCH") && hasId) return "update";
154
- if (method === "DELETE" && hasId) return "delete";
155
-
156
- return kebabCase(method);
157
- }
158
-
159
- function inferRpcAction(op: NormalizedOperation): string {
160
- // Prefer operationId suffix: Contacts.List -> list
161
- if (op.operationId) {
162
- const { suffix } = splitOperationId(op.operationId);
163
- if (suffix) return canonicalizeAction(suffix);
164
- }
165
-
166
- // Else take last segment and split by '.'
167
- const segments = getPathSegments(op.path);
168
- const last = segments[segments.length - 1] ?? "";
169
- if (last.includes(".")) {
170
- const part = last.split(".").pop() ?? last;
171
- return canonicalizeAction(part);
172
- }
173
-
174
- return kebabCase(op.method);
175
- }
176
-
177
- export function planOperation(op: NormalizedOperation): PlannedOperation {
178
- const style = inferStyle(op);
179
- const resource = inferResource(op);
180
- const action = style === "rpc" ? inferRpcAction(op) : inferRestAction(op);
181
-
182
- return {
183
- ...op,
184
- key: op.key,
185
- style,
186
- resource,
187
- action,
188
- canonicalAction: action,
189
- pathArgs: getPathArgs(op.path).map((a) => kebabCase(a)),
190
- };
191
- }
192
-
193
- export function planOperations(ops: NormalizedOperation[]): PlannedOperation[] {
194
- const planned = ops.map(planOperation);
195
-
196
- // Stable collision handling: if resource+action repeats, add a suffix.
197
- const counts = new Map<string, number>();
198
- for (const op of planned) {
199
- const key = `${op.resource}:${op.action}`;
200
- counts.set(key, (counts.get(key) ?? 0) + 1);
201
- }
202
-
203
- const seen = new Map<string, number>();
204
- return planned.map((op) => {
205
- const key = `${op.resource}:${op.action}`;
206
- const total = counts.get(key) ?? 0;
207
- if (total <= 1) return op;
208
-
209
- const idx = (seen.get(key) ?? 0) + 1;
210
- seen.set(key, idx);
211
-
212
- const suffix = op.operationId
213
- ? kebabCase(op.operationId)
214
- : kebabCase(`${op.method}-${op.path}`);
215
-
216
- const disambiguatedAction = `${op.action}-${suffix}-${idx}`;
217
-
218
- return {
219
- ...op,
220
- action: disambiguatedAction,
221
- aliasOf: `${op.resource} ${op.canonicalAction}`,
222
- };
223
- });
224
- }
@@ -1,152 +0,0 @@
1
- import type {
2
- NormalizedOperation,
3
- NormalizedParameter,
4
- NormalizedRequestBody,
5
- OpenApiDoc,
6
- } from "./types.ts";
7
-
8
- function operationKey(method: string, path: string): string {
9
- return `${method.toUpperCase()} ${path}`;
10
- }
11
-
12
- const HTTP_METHODS = [
13
- "get",
14
- "post",
15
- "put",
16
- "patch",
17
- "delete",
18
- "options",
19
- "head",
20
- "trace",
21
- ] as const;
22
-
23
- type RawParameter = {
24
- in?: string;
25
- name?: string;
26
- required?: boolean;
27
- description?: string;
28
- schema?: unknown;
29
- };
30
-
31
- type RawRequestBody = {
32
- required?: boolean;
33
- content?: Record<string, { schema?: unknown } | undefined>;
34
- };
35
-
36
- type RawOperation = {
37
- operationId?: string;
38
- tags?: string[];
39
- summary?: string;
40
- description?: string;
41
- deprecated?: boolean;
42
- security?: OpenApiDoc["security"];
43
- parameters?: RawParameter[];
44
- requestBody?: RawRequestBody;
45
- };
46
-
47
- type RawPathItem = {
48
- parameters?: RawParameter[];
49
- } & Partial<Record<(typeof HTTP_METHODS)[number], RawOperation>>;
50
-
51
- function normalizeParam(p: RawParameter): NormalizedParameter | undefined {
52
- if (!p || typeof p !== "object") return undefined;
53
- const loc = p.in;
54
- const name = p.name;
55
- if (
56
- loc !== "path" &&
57
- loc !== "query" &&
58
- loc !== "header" &&
59
- loc !== "cookie"
60
- ) {
61
- return undefined;
62
- }
63
- if (!name) return undefined;
64
-
65
- return {
66
- in: loc,
67
- name,
68
- required: Boolean(p.required || loc === "path"),
69
- description: p.description,
70
- schema: p.schema,
71
- };
72
- }
73
-
74
- function mergeParameters(
75
- pathParams: RawParameter[] | undefined,
76
- opParams: RawParameter[] | undefined,
77
- ): NormalizedParameter[] {
78
- const merged = new Map<string, NormalizedParameter>();
79
-
80
- for (const p of pathParams ?? []) {
81
- const normalized = normalizeParam(p);
82
- if (!normalized) continue;
83
- merged.set(`${normalized.in}:${normalized.name}`, normalized);
84
- }
85
-
86
- for (const p of opParams ?? []) {
87
- const normalized = normalizeParam(p);
88
- if (!normalized) continue;
89
- merged.set(`${normalized.in}:${normalized.name}`, normalized);
90
- }
91
-
92
- return [...merged.values()];
93
- }
94
-
95
- function normalizeRequestBody(
96
- rb: RawRequestBody | undefined,
97
- ): NormalizedRequestBody | undefined {
98
- if (!rb) return undefined;
99
-
100
- const content = rb.content ?? {};
101
- const contentTypes = Object.keys(content);
102
- const schemasByContentType: Record<string, unknown | undefined> = {};
103
-
104
- for (const contentType of contentTypes) {
105
- schemasByContentType[contentType] = content[contentType]?.schema;
106
- }
107
-
108
- return {
109
- required: Boolean(rb.required),
110
- contentTypes,
111
- schemasByContentType,
112
- };
113
- }
114
-
115
- export function indexOperations(doc: OpenApiDoc): NormalizedOperation[] {
116
- const out: NormalizedOperation[] = [];
117
- const paths = doc.paths ?? {};
118
-
119
- for (const [path, rawPathItem] of Object.entries(paths)) {
120
- if (!rawPathItem || typeof rawPathItem !== "object") continue;
121
-
122
- const pathItem = rawPathItem as RawPathItem;
123
-
124
- for (const method of HTTP_METHODS) {
125
- const op = pathItem[method];
126
- if (!op) continue;
127
-
128
- const parameters = mergeParameters(pathItem.parameters, op.parameters);
129
- const normalizedMethod = method.toUpperCase();
130
- out.push({
131
- key: operationKey(normalizedMethod, path),
132
- method: normalizedMethod,
133
- path,
134
- operationId: op.operationId,
135
- tags: op.tags ?? [],
136
- summary: op.summary,
137
- description: op.description,
138
- deprecated: op.deprecated,
139
- security: (op.security ?? doc.security) as OpenApiDoc["security"],
140
- parameters,
141
- requestBody: normalizeRequestBody(op.requestBody),
142
- });
143
- }
144
- }
145
-
146
- out.sort((a, b) => {
147
- if (a.path !== b.path) return a.path.localeCompare(b.path);
148
- return a.method.localeCompare(b.method);
149
- });
150
-
151
- return out;
152
- }
package/src/cli/params.ts DELETED
@@ -1,71 +0,0 @@
1
- import {
2
- getSchemaEnumStrings,
3
- getSchemaFormat,
4
- getSchemaType,
5
- } from "./schema-shape.ts";
6
- import { kebabCase } from "./strings.ts";
7
- import type { NormalizedOperation, NormalizedParameter } from "./types.ts";
8
-
9
- export type ParamType = import("./schema-shape.ts").ParamType;
10
-
11
- export type ParamSpec = {
12
- kind: "positional" | "flag";
13
- in: NormalizedParameter["in"];
14
- name: string;
15
- flag: string;
16
- required: boolean;
17
- description?: string;
18
- type: ParamType;
19
- format?: string;
20
- enum?: string[];
21
-
22
- // Arrays
23
- itemType?: ParamType;
24
- itemFormat?: string;
25
- itemEnum?: string[];
26
-
27
- // Original schema for Ajv validation and future advanced flag expansion.
28
- schema?: import("./types.ts").JsonSchema;
29
- };
30
-
31
- export function deriveParamSpecs(op: NormalizedOperation): ParamSpec[] {
32
- const out: ParamSpec[] = [];
33
-
34
- for (const p of op.parameters) {
35
- const flag = `--${kebabCase(p.name)}`;
36
- const type = getSchemaType(p.schema);
37
- const schemaObj =
38
- p.schema && typeof p.schema === "object"
39
- ? (p.schema as import("./types.ts").JsonSchema)
40
- : undefined;
41
-
42
- const itemsSchema =
43
- schemaObj && type === "array" && typeof schemaObj.items === "object"
44
- ? (schemaObj.items as unknown)
45
- : undefined;
46
-
47
- out.push({
48
- kind: p.in === "path" ? "positional" : "flag",
49
- in: p.in,
50
- name: p.name,
51
- flag,
52
- required: p.required,
53
- description: p.description,
54
- type,
55
- format: getSchemaFormat(p.schema),
56
- enum: getSchemaEnumStrings(p.schema),
57
- itemType: type === "array" ? getSchemaType(itemsSchema) : undefined,
58
- itemFormat: type === "array" ? getSchemaFormat(itemsSchema) : undefined,
59
- itemEnum:
60
- type === "array" ? getSchemaEnumStrings(itemsSchema) : undefined,
61
- schema: schemaObj,
62
- });
63
- }
64
-
65
- out.sort((a, b) => {
66
- if (a.in !== b.in) return a.in.localeCompare(b.in);
67
- return a.name.localeCompare(b.name);
68
- });
69
-
70
- return out;
71
- }
@@ -1,41 +0,0 @@
1
- const IRREGULAR: Record<string, string> = {
2
- person: "people",
3
- man: "men",
4
- woman: "women",
5
- child: "children",
6
- tooth: "teeth",
7
- foot: "feet",
8
- mouse: "mice",
9
- goose: "geese",
10
- };
11
-
12
- const UNCOUNTABLE = new Set([
13
- "metadata",
14
- "information",
15
- "equipment",
16
- "money",
17
- "series",
18
- "species",
19
- ]);
20
-
21
- export function pluralize(word: string): string {
22
- const w = word.trim();
23
- if (!w) return w;
24
-
25
- const lower = w.toLowerCase();
26
- if (UNCOUNTABLE.has(lower)) return lower;
27
- if (IRREGULAR[lower]) return IRREGULAR[lower];
28
-
29
- // already plural-ish
30
- if (lower.endsWith("s")) return lower;
31
-
32
- if (/[bcdfghjklmnpqrstvwxyz]y$/.test(lower)) {
33
- return lower.replace(/y$/, "ies");
34
- }
35
-
36
- if (/(ch|sh|x|z)$/.test(lower)) {
37
- return `${lower}es`;
38
- }
39
-
40
- return `${lower}s`;
41
- }
@@ -1,75 +0,0 @@
1
- import type { ParamSpec } from "./params.ts";
2
-
3
- export type ActionShapeForCli = {
4
- pathArgs: string[];
5
- params: ParamSpec[];
6
- };
7
-
8
- export type PositionalArg = {
9
- name: string;
10
- required: boolean;
11
- description?: string;
12
- type: import("./schema-shape.ts").ParamType;
13
- format?: string;
14
- enum?: string[];
15
- };
16
-
17
- export type FlagsIndex = {
18
- flags: Array<
19
- Pick<
20
- import("./params.ts").ParamSpec,
21
- | "in"
22
- | "name"
23
- | "flag"
24
- | "required"
25
- | "description"
26
- | "type"
27
- | "format"
28
- | "enum"
29
- | "itemType"
30
- | "itemFormat"
31
- | "itemEnum"
32
- >
33
- >;
34
- };
35
-
36
- export function derivePositionals(action: ActionShapeForCli): PositionalArg[] {
37
- const byName = new Map<string, PositionalArg>();
38
-
39
- // Use pathArgs order; match metadata from params when available.
40
- for (const name of action.pathArgs) {
41
- const p = action.params.find(
42
- (x: ParamSpec) => x.in === "path" && x.name === name,
43
- );
44
- byName.set(name, {
45
- name,
46
- required: true,
47
- description: p?.description,
48
- type: p?.type ?? "unknown",
49
- format: p?.format,
50
- enum: p?.enum,
51
- });
52
- }
53
-
54
- return [...byName.values()];
55
- }
56
-
57
- export function deriveFlags(action: ActionShapeForCli): FlagsIndex {
58
- return {
59
- flags: action.params
60
- .filter((p: ParamSpec) => p.kind === "flag")
61
- .map((p: ParamSpec) => ({
62
- in: p.in,
63
- name: p.name,
64
- flag: p.flag,
65
- required: p.required,
66
- description: p.description,
67
- type: p.type,
68
- format: p.format,
69
- enum: p.enum,
70
- itemType: p.itemType,
71
- itemFormat: p.itemFormat,
72
- itemEnum: p.itemEnum,
73
- })),
74
- };
75
- }
@@ -1,94 +0,0 @@
1
- import {
2
- getSchemaEnumStrings,
3
- getSchemaFormat,
4
- getSchemaType,
5
- } from "./schema-shape.ts";
6
- import type {
7
- JsonSchema,
8
- NormalizedOperation,
9
- NormalizedRequestBody,
10
- } from "./types.ts";
11
- import { isJsonSchema } from "./types.ts";
12
-
13
- export type RequestBodyContent = {
14
- contentType: string;
15
- required: boolean;
16
- schemaType: import("./schema-shape.ts").ParamType;
17
- schemaFormat?: string;
18
- schemaEnum?: string[];
19
- };
20
-
21
- export type RequestBodyInfo = {
22
- required: boolean;
23
- content: RequestBodyContent[];
24
- // Convenience flags for later arg generation.
25
- hasJson: boolean;
26
- hasFormUrlEncoded: boolean;
27
- hasMultipart: boolean;
28
-
29
- // Phase 1 planning: supported generic body inputs.
30
- bodyFlags: string[];
31
- preferredContentType?: string;
32
-
33
- // Original JSON Schema (for expanded flags + validation)
34
- preferredSchema?: JsonSchema;
35
- };
36
-
37
- function getRequestBody(
38
- op: NormalizedOperation,
39
- ): NormalizedRequestBody | undefined {
40
- return op.requestBody;
41
- }
42
-
43
- export function deriveRequestBodyInfo(
44
- op: NormalizedOperation,
45
- ): RequestBodyInfo | undefined {
46
- const rb = getRequestBody(op);
47
- if (!rb) return undefined;
48
-
49
- const content: RequestBodyContent[] = [];
50
- for (const contentType of rb.contentTypes) {
51
- const schema = rb.schemasByContentType[contentType];
52
- content.push({
53
- contentType,
54
- required: rb.required,
55
- schemaType: getSchemaType(schema),
56
- schemaFormat: getSchemaFormat(schema),
57
- schemaEnum: getSchemaEnumStrings(schema),
58
- });
59
- }
60
-
61
- content.sort((a, b) => a.contentType.localeCompare(b.contentType));
62
-
63
- const hasJson = content.some((c) => c.contentType.includes("json"));
64
- const hasFormUrlEncoded = content.some(
65
- (c) => c.contentType === "application/x-www-form-urlencoded",
66
- );
67
- const hasMultipart = content.some((c) =>
68
- c.contentType.startsWith("multipart/"),
69
- );
70
-
71
- const bodyFlags = ["--data", "--file"]; // always available when requestBody exists
72
-
73
- const preferredContentType =
74
- content.find((c) => c.contentType === "application/json")?.contentType ??
75
- content.find((c) => c.contentType.includes("json"))?.contentType ??
76
- content[0]?.contentType;
77
-
78
- const preferredSchema = preferredContentType
79
- ? rb.schemasByContentType[preferredContentType]
80
- : undefined;
81
-
82
- return {
83
- required: rb.required,
84
- content,
85
- hasJson,
86
- hasFormUrlEncoded,
87
- hasMultipart,
88
- bodyFlags,
89
- preferredContentType,
90
- preferredSchema: isJsonSchema(preferredSchema)
91
- ? preferredSchema
92
- : undefined,
93
- };
94
- }
@@ -1,14 +0,0 @@
1
- export function getArgValue(argv: string[], key: string): string | undefined {
2
- for (let i = 0; i < argv.length; i++) {
3
- const a = argv[i];
4
- if (!a) continue;
5
-
6
- if (a === key) return argv[i + 1];
7
- if (a.startsWith(`${key}=`)) return a.slice(key.length + 1);
8
- }
9
- return undefined;
10
- }
11
-
12
- export function hasAnyArg(argv: string[], names: string[]): boolean {
13
- return argv.some((a) => a && names.includes(a));
14
- }