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
@@ -0,0 +1,43 @@
1
+ //#region src/util/utils.ts
2
+ function getRootCommand(cmd) {
3
+ let current = cmd;
4
+ while (current.parent) current = current.parent;
5
+ return current;
6
+ }
7
+ async function readVersionFromPackageJson() {
8
+ try {
9
+ const fs = await import("node:fs");
10
+ const path = await import("node:path");
11
+ let dir = process.cwd();
12
+ for (let i = 0; i < 10; i++) {
13
+ const pkgPath = path.join(dir, "package.json");
14
+ if (fs.existsSync(pkgPath)) {
15
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
16
+ if (pkg.version) return pkg.version;
17
+ }
18
+ const parentDir = path.dirname(dir);
19
+ if (parentDir === dir) break;
20
+ dir = parentDir;
21
+ }
22
+ } catch {}
23
+ return "0.0.0";
24
+ }
25
+ /**
26
+ * Attempts to get the version from various sources:
27
+ * 1. Explicit version set on the command
28
+ * 2. npm_package_version environment variable (set by npm/yarn/pnpm when running scripts)
29
+ * 3. package.json in current or parent directories
30
+ *
31
+ * Returns synchronously when an explicit version or env var is available.
32
+ * Falls back to async package.json discovery otherwise.
33
+ */
34
+ function getVersion(explicitVersion) {
35
+ if (explicitVersion) return explicitVersion;
36
+ if (typeof process !== "undefined" && process.env?.npm_package_version) return process.env.npm_package_version;
37
+ if (typeof process !== "undefined") return readVersionFromPackageJson();
38
+ return "0.0.0";
39
+ }
40
+ //#endregion
41
+ export { getRootCommand, getVersion };
42
+
43
+ //# sourceMappingURL=utils.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.mjs","names":[],"sources":["../../src/util/utils.ts"],"sourcesContent":["import type { AnyPadroneCommand } from '../types/index.ts';\n\nexport function getRootCommand(cmd: AnyPadroneCommand): AnyPadroneCommand {\n let current = cmd;\n while (current.parent) current = current.parent;\n return current;\n}\n\nasync function readVersionFromPackageJson(): Promise<string> {\n try {\n const fs = await import('node:fs');\n const path = await import('node:path');\n let dir = process.cwd();\n\n // Walk up the directory tree looking for package.json\n for (let i = 0; i < 10; i++) {\n const pkgPath = path.join(dir, 'package.json');\n if (fs.existsSync(pkgPath)) {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));\n if (pkg.version) return pkg.version;\n }\n const parentDir = path.dirname(dir);\n if (parentDir === dir) break; // Reached root\n dir = parentDir;\n }\n } catch {\n // Ignore errors (e.g., fs not available in browser)\n }\n return '0.0.0';\n}\n\n/**\n * Attempts to get the version from various sources:\n * 1. Explicit version set on the command\n * 2. npm_package_version environment variable (set by npm/yarn/pnpm when running scripts)\n * 3. package.json in current or parent directories\n *\n * Returns synchronously when an explicit version or env var is available.\n * Falls back to async package.json discovery otherwise.\n */\nexport function getVersion(explicitVersion?: string): string | Promise<string> {\n if (explicitVersion) return explicitVersion;\n\n if (typeof process !== 'undefined' && process.env?.npm_package_version) {\n return process.env.npm_package_version;\n }\n\n if (typeof process !== 'undefined') return readVersionFromPackageJson();\n\n return '0.0.0';\n}\n"],"mappings":";AAEA,SAAgB,eAAe,KAA2C;CACxE,IAAI,UAAU;CACd,OAAO,QAAQ,QAAQ,UAAU,QAAQ;CACzC,OAAO;AACT;AAEA,eAAe,6BAA8C;CAC3D,IAAI;EACF,MAAM,KAAK,MAAM,OAAO;EACxB,MAAM,OAAO,MAAM,OAAO;EAC1B,IAAI,MAAM,QAAQ,IAAI;EAGtB,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KAAK;GAC3B,MAAM,UAAU,KAAK,KAAK,KAAK,cAAc;GAC7C,IAAI,GAAG,WAAW,OAAO,GAAG;IAC1B,MAAM,MAAM,KAAK,MAAM,GAAG,aAAa,SAAS,OAAO,CAAC;IACxD,IAAI,IAAI,SAAS,OAAO,IAAI;GAC9B;GACA,MAAM,YAAY,KAAK,QAAQ,GAAG;GAClC,IAAI,cAAc,KAAK;GACvB,MAAM;EACR;CACF,QAAQ,CAER;CACA,OAAO;AACT;;;;;;;;;;AAWA,SAAgB,WAAW,iBAAoD;CAC7E,IAAI,iBAAiB,OAAO;CAE5B,IAAI,OAAO,YAAY,eAAe,QAAQ,KAAK,qBACjD,OAAO,QAAQ,IAAI;CAGrB,IAAI,OAAO,YAAY,aAAa,OAAO,2BAA2B;CAEtE,OAAO;AACT"}
package/dist/zod.d.mts CHANGED
@@ -1,32 +1 @@
1
- import { ut as PadroneSchema } from "./index-D-Dpz7l_.mjs";
2
- import * as z from "zod/v4";
3
-
4
- //#region src/schema/zod.d.ts
5
- /**
6
- * Creates a Zod schema for an async stream field, ready to use in `.arguments()`.
7
- * Wraps `z.custom<AsyncIterable<T>>()` with the `asyncStream()` metadata automatically.
8
- *
9
- * @param itemSchema - Optional item schema for per-item validation.
10
- *
11
- * @example
12
- * ```ts
13
- * import { zodAsyncStream } from 'padrone/zod';
14
- *
15
- * // String lines
16
- * z.object({ lines: zodAsyncStream() })
17
- *
18
- * // Typed items — each line JSON.parse'd and validated
19
- * const recordSchema = z.object({ name: z.string(), age: z.number() });
20
- * z.object({ records: zodAsyncStream(jsonCodec(recordSchema)) })
21
- * ```
22
- */
23
- declare function zodAsyncStream<T = string>(itemSchema?: PadroneSchema<unknown, T>): z.ZodCustom<AsyncIterable<T>, AsyncIterable<T>>;
24
- /**
25
- * JSON codec for Zod schemas
26
- * @see https://zod.dev/codecs?id=jsonschema
27
- * Unlike the example in the docs, this codec also handles the case where the input is already an object
28
- */
29
- declare const jsonCodec: <T extends z.ZodType>(schema: T) => z.ZodCodec<z.ZodUnion<readonly [z.ZodString, z.ZodUnknown]>, T>;
30
- //#endregion
31
- export { jsonCodec, zodAsyncStream };
32
- //# sourceMappingURL=zod.d.mts.map
1
+ export { };
package/dist/zod.mjs CHANGED
@@ -1,50 +1,2 @@
1
- import { t as asyncStream } from "./stream-DC4H8YTx.mjs";
2
- import * as z from "zod/v4";
3
- //#region src/schema/zod.ts
4
- /**
5
- * Creates a Zod schema for an async stream field, ready to use in `.arguments()`.
6
- * Wraps `z.custom<AsyncIterable<T>>()` with the `asyncStream()` metadata automatically.
7
- *
8
- * @param itemSchema - Optional item schema for per-item validation.
9
- *
10
- * @example
11
- * ```ts
12
- * import { zodAsyncStream } from 'padrone/zod';
13
- *
14
- * // String lines
15
- * z.object({ lines: zodAsyncStream() })
16
- *
17
- * // Typed items — each line JSON.parse'd and validated
18
- * const recordSchema = z.object({ name: z.string(), age: z.number() });
19
- * z.object({ records: zodAsyncStream(jsonCodec(recordSchema)) })
20
- * ```
21
- */
22
- function zodAsyncStream(itemSchema) {
23
- return z.custom().meta(asyncStream(itemSchema));
24
- }
25
- /**
26
- * JSON codec for Zod schemas
27
- * @see https://zod.dev/codecs?id=jsonschema
28
- * Unlike the example in the docs, this codec also handles the case where the input is already an object
29
- */
30
- const jsonCodec = (schema) => z.codec(z.union([z.string(), z.unknown()]), schema, {
31
- decode: (jsonString, ctx) => {
32
- try {
33
- if (typeof jsonString !== "string") return jsonString;
34
- return JSON.parse(jsonString);
35
- } catch (err) {
36
- ctx.issues.push({
37
- code: "invalid_format",
38
- format: "json",
39
- input: typeof jsonString === "string" ? jsonString : JSON.stringify(jsonString),
40
- message: err.message
41
- });
42
- return z.NEVER;
43
- }
44
- },
45
- encode: (value) => JSON.stringify(value)
46
- });
47
- //#endregion
1
+ import { jsonCodec, zodAsyncStream } from "./schema/zod.mjs";
48
2
  export { jsonCodec, zodAsyncStream };
49
-
50
- //# sourceMappingURL=zod.mjs.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "padrone",
3
- "version": "1.8.2",
3
+ "version": "2.0.0",
4
4
  "description": "Create type-safe, interactive CLI apps with Zod schemas",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -21,13 +21,13 @@
21
21
  "vercel-ai",
22
22
  "standard-schema"
23
23
  ],
24
- "homepage": "https://github.com/KurtGokhan/padrone",
24
+ "homepage": "https://github.com/gkurt/padrone",
25
25
  "bugs": {
26
- "url": "https://github.com/KurtGokhan/padrone/issues"
26
+ "url": "https://github.com/gkurt/padrone/issues"
27
27
  },
28
28
  "repository": {
29
29
  "type": "git",
30
- "url": "git+https://github.com/KurtGokhan/padrone.git"
30
+ "url": "git+https://github.com/gkurt/padrone.git"
31
31
  },
32
32
  "author": {
33
33
  "name": "Gokhan Kurt",
@@ -68,16 +68,16 @@
68
68
  "./codegen": {
69
69
  "padrone@dev": "./src/codegen/index.ts",
70
70
  "import": {
71
- "types": "./dist/codegen.d.mts",
72
- "default": "./dist/codegen.mjs"
71
+ "types": "./dist/codegen/index.d.mts",
72
+ "default": "./dist/codegen/index.mjs"
73
73
  },
74
74
  "source": "./src/codegen/index.ts"
75
75
  },
76
76
  "./docs": {
77
77
  "padrone@dev": "./src/docs/index.ts",
78
78
  "import": {
79
- "types": "./dist/docs.d.mts",
80
- "default": "./dist/docs.mjs"
79
+ "types": "./dist/docs/index.d.mts",
80
+ "default": "./dist/docs/index.mjs"
81
81
  },
82
82
  "source": "./src/docs/index.ts"
83
83
  },
@@ -89,10 +89,58 @@
89
89
  },
90
90
  "source": "./src/zod.ts"
91
91
  },
92
+ "./ink": {
93
+ "padrone@dev": "./src/ink.ts",
94
+ "import": {
95
+ "types": "./dist/ink.d.mts",
96
+ "default": "./dist/ink.mjs"
97
+ },
98
+ "source": "./src/ink.ts"
99
+ },
100
+ "./mcp": {
101
+ "padrone@dev": "./src/mcp.ts",
102
+ "import": {
103
+ "types": "./dist/mcp.d.mts",
104
+ "default": "./dist/mcp.mjs"
105
+ },
106
+ "source": "./src/mcp.ts"
107
+ },
108
+ "./serve": {
109
+ "padrone@dev": "./src/serve.ts",
110
+ "import": {
111
+ "types": "./dist/serve.d.mts",
112
+ "default": "./dist/serve.mjs"
113
+ },
114
+ "source": "./src/serve.ts"
115
+ },
116
+ "./tracing": {
117
+ "padrone@dev": "./src/tracing.ts",
118
+ "import": {
119
+ "types": "./dist/tracing.d.mts",
120
+ "default": "./dist/tracing.mjs"
121
+ },
122
+ "source": "./src/tracing.ts"
123
+ },
124
+ "./completion": {
125
+ "padrone@dev": "./src/completion.ts",
126
+ "import": {
127
+ "types": "./dist/completion.d.mts",
128
+ "default": "./dist/completion.mjs"
129
+ },
130
+ "source": "./src/completion.ts"
131
+ },
132
+ "./man": {
133
+ "padrone@dev": "./src/man.ts",
134
+ "import": {
135
+ "types": "./dist/man.d.mts",
136
+ "default": "./dist/man.mjs"
137
+ },
138
+ "source": "./src/man.ts"
139
+ },
92
140
  "./package.json": "./package.json"
93
141
  },
94
142
  "scripts": {
95
- "build": "tsdown src/index.ts src/test.ts src/zod.ts src/codegen/index.ts src/docs/index.ts --dts --sourcemap",
143
+ "build": "tsdown src/index.ts src/test.ts src/zod.ts src/ink.ts src/mcp.ts src/serve.ts src/tracing.ts src/completion.ts src/man.ts src/codegen/index.ts src/docs/index.ts --dts --sourcemap --unbundle",
96
144
  "start": "bun --conditions=padrone@dev src/cli/index.ts",
97
145
  "dev": "bun --conditions=padrone@dev --watch src/cli/index.ts",
98
146
  "test": "bun test --conditions=padrone@dev",
@@ -105,16 +153,16 @@
105
153
  "enquirer": "^2.4.1"
106
154
  },
107
155
  "devDependencies": {
108
- "@types/react": "^19.2.14",
109
- "ai": "^6.0.146",
110
- "ink": "^6.8.0",
111
- "react": "^19.2.4",
112
- "tsdown": "^0.21.7",
113
- "zod": "^4.3.6"
156
+ "@types/react": "^19.2.17",
157
+ "ai": "^7.0.8",
158
+ "ink": "^7.1.0",
159
+ "react": "^19.2.7",
160
+ "tsdown": "^0.22.3",
161
+ "zod": "^4.4.3"
114
162
  },
115
163
  "peerDependencies": {
116
- "ai": "5 || 6",
117
- "ink": "^6.0.0",
164
+ "ai": "5 || 6 || 7",
165
+ "ink": "^6.0.0 || ^7.0.0",
118
166
  "react": ">=18.0.0",
119
167
  "zod": "^3.25.0 || ^4.0.0"
120
168
  },
@@ -0,0 +1,2 @@
1
+ export type { WithCompletion } from './extension/completion.ts';
2
+ export { padroneCompletion } from './extension/completion.ts';
package/src/core/args.ts CHANGED
@@ -208,10 +208,58 @@ export function preprocessArgs(
208
208
  return result;
209
209
  }
210
210
 
211
+ /**
212
+ * Walk a JSON schema fragment and collect the set of allowed primitive types,
213
+ * descending into `anyOf` / `oneOf` (used for unions). For variants whose type
214
+ * is `array`, item types are collected separately into `itemTypes`.
215
+ */
216
+ function collectAllowedTypes(prop: Record<string, any> | undefined, types: Set<string>, itemTypes: Set<string>): void {
217
+ if (!prop) return;
218
+
219
+ if (prop.type !== undefined) {
220
+ const list = Array.isArray(prop.type) ? prop.type : [prop.type];
221
+ for (const t of list) {
222
+ if (typeof t === 'string') types.add(t);
223
+ }
224
+ if (list.includes('array') && prop.items) {
225
+ collectAllowedTypes(prop.items, itemTypes, new Set());
226
+ }
227
+ }
228
+
229
+ const variants = prop.anyOf ?? prop.oneOf;
230
+ if (Array.isArray(variants)) {
231
+ for (const variant of variants) collectAllowedTypes(variant, types, itemTypes);
232
+ }
233
+ }
234
+
235
+ /** Coerce a single CLI string to a primitive based on the set of allowed types. */
236
+ function coerceScalar(value: unknown, allowedTypes: Set<string>): unknown {
237
+ if (typeof value !== 'string') return value;
238
+
239
+ if (allowedTypes.has('boolean')) {
240
+ const lower = value.toLowerCase();
241
+ if (lower === 'true' || lower === '1' || lower === 'yes' || lower === 'on') return true;
242
+ if (lower === 'false' || lower === '0' || lower === 'no' || lower === 'off') return false;
243
+ }
244
+
245
+ if (allowedTypes.has('number') || allowedTypes.has('integer')) {
246
+ const trimmed = value.trim();
247
+ if (trimmed !== '') {
248
+ const num = Number(trimmed);
249
+ if (!Number.isNaN(num)) return num;
250
+ }
251
+ }
252
+
253
+ return value;
254
+ }
255
+
211
256
  /**
212
257
  * Auto-coerce CLI string values to match the expected schema types.
213
258
  * Handles: string → number, string → boolean for primitive schema fields.
214
259
  * Arrays of primitives are also coerced element-wise.
260
+ * Union types (`anyOf` / `oneOf`) are coerced to the most specific matching
261
+ * primitive — e.g. `--test true` for `z.union([z.boolean(), z.string()])`
262
+ * becomes the boolean `true` rather than the string "true".
215
263
  */
216
264
  export function coerceArgs(data: Record<string, unknown>, schema: StandardJSONSchemaV1): Record<string, unknown> {
217
265
  let properties: Record<string, any>;
@@ -229,43 +277,21 @@ export function coerceArgs(data: Record<string, unknown>, schema: StandardJSONSc
229
277
  const prop = properties[key];
230
278
  if (!prop) continue;
231
279
 
232
- const targetType = prop.type as string | undefined;
233
-
234
- if (targetType === 'number' || targetType === 'integer') {
235
- if (typeof value === 'string') {
236
- const num = Number(value);
237
- if (!Number.isNaN(num)) result[key] = num;
238
- }
239
- } else if (targetType === 'boolean') {
240
- if (typeof value === 'string') {
241
- const lower = value.toLowerCase();
242
- if (lower === 'true' || lower === '1' || lower === 'yes' || lower === 'on') result[key] = true;
243
- else if (lower === 'false' || lower === '0' || lower === 'no' || lower === 'off') result[key] = false;
244
- }
245
- } else if (targetType === 'array') {
246
- // Coerce single items to array
247
- const arr = Array.isArray(value) ? value : [value];
248
- const itemType = prop.items?.type as string | undefined;
249
- if (itemType === 'number' || itemType === 'integer') {
250
- result[key] = arr.map((v) => {
251
- if (typeof v === 'string') {
252
- const num = Number(v);
253
- return Number.isNaN(num) ? v : num;
254
- }
255
- return v;
256
- });
257
- } else if (itemType === 'boolean') {
258
- result[key] = arr.map((v) => {
259
- if (typeof v === 'string') {
260
- const lower = v.toLowerCase();
261
- if (lower === 'true' || lower === '1' || lower === 'yes' || lower === 'on') return true;
262
- if (lower === 'false' || lower === '0' || lower === 'no' || lower === 'off') return false;
263
- }
264
- return v;
265
- });
266
- } else if (!Array.isArray(value)) {
267
- result[key] = arr;
268
- }
280
+ const types = new Set<string>();
281
+ const itemTypes = new Set<string>();
282
+ collectAllowedTypes(prop, types, itemTypes);
283
+
284
+ const isArrayValue = Array.isArray(value);
285
+ const allowsArray = types.has('array');
286
+ const allowsScalar = types.has('string') || types.has('boolean') || types.has('number') || types.has('integer');
287
+
288
+ if (isArrayValue && allowsArray) {
289
+ result[key] = value.map((v) => coerceScalar(v, itemTypes));
290
+ } else if (!isArrayValue && allowsArray && !allowsScalar) {
291
+ // Wrap single value into an array when only array shapes are allowed
292
+ result[key] = [coerceScalar(value, itemTypes)];
293
+ } else if (!isArrayValue) {
294
+ result[key] = coerceScalar(value, types);
269
295
  }
270
296
  }
271
297
 
@@ -4,14 +4,14 @@ import type { HelpFormat } from '../output/formatter.ts';
4
4
  /** Process signals that Padrone can handle for graceful shutdown. */
5
5
  export type PadroneSignal = 'SIGINT' | 'SIGTERM' | 'SIGHUP';
6
6
 
7
- /** Value accepted by `PadroneProgressIndicator.update()`. */
7
+ /** Value accepted by `PadroneProgress.update()`. */
8
8
  export type PadroneProgressUpdate = string | number | { message?: string; progress?: number; indeterminate?: boolean; time?: boolean };
9
9
 
10
10
  /**
11
11
  * A progress indicator instance (spinner, progress bar, etc).
12
12
  * Created by the runtime's `progress` factory and used to show loading state during command execution.
13
13
  */
14
- export type PadroneProgressIndicator = {
14
+ export type PadroneProgress = {
15
15
  /**
16
16
  * Update the indicator.
17
17
  * - `string` — update the displayed message.
@@ -31,6 +31,15 @@ export type PadroneProgressIndicator = {
31
31
  succeed: (message?: string | null, options?: { indicator?: string }) => void;
32
32
  /** Mark as failed and stop. Pass `null` to stop without rendering a final message. */
33
33
  fail: (message?: string | null, options?: { indicator?: string }) => void;
34
+ /** Control ETA (estimated time remaining) display at runtime. */
35
+ eta: {
36
+ /** Enable ETA tracking. Starts collecting samples from subsequent `update()` calls. */
37
+ start: () => void;
38
+ /** Disable ETA display. */
39
+ stop: () => void;
40
+ /** Clear collected samples and restart estimation. Useful between operation phases. */
41
+ reset: () => void;
42
+ };
34
43
  /** Stop without success/fail status. */
35
44
  stop: () => void;
36
45
  /** Temporarily hide the indicator so other output can be written cleanly. */
@@ -21,6 +21,9 @@ export type WithCompletion<T> = WithCommand<T, 'completion', CompletionCommand>;
21
21
  *
22
22
  * Usage:
23
23
  * ```ts
24
+ * import { createPadrone } from 'padrone';
25
+ * import { padroneCompletion } from 'padrone/completion';
26
+ *
24
27
  * createPadrone('my-cli').extend(padroneCompletion())
25
28
  * ```
26
29
  */
@@ -2,23 +2,15 @@ export type { WithAsync } from '../util/type-utils.ts';
2
2
  export type { PadroneAutoOutputOptions } from './auto-output.ts';
3
3
  export { padroneAutoOutput } from './auto-output.ts';
4
4
  export { padroneColor } from './color.ts';
5
- export type { WithCompletion } from './completion.ts';
6
- export { padroneCompletion } from './completion.ts';
7
5
  export type { PadroneConfigOptions } from './config.ts';
8
6
  export { padroneConfig } from './config.ts';
9
7
  export type { PadroneEnvOptions } from './env.ts';
10
8
  export { padroneEnv } from './env.ts';
11
9
  export type { HelpCommand, WithHelp } from './help.ts';
12
10
  export { padroneHelp } from './help.ts';
13
- export type { InkOptions } from './ink.ts';
14
- export { isReactElement, padroneInk } from './ink.ts';
15
11
  export { padroneInteractive } from './interactive.ts';
16
12
  export type { PadroneLogger, PadroneLoggerConfig, PadroneLogLevel, WithLogger } from './logger.ts';
17
13
  export { padroneLogger } from './logger.ts';
18
- export type { WithMan } from './man.ts';
19
- export { padroneMan } from './man.ts';
20
- export type { WithMcp } from './mcp.ts';
21
- export { padroneMcp } from './mcp.ts';
22
14
  export type {
23
15
  PadroneProgressConfig,
24
16
  PadroneProgressDefaults,
@@ -31,15 +23,11 @@ export type { PadroneProgressRenderer } from './progress-renderer.ts';
31
23
  export { createTerminalProgress } from './progress-renderer.ts';
32
24
  export type { WithRepl } from './repl.ts';
33
25
  export { padroneRepl } from './repl.ts';
34
- export type { WithServe } from './serve.ts';
35
- export { padroneServe } from './serve.ts';
36
26
  export { padroneSignalHandling } from './signal.ts';
37
27
  export { padroneStdin } from './stdin.ts';
38
28
  export { padroneSuggestions } from './suggestions.ts';
39
29
  export type { PadroneTimingOptions } from './timing.ts';
40
30
  export { padroneTiming } from './timing.ts';
41
- export type { OtelSpan, OtelTracer, OtelTracerProvider, PadroneTracer, PadroneTracingConfig, WithTracing } from './tracing.ts';
42
- export { padroneTracing } from './tracing.ts';
43
31
  export { padroneUpdateCheck } from './update-check.ts';
44
32
  export type { VersionCommand, WithVersion } from './version.ts';
45
33
  export { padroneVersion } from './version.ts';
@@ -78,7 +78,8 @@ function createInkInterceptor(rawOptions?: InkOptions) {
78
78
  * Requires `ink` and `react` as peer dependencies.
79
79
  *
80
80
  * ```ts
81
- * import { createPadrone, padroneInk } from 'padrone';
81
+ * import { createPadrone } from 'padrone';
82
+ * import { padroneInk } from 'padrone/ink';
82
83
  *
83
84
  * const program = createPadrone('my-tui')
84
85
  * .extend(padroneInk())
@@ -20,6 +20,9 @@ export type WithMan<T> = WithCommand<T, 'man', ManCommand>;
20
20
  *
21
21
  * Usage:
22
22
  * ```ts
23
+ * import { createPadrone } from 'padrone';
24
+ * import { padroneMan } from 'padrone/man';
25
+ *
23
26
  * createPadrone('my-cli').extend(padroneMan())
24
27
  * ```
25
28
  */
@@ -21,6 +21,9 @@ export type WithMcp<T> = WithCommand<T, 'mcp', McpCommand>;
21
21
  *
22
22
  * Usage:
23
23
  * ```ts
24
+ * import { createPadrone } from 'padrone';
25
+ * import { padroneMcp } from 'padrone/mcp';
26
+ *
24
27
  * createPadrone('my-cli').extend(padroneMcp())
25
28
  * ```
26
29
  */
@@ -1,6 +1,6 @@
1
1
  import type {
2
2
  PadroneBarConfig,
3
- PadroneProgressIndicator,
3
+ PadroneProgress,
4
4
  PadroneProgressOptions,
5
5
  PadroneProgressShow,
6
6
  PadroneProgressUpdate,
@@ -134,8 +134,8 @@ function estimateEta(samples: { time: number; progress: number }[]): number | un
134
134
  // Factory type
135
135
  // ---------------------------------------------------------------------------
136
136
 
137
- /** Factory function that creates a `PadroneProgressIndicator`. */
138
- export type PadroneProgressRenderer = (message: string, options?: PadroneProgressOptions) => PadroneProgressIndicator;
137
+ /** Factory function that creates a `PadroneProgress`. */
138
+ export type PadroneProgressRenderer = (message: string, options?: PadroneProgressOptions) => PadroneProgress;
139
139
 
140
140
  // ---------------------------------------------------------------------------
141
141
  // Default terminal renderer
@@ -145,7 +145,7 @@ export type PadroneProgressRenderer = (message: string, options?: PadroneProgres
145
145
  * Creates a terminal progress indicator (spinner, bar, or both).
146
146
  * Returns a no-op indicator in non-TTY/CI environments.
147
147
  */
148
- export function createTerminalProgress(message: string, options?: PadroneProgressOptions): PadroneProgressIndicator {
148
+ export function createTerminalProgress(message: string, options?: PadroneProgressOptions): PadroneProgress {
149
149
  const spinnerCfg = resolveSpinnerConfig(options?.spinner);
150
150
  const successIcon = options?.successIndicator ?? '✔';
151
151
  const errorIcon = options?.errorIndicator ?? '✖';
@@ -154,8 +154,10 @@ export function createTerminalProgress(message: string, options?: PadroneProgres
154
154
  const formatFinal = (icon: string, msg: string) => (icon ? `${icon} ${msg}\n` : `${msg}\n`);
155
155
 
156
156
  if (typeof process === 'undefined' || !process.stderr?.isTTY) {
157
+ const noopEta = { start() {}, stop() {}, reset() {} };
157
158
  return {
158
159
  update() {},
160
+ eta: noopEta,
159
161
  succeed(msg, opts) {
160
162
  if (msg === null) return;
161
163
  const icon = opts?.indicator ?? successIcon;
@@ -176,11 +178,11 @@ export function createTerminalProgress(message: string, options?: PadroneProgres
176
178
  const ansiPattern = /\x1b\[[0-9;]*m/g;
177
179
 
178
180
  if (spinnerCfg.show === 'never' && (!barCfg || barCfg.show === 'never') && !message) {
179
- return { update() {}, succeed() {}, fail() {}, stop() {}, pause() {}, resume() {} };
181
+ return { update() {}, eta: { start() {}, stop() {}, reset() {} }, succeed() {}, fail() {}, stop() {}, pause() {}, resume() {} };
180
182
  }
181
183
 
182
184
  const showTime = options?.time ?? false;
183
- const showEta = options?.eta ?? false;
185
+ let etaEnabled = options?.eta ?? false;
184
186
 
185
187
  let spinnerFrame = 0;
186
188
  let barFrame = 0;
@@ -224,7 +226,7 @@ export function createTerminalProgress(message: string, options?: PadroneProgres
224
226
 
225
227
  let line = '';
226
228
  if (barVisible) line += formatBar(progress, barCfg!, barFrame);
227
- const hasEta = showEta && progress !== undefined && progress < 1 && etaMs !== undefined;
229
+ const hasEta = etaEnabled && progress !== undefined && progress < 1 && etaMs !== undefined;
228
230
  if (timeEnabled || hasEta) {
229
231
  const parts: string[] = [];
230
232
  if (timeEnabled) parts.push(`⏱ ${formatDuration(Date.now() - startTime)}`);
@@ -278,6 +280,27 @@ export function createTerminalProgress(message: string, options?: PadroneProgres
278
280
  clearLines();
279
281
  };
280
282
 
283
+ const eta = {
284
+ start() {
285
+ if (stopped) return;
286
+ etaEnabled = true;
287
+ render();
288
+ },
289
+ stop() {
290
+ if (stopped) return;
291
+ etaEnabled = false;
292
+ etaMs = undefined;
293
+ render();
294
+ },
295
+ reset() {
296
+ if (stopped) return;
297
+ etaSamples.length = 0;
298
+ etaMs = undefined;
299
+ etaCalculatedAt = 0;
300
+ render();
301
+ },
302
+ };
303
+
281
304
  return {
282
305
  update(value) {
283
306
  if (stopped) return;
@@ -285,7 +308,7 @@ export function createTerminalProgress(message: string, options?: PadroneProgres
285
308
  if (parsed.message !== undefined) text = parsed.message;
286
309
  if (parsed.progress !== undefined) {
287
310
  progress = parsed.progress;
288
- if (showEta) {
311
+ if (etaEnabled) {
289
312
  const now = Date.now();
290
313
  etaSamples.push({ time: now, progress: parsed.progress });
291
314
  const estimated = estimateEta(etaSamples);
@@ -309,6 +332,7 @@ export function createTerminalProgress(message: string, options?: PadroneProgres
309
332
  }
310
333
  render();
311
334
  },
335
+ eta,
312
336
  succeed(msg, opts) {
313
337
  clear();
314
338
  if (msg === null) return;