command-stream 0.8.2 → 0.9.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 (500) hide show
  1. package/js/examples/01-basic-streaming.mjs +14 -0
  2. package/js/examples/02-async-iterator.mjs +9 -0
  3. package/js/examples/03-file-and-console.mjs +16 -0
  4. package/js/examples/04-claude-jq-pipe.mjs +16 -0
  5. package/js/examples/CI-DEBUG-README.md +138 -0
  6. package/js/examples/README-examples.mjs +111 -0
  7. package/js/examples/README.md +345 -0
  8. package/js/examples/STREAMING_INTERFACES_SUMMARY.md +116 -0
  9. package/js/examples/add-test-timeouts.js +107 -0
  10. package/js/examples/ansi-default-preserved.mjs +11 -0
  11. package/js/examples/ansi-global-config.mjs +12 -0
  12. package/js/examples/ansi-reset-default.mjs +12 -0
  13. package/js/examples/ansi-strip-utils.mjs +12 -0
  14. package/js/examples/baseline-child-process.mjs +23 -0
  15. package/js/examples/baseline-claude-test.mjs +47 -0
  16. package/js/examples/baseline-working.mjs +34 -0
  17. package/js/examples/capture-mirror-comparison.mjs +23 -0
  18. package/js/examples/capture-mirror-default.mjs +11 -0
  19. package/js/examples/capture-mirror-performance.mjs +16 -0
  20. package/js/examples/capture-mirror-show-only.mjs +16 -0
  21. package/js/examples/capture-mirror-silent-processing.mjs +16 -0
  22. package/js/examples/ci-debug-baseline-vs-library.mjs +265 -0
  23. package/js/examples/ci-debug-es-module-loading.mjs +184 -0
  24. package/js/examples/ci-debug-signal-handling.mjs +225 -0
  25. package/js/examples/ci-debug-stdout-buffering.mjs +94 -0
  26. package/js/examples/ci-debug-test-timeouts.mjs +259 -0
  27. package/js/examples/claude-exact-file-output.mjs +20 -0
  28. package/js/examples/claude-exact-jq.mjs +13 -0
  29. package/js/examples/claude-exact-streaming.mjs +13 -0
  30. package/js/examples/claude-jq-pipeline.mjs +13 -0
  31. package/js/examples/claude-json-stream.mjs +39 -0
  32. package/js/examples/claude-streaming-basic.mjs +99 -0
  33. package/js/examples/claude-streaming-demo.mjs +126 -0
  34. package/js/examples/claude-streaming-final.mjs +20 -0
  35. package/js/examples/cleanup-verification-test.mjs +115 -0
  36. package/js/examples/colors-buffer-processing.mjs +14 -0
  37. package/js/examples/colors-default-preserved.mjs +15 -0
  38. package/js/examples/colors-per-command-config.mjs +15 -0
  39. package/js/examples/colors-strip-ansi.mjs +13 -0
  40. package/js/examples/commandstream-jq.mjs +29 -0
  41. package/js/examples/commandstream-working.mjs +23 -0
  42. package/js/examples/comprehensive-streams-demo.mjs +121 -0
  43. package/js/examples/ctrl-c-concurrent-processes.mjs +20 -0
  44. package/js/examples/ctrl-c-long-running-command.mjs +20 -0
  45. package/js/examples/ctrl-c-real-system-command.mjs +17 -0
  46. package/js/examples/ctrl-c-sleep-command.mjs +17 -0
  47. package/js/examples/ctrl-c-stdin-forwarding.mjs +20 -0
  48. package/js/examples/ctrl-c-virtual-command.mjs +17 -0
  49. package/js/examples/debug-already-started.mjs +20 -0
  50. package/js/examples/debug-ansi-processing.mjs +42 -0
  51. package/js/examples/debug-basic-streaming.mjs +44 -0
  52. package/js/examples/debug-buildshellcommand.mjs +82 -0
  53. package/js/examples/debug-child-process.mjs +43 -0
  54. package/js/examples/debug-child-state.mjs +55 -0
  55. package/js/examples/debug-chunking.mjs +38 -0
  56. package/js/examples/debug-command-parsing.mjs +61 -0
  57. package/js/examples/debug-complete-consolidation.mjs +97 -0
  58. package/js/examples/debug-echo-args.mjs +22 -0
  59. package/js/examples/debug-emit-timing.mjs +28 -0
  60. package/js/examples/debug-end-event.mjs +56 -0
  61. package/js/examples/debug-errexit.mjs +16 -0
  62. package/js/examples/debug-event-emission.mjs +40 -0
  63. package/js/examples/debug-event-timing.mjs +67 -0
  64. package/js/examples/debug-event-vs-result.mjs +30 -0
  65. package/js/examples/debug-exact-command.mjs +28 -0
  66. package/js/examples/debug-exact-test-scenario.mjs +44 -0
  67. package/js/examples/debug-execution-path.mjs +27 -0
  68. package/js/examples/debug-exit-command.mjs +38 -0
  69. package/js/examples/debug-exit-virtual.mjs +54 -0
  70. package/js/examples/debug-finish-consolidation.mjs +44 -0
  71. package/js/examples/debug-force-cleanup.mjs +47 -0
  72. package/js/examples/debug-getter-basic.mjs +13 -0
  73. package/js/examples/debug-getter-direct.mjs +23 -0
  74. package/js/examples/debug-getter-internals.mjs +61 -0
  75. package/js/examples/debug-handler-detection.mjs +65 -0
  76. package/js/examples/debug-idempotent-finish.mjs +54 -0
  77. package/js/examples/debug-idempotent-kill.mjs +58 -0
  78. package/js/examples/debug-interpolation-individual.mjs +88 -0
  79. package/js/examples/debug-interpolation-issue.mjs +101 -0
  80. package/js/examples/debug-jq-streaming.mjs +57 -0
  81. package/js/examples/debug-jq-tty-colors.mjs +168 -0
  82. package/js/examples/debug-kill-cleanup.mjs +56 -0
  83. package/js/examples/debug-kill-method.mjs +33 -0
  84. package/js/examples/debug-listener-interference.mjs +38 -0
  85. package/js/examples/debug-listener-lifecycle.mjs +50 -0
  86. package/js/examples/debug-listener-timing.mjs +62 -0
  87. package/js/examples/debug-listeners-property.mjs +34 -0
  88. package/js/examples/debug-map-methods.mjs +39 -0
  89. package/js/examples/debug-not-awaited-cleanup.mjs +106 -0
  90. package/js/examples/debug-off-method.mjs +28 -0
  91. package/js/examples/debug-option-merging.mjs +17 -0
  92. package/js/examples/debug-options.mjs +36 -0
  93. package/js/examples/debug-output.mjs +25 -0
  94. package/js/examples/debug-pattern-matching.mjs +69 -0
  95. package/js/examples/debug-pipeline-cat.mjs +28 -0
  96. package/js/examples/debug-pipeline-cleanup.mjs +71 -0
  97. package/js/examples/debug-pipeline-error-detailed.mjs +78 -0
  98. package/js/examples/debug-pipeline-error.mjs +65 -0
  99. package/js/examples/debug-pipeline-issue.mjs +26 -0
  100. package/js/examples/debug-pipeline-method.mjs +22 -0
  101. package/js/examples/debug-pipeline-stream.mjs +66 -0
  102. package/js/examples/debug-pipeline.mjs +14 -0
  103. package/js/examples/debug-process-exit-trace.mjs +41 -0
  104. package/js/examples/debug-process-path.mjs +38 -0
  105. package/js/examples/debug-property-check.mjs +29 -0
  106. package/js/examples/debug-resource-cleanup.mjs +83 -0
  107. package/js/examples/debug-shell-args.mjs +103 -0
  108. package/js/examples/debug-sigint-child-handler.mjs +44 -0
  109. package/js/examples/debug-sigint-forwarding.mjs +61 -0
  110. package/js/examples/debug-sigint-handler-install.mjs +79 -0
  111. package/js/examples/debug-sigint-handler-order.mjs +85 -0
  112. package/js/examples/debug-sigint-listeners.mjs +48 -0
  113. package/js/examples/debug-sigint-start-pattern.mjs +62 -0
  114. package/js/examples/debug-sigint-timer.mjs +40 -0
  115. package/js/examples/debug-simple-command.mjs +49 -0
  116. package/js/examples/debug-simple-getter.mjs +30 -0
  117. package/js/examples/debug-simple.mjs +39 -0
  118. package/js/examples/debug-simplified-finished.mjs +102 -0
  119. package/js/examples/debug-stack-overflow.mjs +25 -0
  120. package/js/examples/debug-stdin-simple.mjs +28 -0
  121. package/js/examples/debug-stdin.mjs +28 -0
  122. package/js/examples/debug-stream-emitter-isolated.mjs +45 -0
  123. package/js/examples/debug-stream-emitter.mjs +25 -0
  124. package/js/examples/debug-stream-events.mjs +70 -0
  125. package/js/examples/debug-stream-generator.mjs +23 -0
  126. package/js/examples/debug-stream-getter-issue.mjs +37 -0
  127. package/js/examples/debug-stream-getter.mjs +19 -0
  128. package/js/examples/debug-stream-internals.mjs +64 -0
  129. package/js/examples/debug-stream-method.mjs +46 -0
  130. package/js/examples/debug-stream-object.mjs +58 -0
  131. package/js/examples/debug-stream-properties.mjs +37 -0
  132. package/js/examples/debug-stream-timing.mjs +28 -0
  133. package/js/examples/debug-streaming.mjs +24 -0
  134. package/js/examples/debug-test-isolation.mjs +54 -0
  135. package/js/examples/debug-test-state.mjs +27 -0
  136. package/js/examples/debug-user-sigint.mjs +19 -0
  137. package/js/examples/debug-virtual-disable.mjs +21 -0
  138. package/js/examples/debug-virtual-vs-real.mjs +68 -0
  139. package/js/examples/debug-with-trace.mjs +23 -0
  140. package/js/examples/debug_parent_stream.mjs +22 -0
  141. package/js/examples/emulate-claude-stream.mjs +30 -0
  142. package/js/examples/emulated-streaming-direct.mjs +22 -0
  143. package/js/examples/emulated-streaming-jq-pipe.mjs +22 -0
  144. package/js/examples/emulated-streaming-sh-pipe.mjs +23 -0
  145. package/js/examples/events-build-process.mjs +73 -0
  146. package/js/examples/events-concurrent-streams.mjs +51 -0
  147. package/js/examples/events-error-handling.mjs +59 -0
  148. package/js/examples/events-file-monitoring.mjs +66 -0
  149. package/js/examples/events-interactive-simulation.mjs +69 -0
  150. package/js/examples/events-log-processing.mjs +72 -0
  151. package/js/examples/events-network-monitoring.mjs +68 -0
  152. package/js/examples/events-ping-basic.mjs +37 -0
  153. package/js/examples/events-progress-tracking.mjs +55 -0
  154. package/js/examples/events-stdin-input.mjs +34 -0
  155. package/js/examples/example-ansi-ls.mjs +39 -0
  156. package/js/examples/example-top.mjs +27 -0
  157. package/js/examples/final-ping-stdin-proof.mjs +88 -0
  158. package/js/examples/final-test-shell-operators.mjs +123 -0
  159. package/js/examples/final-working-examples.mjs +162 -0
  160. package/js/examples/gh-auth-test.mjs +103 -0
  161. package/js/examples/gh-delete-hang-test.mjs +79 -0
  162. package/js/examples/gh-gist-creation-test.mjs +276 -0
  163. package/js/examples/gh-gist-minimal-test.mjs +89 -0
  164. package/js/examples/gh-hang-exact-original.mjs +83 -0
  165. package/js/examples/gh-hang-reproduction.mjs +151 -0
  166. package/js/examples/gh-hang-test-with-redirect.mjs +45 -0
  167. package/js/examples/gh-hang-test-without-redirect.mjs +43 -0
  168. package/js/examples/gh-minimal-hang-check.mjs +33 -0
  169. package/js/examples/gh-operations-with-cd.mjs +187 -0
  170. package/js/examples/gh-output-test.mjs +102 -0
  171. package/js/examples/gh-reproduce-hang.mjs +41 -0
  172. package/js/examples/git-operations-with-cd.mjs +186 -0
  173. package/js/examples/interactive-math-calc.mjs +45 -0
  174. package/js/examples/interactive-top-fixed.mjs +25 -0
  175. package/js/examples/interactive-top-improved.mjs +72 -0
  176. package/js/examples/interactive-top-pty-logging.mjs +69 -0
  177. package/js/examples/interactive-top-pty.mjs +27 -0
  178. package/js/examples/interactive-top-with-logging.mjs +56 -0
  179. package/js/examples/interactive-top.mjs +29 -0
  180. package/js/examples/jq-color-demo.mjs +53 -0
  181. package/js/examples/jq-colors-streaming.mjs +42 -0
  182. package/js/examples/manual-ctrl-c-test.mjs +50 -0
  183. package/js/examples/methods-multiple-options.mjs +25 -0
  184. package/js/examples/methods-run-basic.mjs +10 -0
  185. package/js/examples/methods-start-basic.mjs +10 -0
  186. package/js/examples/node-compat-data-events.mjs +36 -0
  187. package/js/examples/node-compat-readable-event.mjs +29 -0
  188. package/js/examples/node-compat-small-buffer.mjs +33 -0
  189. package/js/examples/options-capture-false.mjs +12 -0
  190. package/js/examples/options-combined-settings.mjs +13 -0
  191. package/js/examples/options-custom-input.mjs +16 -0
  192. package/js/examples/options-default-behavior.mjs +10 -0
  193. package/js/examples/options-maximum-performance.mjs +15 -0
  194. package/js/examples/options-mirror-false.mjs +10 -0
  195. package/js/examples/options-performance-mode.mjs +13 -0
  196. package/js/examples/options-performance-optimization.mjs +14 -0
  197. package/js/examples/options-run-alias-demo.mjs +15 -0
  198. package/js/examples/options-run-alias.mjs +10 -0
  199. package/js/examples/options-silent-execution.mjs +14 -0
  200. package/js/examples/options-streaming-capture.mjs +24 -0
  201. package/js/examples/options-streaming-multiple.mjs +35 -0
  202. package/js/examples/options-streaming-silent.mjs +21 -0
  203. package/js/examples/options-streaming-stdin.mjs +21 -0
  204. package/js/examples/ping-streaming-filtered.mjs +22 -0
  205. package/js/examples/ping-streaming-interruptible.mjs +47 -0
  206. package/js/examples/ping-streaming-silent.mjs +24 -0
  207. package/js/examples/ping-streaming-simple.mjs +13 -0
  208. package/js/examples/ping-streaming-statistics.mjs +49 -0
  209. package/js/examples/ping-streaming-timestamps.mjs +22 -0
  210. package/js/examples/ping-streaming.mjs +48 -0
  211. package/js/examples/prove-ping-stdin-limitation.mjs +94 -0
  212. package/js/examples/readme-example.mjs +39 -0
  213. package/js/examples/realtime-json-stream.mjs +143 -0
  214. package/js/examples/reliable-stdin-commands.mjs +135 -0
  215. package/js/examples/reproduce-issue-135-v2.mjs +15 -0
  216. package/js/examples/reproduce-issue-135.mjs +17 -0
  217. package/js/examples/shell-cd-behavior.mjs +88 -0
  218. package/js/examples/sigint-forwarding-test.mjs +60 -0
  219. package/js/examples/sigint-handler-test.mjs +72 -0
  220. package/js/examples/simple-async-test.mjs +49 -0
  221. package/js/examples/simple-claude-test.mjs +17 -0
  222. package/js/examples/simple-event-test.mjs +33 -0
  223. package/js/examples/simple-jq-streaming.mjs +48 -0
  224. package/js/examples/simple-stream-demo.mjs +35 -0
  225. package/js/examples/simple-test-sleep.js +30 -0
  226. package/js/examples/simple-working-stdin.mjs +30 -0
  227. package/js/examples/streaming-behavior-test.mjs +116 -0
  228. package/js/examples/streaming-direct-command.mjs +21 -0
  229. package/js/examples/streaming-filtered-output.mjs +33 -0
  230. package/js/examples/streaming-grep-pipeline.mjs +21 -0
  231. package/js/examples/streaming-interactive-stdin.mjs +24 -0
  232. package/js/examples/streaming-jq-pipeline.mjs +23 -0
  233. package/js/examples/streaming-multistage-pipeline.mjs +23 -0
  234. package/js/examples/streaming-pipes-event-pattern.mjs +27 -0
  235. package/js/examples/streaming-pipes-multistage.mjs +22 -0
  236. package/js/examples/streaming-pipes-realtime-jq.mjs +23 -0
  237. package/js/examples/streaming-progress-tracking.mjs +34 -0
  238. package/js/examples/streaming-reusable-configs.mjs +52 -0
  239. package/js/examples/streaming-silent-capture.mjs +20 -0
  240. package/js/examples/streaming-test-simple.mjs +70 -0
  241. package/js/examples/streaming-virtual-pipeline.mjs +18 -0
  242. package/js/examples/syntax-basic-comparison.mjs +31 -0
  243. package/js/examples/syntax-basic-options.mjs +12 -0
  244. package/js/examples/syntax-combined-options.mjs +19 -0
  245. package/js/examples/syntax-command-chaining.mjs +12 -0
  246. package/js/examples/syntax-custom-directory.mjs +10 -0
  247. package/js/examples/syntax-custom-environment.mjs +13 -0
  248. package/js/examples/syntax-custom-stdin.mjs +10 -0
  249. package/js/examples/syntax-mixed-regular.mjs +11 -0
  250. package/js/examples/syntax-mixed-usage.mjs +15 -0
  251. package/js/examples/syntax-multiple-listeners.mjs +87 -0
  252. package/js/examples/syntax-piping-comparison.mjs +32 -0
  253. package/js/examples/syntax-reusable-config.mjs +16 -0
  254. package/js/examples/syntax-reusable-configs.mjs +21 -0
  255. package/js/examples/syntax-silent-operations.mjs +10 -0
  256. package/js/examples/syntax-stdin-option.mjs +12 -0
  257. package/js/examples/temp-sigint-test.mjs +21 -0
  258. package/js/examples/test-actual-buildshell.mjs +44 -0
  259. package/js/examples/test-async-streams-working.mjs +102 -0
  260. package/js/examples/test-async-streams.mjs +90 -0
  261. package/js/examples/test-auth-parse.mjs +74 -0
  262. package/js/examples/test-auto-quoting.mjs +57 -0
  263. package/js/examples/test-auto-start-fix.mjs +95 -0
  264. package/js/examples/test-baseline-sigint.mjs +38 -0
  265. package/js/examples/test-buffer-behavior.mjs +39 -0
  266. package/js/examples/test-buffers-simple.mjs +35 -0
  267. package/js/examples/test-bun-specific-issue.mjs +106 -0
  268. package/js/examples/test-bun-streaming.mjs +81 -0
  269. package/js/examples/test-cat-direct.mjs +41 -0
  270. package/js/examples/test-cat-pipe.mjs +34 -0
  271. package/js/examples/test-cd-behavior.mjs +42 -0
  272. package/js/examples/test-child-process-timing.mjs +53 -0
  273. package/js/examples/test-child-sigint-handler.mjs +62 -0
  274. package/js/examples/test-cleanup-simple.mjs +21 -0
  275. package/js/examples/test-comprehensive-tracing.mjs +58 -0
  276. package/js/examples/test-correct-space-handling.mjs +46 -0
  277. package/js/examples/test-ctrl-c-debug.mjs +44 -0
  278. package/js/examples/test-ctrl-c-inherit.mjs +30 -0
  279. package/js/examples/test-ctrl-c-sleep.mjs +31 -0
  280. package/js/examples/test-ctrl-c.mjs +17 -0
  281. package/js/examples/test-debug-new-options.mjs +55 -0
  282. package/js/examples/test-debug-pty.mjs +49 -0
  283. package/js/examples/test-debug-tee.mjs +38 -0
  284. package/js/examples/test-debug.mjs +25 -0
  285. package/js/examples/test-direct-jq.mjs +47 -0
  286. package/js/examples/test-direct-pipe-reading.mjs +119 -0
  287. package/js/examples/test-direct-pipe.sh +28 -0
  288. package/js/examples/test-double-quoting-prevention.mjs +138 -0
  289. package/js/examples/test-edge-cases-quoting.mjs +89 -0
  290. package/js/examples/test-events.mjs +37 -0
  291. package/js/examples/test-explicit-stdio.mjs +51 -0
  292. package/js/examples/test-final-streaming.mjs +71 -0
  293. package/js/examples/test-fix.mjs +71 -0
  294. package/js/examples/test-incremental-streaming.mjs +46 -0
  295. package/js/examples/test-individual-spawn.mjs +35 -0
  296. package/js/examples/test-inherit-stdout-not-stdin.mjs +133 -0
  297. package/js/examples/test-injection-protection.mjs +77 -0
  298. package/js/examples/test-interactive-streaming.mjs +140 -0
  299. package/js/examples/test-interactive-top.md +24 -0
  300. package/js/examples/test-interactive.mjs +17 -0
  301. package/js/examples/test-interpolation.mjs +14 -0
  302. package/js/examples/test-interrupt.mjs +40 -0
  303. package/js/examples/test-issue-135-comprehensive.mjs +41 -0
  304. package/js/examples/test-issue12-detailed.mjs +89 -0
  305. package/js/examples/test-issue12-exact.mjs +33 -0
  306. package/js/examples/test-jq-color.mjs +57 -0
  307. package/js/examples/test-jq-colors.mjs +41 -0
  308. package/js/examples/test-jq-compact.mjs +33 -0
  309. package/js/examples/test-jq-native.sh +10 -0
  310. package/js/examples/test-jq-pipeline-behavior.mjs +80 -0
  311. package/js/examples/test-jq-realtime.mjs +40 -0
  312. package/js/examples/test-manual-start.mjs +54 -0
  313. package/js/examples/test-mixed-quoting.mjs +88 -0
  314. package/js/examples/test-multi-stream.mjs +50 -0
  315. package/js/examples/test-multistage-debug.mjs +44 -0
  316. package/js/examples/test-native-spawn-vs-command-stream.mjs +154 -0
  317. package/js/examples/test-no-parse-pipeline.mjs +33 -0
  318. package/js/examples/test-non-virtual.mjs +52 -0
  319. package/js/examples/test-operators.mjs +53 -0
  320. package/js/examples/test-parent-continues.mjs +44 -0
  321. package/js/examples/test-path-interpolation.mjs +86 -0
  322. package/js/examples/test-ping-kill-and-stdin.mjs +98 -0
  323. package/js/examples/test-ping.mjs +12 -0
  324. package/js/examples/test-pty-spawn.mjs +101 -0
  325. package/js/examples/test-pty.mjs +38 -0
  326. package/js/examples/test-quote-behavior-summary.mjs +110 -0
  327. package/js/examples/test-quote-edge-cases.mjs +69 -0
  328. package/js/examples/test-quote-parsing.mjs +23 -0
  329. package/js/examples/test-raw-function.mjs +153 -0
  330. package/js/examples/test-raw-streaming.mjs +47 -0
  331. package/js/examples/test-readme-examples.mjs +142 -0
  332. package/js/examples/test-real-cat.mjs +28 -0
  333. package/js/examples/test-real-commands.mjs +21 -0
  334. package/js/examples/test-real-shell.mjs +31 -0
  335. package/js/examples/test-real-stdin-commands.mjs +160 -0
  336. package/js/examples/test-runner-batched.mjs +98 -0
  337. package/js/examples/test-runner-simple.mjs +80 -0
  338. package/js/examples/test-runner.mjs +67 -0
  339. package/js/examples/test-scope-parse.mjs +31 -0
  340. package/js/examples/test-sh-pipeline.mjs +24 -0
  341. package/js/examples/test-shell-detection.mjs +71 -0
  342. package/js/examples/test-shell-parser.mjs +37 -0
  343. package/js/examples/test-sigint-behavior.mjs +241 -0
  344. package/js/examples/test-sigint-handling.sh +14 -0
  345. package/js/examples/test-simple-pipe.mjs +12 -0
  346. package/js/examples/test-simple-streaming.mjs +32 -0
  347. package/js/examples/test-sleep-stdin.js +27 -0
  348. package/js/examples/test-sleep.mjs +56 -0
  349. package/js/examples/test-smart-quoting.mjs +180 -0
  350. package/js/examples/test-spaces-in-path.mjs +48 -0
  351. package/js/examples/test-special-chars-quoting.mjs +54 -0
  352. package/js/examples/test-stdin-after-start.mjs +39 -0
  353. package/js/examples/test-stdin-simple.mjs +67 -0
  354. package/js/examples/test-stdin-timing.mjs +74 -0
  355. package/js/examples/test-stdio-combinations.mjs +124 -0
  356. package/js/examples/test-stream-access.mjs +84 -0
  357. package/js/examples/test-stream-cleanup.mjs +27 -0
  358. package/js/examples/test-stream-readers.mjs +152 -0
  359. package/js/examples/test-streaming-final.mjs +57 -0
  360. package/js/examples/test-streaming-interfaces.mjs +141 -0
  361. package/js/examples/test-streaming-timing.mjs +27 -0
  362. package/js/examples/test-streaming.mjs +32 -0
  363. package/js/examples/test-streams-stdin-comprehensive.mjs +134 -0
  364. package/js/examples/test-streams-stdin-ctrl-c.mjs +96 -0
  365. package/js/examples/test-template-literal.mjs +26 -0
  366. package/js/examples/test-template-vs-interpolation.mjs +49 -0
  367. package/js/examples/test-timing.mjs +41 -0
  368. package/js/examples/test-top-inherit-stdout-stdin-control.mjs +123 -0
  369. package/js/examples/test-top-quit-stdin.mjs +118 -0
  370. package/js/examples/test-trace-option.mjs +21 -0
  371. package/js/examples/test-user-double-quotes.mjs +36 -0
  372. package/js/examples/test-user-single-quotes.mjs +36 -0
  373. package/js/examples/test-verbose.mjs +18 -0
  374. package/js/examples/test-verbose2.mjs +32 -0
  375. package/js/examples/test-virtual-streaming.mjs +125 -0
  376. package/js/examples/test-waiting-command.mjs +52 -0
  377. package/js/examples/test-waiting-commands.mjs +83 -0
  378. package/js/examples/test-watch-mode.mjs +104 -0
  379. package/js/examples/test-yes-cancellation.mjs +26 -0
  380. package/js/examples/test-yes-detailed.mjs +58 -0
  381. package/js/examples/test-yes-trace.mjs +28 -0
  382. package/js/examples/trace-abort-controller.mjs +30 -0
  383. package/js/examples/trace-error-handling.mjs +22 -0
  384. package/js/examples/trace-pipeline-command.mjs +22 -0
  385. package/js/examples/trace-signal-handling.mjs +35 -0
  386. package/js/examples/trace-simple-command.mjs +18 -0
  387. package/js/examples/trace-stderr-output.mjs +22 -0
  388. package/js/examples/verify-fix-both-runtimes.mjs +73 -0
  389. package/js/examples/verify-issue12-fixed.mjs +78 -0
  390. package/js/examples/which-command-common-commands.mjs +19 -0
  391. package/js/examples/which-command-gh-test.mjs +23 -0
  392. package/js/examples/which-command-nonexistent.mjs +20 -0
  393. package/js/examples/which-command-system-comparison.mjs +28 -0
  394. package/js/examples/working-example.mjs +13 -0
  395. package/js/examples/working-stdin-examples.mjs +138 -0
  396. package/js/examples/working-streaming-demo.mjs +49 -0
  397. package/{src → js/src}/$.mjs +20 -4
  398. package/{src → js/src}/$.utils.mjs +14 -2
  399. package/js/tests/$.features.test.mjs +283 -0
  400. package/js/tests/$.test.mjs +935 -0
  401. package/js/tests/builtin-commands.test.mjs +387 -0
  402. package/js/tests/bun-shell-path-fix.test.mjs +115 -0
  403. package/js/tests/bun.features.test.mjs +189 -0
  404. package/js/tests/cd-virtual-command.test.mjs +622 -0
  405. package/js/tests/cleanup-verification.test.mjs +127 -0
  406. package/js/tests/ctrl-c-baseline.test.mjs +207 -0
  407. package/js/tests/ctrl-c-basic.test.mjs +220 -0
  408. package/js/tests/ctrl-c-library.test.mjs +197 -0
  409. package/js/tests/ctrl-c-signal.test.mjs +915 -0
  410. package/js/tests/examples.test.mjs +252 -0
  411. package/js/tests/execa.features.test.mjs +198 -0
  412. package/js/tests/gh-commands.test.mjs +164 -0
  413. package/js/tests/gh-gist-operations.test.mjs +221 -0
  414. package/js/tests/git-gh-cd.test.mjs +466 -0
  415. package/js/tests/interactive-option.test.mjs +114 -0
  416. package/js/tests/interactive-streaming.test.mjs +307 -0
  417. package/js/tests/issue-135-final.test.mjs +58 -0
  418. package/js/tests/jq-color-behavior.test.mjs +140 -0
  419. package/js/tests/jq.test.mjs +318 -0
  420. package/js/tests/options-examples.test.mjs +106 -0
  421. package/js/tests/options-syntax.test.mjs +112 -0
  422. package/js/tests/path-interpolation.test.mjs +412 -0
  423. package/js/tests/pipe.test.mjs +291 -0
  424. package/js/tests/raw-function.test.mjs +266 -0
  425. package/js/tests/readme-examples.test.mjs +427 -0
  426. package/js/tests/resource-cleanup-internals.test.mjs +669 -0
  427. package/js/tests/shell-settings.test.mjs +279 -0
  428. package/js/tests/sigint-cleanup-isolated.test.mjs +151 -0
  429. package/js/tests/sigint-cleanup.test.mjs +118 -0
  430. package/js/tests/start-run-edge-cases.test.mjs +152 -0
  431. package/js/tests/start-run-options.test.mjs +181 -0
  432. package/js/tests/stderr-output-handling.test.mjs +279 -0
  433. package/js/tests/streaming-interfaces.test.mjs +194 -0
  434. package/js/tests/sync.test.mjs +297 -0
  435. package/js/tests/system-pipe.test.mjs +226 -0
  436. package/js/tests/test-cleanup.mjs +200 -0
  437. package/js/tests/test-helper-fixed.mjs +148 -0
  438. package/js/tests/test-helper-v2.mjs +118 -0
  439. package/js/tests/test-helper.mjs +171 -0
  440. package/js/tests/test-sigint-child.js +15 -0
  441. package/js/tests/text-method.test.mjs +225 -0
  442. package/js/tests/virtual.test.mjs +364 -0
  443. package/js/tests/yes-command-cleanup.test.mjs +208 -0
  444. package/js/tests/zx.features.test.mjs +233 -0
  445. package/package.json +13 -12
  446. package/rust/Cargo.lock +947 -0
  447. package/rust/Cargo.toml +47 -0
  448. package/rust/src/commands/basename.rs +69 -0
  449. package/rust/src/commands/cat.rs +123 -0
  450. package/rust/src/commands/cd.rs +67 -0
  451. package/rust/src/commands/cp.rs +187 -0
  452. package/rust/src/commands/dirname.rs +57 -0
  453. package/rust/src/commands/echo.rs +73 -0
  454. package/rust/src/commands/env.rs +33 -0
  455. package/rust/src/commands/exit.rs +36 -0
  456. package/rust/src/commands/false.rs +24 -0
  457. package/rust/src/commands/ls.rs +182 -0
  458. package/rust/src/commands/mkdir.rs +98 -0
  459. package/rust/src/commands/mod.rs +200 -0
  460. package/rust/src/commands/mv.rs +180 -0
  461. package/rust/src/commands/pwd.rs +28 -0
  462. package/rust/src/commands/rm.rs +150 -0
  463. package/rust/src/commands/seq.rs +179 -0
  464. package/rust/src/commands/sleep.rs +97 -0
  465. package/rust/src/commands/test.rs +204 -0
  466. package/rust/src/commands/touch.rs +99 -0
  467. package/rust/src/commands/true.rs +24 -0
  468. package/rust/src/commands/which.rs +87 -0
  469. package/rust/src/commands/yes.rs +99 -0
  470. package/rust/src/lib.rs +492 -0
  471. package/rust/src/main.rs +37 -0
  472. package/rust/src/shell_parser.rs +565 -0
  473. package/rust/src/utils.rs +335 -0
  474. package/rust/tests/builtin_commands.rs +549 -0
  475. package/rust/tests/process_runner.rs +286 -0
  476. package/rust/tests/shell_parser.rs +296 -0
  477. package/rust/tests/utils.rs +282 -0
  478. package/rust/tests/virtual_commands.rs +199 -0
  479. /package/{src → js/src}/commands/$.basename.mjs +0 -0
  480. /package/{src → js/src}/commands/$.cat.mjs +0 -0
  481. /package/{src → js/src}/commands/$.cd.mjs +0 -0
  482. /package/{src → js/src}/commands/$.cp.mjs +0 -0
  483. /package/{src → js/src}/commands/$.dirname.mjs +0 -0
  484. /package/{src → js/src}/commands/$.echo.mjs +0 -0
  485. /package/{src → js/src}/commands/$.env.mjs +0 -0
  486. /package/{src → js/src}/commands/$.exit.mjs +0 -0
  487. /package/{src → js/src}/commands/$.false.mjs +0 -0
  488. /package/{src → js/src}/commands/$.ls.mjs +0 -0
  489. /package/{src → js/src}/commands/$.mkdir.mjs +0 -0
  490. /package/{src → js/src}/commands/$.mv.mjs +0 -0
  491. /package/{src → js/src}/commands/$.pwd.mjs +0 -0
  492. /package/{src → js/src}/commands/$.rm.mjs +0 -0
  493. /package/{src → js/src}/commands/$.seq.mjs +0 -0
  494. /package/{src → js/src}/commands/$.sleep.mjs +0 -0
  495. /package/{src → js/src}/commands/$.test.mjs +0 -0
  496. /package/{src → js/src}/commands/$.touch.mjs +0 -0
  497. /package/{src → js/src}/commands/$.true.mjs +0 -0
  498. /package/{src → js/src}/commands/$.which.mjs +0 -0
  499. /package/{src → js/src}/commands/$.yes.mjs +0 -0
  500. /package/{src → js/src}/shell-parser.mjs +0 -0
@@ -0,0 +1,318 @@
1
+ import { $ } from '../src/$.mjs';
2
+ import { trace } from '../src/$.utils.mjs';
3
+ import { describe, test, expect } from 'bun:test';
4
+ import './test-helper.mjs'; // Automatically sets up beforeEach/afterEach cleanup
5
+
6
+ // Platform detection - These tests use Unix shell commands (sh, printf)
7
+ const isWindows = process.platform === 'win32';
8
+
9
+ // Skip on Windows - uses printf and jq (Unix utilities)
10
+ describe.skipIf(isWindows)('jq streaming tests', () => {
11
+ test('stream of JSON objects through jq -c', async () => {
12
+ // Generate a stream of JSON objects using printf
13
+ const result =
14
+ await $`printf '{"id":1,"name":"Alice"}\n{"id":2,"name":"Bob"}\n{"id":3,"name":"Charlie"}\n'`.pipe(
15
+ $`jq -c .`
16
+ );
17
+
18
+ // Each object should be on its own line in compact format
19
+ const lines = result.stdout.trim().split('\n');
20
+ expect(lines).toHaveLength(3);
21
+ expect(lines[0]).toBe('{"id":1,"name":"Alice"}');
22
+ expect(lines[1]).toBe('{"id":2,"name":"Bob"}');
23
+ expect(lines[2]).toBe('{"id":3,"name":"Charlie"}');
24
+ });
25
+
26
+ test('stream JSON objects with filtering through jq', async () => {
27
+ // Generate stream and filter for id > 1
28
+ const result =
29
+ await $`printf '{"id":1,"value":10}\n{"id":2,"value":20}\n{"id":3,"value":30}\n'`.pipe(
30
+ $`jq -c 'select(.id > 1)'`
31
+ );
32
+
33
+ const lines = result.stdout.trim().split('\n');
34
+ expect(lines).toHaveLength(2);
35
+ expect(JSON.parse(lines[0])).toEqual({ id: 2, value: 20 });
36
+ expect(JSON.parse(lines[1])).toEqual({ id: 3, value: 30 });
37
+ });
38
+
39
+ test('generate JSON stream using echo in loop', async () => {
40
+ // Generate JSON objects using a loop
41
+ const result =
42
+ await $`sh -c 'for i in 1 2 3; do echo "{\\"index\\":$i,\\"squared\\":$((i*i))}"; done'`.pipe(
43
+ $`jq -c .`
44
+ );
45
+
46
+ const lines = result.stdout.trim().split('\n');
47
+ expect(lines).toHaveLength(3);
48
+ expect(JSON.parse(lines[0])).toEqual({ index: 1, squared: 1 });
49
+ expect(JSON.parse(lines[1])).toEqual({ index: 2, squared: 4 });
50
+ expect(JSON.parse(lines[2])).toEqual({ index: 3, squared: 9 });
51
+ });
52
+
53
+ test('transform JSON stream with jq', async () => {
54
+ // Generate stream and transform each object
55
+ const result =
56
+ await $`printf '{"name":"Alice","age":30}\n{"name":"Bob","age":25}\n'`.pipe(
57
+ $`jq -c '{user: .name, years: .age}'`
58
+ );
59
+
60
+ const lines = result.stdout.trim().split('\n');
61
+ expect(lines).toHaveLength(2);
62
+ expect(JSON.parse(lines[0])).toEqual({ user: 'Alice', years: 30 });
63
+ expect(JSON.parse(lines[1])).toEqual({ user: 'Bob', years: 25 });
64
+ });
65
+
66
+ test('generate and process array elements as stream', async () => {
67
+ // Generate an array and convert to stream of objects
68
+ const result = await $`echo '[{"x":1},{"x":2},{"x":3}]'`.pipe(
69
+ $`jq -c '.[]'`
70
+ );
71
+
72
+ const lines = result.stdout.trim().split('\n');
73
+ expect(lines).toHaveLength(3);
74
+ expect(lines[0]).toBe('{"x":1}');
75
+ expect(lines[1]).toBe('{"x":2}');
76
+ expect(lines[2]).toBe('{"x":3}');
77
+ });
78
+
79
+ test('combine multiple JSON sources into stream', async () => {
80
+ // Combine multiple echo commands into a single stream
81
+ const result =
82
+ await $`sh -c 'echo "{\\"source\\":\\"A\\",\\"data\\":100}"; echo "{\\"source\\":\\"B\\",\\"data\\":200}"'`.pipe(
83
+ $`jq -c .`
84
+ );
85
+
86
+ const lines = result.stdout.trim().split('\n');
87
+ expect(lines).toHaveLength(2);
88
+ expect(JSON.parse(lines[0])).toEqual({ source: 'A', data: 100 });
89
+ expect(JSON.parse(lines[1])).toEqual({ source: 'B', data: 200 });
90
+ });
91
+ });
92
+
93
+ // Skip on Windows - uses printf and jq (Unix utilities)
94
+ describe.skipIf(isWindows)('jq streaming with pipe | syntax', () => {
95
+ test('stream of JSON objects through jq -c using pipe syntax', async () => {
96
+ // Generate a stream of JSON objects using printf with pipe syntax
97
+ const result =
98
+ await $`printf '{"id":1,"name":"Alice"}\n{"id":2,"name":"Bob"}\n{"id":3,"name":"Charlie"}\n' | jq -c .`;
99
+
100
+ // Each object should be on its own line in compact format
101
+ const lines = result.stdout.trim().split('\n');
102
+ expect(lines).toHaveLength(3);
103
+ expect(lines[0]).toBe('{"id":1,"name":"Alice"}');
104
+ expect(lines[1]).toBe('{"id":2,"name":"Bob"}');
105
+ expect(lines[2]).toBe('{"id":3,"name":"Charlie"}');
106
+ });
107
+
108
+ test('stream JSON with filtering using pipe syntax', async () => {
109
+ // Generate stream and filter for value > 15
110
+ const result =
111
+ await $`printf '{"id":1,"value":10}\n{"id":2,"value":20}\n{"id":3,"value":30}\n' | jq -c 'select(.value > 15)'`;
112
+
113
+ const lines = result.stdout.trim().split('\n');
114
+ expect(lines).toHaveLength(2);
115
+ expect(JSON.parse(lines[0])).toEqual({ id: 2, value: 20 });
116
+ expect(JSON.parse(lines[1])).toEqual({ id: 3, value: 30 });
117
+ });
118
+
119
+ test('transform JSON stream with jq using pipe syntax', async () => {
120
+ // Generate stream and transform each object
121
+ const result =
122
+ await $`printf '{"name":"Alice","age":30}\n{"name":"Bob","age":25}\n' | jq -c '{user: .name, years: .age}'`;
123
+
124
+ const lines = result.stdout.trim().split('\n');
125
+ expect(lines).toHaveLength(2);
126
+ expect(JSON.parse(lines[0])).toEqual({ user: 'Alice', years: 30 });
127
+ expect(JSON.parse(lines[1])).toEqual({ user: 'Bob', years: 25 });
128
+ });
129
+
130
+ test('process array elements as stream using pipe syntax', async () => {
131
+ // Generate an array and convert to stream of objects
132
+ const result = await $`echo '[{"x":1},{"x":2},{"x":3}]' | jq -c '.[]'`;
133
+
134
+ const lines = result.stdout.trim().split('\n');
135
+ expect(lines).toHaveLength(3);
136
+ expect(lines[0]).toBe('{"x":1}');
137
+ expect(lines[1]).toBe('{"x":2}');
138
+ expect(lines[2]).toBe('{"x":3}');
139
+ });
140
+
141
+ test('multi-pipe JSON processing', async () => {
142
+ // Use multiple pipes to process JSON
143
+ const result =
144
+ await $`echo '[{"name":"alice","score":95},{"name":"bob","score":87},{"name":"charlie","score":92}]' | jq -c '.[]' | jq -c 'select(.score > 90)'`;
145
+
146
+ const lines = result.stdout.trim().split('\n');
147
+ expect(lines).toHaveLength(2);
148
+ expect(JSON.parse(lines[0])).toEqual({ name: 'alice', score: 95 });
149
+ expect(JSON.parse(lines[1])).toEqual({ name: 'charlie', score: 92 });
150
+ });
151
+
152
+ test('complex JSON stream manipulation with pipes', async () => {
153
+ // Multiple transformations in a pipeline
154
+ const result =
155
+ await $`printf '{"user":"alice","points":100}\n{"user":"bob","points":150}\n{"user":"charlie","points":75}\n' | jq -c 'select(.points >= 100)' | jq -c '{name: .user, level: (if .points >= 150 then "gold" else "silver" end)}'`;
156
+
157
+ const lines = result.stdout.trim().split('\n');
158
+ expect(lines).toHaveLength(2);
159
+ expect(JSON.parse(lines[0])).toEqual({ name: 'alice', level: 'silver' });
160
+ expect(JSON.parse(lines[1])).toEqual({ name: 'bob', level: 'gold' });
161
+ });
162
+ });
163
+
164
+ // Skip on Windows - uses sh -c and Unix utilities
165
+ describe.skipIf(isWindows)('realtime JSON streaming with delays', () => {
166
+ test('stream JSON with random delays between outputs', async () => {
167
+ // Simulate realtime stream with random delays between 0.01 and 0.05 seconds
168
+ const result =
169
+ await $`sh -c 'for i in 1 2 3 4 5; do echo "{\\"timestamp\\":$(date +%s),\\"event\\":\\"event$i\\",\\"value\\":$((i * 10))}"; sleep 0.0$((RANDOM % 5 + 1)); done' | jq -c .`;
170
+
171
+ const lines = result.stdout.trim().split('\n');
172
+ expect(lines).toHaveLength(5);
173
+
174
+ // Verify each JSON object is valid and has expected structure
175
+ for (let i = 0; i < 5; i++) {
176
+ const obj = JSON.parse(lines[i]);
177
+ expect(obj).toHaveProperty('timestamp');
178
+ expect(obj).toHaveProperty('event');
179
+ expect(obj).toHaveProperty('value');
180
+ expect(obj.event).toBe(`event${i + 1}`);
181
+ expect(obj.value).toBe((i + 1) * 10);
182
+ }
183
+ });
184
+
185
+ test('stream JSON with fixed delays using printf and sleep', async () => {
186
+ // Use printf and sleep to simulate delayed streaming
187
+ const result =
188
+ await $`sh -c 'for i in 1 2 3; do printf "{\\"id\\":%d,\\"time\\":\\"now\\"}\\n" $i; sleep 0.01; done' | jq -c .`;
189
+
190
+ const lines = result.stdout.trim().split('\n');
191
+ expect(lines).toHaveLength(3);
192
+ expect(JSON.parse(lines[0])).toEqual({ id: 1, time: 'now' });
193
+ expect(JSON.parse(lines[1])).toEqual({ id: 2, time: 'now' });
194
+ expect(JSON.parse(lines[2])).toEqual({ id: 3, time: 'now' });
195
+ });
196
+
197
+ test('simulate server logs with delayed JSON output', async () => {
198
+ // Simulate server logs that arrive at different intervals
199
+ const result =
200
+ await $`sh -c 'echo "{\\"level\\":\\"info\\",\\"msg\\":\\"Server starting\\",\\"port\\":3000}"; sleep 0.02; echo "{\\"level\\":\\"debug\\",\\"msg\\":\\"Database connected\\",\\"host\\":\\"localhost\\"}"; sleep 0.03; echo "{\\"level\\":\\"info\\",\\"msg\\":\\"Server ready\\",\\"status\\":\\"listening\\"}"; sleep 0.01; echo "{\\"level\\":\\"warn\\",\\"msg\\":\\"High memory usage\\",\\"usage\\":85}"' | jq -c 'select(.level != "debug")'`;
201
+
202
+ const lines = result.stdout.trim().split('\n');
203
+ expect(lines).toHaveLength(3); // Should filter out debug message
204
+
205
+ const logs = lines.map((line) => JSON.parse(line));
206
+ expect(logs[0]).toMatchObject({ level: 'info', msg: 'Server starting' });
207
+ expect(logs[1]).toMatchObject({ level: 'info', msg: 'Server ready' });
208
+ expect(logs[2]).toMatchObject({ level: 'warn', msg: 'High memory usage' });
209
+ });
210
+
211
+ test('process streaming metrics with delays and aggregation', async () => {
212
+ // Simulate streaming metrics that arrive over time
213
+ const result =
214
+ await $`sh -c 'for i in 1 2 3 4 5; do echo "{\\"metric\\":\\"cpu\\",\\"value\\":$((50 + i * 5)),\\"host\\":\\"server$i\\"}"; sleep 0.015; done' | jq -c 'select(.value > 60)'`;
215
+
216
+ const lines = result.stdout.trim().split('\n');
217
+ expect(lines).toHaveLength(3); // Only values > 60 (65, 70, 75)
218
+
219
+ const metrics = lines.map((line) => JSON.parse(line));
220
+ expect(metrics[0].value).toBe(65);
221
+ expect(metrics[1].value).toBe(70);
222
+ expect(metrics[2].value).toBe(75);
223
+ });
224
+
225
+ test('handle burst then delay pattern', async () => {
226
+ // Simulate burst of messages followed by delays
227
+ const result =
228
+ await $`sh -c 'echo "{\\"batch\\":1,\\"msg\\":\\"burst1\\"}"; echo "{\\"batch\\":1,\\"msg\\":\\"burst2\\"}"; echo "{\\"batch\\":1,\\"msg\\":\\"burst3\\"}"; sleep 0.05; echo "{\\"batch\\":2,\\"msg\\":\\"burst4\\"}"; echo "{\\"batch\\":2,\\"msg\\":\\"burst5\\"}"' | jq -c .`;
229
+
230
+ const lines = result.stdout.trim().split('\n');
231
+ expect(lines).toHaveLength(5);
232
+
233
+ const messages = lines.map((line) => JSON.parse(line));
234
+ expect(messages.filter((m) => m.batch === 1)).toHaveLength(3);
235
+ expect(messages.filter((m) => m.batch === 2)).toHaveLength(2);
236
+ });
237
+
238
+ test('stream with varying delay intervals', async () => {
239
+ // Different delay patterns to test buffering
240
+ const result =
241
+ await $`sh -c 'echo "{\\"seq\\":1,\\"delay\\":\\"none\\"}"; sleep 0.001; echo "{\\"seq\\":2,\\"delay\\":\\"1ms\\"}"; sleep 0.01; echo "{\\"seq\\":3,\\"delay\\":\\"10ms\\"}"; sleep 0.02; echo "{\\"seq\\":4,\\"delay\\":\\"20ms\\"}"; sleep 0.005; echo "{\\"seq\\":5,\\"delay\\":\\"5ms\\"}"' | jq -c '{id: .seq, type: .delay}'`;
242
+
243
+ const lines = result.stdout.trim().split('\n');
244
+ expect(lines).toHaveLength(5);
245
+
246
+ // Verify transformation was applied correctly despite delays
247
+ for (let i = 0; i < 5; i++) {
248
+ const obj = JSON.parse(lines[i]);
249
+ expect(obj).toHaveProperty('id');
250
+ expect(obj).toHaveProperty('type');
251
+ expect(obj.id).toBe(i + 1);
252
+ }
253
+ });
254
+
255
+ test('verify immediate streaming output from jq', async () => {
256
+ // Test that jq outputs each object immediately as it arrives
257
+ const startTime = Date.now();
258
+ const timestamps = [];
259
+
260
+ // Create a command that outputs JSON with significant delays
261
+ const cmd = $`sh -c 'echo "{\\"id\\":1}"; sleep 0.2; echo "{\\"id\\":2}"; sleep 0.2; echo "{\\"id\\":3}"' | jq -c .`;
262
+
263
+ // Use streaming to capture output as it arrives
264
+ const chunks = [];
265
+ let iterations = 0;
266
+ const maxIterations = 10; // Prevent infinite loop
267
+
268
+ try {
269
+ for await (const chunk of cmd.stream()) {
270
+ iterations++;
271
+ if (iterations > maxIterations) {
272
+ cmd.kill();
273
+ break;
274
+ }
275
+
276
+ if (chunk.type === 'stdout') {
277
+ const now = Date.now();
278
+ timestamps.push(now - startTime);
279
+ chunks.push(chunk.data.toString());
280
+ }
281
+ }
282
+ } catch (error) {
283
+ // If streaming fails, just skip the test
284
+ trace(
285
+ 'JqTest',
286
+ () => `Streaming test failed, skipping: ${error.message}`
287
+ );
288
+ return;
289
+ }
290
+
291
+ // We should have received chunks at different times, not all at once
292
+ expect(chunks.length).toBeGreaterThan(0);
293
+
294
+ // Check if we got output in realtime (with some delays between)
295
+ // The timestamps should show delays if streaming is working properly
296
+ if (timestamps.length >= 3) {
297
+ // Allow for some variance but expect delays
298
+ const delay1 = timestamps[1] - timestamps[0];
299
+ const delay2 = timestamps[2] - timestamps[1];
300
+
301
+ // At least one of the delays should be significant (>100ms)
302
+ // showing that output came as it was produced
303
+ expect(Math.max(delay1, delay2)).toBeGreaterThan(100);
304
+ }
305
+
306
+ // Verify we got all the JSON objects
307
+ const output = chunks.join('');
308
+ const lines = output
309
+ .trim()
310
+ .split('\n')
311
+ .filter((l) => l.trim());
312
+ if (lines.length === 3) {
313
+ expect(JSON.parse(lines[0])).toEqual({ id: 1 });
314
+ expect(JSON.parse(lines[1])).toEqual({ id: 2 });
315
+ expect(JSON.parse(lines[2])).toEqual({ id: 3 });
316
+ }
317
+ }, 4000); // Set a shorter timeout for this test
318
+ });
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { test, expect, describe } from 'bun:test';
4
+ import { isWindows } from './test-helper.mjs'; // Automatically sets up beforeEach/afterEach cleanup
5
+ import { $ } from '../src/$.mjs';
6
+
7
+ describe('Options Examples (Feature Demo)', () => {
8
+ test('example: disable capture for performance', async () => {
9
+ // When you don't need the output stored in memory
10
+ const result = await $`echo "performance optimization"`.start({
11
+ capture: false,
12
+ });
13
+
14
+ // Output goes to console but not stored in result
15
+ expect(result.stdout).toBeUndefined();
16
+ expect(result.code).toBe(0);
17
+ });
18
+
19
+ test('example: disable mirroring for silent execution', async () => {
20
+ // When you want to capture output but not show it on console
21
+ const result = await $`echo "silent execution"`.start({ mirror: false });
22
+
23
+ // Output is captured but not shown on console
24
+ expect(result.stdout).toBe('silent execution\n');
25
+ expect(result.code).toBe(0);
26
+ });
27
+
28
+ test('example: both disabled for maximum performance', async () => {
29
+ // When you just want to run a command and check exit code
30
+ const result = await $`echo "max performance"`.start({
31
+ capture: false,
32
+ mirror: false,
33
+ });
34
+
35
+ expect(result.stdout).toBeUndefined();
36
+ expect(result.code).toBe(0);
37
+ });
38
+
39
+ test('example: custom stdin with options', async () => {
40
+ // Pass custom input and configure output behavior
41
+ const result = await $`cat`.start({
42
+ stdin: 'Hello from stdin!',
43
+ mirror: false, // Don't show on console
44
+ capture: true, // But do capture the result
45
+ });
46
+
47
+ expect(result.stdout).toBe('Hello from stdin!');
48
+ expect(result.code).toBe(0);
49
+ });
50
+
51
+ test('example: using .run() alias', async () => {
52
+ // .run() works exactly like .start()
53
+ const result1 = await $`echo "using run method"`.run({ capture: false });
54
+ const result2 = await $`echo "using start method"`.start({
55
+ capture: false,
56
+ });
57
+
58
+ expect(result1.stdout).toBeUndefined();
59
+ expect(result2.stdout).toBeUndefined();
60
+ expect(result1.code).toBe(0);
61
+ expect(result2.code).toBe(0);
62
+ });
63
+
64
+ test('example: comparison with sh() function', async () => {
65
+ // Before: had to use sh() function for options
66
+ // const result = await sh('echo "with sh function"', { mirror: false });
67
+
68
+ // Now: can use template literal syntax with options
69
+ const result = await $`echo "with template literal"`.start({
70
+ mirror: false,
71
+ });
72
+
73
+ expect(result.stdout).toBe('with template literal\n');
74
+ expect(result.code).toBe(0);
75
+ });
76
+
77
+ // Skip on Windows - uses 'ls /tmp' which is Unix-specific
78
+ test.skipIf(isWindows)(
79
+ 'example: real shell command vs virtual command',
80
+ async () => {
81
+ // Both work the same way
82
+ const virtualResult = await $`echo "virtual command"`.start({
83
+ capture: false,
84
+ });
85
+ const realResult = await $`ls /tmp`.start({ capture: false });
86
+
87
+ expect(virtualResult.stdout).toBeUndefined();
88
+ expect(realResult.stdout).toBeUndefined();
89
+ expect(virtualResult.code).toBe(0);
90
+ expect(realResult.code).toBe(0);
91
+ }
92
+ );
93
+
94
+ test('example: chaining still works', async () => {
95
+ // You can still use all other methods after .start() or .run()
96
+ const runner = $`echo "chainable"`;
97
+ const result = await runner.start({ mirror: false });
98
+
99
+ expect(result.stdout).toBe('chainable\n');
100
+ expect(result.code).toBe(0);
101
+
102
+ // The result object has the standard properties
103
+ expect(result).toHaveProperty('stderr');
104
+ expect(result).toHaveProperty('stdin');
105
+ });
106
+ });
@@ -0,0 +1,112 @@
1
+ import { describe, it, expect } from 'bun:test';
2
+ import './test-helper.mjs'; // Automatically sets up beforeEach/afterEach cleanup
3
+ import { $ } from '../src/$.mjs';
4
+
5
+ describe('$({ options }) syntax', () => {
6
+ it('should support $({ options }) syntax for custom options', async () => {
7
+ // Test with stdin option
8
+ const $withStdin = $({ stdin: 'test input\n' });
9
+ const result1 = await $withStdin`cat`;
10
+ expect(result1.stdout).toBe('test input\n');
11
+ expect(result1.code).toBe(0);
12
+ });
13
+
14
+ it('should support capture and mirror options', async () => {
15
+ // Test with capture: false
16
+ const $noCapture = $({ capture: false });
17
+ const result = await $noCapture`echo "test"`;
18
+ expect(result.stdout).toBeUndefined();
19
+ expect(result.code).toBe(0);
20
+ });
21
+
22
+ it('should support multiple options at once', async () => {
23
+ // Test with multiple options
24
+ const $custom = $({
25
+ stdin: 'hello world',
26
+ capture: true,
27
+ mirror: false,
28
+ });
29
+ const result = await $custom`cat`;
30
+ expect(result.stdout).toBe('hello world');
31
+ expect(result.code).toBe(0);
32
+ });
33
+
34
+ it('should work with environment variables', async () => {
35
+ // Test with custom environment
36
+ const $withEnv = $({
37
+ env: { ...process.env, TEST_VAR: 'custom_value' },
38
+ });
39
+ const result = await $withEnv`printenv TEST_VAR`;
40
+ expect(result.stdout.trim()).toBe('custom_value');
41
+ });
42
+
43
+ it('should work with custom working directory', async () => {
44
+ // Test with custom cwd
45
+ const $withCwd = $({ cwd: '/tmp' });
46
+ const result = await $withCwd`pwd`;
47
+ expect(result.stdout.trim()).toBe('/tmp');
48
+ });
49
+
50
+ it('should be reusable for multiple commands', async () => {
51
+ // Create a reusable $ with options
52
+ const $silent = $({ mirror: false, capture: true });
53
+
54
+ const result1 = await $silent`echo "first"`;
55
+ expect(result1.stdout.trim()).toBe('first');
56
+
57
+ const result2 = await $silent`echo "second"`;
58
+ expect(result2.stdout.trim()).toBe('second');
59
+
60
+ const result3 = await $silent`echo "third"`;
61
+ expect(result3.stdout.trim()).toBe('third');
62
+ });
63
+
64
+ it('should work alongside regular $ usage', async () => {
65
+ // Mix regular and options syntax
66
+ const regular = await $`echo "regular"`;
67
+ expect(regular.stdout.trim()).toBe('regular');
68
+
69
+ const withOptions = await $({ mirror: false })`echo "with options"`;
70
+ expect(withOptions.stdout.trim()).toBe('with options');
71
+
72
+ const regular2 = await $`echo "regular again"`;
73
+ expect(regular2.stdout.trim()).toBe('regular again');
74
+ });
75
+
76
+ it('should handle stdin as ignore', async () => {
77
+ const $noStdin = $({ stdin: 'ignore' });
78
+ const result = await $noStdin`echo "test"`;
79
+ expect(result.stdout.trim()).toBe('test');
80
+ expect(result.code).toBe(0);
81
+ });
82
+
83
+ it('should handle stdin as inherit (default)', async () => {
84
+ const $inheritStdin = $({ stdin: 'inherit' });
85
+ const result = await $inheritStdin`echo "test"`;
86
+ expect(result.stdout.trim()).toBe('test');
87
+ expect(result.code).toBe(0);
88
+ });
89
+
90
+ it('should work with interpolation', async () => {
91
+ const name = 'World';
92
+ const $custom = $({ capture: true, mirror: false });
93
+ const result = await $custom`echo Hello, ${name}!`;
94
+ // Interpolation should apply quoting, but the final output depends on whether
95
+ // virtual or real echo is used. Both behaviors are acceptable.
96
+ const expected = ["Hello, 'World'!", 'Hello, World!'];
97
+ expect(expected).toContain(result.stdout.trim());
98
+ });
99
+
100
+ it('should work with command chaining', async () => {
101
+ const $silent = $({ mirror: false });
102
+ const result = await $silent`echo "test" | tr 'a-z' 'A-Z'`;
103
+ expect(result.stdout.trim()).toBe('TEST');
104
+ });
105
+
106
+ it('should handle errors with custom options', async () => {
107
+ const $custom = $({ capture: true, mirror: false });
108
+ const result = await $custom`ls /nonexistent-path-${Date.now()}`;
109
+ expect(result.code).toBeGreaterThan(0);
110
+ expect(result.stderr).toContain('No such file or directory');
111
+ });
112
+ });