padrone 1.9.0 → 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 (328) hide show
  1. package/CHANGELOG.md +13 -0
  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-WmyGc59s.mjs → core/args.mjs} +5 -81
  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-ohEApqIw.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-D8qkAinX.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-wCoVFTXz.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-ICZFl3xr.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 -902
  220. package/dist/index.mjs +25 -4377
  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/extension/completion.ts +3 -0
  295. package/src/extension/index.ts +0 -12
  296. package/src/extension/ink.ts +2 -1
  297. package/src/extension/man.ts +3 -0
  298. package/src/extension/mcp.ts +3 -0
  299. package/src/extension/serve.ts +3 -0
  300. package/src/extension/tracing.ts +2 -0
  301. package/src/index.ts +0 -19
  302. package/src/ink.ts +2 -0
  303. package/src/man.ts +2 -0
  304. package/src/mcp.ts +3 -0
  305. package/src/serve.ts +2 -0
  306. package/src/tracing.ts +9 -0
  307. package/src/zod.ts +1 -1
  308. package/dist/args-WmyGc59s.mjs.map +0 -1
  309. package/dist/codegen/index.d.mts.map +0 -1
  310. package/dist/codegen/index.mjs.map +0 -1
  311. package/dist/commands-ohEApqIw.mjs.map +0 -1
  312. package/dist/completion-D8qkAinX.mjs.map +0 -1
  313. package/dist/errors-DA4KzK1M.mjs.map +0 -1
  314. package/dist/formatter-CY3KrOEd.d.mts.map +0 -1
  315. package/dist/help-CeI45CJx.mjs +0 -892
  316. package/dist/help-CeI45CJx.mjs.map +0 -1
  317. package/dist/index-C3Ed1LYN.d.mts +0 -1432
  318. package/dist/index-C3Ed1LYN.d.mts.map +0 -1
  319. package/dist/index.d.mts.map +0 -1
  320. package/dist/index.mjs.map +0 -1
  321. package/dist/mcp-wCoVFTXz.mjs.map +0 -1
  322. package/dist/serve-ICZFl3xr.mjs.map +0 -1
  323. package/dist/stream-DC4H8YTx.mjs.map +0 -1
  324. package/dist/test.d.mts.map +0 -1
  325. package/dist/test.mjs.map +0 -1
  326. package/dist/update-check-CZ2VqjnV.mjs.map +0 -1
  327. package/dist/zod.d.mts.map +0 -1
  328. package/dist/zod.mjs.map +0 -1
@@ -0,0 +1,63 @@
1
+ import { PadroneSchema } from "../types/schema.mjs";
2
+ import { CommandTypesBase } from "../types/command.mjs";
3
+ import { DefineCommandBuilder, DefineCommandContext, PadroneBuilder, PadroneProgram } from "../types/builder.mjs";
4
+ import { buildReplCompleter } from "./commands.mjs";
5
+ import { HelpCommand } from "../extension/help.mjs";
6
+ import { VersionCommand } from "../extension/version.mjs";
7
+ import { asyncSchema } from "./results.mjs";
8
+
9
+ //#region src/core/create.d.ts
10
+ /**
11
+ * Options for configuring which built-in extensions are applied by default.
12
+ */
13
+ type PadroneBuiltins = {
14
+ /** Enable `help` command, `--help` / `-h` flags, and default help display. Defaults to `true`. */help?: boolean; /** Enable `version` command and `--version` / `-v` / `-V` flags. Defaults to `true`. */
15
+ version?: boolean; /** Enable `repl` command and `--repl` flag. Defaults to `true`. */
16
+ repl?: boolean; /** Enable `--color` / `--no-color` flag support. Defaults to `true`. */
17
+ color?: boolean; /** Enable "Did you mean?" suggestions for unknown commands and options. Defaults to `true`. */
18
+ suggestions?: boolean; /** Enable signal handling (SIGINT, SIGTERM, SIGHUP). Defaults to `true`. */
19
+ signal?: boolean; /** Enable automatic result output for `cli()`. Defaults to `true`. */
20
+ autoOutput?: boolean; /** Enable stdin piping support. Defaults to `true`. */
21
+ stdin?: boolean; /** Enable interactive prompting for missing arguments. Defaults to `true`. */
22
+ interactive?: boolean;
23
+ };
24
+ type PadroneOptions = {
25
+ builtins?: PadroneBuiltins;
26
+ };
27
+ type DefaultBuiltins = {};
28
+ type BuiltinCommands<B> = [...(B extends {
29
+ help: false;
30
+ } ? [] : [HelpCommand]), ...(B extends {
31
+ version: false;
32
+ } ? [] : [VersionCommand])];
33
+ declare function createPadrone<TProgramName extends string, const TBuiltins extends PadroneBuiltins = DefaultBuiltins>(name: TProgramName, options?: {
34
+ builtins?: TBuiltins;
35
+ }): PadroneProgram<TProgramName, '', '', PadroneSchema<void>, void, BuiltinCommands<TBuiltins>>;
36
+ /**
37
+ * Identity helper that contextually types a command builder callback while preserving its full return type.
38
+ * Use this when defining commands in separate files — the parent program retains exact type information
39
+ * about the subcommand's args, result, and nested commands.
40
+ *
41
+ * The builder's context includes `DefineCommandContext` by default (optional `logger`, `tracing`, `progress`).
42
+ * Override globally via module augmentation on `DefineCommandContext`, or per-command via `.requires()`.
43
+ *
44
+ * @example Direct form (most common)
45
+ * ```ts
46
+ * export const myCommand = defineCommand((c) =>
47
+ * c.arguments(z.object({ name: z.string() }))
48
+ * .action((args) => console.log(args.name))
49
+ * );
50
+ * ```
51
+ *
52
+ * @example With required interceptor context
53
+ * ```ts
54
+ * export const adminCommand = defineCommand()
55
+ * .requires<{ adminDb: AdminDB }>()
56
+ * .define((c) => c.action((_args, ctx) => ctx.context.adminDb.query(...)));
57
+ * ```
58
+ */
59
+ declare function defineCommand<TContext = unknown, TOut extends CommandTypesBase = CommandTypesBase>(fn: (builder: PadroneBuilder<string, string, string, PadroneSchema<void>, void, [], any, false, TContext, DefineCommandContext>) => TOut): typeof fn;
60
+ declare function defineCommand(): DefineCommandBuilder;
61
+ //#endregion
62
+ export { PadroneBuiltins, PadroneOptions, createPadrone, defineCommand };
63
+ //# sourceMappingURL=create.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.d.mts","names":[],"sources":["../../src/core/create.ts"],"mappings":";;;;;;;;;;;;KA0CY,eAAA;EAAA,kGAEV,IAAA;EAEA,OAAA,YAFA;EAIA,IAAA;EAEA,KAAA,YAEA;EAAA,WAAA,YAIA;EAFA,MAAA,YAMA;EAJA,UAAA,YAIW;EAFX,KAAA,YAKwB;EAHxB,WAAA;AAAA;AAAA,KAGU,cAAA;EAAmB,QAAA,GAAW,eAAe;AAAA;AAAA,KAGpD,eAAA;AAAA,KAEA,eAAA,WAA0B,CAAA;EAAY,IAAA;AAAA,UAAsB,WAAA,QAAmB,CAAA;EAAY,OAAA;AAAA,UAAyB,cAAA;AAAA,iBAEzG,aAAA,sDAAmE,eAAA,GAAkB,eAAA,EACnG,IAAA,EAAM,YAAA,EACN,OAAA;EAAY,QAAA,GAAW,SAAA;AAAA,IACtB,cAAA,CAAe,YAAA,UAAsB,aAAA,cAA2B,eAAA,CAAgB,SAAA;;;;;;;;;AALoD;AAEvI;;;;;;;;;;;;;;iBAkOgB,aAAA,kCAA+C,gBAAA,GAAmB,gBAAA,EAChF,EAAA,GAAK,OAAA,EAAS,cAAA,yBAAuC,aAAA,8BAA2C,QAAA,EAAU,oBAAA,MAA0B,IAAA,UAC5H,EAAA;AAAA,iBACM,aAAA,IAAiB,oBAAoB"}
@@ -0,0 +1,230 @@
1
+ import { commandSymbol, findCommandByName, lazyResolver, mergeCommands, repathCommandTree, resolveCommand } from "./commands.mjs";
2
+ import { hasInteractiveConfig, isAsyncBranded, makeThenable, noop, withPromiseDrain } from "./results.mjs";
3
+ import { toRegisteredInterceptor } from "./interceptors.mjs";
4
+ import { padroneAutoOutput } from "../extension/auto-output.mjs";
5
+ import { padroneColor } from "../extension/color.mjs";
6
+ import { RoutingError } from "./errors.mjs";
7
+ import { parseCommand } from "./validate.mjs";
8
+ import { padroneHelp } from "../extension/help.mjs";
9
+ import { padroneInteractive } from "../extension/interactive.mjs";
10
+ import { padroneRepl } from "../extension/repl.mjs";
11
+ import { padroneSignalHandling } from "../extension/signal.mjs";
12
+ import { padroneStdin } from "../extension/stdin.mjs";
13
+ import { padroneSuggestions } from "../extension/suggestions.mjs";
14
+ import { padroneVersion } from "../extension/version.mjs";
15
+ import { createWrapHandler } from "../feature/wrap.mjs";
16
+ import { collectInterceptors, errorResultWithSignal, execCommand } from "./exec.mjs";
17
+ import { createProgramMethods } from "./program-methods.mjs";
18
+ //#region src/core/create.ts
19
+ function createPadrone(name, options) {
20
+ let builder = createPadroneBuilder({
21
+ name,
22
+ path: "",
23
+ commands: []
24
+ });
25
+ const b = options?.builtins;
26
+ if (b?.help !== false) builder = builder.extend(padroneHelp());
27
+ if (b?.version !== false) builder = builder.extend(padroneVersion());
28
+ if (b?.repl !== false) builder = builder.extend(padroneRepl());
29
+ if (b?.color !== false) builder = builder.extend(padroneColor());
30
+ if (b?.suggestions !== false) builder = builder.extend(padroneSuggestions());
31
+ if (b?.signal !== false) builder = builder.extend(padroneSignalHandling());
32
+ if (b?.autoOutput !== false) builder = builder.extend(padroneAutoOutput());
33
+ if (b?.stdin !== false) builder = builder.extend(padroneStdin());
34
+ if (b?.interactive !== false) builder = builder.extend(padroneInteractive());
35
+ return builder;
36
+ }
37
+ function createPadroneBuilder(inputCommand) {
38
+ const existingCommand = inputCommand.commands?.length && inputCommand.commands.some((c) => c.parent && c.parent !== inputCommand) ? {
39
+ ...inputCommand,
40
+ commands: inputCommand.commands.map((c) => c.parent && c.parent !== inputCommand ? {
41
+ ...c,
42
+ parent: inputCommand
43
+ } : c)
44
+ } : inputCommand;
45
+ const parseCommandFn = (input) => parseCommand(input, existingCommand, findCommandByName);
46
+ const collectInterceptorsFn = (cmd) => collectInterceptors(cmd, existingCommand);
47
+ const execCtx = {
48
+ rootCommand: existingCommand,
49
+ builder: void 0,
50
+ parseCommandFn,
51
+ collectInterceptorsFn
52
+ };
53
+ const evalCommand = (input, evalOptions) => {
54
+ try {
55
+ const result = execCommand(input, execCtx, evalOptions, "soft", evalOptions?.caller ?? "eval");
56
+ if (result instanceof Promise) return withPromiseDrain(result.catch((err) => errorResultWithSignal(err)));
57
+ return makeThenable(result);
58
+ } catch (err) {
59
+ return makeThenable(errorResultWithSignal(err));
60
+ }
61
+ };
62
+ const builder = {
63
+ extend(extension) {
64
+ return extension(builder);
65
+ },
66
+ configure(config) {
67
+ return createPadroneBuilder({
68
+ ...existingCommand,
69
+ ...config
70
+ });
71
+ },
72
+ runtime(runtimeConfig) {
73
+ return createPadroneBuilder({
74
+ ...existingCommand,
75
+ runtime: {
76
+ ...existingCommand.runtime,
77
+ ...runtimeConfig
78
+ }
79
+ });
80
+ },
81
+ async() {
82
+ return createPadroneBuilder({
83
+ ...existingCommand,
84
+ isAsync: true
85
+ });
86
+ },
87
+ context(transform) {
88
+ if (!transform) return createPadroneBuilder({ ...existingCommand });
89
+ const existing = existingCommand.contextTransform;
90
+ const composed = existing ? (ctx) => transform(existing(ctx)) : transform;
91
+ return createPadroneBuilder({
92
+ ...existingCommand,
93
+ contextTransform: composed
94
+ });
95
+ },
96
+ arguments(schema, meta) {
97
+ const resolvedArgs = typeof schema === "function" ? schema(existingCommand.argsSchema) : schema;
98
+ const isAsync = existingCommand.isAsync || isAsyncBranded(resolvedArgs) || hasInteractiveConfig(meta);
99
+ return createPadroneBuilder({
100
+ ...existingCommand,
101
+ argsSchema: resolvedArgs,
102
+ meta,
103
+ isAsync
104
+ });
105
+ },
106
+ action(handler = noop) {
107
+ const baseHandler = existingCommand.action ?? noop;
108
+ return createPadroneBuilder({
109
+ ...existingCommand,
110
+ action: (args, ctx) => handler(args, ctx, baseHandler)
111
+ });
112
+ },
113
+ wrap(config) {
114
+ const handler = createWrapHandler(config, existingCommand.argsSchema, existingCommand.meta?.positional);
115
+ return createPadroneBuilder({
116
+ ...existingCommand,
117
+ action: handler
118
+ });
119
+ },
120
+ command(nameOrNames, builderFn) {
121
+ const name = Array.isArray(nameOrNames) ? nameOrNames[0] : nameOrNames;
122
+ const aliases = Array.isArray(nameOrNames) && nameOrNames.length > 1 ? nameOrNames.slice(1) : void 0;
123
+ const existingSubcommand = existingCommand.commands?.find((c) => c.name === name);
124
+ if (existingSubcommand) resolveCommand(existingSubcommand);
125
+ const initialCommand = existingSubcommand ? {
126
+ ...existingSubcommand,
127
+ aliases: aliases ?? existingSubcommand.aliases,
128
+ parent: existingCommand
129
+ } : {
130
+ name,
131
+ path: existingCommand.path ? `${existingCommand.path} ${name}` : name,
132
+ aliases,
133
+ parent: existingCommand,
134
+ "~types": {}
135
+ };
136
+ if (builderFn) {
137
+ const lazyCmd = { ...initialCommand };
138
+ lazyCmd[lazyResolver] = (target) => {
139
+ const savedParent = target.parent;
140
+ const commandObj = builderFn(createPadroneBuilder(target))?.[commandSymbol] ?? target;
141
+ const mergedCommandObj = existingSubcommand ? mergeCommands(existingSubcommand, commandObj) : commandObj;
142
+ Object.assign(target, mergedCommandObj);
143
+ target.parent = savedParent;
144
+ };
145
+ const commands = existingCommand.commands || [];
146
+ const existingIndex = commands.findIndex((c) => c.name === name);
147
+ const updatedCommands = existingIndex >= 0 ? [
148
+ ...commands.slice(0, existingIndex),
149
+ lazyCmd,
150
+ ...commands.slice(existingIndex + 1)
151
+ ] : [...commands, lazyCmd];
152
+ return createPadroneBuilder({
153
+ ...existingCommand,
154
+ commands: updatedCommands
155
+ });
156
+ }
157
+ const commands = existingCommand.commands || [];
158
+ const existingIndex = commands.findIndex((c) => c.name === name);
159
+ const updatedCommands = existingIndex >= 0 ? [
160
+ ...commands.slice(0, existingIndex),
161
+ initialCommand,
162
+ ...commands.slice(existingIndex + 1)
163
+ ] : [...commands, initialCommand];
164
+ return createPadroneBuilder({
165
+ ...existingCommand,
166
+ commands: updatedCommands
167
+ });
168
+ },
169
+ mount(nameOrNames, program, options) {
170
+ const name = Array.isArray(nameOrNames) ? nameOrNames[0] : nameOrNames;
171
+ const aliases = Array.isArray(nameOrNames) && nameOrNames.length > 1 ? nameOrNames.slice(1) : void 0;
172
+ const programCommand = program[commandSymbol];
173
+ if (!programCommand) throw new RoutingError("Cannot mount: not a valid Padrone program");
174
+ const remounted = repathCommandTree(programCommand, name, existingCommand.path || "", existingCommand);
175
+ remounted.aliases = aliases;
176
+ if (options?.context) {
177
+ const existing = remounted.contextTransform;
178
+ remounted.contextTransform = existing ? (ctx) => existing(options.context(ctx)) : options.context;
179
+ }
180
+ const existingSubcommand = existingCommand.commands?.find((c) => c.name === name);
181
+ const mergedCommandObj = existingSubcommand ? mergeCommands(existingSubcommand, remounted) : remounted;
182
+ const commands = existingCommand.commands || [];
183
+ const existingIndex = commands.findIndex((c) => c.name === name);
184
+ const updatedCommands = existingIndex >= 0 ? [
185
+ ...commands.slice(0, existingIndex),
186
+ mergedCommandObj,
187
+ ...commands.slice(existingIndex + 1)
188
+ ] : [...commands, mergedCommandObj];
189
+ return createPadroneBuilder({
190
+ ...existingCommand,
191
+ commands: updatedCommands
192
+ });
193
+ },
194
+ intercept(metaOrFn, factory) {
195
+ const registered = toRegisteredInterceptor(metaOrFn, factory);
196
+ return createPadroneBuilder({
197
+ ...existingCommand,
198
+ interceptors: [...existingCommand.interceptors ?? [], registered]
199
+ });
200
+ },
201
+ ...createProgramMethods(execCtx, evalCommand),
202
+ get info() {
203
+ return {
204
+ name: existingCommand.name,
205
+ title: existingCommand.title,
206
+ description: existingCommand.description,
207
+ version: existingCommand.version,
208
+ examples: existingCommand.examples,
209
+ deprecated: existingCommand.deprecated,
210
+ commands: (existingCommand.commands ?? []).map((c) => c.name)
211
+ };
212
+ },
213
+ "~types": {},
214
+ [commandSymbol]: existingCommand
215
+ };
216
+ execCtx.builder = builder;
217
+ return builder;
218
+ }
219
+ function defineCommand(fn) {
220
+ if (fn) return fn;
221
+ const builder = {
222
+ requires: () => builder,
223
+ define: (f) => f
224
+ };
225
+ return builder;
226
+ }
227
+ //#endregion
228
+ export { createPadrone, createPadroneBuilder, defineCommand };
229
+
230
+ //# sourceMappingURL=create.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.mjs","names":[],"sources":["../../src/core/create.ts"],"sourcesContent":["import { padroneAutoOutput } from '../extension/auto-output.ts';\nimport { padroneColor } from '../extension/color.ts';\nimport type { HelpCommand } from '../extension/help.ts';\nimport { padroneHelp } from '../extension/help.ts';\nimport { padroneInteractive } from '../extension/interactive.ts';\nimport { padroneRepl } from '../extension/repl.ts';\nimport { padroneSignalHandling } from '../extension/signal.ts';\nimport { padroneStdin } from '../extension/stdin.ts';\nimport { padroneSuggestions } from '../extension/suggestions.ts';\nimport type { VersionCommand } from '../extension/version.ts';\nimport { padroneVersion } from '../extension/version.ts';\nimport { createWrapHandler } from '../feature/wrap.ts';\nimport type {\n AnyPadroneCommand,\n AnyPadroneProgram,\n CommandTypesBase,\n DefineCommandBuilder,\n DefineCommandContext,\n InterceptorFactory,\n InterceptorMeta,\n PadroneBuilder,\n PadroneCommand,\n PadroneInterceptorFn,\n PadroneProgram,\n PadroneSchema,\n RegisteredInterceptor,\n} from '../types/index.ts';\nimport { commandSymbol, findCommandByName, lazyResolver, mergeCommands, repathCommandTree, resolveCommand } from './commands.ts';\nimport { RoutingError } from './errors.ts';\nimport type { ExecContext } from './exec.ts';\nimport { collectInterceptors, errorResultWithSignal, execCommand } from './exec.ts';\nimport { toRegisteredInterceptor } from './interceptors.ts';\nimport { createProgramMethods } from './program-methods.ts';\nimport { hasInteractiveConfig, isAsyncBranded, makeThenable, noop, withPromiseDrain } from './results.ts';\nimport { parseCommand } from './validate.ts';\n\nexport { buildReplCompleter } from './commands.ts';\nexport { asyncSchema } from './results.ts';\n\n/**\n * Options for configuring which built-in extensions are applied by default.\n */\nexport type PadroneBuiltins = {\n /** Enable `help` command, `--help` / `-h` flags, and default help display. Defaults to `true`. */\n help?: boolean;\n /** Enable `version` command and `--version` / `-v` / `-V` flags. Defaults to `true`. */\n version?: boolean;\n /** Enable `repl` command and `--repl` flag. Defaults to `true`. */\n repl?: boolean;\n /** Enable `--color` / `--no-color` flag support. Defaults to `true`. */\n color?: boolean;\n /** Enable \"Did you mean?\" suggestions for unknown commands and options. Defaults to `true`. */\n suggestions?: boolean;\n /** Enable signal handling (SIGINT, SIGTERM, SIGHUP). Defaults to `true`. */\n signal?: boolean;\n /** Enable automatic result output for `cli()`. Defaults to `true`. */\n autoOutput?: boolean;\n /** Enable stdin piping support. Defaults to `true`. */\n stdin?: boolean;\n /** Enable interactive prompting for missing arguments. Defaults to `true`. */\n interactive?: boolean;\n};\n\nexport type PadroneOptions = { builtins?: PadroneBuiltins };\n\n// biome-ignore lint/complexity/noBannedTypes: empty object signals \"all defaults enabled\"\ntype DefaultBuiltins = {};\n\ntype BuiltinCommands<B> = [...(B extends { help: false } ? [] : [HelpCommand]), ...(B extends { version: false } ? [] : [VersionCommand])];\n\nexport function createPadrone<TProgramName extends string, const TBuiltins extends PadroneBuiltins = DefaultBuiltins>(\n name: TProgramName,\n options?: { builtins?: TBuiltins },\n): PadroneProgram<TProgramName, '', '', PadroneSchema<void>, void, BuiltinCommands<TBuiltins>> {\n let builder: any = createPadroneBuilder({ name, path: '', commands: [] } as any);\n\n const b = options?.builtins;\n if (b?.help !== false) builder = builder.extend(padroneHelp());\n if (b?.version !== false) builder = builder.extend(padroneVersion());\n if (b?.repl !== false) builder = builder.extend(padroneRepl());\n if (b?.color !== false) builder = builder.extend(padroneColor());\n if (b?.suggestions !== false) builder = builder.extend(padroneSuggestions());\n if (b?.signal !== false) builder = builder.extend(padroneSignalHandling());\n if (b?.autoOutput !== false) builder = builder.extend(padroneAutoOutput());\n if (b?.stdin !== false) builder = builder.extend(padroneStdin());\n if (b?.interactive !== false) builder = builder.extend(padroneInteractive());\n\n return builder as any;\n}\n\nexport function createPadroneBuilder<TBuilder extends PadroneProgram = PadroneProgram>(\n inputCommand: AnyPadroneCommand,\n): TBuilder & { [commandSymbol]: AnyPadroneCommand } {\n // Re-parent direct subcommands so getCommandRuntime walks to the current root,\n // not a stale parent from before .runtime()/.configure()/etc.\n const existingCommand =\n inputCommand.commands?.length && inputCommand.commands.some((c) => c.parent && c.parent !== inputCommand)\n ? {\n ...inputCommand,\n commands: inputCommand.commands.map((c) => (c.parent && c.parent !== inputCommand ? { ...c, parent: inputCommand } : c)),\n }\n : inputCommand;\n\n const parseCommandFn = (input: string | undefined) => parseCommand(input, existingCommand, findCommandByName);\n const collectInterceptorsFn = (cmd: AnyPadroneCommand) => collectInterceptors(cmd, existingCommand);\n\n // Execution context shared by exec and program methods.\n // `builder` is assigned after the builder object is created (forward ref resolved at runtime only).\n const execCtx: ExecContext = {\n rootCommand: existingCommand,\n builder: undefined as any,\n parseCommandFn,\n collectInterceptorsFn,\n };\n\n const evalCommand: AnyPadroneProgram['eval'] = (input, evalOptions) => {\n try {\n const result = execCommand(input as string, execCtx, evalOptions, 'soft', evalOptions?.caller ?? 'eval');\n if (result instanceof Promise) return withPromiseDrain(result.catch((err: unknown) => errorResultWithSignal(err))) as any;\n return makeThenable(result);\n } catch (err) {\n return makeThenable(errorResultWithSignal(err)) as any;\n }\n };\n\n const programMethods = createProgramMethods(execCtx, evalCommand);\n\n const builder = {\n extend(extension: (builder: any) => any) {\n return extension(builder);\n },\n configure(config) {\n return createPadroneBuilder({ ...existingCommand, ...config }) as any;\n },\n runtime(runtimeConfig) {\n return createPadroneBuilder({ ...existingCommand, runtime: { ...existingCommand.runtime, ...runtimeConfig } }) as any;\n },\n async() {\n return createPadroneBuilder({ ...existingCommand, isAsync: true }) as any;\n },\n context(transform?: (ctx: unknown) => unknown) {\n if (!transform) return createPadroneBuilder({ ...existingCommand }) as any;\n const existing = existingCommand.contextTransform;\n const composed = existing ? (ctx: unknown) => transform(existing(ctx)) : transform;\n return createPadroneBuilder({ ...existingCommand, contextTransform: composed }) as any;\n },\n arguments(schema, meta) {\n const resolvedArgs = typeof schema === 'function' ? schema(existingCommand.argsSchema as any) : schema;\n const isAsync = existingCommand.isAsync || isAsyncBranded(resolvedArgs) || hasInteractiveConfig(meta);\n return createPadroneBuilder({ ...existingCommand, argsSchema: resolvedArgs, meta, isAsync }) as any;\n },\n action(handler = noop) {\n const baseHandler = existingCommand.action ?? noop;\n return createPadroneBuilder({\n ...existingCommand,\n action: (args: any, ctx: any) => (handler as any)(args, ctx, baseHandler),\n }) as any;\n },\n wrap(config) {\n const handler = createWrapHandler(config, existingCommand.argsSchema as any, existingCommand.meta?.positional);\n return createPadroneBuilder({ ...existingCommand, action: handler }) as any;\n },\n command(nameOrNames: string | readonly string[], builderFn?: (builder: any) => any) {\n const name = Array.isArray(nameOrNames) ? nameOrNames[0] : nameOrNames;\n const aliases = Array.isArray(nameOrNames) && nameOrNames.length > 1 ? (nameOrNames.slice(1) as string[]) : undefined;\n\n const existingSubcommand = existingCommand.commands?.find((c) => c.name === name) as AnyPadroneCommand | undefined;\n if (existingSubcommand) resolveCommand(existingSubcommand);\n\n const initialCommand: AnyPadroneCommand = existingSubcommand\n ? { ...existingSubcommand, aliases: aliases ?? existingSubcommand.aliases, parent: existingCommand }\n : ({\n name,\n path: existingCommand.path ? `${existingCommand.path} ${name}` : name,\n aliases,\n parent: existingCommand,\n '~types': {} as any,\n } satisfies PadroneCommand);\n\n if (builderFn) {\n const lazyCmd: AnyPadroneCommand = { ...initialCommand };\n (lazyCmd as any)[lazyResolver] = (target: AnyPadroneCommand) => {\n const savedParent = target.parent;\n const b = createPadroneBuilder(target);\n const commandObj = ((builderFn(b as any) as unknown as typeof b)?.[commandSymbol] as AnyPadroneCommand) ?? target;\n const mergedCommandObj = existingSubcommand ? mergeCommands(existingSubcommand, commandObj) : commandObj;\n Object.assign(target, mergedCommandObj);\n // Restore parent: mergeCommands copies the existing command's parent which may be stale\n // (e.g. when an extension is applied twice, the merged parent predates re-parenting).\n target.parent = savedParent;\n };\n\n const commands = existingCommand.commands || [];\n const existingIndex = commands.findIndex((c) => c.name === name);\n const updatedCommands =\n existingIndex >= 0\n ? [...commands.slice(0, existingIndex), lazyCmd, ...commands.slice(existingIndex + 1)]\n : [...commands, lazyCmd];\n\n return createPadroneBuilder({ ...existingCommand, commands: updatedCommands }) as any;\n }\n\n const commands = existingCommand.commands || [];\n const existingIndex = commands.findIndex((c) => c.name === name);\n const updatedCommands =\n existingIndex >= 0\n ? [...commands.slice(0, existingIndex), initialCommand, ...commands.slice(existingIndex + 1)]\n : [...commands, initialCommand];\n\n return createPadroneBuilder({ ...existingCommand, commands: updatedCommands }) as any;\n },\n\n mount(nameOrNames: string | readonly string[], program: unknown, options?: { context?: (ctx: unknown) => unknown }) {\n const name = Array.isArray(nameOrNames) ? nameOrNames[0] : nameOrNames;\n const aliases = Array.isArray(nameOrNames) && nameOrNames.length > 1 ? (nameOrNames.slice(1) as string[]) : undefined;\n\n const programCommand = (program as any)[commandSymbol] as AnyPadroneCommand | undefined;\n if (!programCommand) throw new RoutingError('Cannot mount: not a valid Padrone program');\n\n const remounted = repathCommandTree(programCommand, name, existingCommand.path || '', existingCommand);\n remounted.aliases = aliases;\n\n if (options?.context) {\n const existing = remounted.contextTransform;\n remounted.contextTransform = existing ? (ctx: unknown) => existing(options.context!(ctx)) : options.context;\n }\n\n const existingSubcommand = existingCommand.commands?.find((c) => c.name === name) as AnyPadroneCommand | undefined;\n const mergedCommandObj = existingSubcommand ? mergeCommands(existingSubcommand, remounted) : remounted;\n\n const commands = existingCommand.commands || [];\n const existingIndex = commands.findIndex((c) => c.name === name);\n const updatedCommands =\n existingIndex >= 0\n ? [...commands.slice(0, existingIndex), mergedCommandObj, ...commands.slice(existingIndex + 1)]\n : [...commands, mergedCommandObj];\n\n return createPadroneBuilder({ ...existingCommand, commands: updatedCommands }) as any;\n },\n\n intercept(metaOrFn: InterceptorMeta | PadroneInterceptorFn<any, any, any>, factory?: InterceptorFactory<any, any, any>) {\n const registered: RegisteredInterceptor = toRegisteredInterceptor(metaOrFn, factory);\n return createPadroneBuilder({\n ...existingCommand,\n interceptors: [...(existingCommand.interceptors ?? []), registered],\n }) as any;\n },\n\n ...programMethods,\n\n get info() {\n return {\n name: existingCommand.name,\n title: existingCommand.title,\n description: existingCommand.description,\n version: existingCommand.version,\n examples: existingCommand.examples,\n deprecated: existingCommand.deprecated,\n commands: (existingCommand.commands ?? []).map((c) => c.name),\n };\n },\n\n '~types': {} as any,\n\n [commandSymbol]: existingCommand,\n } satisfies AnyPadroneProgram & { [commandSymbol]: AnyPadroneCommand } as any;\n\n // Fix forward reference: execCtx.builder needs to reference the builder after it's created\n execCtx.builder = builder;\n\n return builder as TBuilder & { [commandSymbol]: AnyPadroneCommand };\n}\n\n/**\n * Identity helper that contextually types a command builder callback while preserving its full return type.\n * Use this when defining commands in separate files — the parent program retains exact type information\n * about the subcommand's args, result, and nested commands.\n *\n * The builder's context includes `DefineCommandContext` by default (optional `logger`, `tracing`, `progress`).\n * Override globally via module augmentation on `DefineCommandContext`, or per-command via `.requires()`.\n *\n * @example Direct form (most common)\n * ```ts\n * export const myCommand = defineCommand((c) =>\n * c.arguments(z.object({ name: z.string() }))\n * .action((args) => console.log(args.name))\n * );\n * ```\n *\n * @example With required interceptor context\n * ```ts\n * export const adminCommand = defineCommand()\n * .requires<{ adminDb: AdminDB }>()\n * .define((c) => c.action((_args, ctx) => ctx.context.adminDb.query(...)));\n * ```\n */\nexport function defineCommand<TContext = unknown, TOut extends CommandTypesBase = CommandTypesBase>(\n fn: (builder: PadroneBuilder<string, string, string, PadroneSchema<void>, void, [], any, false, TContext, DefineCommandContext>) => TOut,\n): typeof fn;\nexport function defineCommand(): DefineCommandBuilder;\nexport function defineCommand(fn?: any): any {\n if (fn) return fn;\n const builder: DefineCommandBuilder = {\n requires: () => builder as any,\n define: (f: any) => f,\n };\n return builder;\n}\n"],"mappings":"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"}
@@ -0,0 +1,198 @@
1
+ import { readStreamAsText } from "../util/stream.mjs";
2
+ import { REPL_SIGINT } from "./runtime.mjs";
3
+ //#region src/core/default-runtime.ts
4
+ /**
5
+ * Default terminal prompt implementation powered by Enquirer.
6
+ * Lazily imported to avoid loading Enquirer when not needed.
7
+ */
8
+ async function defaultTerminalPrompt(config) {
9
+ const Enquirer = (await import("enquirer")).default;
10
+ const question = {
11
+ type: config.type,
12
+ name: config.name,
13
+ message: config.message
14
+ };
15
+ if (config.default !== void 0) question.initial = config.default;
16
+ if (config.choices) question.choices = config.choices.map((c) => ({
17
+ name: String(c.value),
18
+ message: c.label
19
+ }));
20
+ return (await Enquirer.prompt(question))[config.name];
21
+ }
22
+ function createTerminalReplSession(config) {
23
+ let history = config.history ? [...config.history] : [];
24
+ let currentCompleter = config.completer;
25
+ return {
26
+ /** Update the tab completer (e.g. when REPL scope changes). Takes effect on the next question. */
27
+ set completer(fn) {
28
+ currentCompleter = fn;
29
+ },
30
+ async question(prompt) {
31
+ const { createInterface } = await import("node:readline");
32
+ const opts = {
33
+ input: process.stdin,
34
+ output: process.stdout,
35
+ terminal: true,
36
+ history: [...history],
37
+ historySize: Math.max(history.length, 1e3)
38
+ };
39
+ if (currentCompleter) opts.completer = currentCompleter;
40
+ const rl = createInterface(opts);
41
+ return new Promise((resolve) => {
42
+ let resolved = false;
43
+ const settle = (value) => {
44
+ if (resolved) return;
45
+ resolved = true;
46
+ rl.close();
47
+ resolve(value);
48
+ };
49
+ rl.question(prompt, (answer) => {
50
+ if (Array.isArray(rl.history)) history = [...rl.history];
51
+ settle(answer);
52
+ });
53
+ rl.once("SIGINT", () => {
54
+ process.stdout.write("\n");
55
+ settle(REPL_SIGINT);
56
+ });
57
+ rl.once("close", () => {
58
+ process.stdout.write("\n");
59
+ settle(null);
60
+ });
61
+ });
62
+ },
63
+ close() {}
64
+ };
65
+ }
66
+ /**
67
+ * Auto-detect interactive mode when not explicitly set.
68
+ * Returns 'disabled' in CI environments or non-TTY contexts, 'supported' otherwise.
69
+ */
70
+ function detectInteractiveMode() {
71
+ if (typeof process === "undefined") return "disabled";
72
+ if (process.env.CI || process.env.CONTINUOUS_INTEGRATION) return "disabled";
73
+ if (!process.stdout?.isTTY) return "disabled";
74
+ return "supported";
75
+ }
76
+ /**
77
+ * Creates a default stdin reader from `process.stdin`.
78
+ * Only created when a command actually declares a `stdin` meta field.
79
+ */
80
+ function createDefaultStdin() {
81
+ return {
82
+ get isTTY() {
83
+ if (typeof process === "undefined") return true;
84
+ return process.stdin?.isTTY === true;
85
+ },
86
+ async text() {
87
+ if (typeof process === "undefined") return "";
88
+ return readStreamAsText(process.stdin);
89
+ },
90
+ async *lines() {
91
+ if (typeof process === "undefined") return;
92
+ const { createInterface } = await import("node:readline");
93
+ const rl = createInterface({ input: process.stdin });
94
+ try {
95
+ for await (const line of rl) yield line;
96
+ } finally {
97
+ rl.close();
98
+ }
99
+ }
100
+ };
101
+ }
102
+ /**
103
+ * Default signal listener that wires to `process.on(signal)`.
104
+ * Returns an unsubscribe function that removes all listeners.
105
+ */
106
+ function defaultOnSignal(callback) {
107
+ if (typeof process === "undefined") return () => {};
108
+ const signals = [
109
+ "SIGINT",
110
+ "SIGTERM",
111
+ "SIGHUP"
112
+ ];
113
+ const handlers = /* @__PURE__ */ new Map();
114
+ for (const sig of signals) {
115
+ const handler = () => callback(sig);
116
+ handlers.set(sig, handler);
117
+ process.on(sig, handler);
118
+ }
119
+ return () => {
120
+ for (const [sig, handler] of handlers) process.removeListener(sig, handler);
121
+ };
122
+ }
123
+ /**
124
+ * Creates the default Node.js/Bun runtime.
125
+ */
126
+ function defaultExit(code) {
127
+ if (typeof process !== "undefined") process.exit(code);
128
+ throw new Error(`Exit with code ${code}`);
129
+ }
130
+ function getTerminalInfo() {
131
+ if (typeof process === "undefined") return void 0;
132
+ return {
133
+ get columns() {
134
+ return process.stdout?.columns;
135
+ },
136
+ get isTTY() {
137
+ return process.stdout?.isTTY === true;
138
+ }
139
+ };
140
+ }
141
+ function createDefaultRuntime() {
142
+ return {
143
+ output: (...args) => console.log(...args),
144
+ error: (text) => console.error(text),
145
+ argv: () => typeof process !== "undefined" ? process.argv.slice(2) : [],
146
+ env: () => typeof process !== "undefined" ? process.env : {},
147
+ format: "auto",
148
+ prompt: defaultTerminalPrompt,
149
+ interactive: detectInteractiveMode(),
150
+ onSignal: defaultOnSignal,
151
+ terminal: getTerminalInfo(),
152
+ exit: defaultExit
153
+ };
154
+ }
155
+ /**
156
+ * Returns the stdin abstraction: custom runtime stdin > default process.stdin.
157
+ * Returns `undefined` when no custom stdin is provided and process.stdin is not piped.
158
+ */
159
+ function resolveStdin(partial) {
160
+ if (partial?.stdin) return partial.stdin;
161
+ const defaultStdin = createDefaultStdin();
162
+ if (defaultStdin.isTTY) return void 0;
163
+ return defaultStdin;
164
+ }
165
+ /**
166
+ * Like `resolveStdin`, but always returns a stdin source even when it's a TTY.
167
+ * Used for async streams which support interactive (non-piped) input.
168
+ */
169
+ function resolveStdinAlways(partial) {
170
+ if (partial?.stdin) return partial.stdin;
171
+ return createDefaultStdin();
172
+ }
173
+ /**
174
+ * Merges a partial runtime with the default runtime.
175
+ */
176
+ function resolveRuntime(partial) {
177
+ const defaults = createDefaultRuntime();
178
+ if (!partial) return defaults;
179
+ return {
180
+ output: partial.output ?? defaults.output,
181
+ error: partial.error ?? defaults.error,
182
+ argv: partial.argv ?? defaults.argv,
183
+ env: partial.env ?? defaults.env,
184
+ format: partial.format ?? defaults.format,
185
+ interactive: partial.interactive ?? defaults.interactive,
186
+ prompt: partial.prompt ?? defaults.prompt,
187
+ readLine: partial.readLine ?? defaults.readLine,
188
+ stdin: partial.stdin,
189
+ theme: partial.theme,
190
+ onSignal: partial.onSignal ?? defaults.onSignal,
191
+ terminal: partial.terminal ?? defaults.terminal,
192
+ exit: partial.exit ?? defaults.exit
193
+ };
194
+ }
195
+ //#endregion
196
+ export { createDefaultRuntime, createTerminalReplSession, resolveRuntime, resolveStdin, resolveStdinAlways };
197
+
198
+ //# sourceMappingURL=default-runtime.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-runtime.mjs","names":[],"sources":["../../src/core/default-runtime.ts"],"sourcesContent":["import { readStreamAsText } from '../util/stream.ts';\nimport type {\n InteractiveMode,\n InteractivePromptConfig,\n PadroneRuntime,\n PadroneSignal,\n ReplSessionConfig,\n ResolvedPadroneRuntime,\n} from './runtime.ts';\nimport { REPL_SIGINT } from './runtime.ts';\n\n/**\n * Default terminal prompt implementation powered by Enquirer.\n * Lazily imported to avoid loading Enquirer when not needed.\n */\nasync function defaultTerminalPrompt(config: InteractivePromptConfig): Promise<unknown> {\n const Enquirer = (await import('enquirer')).default;\n\n const question: Record<string, unknown> = {\n type: config.type,\n name: config.name,\n message: config.message,\n };\n\n if (config.default !== undefined) {\n question.initial = config.default;\n }\n\n if (config.choices) {\n question.choices = config.choices.map((c) => ({\n name: String(c.value),\n message: c.label,\n }));\n }\n\n const response = (await Enquirer.prompt(question as any)) as Record<string, unknown>;\n return response[config.name];\n}\n\nexport function createTerminalReplSession(config: ReplSessionConfig) {\n // History accumulates across per-call interfaces, giving us\n // up/down arrow navigation without a persistent stdin listener\n // that would conflict with Enquirer or other stdin consumers.\n let history: string[] = config.history ? [...config.history] : [];\n let currentCompleter = config.completer;\n\n return {\n /** Update the tab completer (e.g. when REPL scope changes). Takes effect on the next question. */\n set completer(fn: ((line: string) => [string[], string]) | undefined) {\n currentCompleter = fn;\n },\n async question(prompt: string): Promise<string | typeof REPL_SIGINT | null> {\n const { createInterface } = await import('node:readline');\n const opts: Record<string, unknown> = {\n input: process.stdin,\n output: process.stdout,\n terminal: true,\n history: [...history],\n historySize: Math.max(history.length, 1000),\n };\n if (currentCompleter) {\n opts.completer = currentCompleter;\n }\n const rl = createInterface(opts as any);\n\n return new Promise((resolve) => {\n let resolved = false;\n const settle = (value: string | typeof REPL_SIGINT | null) => {\n if (resolved) return;\n resolved = true;\n rl.close();\n resolve(value);\n };\n\n rl.question(prompt, (answer) => {\n // Grab updated history (includes the new entry) before closing.\n if (Array.isArray((rl as any).history)) history = [...(rl as any).history];\n settle(answer);\n });\n // Ctrl+C: cancel current line, print newline, resolve SIGINT sentinel.\n rl.once('SIGINT', () => {\n process.stdout.write('\\n');\n settle(REPL_SIGINT);\n });\n // EOF (Ctrl+D) fires close without the question callback.\n rl.once('close', () => {\n // Write newline so zsh doesn't show '%' (partial-line indicator).\n process.stdout.write('\\n');\n settle(null);\n });\n });\n },\n close() {\n // No persistent interface to clean up.\n },\n };\n}\n\n/**\n * Auto-detect interactive mode when not explicitly set.\n * Returns 'disabled' in CI environments or non-TTY contexts, 'supported' otherwise.\n */\nfunction detectInteractiveMode(): InteractiveMode {\n if (typeof process === 'undefined') return 'disabled';\n if (process.env.CI || process.env.CONTINUOUS_INTEGRATION) return 'disabled';\n if (!process.stdout?.isTTY) return 'disabled';\n return 'supported';\n}\n\n/**\n * Creates a default stdin reader from `process.stdin`.\n * Only created when a command actually declares a `stdin` meta field.\n */\nfunction createDefaultStdin(): NonNullable<PadroneRuntime['stdin']> {\n return {\n get isTTY() {\n // process.stdin.isTTY is `true` when interactive terminal, `undefined` when piped/redirected.\n // Node.js never sets it to `false` — it's either `true` or absent.\n if (typeof process === 'undefined') return true;\n return process.stdin?.isTTY === true;\n },\n async text() {\n if (typeof process === 'undefined') return '';\n return readStreamAsText(process.stdin);\n },\n async *lines() {\n if (typeof process === 'undefined') return;\n const { createInterface } = await import('node:readline');\n const rl = createInterface({ input: process.stdin });\n try {\n for await (const line of rl) {\n yield line;\n }\n } finally {\n rl.close();\n }\n },\n };\n}\n\n/**\n * Default signal listener that wires to `process.on(signal)`.\n * Returns an unsubscribe function that removes all listeners.\n */\nfunction defaultOnSignal(callback: (signal: PadroneSignal) => void): () => void {\n if (typeof process === 'undefined') return () => {};\n const signals: PadroneSignal[] = ['SIGINT', 'SIGTERM', 'SIGHUP'];\n const handlers = new Map<PadroneSignal, () => void>();\n for (const sig of signals) {\n const handler = () => callback(sig);\n handlers.set(sig, handler);\n process.on(sig, handler);\n }\n return () => {\n for (const [sig, handler] of handlers) {\n process.removeListener(sig, handler);\n }\n };\n}\n\n/**\n * Creates the default Node.js/Bun runtime.\n */\nfunction defaultExit(code: number): never {\n if (typeof process !== 'undefined') process.exit(code);\n throw new Error(`Exit with code ${code}`);\n}\n\nfunction getTerminalInfo(): PadroneRuntime['terminal'] {\n if (typeof process === 'undefined') return undefined;\n return {\n get columns() {\n return process.stdout?.columns;\n },\n get isTTY() {\n return process.stdout?.isTTY === true;\n },\n };\n}\n\nexport function createDefaultRuntime(): ResolvedPadroneRuntime {\n return {\n output: (...args) => console.log(...args),\n error: (text) => console.error(text),\n argv: () => (typeof process !== 'undefined' ? process.argv.slice(2) : []),\n env: () => (typeof process !== 'undefined' ? (process.env as Record<string, string | undefined>) : {}),\n format: 'auto',\n prompt: defaultTerminalPrompt,\n interactive: detectInteractiveMode(),\n onSignal: defaultOnSignal,\n terminal: getTerminalInfo(),\n exit: defaultExit,\n };\n}\n\n/**\n * Returns the stdin abstraction: custom runtime stdin > default process.stdin.\n * Returns `undefined` when no custom stdin is provided and process.stdin is not piped.\n */\nexport function resolveStdin(partial?: PadroneRuntime): NonNullable<PadroneRuntime['stdin']> | undefined {\n if (partial?.stdin) return partial.stdin;\n const defaultStdin = createDefaultStdin();\n // Only use default stdin if it's actually piped (isTTY === false).\n // This avoids accidentally blocking on stdin in tests/CI.\n if (defaultStdin.isTTY) return undefined;\n return defaultStdin;\n}\n\n/**\n * Like `resolveStdin`, but always returns a stdin source even when it's a TTY.\n * Used for async streams which support interactive (non-piped) input.\n */\nexport function resolveStdinAlways(partial?: PadroneRuntime): NonNullable<PadroneRuntime['stdin']> {\n if (partial?.stdin) return partial.stdin;\n return createDefaultStdin();\n}\n\n/**\n * Merges a partial runtime with the default runtime.\n */\nexport function resolveRuntime(partial?: PadroneRuntime): ResolvedPadroneRuntime {\n const defaults = createDefaultRuntime();\n if (!partial) return defaults;\n return {\n output: partial.output ?? defaults.output,\n error: partial.error ?? defaults.error,\n argv: partial.argv ?? defaults.argv,\n env: partial.env ?? defaults.env,\n format: partial.format ?? defaults.format,\n interactive: partial.interactive ?? defaults.interactive,\n prompt: partial.prompt ?? defaults.prompt,\n readLine: partial.readLine ?? defaults.readLine,\n stdin: partial.stdin,\n theme: partial.theme,\n onSignal: partial.onSignal ?? defaults.onSignal,\n terminal: partial.terminal ?? defaults.terminal,\n exit: partial.exit ?? defaults.exit,\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,107 @@
1
+ import { PadroneSignal } from "./runtime.mjs";
2
+
3
+ //#region src/core/errors.d.ts
4
+ type PadroneErrorOptions = {
5
+ /** Process exit code. Defaults to 1. */exitCode?: number; /** Actionable suggestions shown to the user (e.g. "Use --env production"). */
6
+ suggestions?: string[]; /** The command path that produced the error (e.g. "deploy staging"). */
7
+ command?: string; /** The phase where the error occurred. */
8
+ phase?: 'parse' | 'validate' | 'execute' | 'config'; /** Original cause for error chaining. */
9
+ cause?: unknown;
10
+ };
11
+ /**
12
+ * Base error class for all Padrone errors.
13
+ * Carries structured metadata for user-friendly formatting and programmatic handling.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * throw new PadroneError('Something went wrong', {
18
+ * exitCode: 1,
19
+ * suggestions: ['Try --help for usage information'],
20
+ * });
21
+ * ```
22
+ */
23
+ declare class PadroneError extends Error {
24
+ readonly exitCode: number;
25
+ readonly suggestions: string[];
26
+ readonly command?: string;
27
+ readonly phase?: 'parse' | 'validate' | 'execute' | 'config';
28
+ constructor(message: string, options?: PadroneErrorOptions);
29
+ /**
30
+ * Returns a serializable representation of the error,
31
+ * suitable for non-terminal runtimes (web UIs, APIs, etc.).
32
+ */
33
+ toJSON(): {
34
+ name: string;
35
+ message: string;
36
+ exitCode: number;
37
+ suggestions: string[];
38
+ command?: string;
39
+ phase?: string;
40
+ };
41
+ }
42
+ /**
43
+ * Thrown when command routing fails — unknown command, unexpected arguments, etc.
44
+ */
45
+ declare class RoutingError extends PadroneError {
46
+ constructor(message: string, options?: PadroneErrorOptions);
47
+ }
48
+ /**
49
+ * Thrown when argument or schema validation fails.
50
+ * Carries the structured issues from the schema validator.
51
+ */
52
+ declare class ValidationError extends PadroneError {
53
+ readonly issues: readonly {
54
+ path?: PropertyKey[];
55
+ message: string;
56
+ }[];
57
+ constructor(message: string, issues: readonly {
58
+ path?: PropertyKey[];
59
+ message: string;
60
+ }[], options?: PadroneErrorOptions);
61
+ toJSON(): {
62
+ issues: {
63
+ path: string[] | undefined;
64
+ message: string;
65
+ }[];
66
+ name: string;
67
+ message: string;
68
+ exitCode: number;
69
+ suggestions: string[];
70
+ command?: string;
71
+ phase?: string;
72
+ };
73
+ }
74
+ /**
75
+ * Thrown when config file loading or validation fails.
76
+ */
77
+ declare class ConfigError extends PadroneError {
78
+ constructor(message: string, options?: PadroneErrorOptions);
79
+ }
80
+ /**
81
+ * Thrown from user action handlers to surface structured errors with exit codes and suggestions.
82
+ * This is the primary error class users should throw from their command actions.
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * throw new ActionError('Missing environment', {
87
+ * exitCode: 1,
88
+ * suggestions: ['Use --env production or --env staging'],
89
+ * });
90
+ * ```
91
+ */
92
+ declare class ActionError extends PadroneError {
93
+ constructor(message: string, options?: PadroneErrorOptions);
94
+ }
95
+ /**
96
+ * Thrown when command execution is interrupted by a process signal (SIGINT, SIGTERM, SIGHUP).
97
+ * Carries the signal name and the conventional exit code (128 + signal number).
98
+ */
99
+ declare class SignalError extends PadroneError {
100
+ readonly signal: PadroneSignal;
101
+ constructor(signal: PadroneSignal, options?: {
102
+ cause?: unknown;
103
+ });
104
+ }
105
+ //#endregion
106
+ export { ActionError, ConfigError, PadroneError, PadroneErrorOptions, RoutingError, SignalError, ValidationError };
107
+ //# sourceMappingURL=errors.d.mts.map