padrone 1.8.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (333) hide show
  1. package/CHANGELOG.md +20 -1
  2. package/README.md +2 -2
  3. package/dist/codegen/code-builder.d.mts +10 -0
  4. package/dist/codegen/code-builder.d.mts.map +1 -0
  5. package/dist/codegen/code-builder.mjs +185 -0
  6. package/dist/codegen/code-builder.mjs.map +1 -0
  7. package/dist/codegen/discovery.d.mts +44 -0
  8. package/dist/codegen/discovery.d.mts.map +1 -0
  9. package/dist/codegen/discovery.mjs +179 -0
  10. package/dist/codegen/discovery.mjs.map +1 -0
  11. package/dist/codegen/file-emitter.d.mts +10 -0
  12. package/dist/codegen/file-emitter.d.mts.map +1 -0
  13. package/dist/codegen/file-emitter.mjs +58 -0
  14. package/dist/codegen/file-emitter.mjs.map +1 -0
  15. package/dist/codegen/generators/barrel-file.d.mts +10 -0
  16. package/dist/codegen/generators/barrel-file.d.mts.map +1 -0
  17. package/dist/codegen/generators/barrel-file.mjs +16 -0
  18. package/dist/codegen/generators/barrel-file.mjs.map +1 -0
  19. package/dist/codegen/generators/command-file.d.mts +25 -0
  20. package/dist/codegen/generators/command-file.d.mts.map +1 -0
  21. package/dist/codegen/generators/command-file.mjs +130 -0
  22. package/dist/codegen/generators/command-file.mjs.map +1 -0
  23. package/dist/codegen/generators/command-tree.d.mts +17 -0
  24. package/dist/codegen/generators/command-tree.d.mts.map +1 -0
  25. package/dist/codegen/generators/command-tree.mjs +72 -0
  26. package/dist/codegen/generators/command-tree.mjs.map +1 -0
  27. package/dist/codegen/index.d.mts +15 -330
  28. package/dist/codegen/index.mjs +13 -1507
  29. package/dist/codegen/parsers/bash.d.mts +19 -0
  30. package/dist/codegen/parsers/bash.d.mts.map +1 -0
  31. package/dist/codegen/parsers/bash.mjs +112 -0
  32. package/dist/codegen/parsers/bash.mjs.map +1 -0
  33. package/dist/codegen/parsers/fish.d.mts +13 -0
  34. package/dist/codegen/parsers/fish.d.mts.map +1 -0
  35. package/dist/codegen/parsers/fish.mjs +108 -0
  36. package/dist/codegen/parsers/fish.mjs.map +1 -0
  37. package/dist/codegen/parsers/help.d.mts +15 -0
  38. package/dist/codegen/parsers/help.d.mts.map +1 -0
  39. package/dist/codegen/parsers/help.mjs +271 -0
  40. package/dist/codegen/parsers/help.mjs.map +1 -0
  41. package/dist/codegen/parsers/merge.d.mts +14 -0
  42. package/dist/codegen/parsers/merge.d.mts.map +1 -0
  43. package/dist/codegen/parsers/merge.mjs +76 -0
  44. package/dist/codegen/parsers/merge.mjs.map +1 -0
  45. package/dist/codegen/parsers/zsh.d.mts +16 -0
  46. package/dist/codegen/parsers/zsh.d.mts.map +1 -0
  47. package/dist/codegen/parsers/zsh.mjs +161 -0
  48. package/dist/codegen/parsers/zsh.mjs.map +1 -0
  49. package/dist/codegen/schema-to-code.d.mts +24 -0
  50. package/dist/codegen/schema-to-code.d.mts.map +1 -0
  51. package/dist/codegen/schema-to-code.mjs +147 -0
  52. package/dist/codegen/schema-to-code.mjs.map +1 -0
  53. package/dist/codegen/template.d.mts +18 -0
  54. package/dist/codegen/template.d.mts.map +1 -0
  55. package/dist/codegen/template.mjs +37 -0
  56. package/dist/codegen/template.mjs.map +1 -0
  57. package/dist/codegen/types.d.mts +144 -0
  58. package/dist/codegen/types.d.mts.map +1 -0
  59. package/dist/completion.d.mts +2 -0
  60. package/dist/completion.mjs +2 -0
  61. package/dist/core/args.d.mts +3 -0
  62. package/dist/{args-DrCXxXeP.mjs → core/args.mjs} +49 -113
  63. package/dist/core/args.mjs.map +1 -0
  64. package/dist/core/commands.d.mts +13 -0
  65. package/dist/core/commands.d.mts.map +1 -0
  66. package/dist/{commands-DLR0rFgq.mjs → core/commands.mjs} +4 -232
  67. package/dist/core/commands.mjs.map +1 -0
  68. package/dist/core/create.d.mts +63 -0
  69. package/dist/core/create.d.mts.map +1 -0
  70. package/dist/core/create.mjs +230 -0
  71. package/dist/core/create.mjs.map +1 -0
  72. package/dist/core/default-runtime.mjs +198 -0
  73. package/dist/core/default-runtime.mjs.map +1 -0
  74. package/dist/core/errors.d.mts +107 -0
  75. package/dist/core/errors.d.mts.map +1 -0
  76. package/dist/{errors-DA4KzK1M.mjs → core/errors.mjs} +2 -2
  77. package/dist/core/errors.mjs.map +1 -0
  78. package/dist/core/exec.mjs +191 -0
  79. package/dist/core/exec.mjs.map +1 -0
  80. package/dist/core/interceptors.d.mts +33 -0
  81. package/dist/core/interceptors.d.mts.map +1 -0
  82. package/dist/core/interceptors.mjs +253 -0
  83. package/dist/core/interceptors.mjs.map +1 -0
  84. package/dist/core/parse.mjs +181 -0
  85. package/dist/core/parse.mjs.map +1 -0
  86. package/dist/core/program-methods.mjs +256 -0
  87. package/dist/core/program-methods.mjs.map +1 -0
  88. package/dist/core/results.d.mts +13 -0
  89. package/dist/core/results.d.mts.map +1 -0
  90. package/dist/core/results.mjs +150 -0
  91. package/dist/core/results.mjs.map +1 -0
  92. package/dist/core/runtime.d.mts +213 -0
  93. package/dist/core/runtime.d.mts.map +1 -0
  94. package/dist/core/runtime.mjs +10 -0
  95. package/dist/core/runtime.mjs.map +1 -0
  96. package/dist/core/validate.mjs +220 -0
  97. package/dist/core/validate.mjs.map +1 -0
  98. package/dist/docs/index.d.mts +1 -1
  99. package/dist/docs/index.d.mts.map +1 -1
  100. package/dist/docs/index.mjs +2 -2
  101. package/dist/docs/index.mjs.map +1 -1
  102. package/dist/extension/auto-output.d.mts +53 -0
  103. package/dist/extension/auto-output.d.mts.map +1 -0
  104. package/dist/extension/auto-output.mjs +116 -0
  105. package/dist/extension/auto-output.mjs.map +1 -0
  106. package/dist/extension/color.d.mts +19 -0
  107. package/dist/extension/color.d.mts.map +1 -0
  108. package/dist/extension/color.mjs +37 -0
  109. package/dist/extension/color.mjs.map +1 -0
  110. package/dist/extension/completion.d.mts +25 -0
  111. package/dist/extension/completion.d.mts.map +1 -0
  112. package/dist/extension/completion.mjs +40 -0
  113. package/dist/extension/completion.mjs.map +1 -0
  114. package/dist/extension/config.d.mts +55 -0
  115. package/dist/extension/config.d.mts.map +1 -0
  116. package/dist/extension/config.mjs +162 -0
  117. package/dist/extension/config.mjs.map +1 -0
  118. package/dist/extension/env.d.mts +42 -0
  119. package/dist/extension/env.d.mts.map +1 -0
  120. package/dist/extension/env.mjs +44 -0
  121. package/dist/extension/env.mjs.map +1 -0
  122. package/dist/extension/help.d.mts +29 -0
  123. package/dist/extension/help.d.mts.map +1 -0
  124. package/dist/extension/help.mjs +161 -0
  125. package/dist/extension/help.mjs.map +1 -0
  126. package/dist/extension/index.d.mts +18 -0
  127. package/dist/extension/ink.d.mts +31 -0
  128. package/dist/extension/ink.d.mts.map +1 -0
  129. package/dist/extension/ink.mjs +69 -0
  130. package/dist/extension/ink.mjs.map +1 -0
  131. package/dist/extension/interactive.d.mts +16 -0
  132. package/dist/extension/interactive.d.mts.map +1 -0
  133. package/dist/extension/interactive.mjs +89 -0
  134. package/dist/extension/interactive.mjs.map +1 -0
  135. package/dist/extension/logger.d.mts +67 -0
  136. package/dist/extension/logger.d.mts.map +1 -0
  137. package/dist/extension/logger.mjs +188 -0
  138. package/dist/extension/logger.mjs.map +1 -0
  139. package/dist/extension/man.d.mts +25 -0
  140. package/dist/extension/man.d.mts.map +1 -0
  141. package/dist/extension/man.mjs +41 -0
  142. package/dist/extension/man.mjs.map +1 -0
  143. package/dist/extension/mcp.d.mts +28 -0
  144. package/dist/extension/mcp.d.mts.map +1 -0
  145. package/dist/extension/mcp.mjs +44 -0
  146. package/dist/extension/mcp.mjs.map +1 -0
  147. package/dist/extension/progress-renderer.d.mts +13 -0
  148. package/dist/extension/progress-renderer.d.mts.map +1 -0
  149. package/dist/extension/progress-renderer.mjs +351 -0
  150. package/dist/extension/progress-renderer.mjs.map +1 -0
  151. package/dist/extension/progress.d.mts +76 -0
  152. package/dist/extension/progress.d.mts.map +1 -0
  153. package/dist/extension/progress.mjs +225 -0
  154. package/dist/extension/progress.mjs.map +1 -0
  155. package/dist/extension/repl.d.mts +26 -0
  156. package/dist/extension/repl.d.mts.map +1 -0
  157. package/dist/extension/repl.mjs +67 -0
  158. package/dist/extension/repl.mjs.map +1 -0
  159. package/dist/extension/serve.d.mts +27 -0
  160. package/dist/extension/serve.d.mts.map +1 -0
  161. package/dist/extension/serve.mjs +41 -0
  162. package/dist/extension/serve.mjs.map +1 -0
  163. package/dist/extension/signal.d.mts +19 -0
  164. package/dist/extension/signal.d.mts.map +1 -0
  165. package/dist/extension/signal.mjs +81 -0
  166. package/dist/extension/signal.mjs.map +1 -0
  167. package/dist/extension/stdin.d.mts +19 -0
  168. package/dist/extension/stdin.d.mts.map +1 -0
  169. package/dist/extension/stdin.mjs +52 -0
  170. package/dist/extension/stdin.mjs.map +1 -0
  171. package/dist/extension/suggestions.d.mts +6 -0
  172. package/dist/extension/suggestions.d.mts.map +1 -0
  173. package/dist/extension/suggestions.mjs +113 -0
  174. package/dist/extension/suggestions.mjs.map +1 -0
  175. package/dist/extension/timing.d.mts +27 -0
  176. package/dist/extension/timing.d.mts.map +1 -0
  177. package/dist/extension/timing.mjs +71 -0
  178. package/dist/extension/timing.mjs.map +1 -0
  179. package/dist/extension/tracing.d.mts +85 -0
  180. package/dist/extension/tracing.d.mts.map +1 -0
  181. package/dist/extension/tracing.mjs +107 -0
  182. package/dist/extension/tracing.mjs.map +1 -0
  183. package/dist/extension/update-check.d.mts +20 -0
  184. package/dist/extension/update-check.d.mts.map +1 -0
  185. package/dist/extension/update-check.mjs +62 -0
  186. package/dist/extension/update-check.mjs.map +1 -0
  187. package/dist/extension/utils.mjs +43 -0
  188. package/dist/extension/utils.mjs.map +1 -0
  189. package/dist/extension/version.d.mts +20 -0
  190. package/dist/extension/version.d.mts.map +1 -0
  191. package/dist/extension/version.mjs +51 -0
  192. package/dist/extension/version.mjs.map +1 -0
  193. package/dist/{completion-UnBKfGuk.mjs → feature/completion.mjs} +4 -3
  194. package/dist/feature/completion.mjs.map +1 -0
  195. package/dist/feature/interactive.mjs +145 -0
  196. package/dist/feature/interactive.mjs.map +1 -0
  197. package/dist/feature/mcp.d.mts +18 -0
  198. package/dist/feature/mcp.d.mts.map +1 -0
  199. package/dist/{mcp-D6PdtjIs.mjs → feature/mcp.mjs} +6 -6
  200. package/dist/feature/mcp.mjs.map +1 -0
  201. package/dist/feature/repl-loop.mjs +217 -0
  202. package/dist/feature/repl-loop.mjs.map +1 -0
  203. package/dist/feature/serve.d.mts +18 -0
  204. package/dist/feature/serve.d.mts.map +1 -0
  205. package/dist/{serve-PaCLsNoD.mjs → feature/serve.mjs} +7 -7
  206. package/dist/feature/serve.mjs.map +1 -0
  207. package/dist/feature/test.d.mts +109 -0
  208. package/dist/feature/test.d.mts.map +1 -0
  209. package/dist/feature/test.mjs +116 -0
  210. package/dist/feature/test.mjs.map +1 -0
  211. package/dist/feature/update-check.d.mts +35 -0
  212. package/dist/feature/update-check.d.mts.map +1 -0
  213. package/dist/{update-check-CZ2VqjnV.mjs → feature/update-check.mjs} +2 -2
  214. package/dist/feature/update-check.mjs.map +1 -0
  215. package/dist/feature/wrap.d.mts +58 -0
  216. package/dist/feature/wrap.d.mts.map +1 -0
  217. package/dist/feature/wrap.mjs +77 -0
  218. package/dist/feature/wrap.mjs.map +1 -0
  219. package/dist/index.d.mts +38 -901
  220. package/dist/index.mjs +25 -4337
  221. package/dist/ink.d.mts +2 -0
  222. package/dist/ink.mjs +2 -0
  223. package/dist/man.d.mts +2 -0
  224. package/dist/man.mjs +2 -0
  225. package/dist/mcp.d.mts +3 -0
  226. package/dist/mcp.mjs +2 -0
  227. package/dist/output/colorizer.d.mts +28 -0
  228. package/dist/output/colorizer.d.mts.map +1 -0
  229. package/dist/output/colorizer.mjs +94 -0
  230. package/dist/output/colorizer.mjs.map +1 -0
  231. package/dist/{formatter-CY3KrOEd.d.mts → output/formatter.d.mts} +2 -28
  232. package/dist/output/formatter.d.mts.map +1 -0
  233. package/dist/output/formatter.mjs +360 -0
  234. package/dist/output/formatter.mjs.map +1 -0
  235. package/dist/output/help.d.mts +18 -0
  236. package/dist/output/help.d.mts.map +1 -0
  237. package/dist/output/help.mjs +267 -0
  238. package/dist/output/help.mjs.map +1 -0
  239. package/dist/output/output-indicator.d.mts +27 -0
  240. package/dist/output/output-indicator.d.mts.map +1 -0
  241. package/dist/output/output-indicator.mjs +54 -0
  242. package/dist/output/output-indicator.mjs.map +1 -0
  243. package/dist/output/primitives.d.mts +33 -0
  244. package/dist/output/primitives.d.mts.map +1 -0
  245. package/dist/output/primitives.mjs +206 -0
  246. package/dist/output/primitives.mjs.map +1 -0
  247. package/dist/output/styling.d.mts +38 -0
  248. package/dist/output/styling.d.mts.map +1 -0
  249. package/dist/output/styling.mjs +146 -0
  250. package/dist/output/styling.mjs.map +1 -0
  251. package/dist/schema/zod.d.mts +6 -0
  252. package/dist/schema/zod.d.mts.map +1 -0
  253. package/dist/schema/zod.mjs +50 -0
  254. package/dist/schema/zod.mjs.map +1 -0
  255. package/dist/serve.d.mts +2 -0
  256. package/dist/serve.mjs +2 -0
  257. package/dist/test.d.mts +2 -109
  258. package/dist/test.mjs +1 -115
  259. package/dist/tracing.d.mts +2 -0
  260. package/dist/tracing.mjs +2 -0
  261. package/dist/types/args-meta.d.mts +129 -0
  262. package/dist/types/args-meta.d.mts.map +1 -0
  263. package/dist/types/builder.d.mts +212 -0
  264. package/dist/types/builder.d.mts.map +1 -0
  265. package/dist/types/command.d.mts +112 -0
  266. package/dist/types/command.d.mts.map +1 -0
  267. package/dist/types/index.d.mts +8 -0
  268. package/dist/types/interceptor.d.mts +232 -0
  269. package/dist/types/interceptor.d.mts.map +1 -0
  270. package/dist/types/preferences.d.mts +79 -0
  271. package/dist/types/preferences.d.mts.map +1 -0
  272. package/dist/types/result.d.mts +61 -0
  273. package/dist/types/result.d.mts.map +1 -0
  274. package/dist/types/schema.d.mts +24 -0
  275. package/dist/types/schema.d.mts.map +1 -0
  276. package/dist/util/dotenv.mjs +174 -0
  277. package/dist/util/dotenv.mjs.map +1 -0
  278. package/dist/util/shell-utils.mjs +80 -0
  279. package/dist/util/shell-utils.mjs.map +1 -0
  280. package/dist/util/stream.d.mts +33 -0
  281. package/dist/util/stream.d.mts.map +1 -0
  282. package/dist/{stream-DC4H8YTx.mjs → util/stream.mjs} +2 -2
  283. package/dist/util/stream.mjs.map +1 -0
  284. package/dist/util/type-helpers.d.mts +74 -0
  285. package/dist/util/type-helpers.d.mts.map +1 -0
  286. package/dist/util/type-utils.d.mts +186 -0
  287. package/dist/util/type-utils.d.mts.map +1 -0
  288. package/dist/util/utils.mjs +43 -0
  289. package/dist/util/utils.mjs.map +1 -0
  290. package/dist/zod.d.mts +1 -32
  291. package/dist/zod.mjs +1 -49
  292. package/package.json +65 -17
  293. package/src/completion.ts +2 -0
  294. package/src/core/args.ts +63 -37
  295. package/src/core/runtime.ts +11 -2
  296. package/src/extension/completion.ts +3 -0
  297. package/src/extension/index.ts +0 -12
  298. package/src/extension/ink.ts +2 -1
  299. package/src/extension/man.ts +3 -0
  300. package/src/extension/mcp.ts +3 -0
  301. package/src/extension/progress-renderer.ts +32 -8
  302. package/src/extension/progress.ts +19 -9
  303. package/src/extension/serve.ts +3 -0
  304. package/src/extension/tracing.ts +2 -0
  305. package/src/index.ts +1 -20
  306. package/src/ink.ts +2 -0
  307. package/src/man.ts +2 -0
  308. package/src/mcp.ts +3 -0
  309. package/src/serve.ts +2 -0
  310. package/src/tracing.ts +9 -0
  311. package/src/types/builder.ts +2 -2
  312. package/src/zod.ts +1 -1
  313. package/dist/args-DrCXxXeP.mjs.map +0 -1
  314. package/dist/codegen/index.d.mts.map +0 -1
  315. package/dist/codegen/index.mjs.map +0 -1
  316. package/dist/commands-DLR0rFgq.mjs.map +0 -1
  317. package/dist/completion-UnBKfGuk.mjs.map +0 -1
  318. package/dist/errors-DA4KzK1M.mjs.map +0 -1
  319. package/dist/formatter-CY3KrOEd.d.mts.map +0 -1
  320. package/dist/help-B-ZMYyn-.mjs +0 -892
  321. package/dist/help-B-ZMYyn-.mjs.map +0 -1
  322. package/dist/index-D-Dpz7l_.d.mts +0 -1427
  323. package/dist/index-D-Dpz7l_.d.mts.map +0 -1
  324. package/dist/index.d.mts.map +0 -1
  325. package/dist/index.mjs.map +0 -1
  326. package/dist/mcp-D6PdtjIs.mjs.map +0 -1
  327. package/dist/serve-PaCLsNoD.mjs.map +0 -1
  328. package/dist/stream-DC4H8YTx.mjs.map +0 -1
  329. package/dist/test.d.mts.map +0 -1
  330. package/dist/test.mjs.map +0 -1
  331. package/dist/update-check-CZ2VqjnV.mjs.map +0 -1
  332. package/dist/zod.d.mts.map +0 -1
  333. package/dist/zod.mjs.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
+ ## padrone@2.0.0
2
+
3
+ ### Externalize optional integrations to dedicated subpath entry points
4
+
5
+ Optional integrations are now exported from dedicated subpath entry points so bundlers that don't tree-shake re-exports keep their dependencies out of the main bundle. Update imports as follows:
6
+
7
+ - `padroneInk`, `isReactElement`, `InkOptions` → `'padrone/ink'`
8
+ - `padroneMcp`, `WithMcp`, `PadroneMcpPreferences` → `'padrone/mcp'`
9
+ - `padroneServe`, `WithServe` → `'padrone/serve'`
10
+ - `padroneTracing`, `WithTracing`, `PadroneTracer`, `PadroneTracingConfig`, `OtelSpan`, `OtelTracer`, `OtelTracerProvider` → `'padrone/tracing'`
11
+ - `padroneCompletion`, `WithCompletion` → `'padrone/completion'`
12
+ - `padroneMan`, `WithMan` → `'padrone/man'`
13
+
1
14
  # padrone
2
15
 
16
+ ## 1.9.0
17
+
18
+ ### Minor Changes
19
+
20
+ - [`8114f98`](https://github.com/KurtGokhan/padrone/commit/8114f98ce3ae46cb6cdfa152d39e78e35d6ebe7d) Thanks [@KurtGokhan](https://github.com/KurtGokhan)! - Auto-coerce CLI string values for union types (e.g. `z.union([z.boolean(), z.string()])`) — `--flag true` now correctly passes boolean `true` instead of the string `"true"`
21
+
3
22
  ## 1.8.2
4
23
 
5
24
  ### Patch Changes
@@ -140,7 +159,7 @@
140
159
  - Empty string indicators hide the icon prefix entirely
141
160
  - Graceful fallback in non-TTY/CI environments
142
161
 
143
- **New types**: `PadroneProgressIndicator`, `PadroneProgressConfig`, `PadroneProgressMessage`, `PadroneProgressOptions`, `PadroneSpinnerConfig`, `PadroneSpinnerPreset`
162
+ **New types**: `PadroneProgress`, `PadroneProgressConfig`, `PadroneProgressMessage`, `PadroneProgressOptions`, `PadroneSpinnerConfig`, `PadroneSpinnerPreset`
144
163
 
145
164
  - [`6851b48`](https://github.com/KurtGokhan/padrone/commit/6851b4878ab0fc8d48f40e93c2f8924236a40165) Thanks [@KurtGokhan](https://github.com/KurtGokhan)! - Add REST server (`program.serve()`) and `mutation` command config.
146
165
 
package/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  <p align="center">
10
10
  <a href="https://www.npmjs.com/package/padrone"><img src="https://img.shields.io/npm/v/padrone.svg" alt="npm version"></a>
11
11
  <a href="https://www.npmjs.com/package/padrone"><img src="https://img.shields.io/npm/dm/padrone.svg" alt="npm downloads"></a>
12
- <a href="https://github.com/KurtGokhan/padrone/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/padrone.svg" alt="license"></a>
12
+ <a href="https://github.com/gkurt/padrone/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/padrone.svg" alt="license"></a>
13
13
  </p>
14
14
 
15
15
  ---
@@ -185,7 +185,7 @@ program.help('greet', { format: 'json' }); // json, markdown, html, ansi
185
185
  Give your AI coding agent knowledge of the Padrone API:
186
186
 
187
187
  ```bash
188
- npx skills add KurtGokhan/padrone
188
+ npx skills add gkurt/padrone
189
189
  ```
190
190
 
191
191
  ## Requirements
@@ -0,0 +1,10 @@
1
+ import { CodeBuilder } from "./types.mjs";
2
+
3
+ //#region src/codegen/code-builder.d.ts
4
+ /**
5
+ * Create a new CodeBuilder for constructing TypeScript source files.
6
+ */
7
+ declare function createCodeBuilder(): CodeBuilder;
8
+ //#endregion
9
+ export { createCodeBuilder };
10
+ //# sourceMappingURL=code-builder.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-builder.d.mts","names":[],"sources":["../../src/codegen/code-builder.ts"],"mappings":";;;;;AA+NA;iBAAgB,iBAAA,IAAqB,WAAW"}
@@ -0,0 +1,185 @@
1
+ //#region src/codegen/code-builder.ts
2
+ var CodeBuilderImpl = class CodeBuilderImpl {
3
+ imports = /* @__PURE__ */ new Map();
4
+ lines = [];
5
+ indent;
6
+ constructor(indent = 0) {
7
+ this.indent = indent;
8
+ }
9
+ import(specifier, source) {
10
+ const specs = Array.isArray(specifier) ? specifier : [specifier];
11
+ const existing = this.imports.get(source);
12
+ if (existing) {
13
+ for (const s of specs) existing.specifiers.add(s);
14
+ existing.typeOnly = false;
15
+ } else this.imports.set(source, {
16
+ specifiers: new Set(specs),
17
+ typeOnly: false
18
+ });
19
+ return this;
20
+ }
21
+ importDefault(name, source) {
22
+ const existing = this.imports.get(source);
23
+ if (existing) {
24
+ existing.defaultSpecifier = name;
25
+ existing.typeOnly = false;
26
+ } else this.imports.set(source, {
27
+ specifiers: /* @__PURE__ */ new Set(),
28
+ defaultSpecifier: name,
29
+ typeOnly: false
30
+ });
31
+ return this;
32
+ }
33
+ importType(specifier, source) {
34
+ const specs = Array.isArray(specifier) ? specifier : [specifier];
35
+ const existing = this.imports.get(source);
36
+ if (existing) for (const s of specs) existing.specifiers.add(s);
37
+ else this.imports.set(source, {
38
+ specifiers: new Set(specs),
39
+ typeOnly: true
40
+ });
41
+ return this;
42
+ }
43
+ line(code) {
44
+ this.lines.push({
45
+ type: "line",
46
+ content: code ?? ""
47
+ });
48
+ return this;
49
+ }
50
+ block(openOrBuilder, builderOrClose, closeOrBuilder) {
51
+ let open;
52
+ let close;
53
+ let builder;
54
+ if (typeof openOrBuilder === "function") builder = openOrBuilder;
55
+ else if (typeof builderOrClose === "function") {
56
+ open = openOrBuilder;
57
+ builder = builderOrClose;
58
+ close = typeof closeOrBuilder === "string" ? closeOrBuilder : void 0;
59
+ } else if (typeof closeOrBuilder === "function") {
60
+ open = openOrBuilder;
61
+ close = typeof builderOrClose === "string" ? builderOrClose : void 0;
62
+ builder = closeOrBuilder;
63
+ } else throw new Error("Invalid block() arguments");
64
+ this.lines.push({
65
+ type: "block-open",
66
+ content: open ?? ""
67
+ });
68
+ const inner = new CodeBuilderImpl(this.indent + 1);
69
+ builder(inner);
70
+ for (const [source, entry] of inner.imports) {
71
+ const existing = this.imports.get(source);
72
+ if (existing) {
73
+ for (const s of entry.specifiers) existing.specifiers.add(s);
74
+ if (entry.defaultSpecifier) existing.defaultSpecifier = entry.defaultSpecifier;
75
+ if (!entry.typeOnly) existing.typeOnly = false;
76
+ } else this.imports.set(source, {
77
+ specifiers: new Set(entry.specifiers),
78
+ defaultSpecifier: entry.defaultSpecifier,
79
+ typeOnly: entry.typeOnly
80
+ });
81
+ }
82
+ for (const line of inner.lines) this.lines.push(line);
83
+ this.lines.push({
84
+ type: "block-close",
85
+ content: close ?? ""
86
+ });
87
+ return this;
88
+ }
89
+ comment(text) {
90
+ this.lines.push({
91
+ type: "line",
92
+ content: `// ${text}`
93
+ });
94
+ return this;
95
+ }
96
+ docComment(text) {
97
+ const lines = text.split("\n");
98
+ if (lines.length === 1) this.lines.push({
99
+ type: "line",
100
+ content: `/** ${text} */`
101
+ });
102
+ else {
103
+ this.lines.push({
104
+ type: "line",
105
+ content: "/**"
106
+ });
107
+ for (const line of lines) this.lines.push({
108
+ type: "line",
109
+ content: ` * ${line}`
110
+ });
111
+ this.lines.push({
112
+ type: "line",
113
+ content: " */"
114
+ });
115
+ }
116
+ return this;
117
+ }
118
+ todoComment(text) {
119
+ this.lines.push({
120
+ type: "line",
121
+ content: `// TODO: ${text}`
122
+ });
123
+ return this;
124
+ }
125
+ raw(code) {
126
+ this.lines.push({
127
+ type: "raw",
128
+ content: code
129
+ });
130
+ return this;
131
+ }
132
+ build() {
133
+ const parts = [];
134
+ if (this.imports.size > 0) {
135
+ const typeImports = [];
136
+ const valueImports = [];
137
+ for (const [source, entry] of this.imports) {
138
+ const specs = [...entry.specifiers].sort();
139
+ const namedPart = specs.length > 0 ? specs.length === 1 && !specs[0].includes(" ") ? `{ ${specs[0]} }` : `{ ${specs.join(", ")} }` : null;
140
+ const specStr = entry.defaultSpecifier ? namedPart ? `${entry.defaultSpecifier}, ${namedPart}` : entry.defaultSpecifier : namedPart;
141
+ const line = entry.typeOnly ? `import type ${specStr} from '${source}'` : `import ${specStr} from '${source}'`;
142
+ if (entry.typeOnly) typeImports.push(line);
143
+ else valueImports.push(line);
144
+ }
145
+ parts.push([...valueImports, ...typeImports].join("\n"));
146
+ parts.push("");
147
+ }
148
+ let currentIndent = this.indent;
149
+ for (const line of this.lines) if (line.type === "raw") parts.push(line.content);
150
+ else if (line.type === "block-open") {
151
+ if (line.content) {
152
+ const indent = " ".repeat(currentIndent);
153
+ parts.push(`${indent}${line.content}`);
154
+ }
155
+ currentIndent++;
156
+ } else if (line.type === "block-close") {
157
+ currentIndent--;
158
+ if (line.content) {
159
+ const indent = " ".repeat(currentIndent);
160
+ parts.push(`${indent}${line.content}`);
161
+ }
162
+ } else if (line.content === "") parts.push("");
163
+ else {
164
+ const indent = " ".repeat(currentIndent);
165
+ parts.push(`${indent}${line.content}`);
166
+ }
167
+ return {
168
+ text: parts.join("\n"),
169
+ imports: new Map([...this.imports].map(([source, entry]) => [source, {
170
+ specifiers: new Set(entry.specifiers),
171
+ typeOnly: entry.typeOnly
172
+ }]))
173
+ };
174
+ }
175
+ };
176
+ /**
177
+ * Create a new CodeBuilder for constructing TypeScript source files.
178
+ */
179
+ function createCodeBuilder() {
180
+ return new CodeBuilderImpl();
181
+ }
182
+ //#endregion
183
+ export { createCodeBuilder };
184
+
185
+ //# sourceMappingURL=code-builder.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-builder.mjs","names":[],"sources":["../../src/codegen/code-builder.ts"],"sourcesContent":["import type { CodeBuilder, CodeBuildResult } from './types.ts';\n\ninterface ImportEntry {\n specifiers: Set<string>;\n defaultSpecifier?: string;\n typeOnly: boolean;\n}\n\ninterface CodeLine {\n type: 'line' | 'raw' | 'block-open' | 'block-close';\n content: string;\n}\n\nclass CodeBuilderImpl implements CodeBuilder {\n private imports = new Map<string, ImportEntry>();\n private lines: CodeLine[] = [];\n private indent: number;\n\n constructor(indent = 0) {\n this.indent = indent;\n }\n\n import(specifier: string | string[], source: string): CodeBuilder {\n const specs = Array.isArray(specifier) ? specifier : [specifier];\n const existing = this.imports.get(source);\n if (existing) {\n for (const s of specs) existing.specifiers.add(s);\n // If we're adding a value import and existing was type-only, downgrade to value\n existing.typeOnly = false;\n } else {\n this.imports.set(source, { specifiers: new Set(specs), typeOnly: false });\n }\n return this;\n }\n\n importDefault(name: string, source: string): CodeBuilder {\n const existing = this.imports.get(source);\n if (existing) {\n existing.defaultSpecifier = name;\n existing.typeOnly = false;\n } else {\n this.imports.set(source, { specifiers: new Set(), defaultSpecifier: name, typeOnly: false });\n }\n return this;\n }\n\n importType(specifier: string | string[], source: string): CodeBuilder {\n const specs = Array.isArray(specifier) ? specifier : [specifier];\n const existing = this.imports.get(source);\n if (existing) {\n for (const s of specs) existing.specifiers.add(s);\n // Don't downgrade: if existing is value import, keep it as value\n } else {\n this.imports.set(source, { specifiers: new Set(specs), typeOnly: true });\n }\n return this;\n }\n\n line(code?: string): CodeBuilder {\n this.lines.push({ type: 'line', content: code ?? '' });\n return this;\n }\n\n block(\n openOrBuilder: string | ((b: CodeBuilder) => CodeBuilder),\n builderOrClose?: string | ((b: CodeBuilder) => CodeBuilder),\n closeOrBuilder?: string | ((b: CodeBuilder) => CodeBuilder),\n ): CodeBuilder {\n let open: string | undefined;\n let close: string | undefined;\n let builder: (b: CodeBuilder) => CodeBuilder;\n\n if (typeof openOrBuilder === 'function') {\n // block(builder)\n builder = openOrBuilder;\n } else if (typeof builderOrClose === 'function') {\n // block(open, builder, close?)\n open = openOrBuilder;\n builder = builderOrClose;\n close = typeof closeOrBuilder === 'string' ? closeOrBuilder : undefined;\n } else if (typeof closeOrBuilder === 'function') {\n // block(open, close, builder)\n open = openOrBuilder;\n close = typeof builderOrClose === 'string' ? builderOrClose : undefined;\n builder = closeOrBuilder;\n } else {\n throw new Error('Invalid block() arguments');\n }\n\n // Always push block-open to increment indent\n this.lines.push({ type: 'block-open', content: open ?? '' });\n\n const inner = new CodeBuilderImpl(this.indent + 1);\n builder(inner);\n\n // Merge inner imports into ours\n for (const [source, entry] of inner.imports) {\n const existing = this.imports.get(source);\n if (existing) {\n for (const s of entry.specifiers) existing.specifiers.add(s);\n if (entry.defaultSpecifier) existing.defaultSpecifier = entry.defaultSpecifier;\n if (!entry.typeOnly) existing.typeOnly = false;\n } else {\n this.imports.set(source, {\n specifiers: new Set(entry.specifiers),\n defaultSpecifier: entry.defaultSpecifier,\n typeOnly: entry.typeOnly,\n });\n }\n }\n\n // Merge inner lines with extra indentation\n for (const line of inner.lines) {\n this.lines.push(line);\n }\n\n // Always push block-close to decrement indent\n this.lines.push({ type: 'block-close', content: close ?? '' });\n\n return this;\n }\n\n comment(text: string): CodeBuilder {\n this.lines.push({ type: 'line', content: `// ${text}` });\n return this;\n }\n\n docComment(text: string): CodeBuilder {\n const lines = text.split('\\n');\n if (lines.length === 1) {\n this.lines.push({ type: 'line', content: `/** ${text} */` });\n } else {\n this.lines.push({ type: 'line', content: '/**' });\n for (const line of lines) {\n this.lines.push({ type: 'line', content: ` * ${line}` });\n }\n this.lines.push({ type: 'line', content: ' */' });\n }\n return this;\n }\n\n todoComment(text: string): CodeBuilder {\n this.lines.push({ type: 'line', content: `// TODO: ${text}` });\n return this;\n }\n\n raw(code: string): CodeBuilder {\n this.lines.push({ type: 'raw', content: code });\n return this;\n }\n\n build(): CodeBuildResult {\n const parts: string[] = [];\n\n // Emit imports first\n if (this.imports.size > 0) {\n const typeImports: string[] = [];\n const valueImports: string[] = [];\n\n for (const [source, entry] of this.imports) {\n const specs = [...entry.specifiers].sort();\n const namedPart =\n specs.length > 0 ? (specs.length === 1 && !specs[0]!.includes(' ') ? `{ ${specs[0]} }` : `{ ${specs.join(', ')} }`) : null;\n const specStr = entry.defaultSpecifier\n ? namedPart\n ? `${entry.defaultSpecifier}, ${namedPart}`\n : entry.defaultSpecifier\n : namedPart!;\n\n const line = entry.typeOnly ? `import type ${specStr} from '${source}'` : `import ${specStr} from '${source}'`;\n\n if (entry.typeOnly) {\n typeImports.push(line);\n } else {\n valueImports.push(line);\n }\n }\n\n // Value imports first, then type imports\n parts.push([...valueImports, ...typeImports].join('\\n'));\n parts.push('');\n }\n\n // Emit code lines\n let currentIndent = this.indent;\n for (const line of this.lines) {\n if (line.type === 'raw') {\n parts.push(line.content);\n } else if (line.type === 'block-open') {\n if (line.content) {\n const indent = ' '.repeat(currentIndent);\n parts.push(`${indent}${line.content}`);\n }\n currentIndent++;\n } else if (line.type === 'block-close') {\n currentIndent--;\n if (line.content) {\n const indent = ' '.repeat(currentIndent);\n parts.push(`${indent}${line.content}`);\n }\n } else {\n // Regular line\n if (line.content === '') {\n parts.push('');\n } else {\n const indent = ' '.repeat(currentIndent);\n parts.push(`${indent}${line.content}`);\n }\n }\n }\n\n return {\n text: parts.join('\\n'),\n imports: new Map(\n [...this.imports].map(([source, entry]) => [source, { specifiers: new Set(entry.specifiers), typeOnly: entry.typeOnly }]),\n ),\n };\n }\n}\n\n/**\n * Create a new CodeBuilder for constructing TypeScript source files.\n */\nexport function createCodeBuilder(): CodeBuilder {\n return new CodeBuilderImpl();\n}\n"],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ import { CommandMeta, GeneratorLogger } from "./types.mjs";
2
+
3
+ //#region src/codegen/discovery.d.ts
4
+ type DiscoverySource = 'help' | 'completion' | 'bash' | 'fish' | 'zsh';
5
+ interface DiscoveryOptions {
6
+ /** The command to discover (e.g. 'gh', 'docker', 'kubectl'). */
7
+ command: string;
8
+ /**
9
+ * Which parsing sources to use. Default: ['help'].
10
+ * Use `'completion'` to auto-detect the best shell completion source
11
+ * by probing `<cmd> completion <shell>` (bash → fish → zsh).
12
+ */
13
+ sources?: DiscoverySource[];
14
+ /** Max subcommand depth. 0 = root only, undefined = unlimited. */
15
+ depth?: number;
16
+ /** Delay in ms between help invocations. Default: 50 */
17
+ delay?: number;
18
+ /** Logger for progress reporting. */
19
+ log?: GeneratorLogger;
20
+ /** Timeout per help invocation in ms. Default: 10000 */
21
+ timeout?: number;
22
+ }
23
+ interface DiscoveryResult {
24
+ /** The discovered command tree. */
25
+ command: CommandMeta;
26
+ /** Number of help invocations made. */
27
+ invocations: number;
28
+ /** Errors encountered (non-fatal). */
29
+ warnings: string[];
30
+ }
31
+ /**
32
+ * Discover CLI structure by running --help recursively and optionally
33
+ * parsing shell completion scripts.
34
+ */
35
+ declare function discoverCli(options: DiscoveryOptions): Promise<DiscoveryResult>;
36
+ /**
37
+ * Detect the best shell for completion parsing by probing the command.
38
+ * Tries `<cmd> completion <shell>` for bash, fish, zsh (in that order).
39
+ * Returns the shell name if successful, or null if no completion command exists.
40
+ */
41
+ declare function detectCompletionShell(command: string, timeout?: number): Promise<'bash' | 'fish' | 'zsh' | null>;
42
+ //#endregion
43
+ export { DiscoveryOptions, DiscoveryResult, DiscoverySource, detectCompletionShell, discoverCli };
44
+ //# sourceMappingURL=discovery.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.d.mts","names":[],"sources":["../../src/codegen/discovery.ts"],"mappings":";;;KAUY,eAAA;AAAA,UAEK,gBAAA;EAFL;EAIV,OAAA;;;AAJyB;AAE3B;;EAQE,OAAA,GAAU,eAAA;EAMW;EAJrB,KAAA;EAFA;EAIA,KAAA;EAFA;EAIA,GAAA,GAAM,eAAe;EAArB;EAEA,OAAA;AAAA;AAAA,UAGe,eAAA;EAHR;EAKP,OAAA,EAAS,WAAW;EAFU;EAI9B,WAAA;EAFoB;EAIpB,QAAA;AAAA;;;;AAAQ;iBAOY,WAAA,CAAY,OAAA,EAAS,gBAAA,GAAmB,OAAA,CAAQ,eAAA;;;;;;iBA2MhD,qBAAA,CAAsB,OAAA,UAAiB,OAAA,YAAiB,OAAO"}
@@ -0,0 +1,179 @@
1
+ import { parseBashCompletions } from "./parsers/bash.mjs";
2
+ import { parseFishCompletions } from "./parsers/fish.mjs";
3
+ import { parseHelpOutput } from "./parsers/help.mjs";
4
+ import { mergeCommandMeta } from "./parsers/merge.mjs";
5
+ import { parseZshCompletions } from "./parsers/zsh.mjs";
6
+ import { execFile } from "node:child_process";
7
+ import { readFile } from "node:fs/promises";
8
+ //#region src/codegen/discovery.ts
9
+ /**
10
+ * Discover CLI structure by running --help recursively and optionally
11
+ * parsing shell completion scripts.
12
+ */
13
+ async function discoverCli(options) {
14
+ const { command, sources: rawSources = ["help"], depth, delay = 50, log, timeout = 1e4 } = options;
15
+ const sources = await resolveSources(rawSources, command, timeout, log);
16
+ const warnings = [];
17
+ let invocations = 0;
18
+ const results = [];
19
+ if (sources.includes("help")) {
20
+ log?.info(`Discovering ${command} via --help...`);
21
+ const helpResult = await crawlHelp(command, [], {
22
+ depth,
23
+ delay,
24
+ timeout,
25
+ log,
26
+ onInvocation: () => {
27
+ invocations++;
28
+ },
29
+ onWarning: (msg) => {
30
+ warnings.push(msg);
31
+ }
32
+ });
33
+ results.push(helpResult);
34
+ }
35
+ if (sources.includes("bash")) {
36
+ log?.info(`Parsing bash completions for ${command}...`);
37
+ const bashText = await getCompletionScript(command, "bash", timeout);
38
+ if (bashText) results.push(parseBashCompletions(bashText));
39
+ else warnings.push("Could not obtain bash completion script");
40
+ }
41
+ if (sources.includes("fish")) {
42
+ log?.info(`Parsing fish completions for ${command}...`);
43
+ const fishText = await getCompletionScript(command, "fish", timeout);
44
+ if (fishText) results.push(parseFishCompletions(fishText));
45
+ else warnings.push("Could not obtain fish completion script");
46
+ }
47
+ if (sources.includes("zsh")) {
48
+ log?.info(`Parsing zsh completions for ${command}...`);
49
+ const zshText = await getCompletionScript(command, "zsh", timeout);
50
+ if (zshText) results.push(parseZshCompletions(zshText));
51
+ else warnings.push("Could not obtain zsh completion script");
52
+ }
53
+ const merged = results.length > 0 ? mergeCommandMeta(...results) : { name: command };
54
+ if (!merged.name) merged.name = command;
55
+ return {
56
+ command: merged,
57
+ invocations,
58
+ warnings
59
+ };
60
+ }
61
+ /**
62
+ * Breadth-first crawl of --help output.
63
+ */
64
+ async function crawlHelp(command, prefixArgs, options) {
65
+ const fullCmd = [command, ...prefixArgs].join(" ");
66
+ options.onInvocation();
67
+ const helpText = await runHelp(command, prefixArgs, options.timeout);
68
+ if (!helpText) {
69
+ options.onWarning(`No help output from: ${fullCmd} --help`);
70
+ return { name: prefixArgs[prefixArgs.length - 1] || command };
71
+ }
72
+ const parsed = parseHelpOutput(helpText, { name: prefixArgs[prefixArgs.length - 1] || command });
73
+ options.log?.info(` ${fullCmd}: ${parsed.subcommands?.length || 0} subcommands, ${parsed.arguments?.length || 0} options`);
74
+ const currentDepth = prefixArgs.length;
75
+ if (parsed.subcommands && parsed.subcommands.length > 0 && (options.depth === void 0 || currentDepth < options.depth)) {
76
+ const resolvedSubs = [];
77
+ for (const sub of parsed.subcommands) {
78
+ if (options.delay > 0) await sleep(options.delay);
79
+ const resolved = await crawlHelp(command, [...prefixArgs, sub.name], options);
80
+ if (!resolved.description && sub.description) resolved.description = sub.description;
81
+ resolvedSubs.push(resolved);
82
+ }
83
+ parsed.subcommands = resolvedSubs;
84
+ }
85
+ return parsed;
86
+ }
87
+ /**
88
+ * Run `<cmd> --help` or `<cmd> help` and return combined stdout+stderr.
89
+ */
90
+ async function runHelp(command, args, timeout) {
91
+ let result = await runCommand(command, [...args, "--help"], timeout);
92
+ if (result) return result;
93
+ if (args.length > 0) {
94
+ result = await runCommand(command, ["help", ...args], timeout);
95
+ if (result) return result;
96
+ }
97
+ return null;
98
+ }
99
+ /**
100
+ * Run a command and return its combined output, or null on failure.
101
+ */
102
+ async function runCommand(command, args, timeout) {
103
+ try {
104
+ const { stdout, stderr } = await new Promise((resolve) => {
105
+ execFile(command, args, {
106
+ timeout,
107
+ maxBuffer: 10 * 1024 * 1024
108
+ }, (_error, stdout, stderr) => {
109
+ resolve({
110
+ stdout: (stdout ?? "").trim(),
111
+ stderr: (stderr ?? "").trim()
112
+ });
113
+ });
114
+ });
115
+ const combined = stdout || stderr;
116
+ if (!combined) return null;
117
+ if (combined.length < 10) return null;
118
+ return combined;
119
+ } catch {
120
+ return null;
121
+ }
122
+ }
123
+ /**
124
+ * Try to get a shell completion script for a command.
125
+ * Checks both `<cmd> completion <shell>` and well-known file paths.
126
+ */
127
+ async function getCompletionScript(command, shell, timeout) {
128
+ let result = await runCommand(command, ["completion", shell], timeout);
129
+ if (result) return result;
130
+ result = await runCommand(command, ["completions", shell], timeout);
131
+ if (result) return result;
132
+ const paths = shell === "fish" ? [`/usr/share/fish/vendor_completions.d/${command}.fish`, `/usr/local/share/fish/vendor_completions.d/${command}.fish`] : shell === "bash" ? [
133
+ `/usr/share/bash-completion/completions/${command}`,
134
+ `/usr/local/share/bash-completion/completions/${command}`,
135
+ `/etc/bash_completion.d/${command}`
136
+ ] : [`/usr/share/zsh/site-functions/_${command}`, `/usr/local/share/zsh/site-functions/_${command}`];
137
+ for (const path of paths) try {
138
+ return await readFile(path, "utf-8");
139
+ } catch {}
140
+ return null;
141
+ }
142
+ /**
143
+ * Detect the best shell for completion parsing by probing the command.
144
+ * Tries `<cmd> completion <shell>` for bash, fish, zsh (in that order).
145
+ * Returns the shell name if successful, or null if no completion command exists.
146
+ */
147
+ async function detectCompletionShell(command, timeout = 5e3) {
148
+ for (const shell of [
149
+ "bash",
150
+ "fish",
151
+ "zsh"
152
+ ]) if (await getCompletionScript(command, shell, timeout)) return shell;
153
+ return null;
154
+ }
155
+ /**
156
+ * Resolve 'completion' entries in the sources array by probing for the best available shell.
157
+ * Other sources are passed through unchanged.
158
+ */
159
+ async function resolveSources(sources, command, timeout, log) {
160
+ if (!sources.includes("completion")) return sources;
161
+ log?.info(`Probing ${command} for completion command...`);
162
+ const shell = await detectCompletionShell(command, timeout);
163
+ return sources.flatMap((s) => {
164
+ if (s !== "completion") return s;
165
+ if (shell) {
166
+ log?.info(` Found ${shell} completion support`);
167
+ return shell;
168
+ }
169
+ log?.info(" No completion command found, skipping");
170
+ return [];
171
+ });
172
+ }
173
+ function sleep(ms) {
174
+ return new Promise((resolve) => setTimeout(resolve, ms));
175
+ }
176
+ //#endregion
177
+ export { detectCompletionShell, discoverCli };
178
+
179
+ //# sourceMappingURL=discovery.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.mjs","names":[],"sources":["../../src/codegen/discovery.ts"],"sourcesContent":["import { execFile } from 'node:child_process';\nimport { readFile } from 'node:fs/promises';\n\nimport { parseBashCompletions } from './parsers/bash.ts';\nimport { parseFishCompletions } from './parsers/fish.ts';\nimport { parseHelpOutput } from './parsers/help.ts';\nimport { mergeCommandMeta } from './parsers/merge.ts';\nimport { parseZshCompletions } from './parsers/zsh.ts';\nimport type { CommandMeta, GeneratorLogger } from './types.ts';\n\nexport type DiscoverySource = 'help' | 'completion' | 'bash' | 'fish' | 'zsh';\n\nexport interface DiscoveryOptions {\n /** The command to discover (e.g. 'gh', 'docker', 'kubectl'). */\n command: string;\n /**\n * Which parsing sources to use. Default: ['help'].\n * Use `'completion'` to auto-detect the best shell completion source\n * by probing `<cmd> completion <shell>` (bash → fish → zsh).\n */\n sources?: DiscoverySource[];\n /** Max subcommand depth. 0 = root only, undefined = unlimited. */\n depth?: number;\n /** Delay in ms between help invocations. Default: 50 */\n delay?: number;\n /** Logger for progress reporting. */\n log?: GeneratorLogger;\n /** Timeout per help invocation in ms. Default: 10000 */\n timeout?: number;\n}\n\nexport interface DiscoveryResult {\n /** The discovered command tree. */\n command: CommandMeta;\n /** Number of help invocations made. */\n invocations: number;\n /** Errors encountered (non-fatal). */\n warnings: string[];\n}\n\n/**\n * Discover CLI structure by running --help recursively and optionally\n * parsing shell completion scripts.\n */\nexport async function discoverCli(options: DiscoveryOptions): Promise<DiscoveryResult> {\n const { command, sources: rawSources = ['help'], depth, delay = 50, log, timeout = 10000 } = options;\n\n // Resolve 'completion' source by probing for the best available shell\n const sources = await resolveSources(rawSources, command, timeout, log);\n\n const warnings: string[] = [];\n let invocations = 0;\n\n const results: CommandMeta[] = [];\n\n // Source 1: --help recursive crawl\n if (sources.includes('help')) {\n log?.info(`Discovering ${command} via --help...`);\n const helpResult = await crawlHelp(command, [], {\n depth,\n delay,\n timeout,\n log,\n onInvocation: () => {\n invocations++;\n },\n onWarning: (msg) => {\n warnings.push(msg);\n },\n });\n results.push(helpResult);\n }\n\n // Source 2: Bash completions\n if (sources.includes('bash')) {\n log?.info(`Parsing bash completions for ${command}...`);\n const bashText = await getCompletionScript(command, 'bash', timeout);\n if (bashText) {\n results.push(parseBashCompletions(bashText));\n } else {\n warnings.push('Could not obtain bash completion script');\n }\n }\n\n // Source 3: Fish completions\n if (sources.includes('fish')) {\n log?.info(`Parsing fish completions for ${command}...`);\n const fishText = await getCompletionScript(command, 'fish', timeout);\n if (fishText) {\n results.push(parseFishCompletions(fishText));\n } else {\n warnings.push('Could not obtain fish completion script');\n }\n }\n\n // Source 4: Zsh completions\n if (sources.includes('zsh')) {\n log?.info(`Parsing zsh completions for ${command}...`);\n const zshText = await getCompletionScript(command, 'zsh', timeout);\n if (zshText) {\n results.push(parseZshCompletions(zshText));\n } else {\n warnings.push('Could not obtain zsh completion script');\n }\n }\n\n const merged = results.length > 0 ? mergeCommandMeta(...results) : { name: command };\n\n // Ensure the root has the correct name\n if (!merged.name) merged.name = command;\n\n return { command: merged, invocations, warnings };\n}\n\ninterface CrawlOptions {\n depth?: number;\n delay: number;\n timeout: number;\n log?: GeneratorLogger;\n onInvocation: () => void;\n onWarning: (msg: string) => void;\n}\n\n/**\n * Breadth-first crawl of --help output.\n */\nasync function crawlHelp(command: string, prefixArgs: string[], options: CrawlOptions): Promise<CommandMeta> {\n const fullCmd = [command, ...prefixArgs].join(' ');\n\n options.onInvocation();\n const helpText = await runHelp(command, prefixArgs, options.timeout);\n\n if (!helpText) {\n options.onWarning(`No help output from: ${fullCmd} --help`);\n return { name: prefixArgs[prefixArgs.length - 1] || command };\n }\n\n const name = prefixArgs[prefixArgs.length - 1] || command;\n const parsed = parseHelpOutput(helpText, { name });\n\n options.log?.info(` ${fullCmd}: ${parsed.subcommands?.length || 0} subcommands, ${parsed.arguments?.length || 0} options`);\n\n // Recurse into subcommands breadth-first\n const currentDepth = prefixArgs.length;\n if (parsed.subcommands && parsed.subcommands.length > 0 && (options.depth === undefined || currentDepth < options.depth)) {\n const resolvedSubs: CommandMeta[] = [];\n\n for (const sub of parsed.subcommands) {\n if (options.delay > 0) {\n await sleep(options.delay);\n }\n const resolved = await crawlHelp(command, [...prefixArgs, sub.name], options);\n // Preserve description from parent's subcommand list if child didn't have one\n if (!resolved.description && sub.description) {\n resolved.description = sub.description;\n }\n resolvedSubs.push(resolved);\n }\n\n parsed.subcommands = resolvedSubs;\n }\n\n return parsed;\n}\n\n/**\n * Run `<cmd> --help` or `<cmd> help` and return combined stdout+stderr.\n */\nasync function runHelp(command: string, args: string[], timeout: number): Promise<string | null> {\n // Try --help first\n let result = await runCommand(command, [...args, '--help'], timeout);\n if (result) return result;\n\n // Some CLIs use `help <cmd>` instead\n if (args.length > 0) {\n result = await runCommand(command, ['help', ...args], timeout);\n if (result) return result;\n }\n\n return null;\n}\n\n/**\n * Run a command and return its combined output, or null on failure.\n */\nasync function runCommand(command: string, args: string[], timeout: number): Promise<string | null> {\n try {\n const { stdout, stderr } = await new Promise<{ stdout: string; stderr: string }>((resolve) => {\n execFile(command, args, { timeout, maxBuffer: 10 * 1024 * 1024 }, (_error, stdout, stderr) => {\n // Resolve even on non-zero exit — many CLIs exit non-zero on --help\n resolve({ stdout: (stdout ?? '').trim(), stderr: (stderr ?? '').trim() });\n });\n });\n\n // Some CLIs output help to stderr, some exit non-zero on --help\n const combined = stdout || stderr;\n if (!combined) return null;\n\n // Basic sanity check: help text usually has some structure\n if (combined.length < 10) return null;\n\n return combined;\n } catch {\n return null;\n }\n}\n\n/**\n * Try to get a shell completion script for a command.\n * Checks both `<cmd> completion <shell>` and well-known file paths.\n */\nasync function getCompletionScript(command: string, shell: 'bash' | 'fish' | 'zsh', timeout: number): Promise<string | null> {\n // Try `<cmd> completion <shell>`\n const completionArgs = ['completion', shell];\n let result = await runCommand(command, completionArgs, timeout);\n if (result) return result;\n\n // Try `<cmd> completions <shell>`\n result = await runCommand(command, ['completions', shell], timeout);\n if (result) return result;\n\n // Try reading from well-known paths\n const paths =\n shell === 'fish'\n ? [`/usr/share/fish/vendor_completions.d/${command}.fish`, `/usr/local/share/fish/vendor_completions.d/${command}.fish`]\n : shell === 'bash'\n ? [\n `/usr/share/bash-completion/completions/${command}`,\n `/usr/local/share/bash-completion/completions/${command}`,\n `/etc/bash_completion.d/${command}`,\n ]\n : [`/usr/share/zsh/site-functions/_${command}`, `/usr/local/share/zsh/site-functions/_${command}`];\n\n for (const path of paths) {\n try {\n return await readFile(path, 'utf-8');\n } catch {}\n }\n\n return null;\n}\n\n/**\n * Detect the best shell for completion parsing by probing the command.\n * Tries `<cmd> completion <shell>` for bash, fish, zsh (in that order).\n * Returns the shell name if successful, or null if no completion command exists.\n */\nexport async function detectCompletionShell(command: string, timeout = 5000): Promise<'bash' | 'fish' | 'zsh' | null> {\n for (const shell of ['bash', 'fish', 'zsh'] as const) {\n const result = await getCompletionScript(command, shell, timeout);\n if (result) return shell;\n }\n return null;\n}\n\n/**\n * Resolve 'completion' entries in the sources array by probing for the best available shell.\n * Other sources are passed through unchanged.\n */\nasync function resolveSources(\n sources: DiscoverySource[],\n command: string,\n timeout: number,\n log?: GeneratorLogger,\n): Promise<DiscoverySource[]> {\n if (!sources.includes('completion')) return sources;\n\n log?.info(`Probing ${command} for completion command...`);\n const shell = await detectCompletionShell(command, timeout);\n\n return sources.flatMap((s) => {\n if (s !== 'completion') return s;\n if (shell) {\n log?.info(` Found ${shell} completion support`);\n return shell;\n }\n log?.info(' No completion command found, skipping');\n return [];\n });\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { FileEmitter, FileEmitterOptions } from "./types.mjs";
2
+
3
+ //#region src/codegen/file-emitter.d.ts
4
+ /**
5
+ * Create a FileEmitter for writing multiple generated files to disk.
6
+ */
7
+ declare function createFileEmitter(options: FileEmitterOptions): FileEmitter;
8
+ //#endregion
9
+ export { createFileEmitter };
10
+ //# sourceMappingURL=file-emitter.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-emitter.d.mts","names":[],"sources":["../../src/codegen/file-emitter.ts"],"mappings":";;;;;AAsEA;iBAAgB,iBAAA,CAAkB,OAAA,EAAS,kBAAA,GAAqB,WAAW"}
@@ -0,0 +1,58 @@
1
+ import { existsSync, mkdirSync, writeFileSync } from "node:fs";
2
+ import { dirname, join, resolve } from "node:path";
3
+ //#region src/codegen/file-emitter.ts
4
+ var FileEmitterImpl = class {
5
+ files = [];
6
+ options;
7
+ constructor(options) {
8
+ this.options = options;
9
+ }
10
+ addFile(path, content) {
11
+ const text = typeof content === "string" ? content : content.text;
12
+ const fullContent = this.options.header ? `${this.options.header}\n\n${text}` : text;
13
+ this.files.push({
14
+ path,
15
+ content: fullContent
16
+ });
17
+ }
18
+ async emit() {
19
+ const result = {
20
+ written: [],
21
+ skipped: [],
22
+ errors: []
23
+ };
24
+ const outDir = resolve(this.options.outDir);
25
+ for (const file of this.files) {
26
+ const fullPath = join(outDir, file.path);
27
+ try {
28
+ if (existsSync(fullPath) && !this.options.overwrite) {
29
+ result.skipped.push(file.path);
30
+ continue;
31
+ }
32
+ if (this.options.dryRun) {
33
+ result.written.push(file.path);
34
+ continue;
35
+ }
36
+ mkdirSync(dirname(fullPath), { recursive: true });
37
+ writeFileSync(fullPath, file.content, "utf-8");
38
+ result.written.push(file.path);
39
+ } catch (err) {
40
+ result.errors.push({
41
+ file: file.path,
42
+ error: err instanceof Error ? err : new Error(String(err))
43
+ });
44
+ }
45
+ }
46
+ return result;
47
+ }
48
+ };
49
+ /**
50
+ * Create a FileEmitter for writing multiple generated files to disk.
51
+ */
52
+ function createFileEmitter(options) {
53
+ return new FileEmitterImpl(options);
54
+ }
55
+ //#endregion
56
+ export { createFileEmitter };
57
+
58
+ //# sourceMappingURL=file-emitter.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-emitter.mjs","names":[],"sources":["../../src/codegen/file-emitter.ts"],"sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport type { CodeBuildResult, EmitResult, FileEmitter, FileEmitterOptions } from './types.ts';\n\ninterface QueuedFile {\n path: string;\n content: string;\n}\n\nclass FileEmitterImpl implements FileEmitter {\n private files: QueuedFile[] = [];\n private options: FileEmitterOptions;\n\n constructor(options: FileEmitterOptions) {\n this.options = options;\n }\n\n addFile(path: string, content: string | CodeBuildResult): void {\n const text = typeof content === 'string' ? content : content.text;\n const fullContent = this.options.header ? `${this.options.header}\\n\\n${text}` : text;\n\n this.files.push({ path, content: fullContent });\n }\n\n async emit(): Promise<EmitResult> {\n const result: EmitResult = {\n written: [],\n skipped: [],\n errors: [],\n };\n\n const outDir = resolve(this.options.outDir);\n\n for (const file of this.files) {\n const fullPath = join(outDir, file.path);\n\n try {\n // Check if file already exists\n if (existsSync(fullPath) && !this.options.overwrite) {\n result.skipped.push(file.path);\n continue;\n }\n\n if (this.options.dryRun) {\n result.written.push(file.path);\n continue;\n }\n\n // Ensure directory exists\n const dir = dirname(fullPath);\n mkdirSync(dir, { recursive: true });\n\n // Write the file\n writeFileSync(fullPath, file.content, 'utf-8');\n result.written.push(file.path);\n } catch (err) {\n result.errors.push({\n file: file.path,\n error: err instanceof Error ? err : new Error(String(err)),\n });\n }\n }\n\n return result;\n }\n}\n\n/**\n * Create a FileEmitter for writing multiple generated files to disk.\n */\nexport function createFileEmitter(options: FileEmitterOptions): FileEmitter {\n return new FileEmitterImpl(options);\n}\n"],"mappings":";;;AASA,IAAM,kBAAN,MAA6C;CAC3C,QAA8B,CAAC;CAC/B;CAEA,YAAY,SAA6B;EACvC,KAAK,UAAU;CACjB;CAEA,QAAQ,MAAc,SAAyC;EAC7D,MAAM,OAAO,OAAO,YAAY,WAAW,UAAU,QAAQ;EAC7D,MAAM,cAAc,KAAK,QAAQ,SAAS,GAAG,KAAK,QAAQ,OAAO,MAAM,SAAS;EAEhF,KAAK,MAAM,KAAK;GAAE;GAAM,SAAS;EAAY,CAAC;CAChD;CAEA,MAAM,OAA4B;EAChC,MAAM,SAAqB;GACzB,SAAS,CAAC;GACV,SAAS,CAAC;GACV,QAAQ,CAAC;EACX;EAEA,MAAM,SAAS,QAAQ,KAAK,QAAQ,MAAM;EAE1C,KAAK,MAAM,QAAQ,KAAK,OAAO;GAC7B,MAAM,WAAW,KAAK,QAAQ,KAAK,IAAI;GAEvC,IAAI;IAEF,IAAI,WAAW,QAAQ,KAAK,CAAC,KAAK,QAAQ,WAAW;KACnD,OAAO,QAAQ,KAAK,KAAK,IAAI;KAC7B;IACF;IAEA,IAAI,KAAK,QAAQ,QAAQ;KACvB,OAAO,QAAQ,KAAK,KAAK,IAAI;KAC7B;IACF;IAIA,UADY,QAAQ,QACR,GAAG,EAAE,WAAW,KAAK,CAAC;IAGlC,cAAc,UAAU,KAAK,SAAS,OAAO;IAC7C,OAAO,QAAQ,KAAK,KAAK,IAAI;GAC/B,SAAS,KAAK;IACZ,OAAO,OAAO,KAAK;KACjB,MAAM,KAAK;KACX,OAAO,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;IAC3D,CAAC;GACH;EACF;EAEA,OAAO;CACT;AACF;;;;AAKA,SAAgB,kBAAkB,SAA0C;CAC1E,OAAO,IAAI,gBAAgB,OAAO;AACpC"}
@@ -0,0 +1,10 @@
1
+ import { CodeBuilder, GeneratorContext } from "../types.mjs";
2
+
3
+ //#region src/codegen/generators/barrel-file.d.ts
4
+ /**
5
+ * Generate an index.ts barrel file that re-exports all given files.
6
+ */
7
+ declare function generateBarrelFile(files: string[], ctx: GeneratorContext): CodeBuilder;
8
+ //#endregion
9
+ export { generateBarrelFile };
10
+ //# sourceMappingURL=barrel-file.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"barrel-file.d.mts","names":[],"sources":["../../../src/codegen/generators/barrel-file.ts"],"mappings":";;;;;AAKA;iBAAgB,kBAAA,CAAmB,KAAA,YAAiB,GAAA,EAAK,gBAAA,GAAmB,WAAW"}
@@ -0,0 +1,16 @@
1
+ //#region src/codegen/generators/barrel-file.ts
2
+ /**
3
+ * Generate an index.ts barrel file that re-exports all given files.
4
+ */
5
+ function generateBarrelFile(files, ctx) {
6
+ const code = ctx.createCodeBuilder();
7
+ for (const file of files) {
8
+ const importPath = file.startsWith("./") ? file : `./${file}`;
9
+ code.line(`export * from '${importPath}'`);
10
+ }
11
+ return code;
12
+ }
13
+ //#endregion
14
+ export { generateBarrelFile };
15
+
16
+ //# sourceMappingURL=barrel-file.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"barrel-file.mjs","names":[],"sources":["../../../src/codegen/generators/barrel-file.ts"],"sourcesContent":["import type { CodeBuilder, GeneratorContext } from '../types.ts';\n\n/**\n * Generate an index.ts barrel file that re-exports all given files.\n */\nexport function generateBarrelFile(files: string[], ctx: GeneratorContext): CodeBuilder {\n const code = ctx.createCodeBuilder();\n\n for (const file of files) {\n // Strip .ts extension for the import path and ensure relative path\n const importPath = file.startsWith('./') ? file : `./${file}`;\n code.line(`export * from '${importPath}'`);\n }\n\n return code;\n}\n"],"mappings":";;;;AAKA,SAAgB,mBAAmB,OAAiB,KAAoC;CACtF,MAAM,OAAO,IAAI,kBAAkB;CAEnC,KAAK,MAAM,QAAQ,OAAO;EAExB,MAAM,aAAa,KAAK,WAAW,IAAI,IAAI,OAAO,KAAK;EACvD,KAAK,KAAK,kBAAkB,WAAW,EAAE;CAC3C;CAEA,OAAO;AACT"}