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,297 @@
1
+ import { test, expect, describe, beforeEach, afterEach } from 'bun:test';
2
+ import { isWindows } from './test-helper.mjs'; // Automatically sets up beforeEach/afterEach cleanup
3
+ import { $, shell } from '../src/$.mjs';
4
+
5
+ // Reset shell settings before each test
6
+ beforeEach(() => {
7
+ shell.errexit(false);
8
+ shell.verbose(false);
9
+ shell.xtrace(false);
10
+ shell.pipefail(false);
11
+ shell.nounset(false);
12
+ });
13
+
14
+ // Reset shell settings after each test to prevent interference with other test files
15
+ afterEach(() => {
16
+ shell.errexit(false);
17
+ shell.verbose(false);
18
+ shell.xtrace(false);
19
+ shell.pipefail(false);
20
+ shell.nounset(false);
21
+ });
22
+
23
+ describe('Synchronous Execution (.sync())', () => {
24
+ describe('Basic Sync Functionality', () => {
25
+ test('should execute commands synchronously', () => {
26
+ const result = $`echo "hello sync"`.sync();
27
+
28
+ expect(result.stdout.trim()).toBe('hello sync');
29
+ expect(result.code).toBe(0);
30
+ expect(typeof result.stdout).toBe('string');
31
+ expect(typeof result.stderr).toBe('string');
32
+ });
33
+
34
+ test('should handle stderr in sync mode', () => {
35
+ const result = $`sh -c "echo 'stdout'; echo 'stderr' >&2"`.sync();
36
+
37
+ expect(result.stdout.trim()).toBe('stdout');
38
+ expect(result.stderr.trim()).toBe('stderr');
39
+ expect(result.code).toBe(0);
40
+ });
41
+
42
+ test('should handle non-zero exit codes', () => {
43
+ const result = $`exit 42`.sync();
44
+
45
+ expect(result.code).toBe(42);
46
+ });
47
+
48
+ test('should handle command not found', () => {
49
+ const result = $`nonexistent-command-99999`.sync();
50
+
51
+ expect(result.code).not.toBe(0);
52
+ expect(result.stderr).toContain('not found');
53
+ });
54
+ });
55
+
56
+ describe('Events in Sync Mode', () => {
57
+ test('should emit batched events after completion', () => {
58
+ const events = [];
59
+ const cmd = $`echo "sync output"`;
60
+
61
+ cmd.on('data', (chunk) => events.push(`data-${chunk.type}`));
62
+ cmd.on('stdout', () => events.push('stdout'));
63
+ cmd.on('stderr', () => events.push('stderr'));
64
+ cmd.on('end', () => events.push('end'));
65
+ cmd.on('exit', (code) => events.push(`exit-${code}`));
66
+
67
+ const result = cmd.sync();
68
+
69
+ // Events should be emitted after sync completes
70
+ expect(events).toContain('data-stdout');
71
+ expect(events).toContain('stdout');
72
+ expect(events).toContain('end');
73
+ expect(events).toContain('exit-0');
74
+ expect(result.stdout.trim()).toBe('sync output');
75
+ });
76
+
77
+ test('should emit stderr events in sync mode', () => {
78
+ const events = [];
79
+ const cmd = $`sh -c "echo 'error' >&2"`;
80
+
81
+ cmd.on('stderr', () => events.push('stderr'));
82
+ cmd.on('data', (chunk) => {
83
+ if (chunk.type === 'stderr') {
84
+ events.push('data-stderr');
85
+ }
86
+ });
87
+
88
+ cmd.sync();
89
+
90
+ expect(events).toContain('stderr');
91
+ expect(events).toContain('data-stderr');
92
+ });
93
+ });
94
+
95
+ describe('Options in Sync Mode', () => {
96
+ test('should respect mirror option', () => {
97
+ // mirror: true by default - output should appear in terminal
98
+ const result1 = $`echo "mirrored"`.sync();
99
+ expect(result1.stdout.trim()).toBe('mirrored');
100
+
101
+ // mirror: false - no terminal output but still captured
102
+ const cmd2 = $`echo "not mirrored"`;
103
+ cmd2.options.mirror = false;
104
+ const result2 = cmd2.sync();
105
+ expect(result2.stdout.trim()).toBe('not mirrored');
106
+ });
107
+
108
+ test('should respect capture option', () => {
109
+ const cmd = $`echo "test"`;
110
+ cmd.options.capture = false;
111
+ const result = cmd.sync();
112
+
113
+ // capture option doesn't affect sync mode - always captures
114
+ // This is different from async mode
115
+ expect(result.stdout.trim()).toBe('test');
116
+ });
117
+
118
+ test('should handle stdin options', () => {
119
+ const cmd1 = $`cat`;
120
+ cmd1.options.stdin = 'custom input';
121
+ const result1 = cmd1.sync();
122
+ expect(result1.stdout.trim()).toBe('custom input');
123
+
124
+ const cmd2 = $`cat`;
125
+ cmd2.options.stdin = Buffer.from('buffer input');
126
+ const result2 = cmd2.sync();
127
+ expect(result2.stdout.trim()).toBe('buffer input');
128
+
129
+ const cmd3 = $`echo "ignored"`;
130
+ cmd3.options.stdin = 'ignore';
131
+ const result3 = cmd3.sync();
132
+ expect(result3.stdout.trim()).toBe('ignored');
133
+ });
134
+
135
+ // Skip on Windows - uses 'pwd' command and Unix paths
136
+ test.skipIf(isWindows)('should handle cwd option', () => {
137
+ const cmd = $`pwd`;
138
+ cmd.options.cwd = '/tmp';
139
+ const result = cmd.sync();
140
+ // macOS uses /private/tmp symlink
141
+ expect(result.stdout.trim()).toMatch(/^(\/tmp|\/private\/tmp)$/);
142
+ });
143
+ });
144
+
145
+ describe('Shell Settings in Sync Mode', () => {
146
+ test('should respect errexit setting', () => {
147
+ shell.errexit(true);
148
+
149
+ expect(() => {
150
+ $`exit 1`.sync();
151
+ }).toThrow('Command failed with exit code 1');
152
+
153
+ shell.errexit(false);
154
+ const result = $`exit 1`.sync();
155
+ expect(result.code).toBe(1);
156
+ });
157
+
158
+ test('should respect verbose setting', () => {
159
+ const originalLog = console.log;
160
+ const logs = [];
161
+ console.log = (...args) => logs.push(args.join(' '));
162
+
163
+ try {
164
+ shell.verbose(true);
165
+ $`echo "verbose test"`.sync();
166
+
167
+ expect(logs.some((log) => log.includes('echo "verbose test"'))).toBe(
168
+ true
169
+ );
170
+ } finally {
171
+ console.log = originalLog;
172
+ }
173
+ });
174
+
175
+ test('should respect xtrace setting', () => {
176
+ const originalLog = console.log;
177
+ const logs = [];
178
+ console.log = (...args) => logs.push(args.join(' '));
179
+
180
+ try {
181
+ shell.xtrace(true);
182
+ $`echo "trace test"`.sync();
183
+
184
+ expect(logs.some((log) => log.startsWith('+ '))).toBe(true);
185
+ expect(logs.some((log) => log.includes('echo "trace test"'))).toBe(
186
+ true
187
+ );
188
+ } finally {
189
+ console.log = originalLog;
190
+ }
191
+ });
192
+ });
193
+
194
+ describe('Error Handling', () => {
195
+ test('should throw if command already started asynchronously', async () => {
196
+ const cmd = $`echo "test"`;
197
+
198
+ // Start async execution
199
+ const promise = cmd.then();
200
+
201
+ // Try to run sync - should throw
202
+ expect(() => cmd.sync()).toThrow('Command already started');
203
+
204
+ // Clean up
205
+ await promise;
206
+ });
207
+
208
+ test('should include error details when errexit is enabled', () => {
209
+ shell.errexit(true);
210
+
211
+ try {
212
+ $`sh -c "echo 'output'; echo 'error' >&2; exit 5"`.sync();
213
+ expect(true).toBe(false); // Should not reach here
214
+ } catch (error) {
215
+ expect(error.code).toBe(5);
216
+ expect(error.stdout).toContain('output');
217
+ expect(error.stderr).toContain('error');
218
+ expect(error.result).toBeDefined();
219
+ expect(error.message).toContain('exit code 5');
220
+ }
221
+ });
222
+ });
223
+
224
+ describe('Complex Scenarios', () => {
225
+ test('should handle multiline output', () => {
226
+ const result = $`printf '%s\n%s\n%s' 'line1' 'line2' 'line3'`.sync();
227
+
228
+ const lines = result.stdout.trim().split('\n');
229
+ expect(lines).toHaveLength(3);
230
+ expect(lines[0]).toBe('line1');
231
+ expect(lines[1]).toBe('line2');
232
+ expect(lines[2]).toBe('line3');
233
+ });
234
+
235
+ test('should handle large output', () => {
236
+ // Use seq which is more portable than {1..1000} bash expansion
237
+ const result = $`seq 1 1000`.sync();
238
+
239
+ const lines = result.stdout.trim().split('\n');
240
+ expect(lines.length).toBeGreaterThan(900); // Should be 1000 lines
241
+ expect(lines[0]).toBe('1');
242
+ expect(lines[999]).toBe('1000');
243
+ });
244
+
245
+ test('should handle commands with quotes and special characters', () => {
246
+ const result = $`echo "It's a 'test' with \\"quotes\\""`.sync();
247
+
248
+ expect(result.stdout).toContain("It's");
249
+ expect(result.stdout).toContain('test');
250
+ expect(result.stdout).toContain('quotes');
251
+ });
252
+ });
253
+
254
+ describe('Comparison with Async', () => {
255
+ test('should produce same result as async version', async () => {
256
+ const command = 'echo "test"; echo "error" >&2; exit 0';
257
+
258
+ // Sync version
259
+ const syncResult = $`sh -c '${command}'`.sync();
260
+
261
+ // Async version
262
+ const asyncResult = await $`sh -c '${command}'`;
263
+
264
+ expect(syncResult.stdout).toBe(asyncResult.stdout);
265
+ expect(syncResult.stderr).toBe(asyncResult.stderr);
266
+ expect(syncResult.code).toBe(asyncResult.code);
267
+ });
268
+
269
+ test('should handle events differently than async', async () => {
270
+ const syncEvents = [];
271
+ const asyncEvents = [];
272
+
273
+ // Sync version - events after completion
274
+ const syncCmd = $`echo "test"`;
275
+ syncCmd.on('data', () => syncEvents.push(Date.now()));
276
+ const syncStart = Date.now();
277
+ syncCmd.sync();
278
+ const syncEnd = Date.now();
279
+
280
+ // Async version - events during execution
281
+ const asyncCmd = $`echo "test"`;
282
+ asyncCmd.on('data', () => asyncEvents.push(Date.now()));
283
+ const asyncStart = Date.now();
284
+ await asyncCmd;
285
+ const asyncEnd = Date.now();
286
+
287
+ // Both should have events
288
+ expect(syncEvents.length).toBeGreaterThan(0);
289
+ expect(asyncEvents.length).toBeGreaterThan(0);
290
+
291
+ // Sync events should all be after command completion
292
+ syncEvents.forEach((time) => {
293
+ expect(time).toBeGreaterThanOrEqual(syncEnd - 10); // Allow small margin
294
+ });
295
+ });
296
+ });
297
+ });
@@ -0,0 +1,226 @@
1
+ import { test, expect, describe, beforeEach, afterEach } from 'bun:test';
2
+ import './test-helper.mjs'; // Automatically sets up beforeEach/afterEach cleanup
3
+ import { $, shell, disableVirtualCommands } from '../src/$.mjs';
4
+ import { execSync } from 'child_process';
5
+
6
+ // Platform detection - These tests use Unix utilities (printf, grep, sed, awk, etc.)
7
+ const isWindows = process.platform === 'win32';
8
+
9
+ beforeEach(() => {
10
+ shell.errexit(false);
11
+ shell.verbose(false);
12
+ shell.xtrace(false);
13
+ shell.pipefail(false);
14
+ shell.nounset(false);
15
+ disableVirtualCommands();
16
+ });
17
+
18
+ // Reset shell settings after each test to prevent interference with other test files
19
+ afterEach(() => {
20
+ shell.errexit(false);
21
+ shell.verbose(false);
22
+ shell.xtrace(false);
23
+ shell.pipefail(false);
24
+ shell.nounset(false);
25
+ });
26
+
27
+ const hasCommand = (cmd) => {
28
+ try {
29
+ execSync(`which ${cmd}`, { stdio: 'ignore' });
30
+ return true;
31
+ } catch {
32
+ return false;
33
+ }
34
+ };
35
+
36
+ const hasJq = hasCommand('jq');
37
+
38
+ // Skip on Windows - uses Unix utilities (printf, grep, sed, awk, jq, etc.)
39
+ describe.skipIf(isWindows)('System Command Piping (Issue #8)', () => {
40
+ describe('Piping to jq', () => {
41
+ test.skipIf(!hasJq)(
42
+ 'should pipe echo output to jq for JSON processing',
43
+ async () => {
44
+ const result = await $`echo '{"message": "hi", "number": 42}' | jq .`;
45
+
46
+ expect(result.code).toBe(0);
47
+ expect(result.stdout).toContain('"message": "hi"');
48
+ expect(result.stdout).toContain('"number": 42');
49
+ }
50
+ );
51
+
52
+ test.skipIf(!hasJq)('should extract specific field with jq', async () => {
53
+ const result =
54
+ await $`echo '{"message": "hi", "number": 42}' | jq -r .message`;
55
+
56
+ expect(result.code).toBe(0);
57
+ expect(result.stdout.trim()).toBe('hi');
58
+ });
59
+
60
+ test.skipIf(!hasJq)('should handle jq array operations', async () => {
61
+ const result = await $`echo '[1,2,3,4,5]' | jq '. | length'`;
62
+
63
+ expect(result.code).toBe(0);
64
+ expect(result.stdout.trim()).toBe('5');
65
+ });
66
+
67
+ test.skipIf(!hasJq)('should pipe cat output to jq', async () => {
68
+ const result = await $`echo '{"foo": "bar"}' | jq .foo`;
69
+
70
+ expect(result.code).toBe(0);
71
+ expect(result.stdout.trim()).toBe('"bar"');
72
+ });
73
+ });
74
+
75
+ describe('Piping to grep', () => {
76
+ test('should pipe to grep for pattern matching', async () => {
77
+ const result = await $`printf "line1\\nline2\\nline3" | grep line2`;
78
+
79
+ expect(result.code).toBe(0);
80
+ expect(result.stdout.trim()).toBe('line2');
81
+ });
82
+
83
+ test('should handle grep with flags', async () => {
84
+ const result = await $`printf "Line1\\nline2\\nLINE3" | grep -i line`;
85
+
86
+ expect(result.code).toBe(0);
87
+ expect(result.stdout).toContain('Line1');
88
+ expect(result.stdout).toContain('line2');
89
+ expect(result.stdout).toContain('LINE3');
90
+ });
91
+ });
92
+
93
+ describe('Piping to sed', () => {
94
+ test('should pipe to sed for text substitution', async () => {
95
+ const result = await $`echo "hello world" | sed 's/world/universe/'`;
96
+
97
+ expect(result.code).toBe(0);
98
+ expect(result.stdout.trim()).toBe('hello universe');
99
+ });
100
+
101
+ test('should handle sed with multiple operations', async () => {
102
+ const result = await $`echo "foo bar baz" | sed 's/foo/FOO/; s/baz/BAZ/'`;
103
+
104
+ expect(result.code).toBe(0);
105
+ expect(result.stdout.trim()).toBe('FOO bar BAZ');
106
+ });
107
+ });
108
+
109
+ describe('Piping to awk', () => {
110
+ test('should pipe to awk for field extraction', async () => {
111
+ const result = await $`echo "field1 field2 field3" | awk '{print $2}'`;
112
+
113
+ expect(result.code).toBe(0);
114
+ expect(result.stdout.trim()).toBe('field2');
115
+ });
116
+
117
+ test('should handle awk with calculations', async () => {
118
+ const result = await $`echo "1 2 3" | awk '{print $1 + $2 + $3}'`;
119
+
120
+ expect(result.code).toBe(0);
121
+ expect(result.stdout.trim()).toBe('6');
122
+ });
123
+ });
124
+
125
+ describe('Piping to wc', () => {
126
+ test('should pipe to wc for line counting', async () => {
127
+ const result = await $`printf "line1\\nline2\\nline3\\n" | wc -l`;
128
+
129
+ expect(result.code).toBe(0);
130
+ expect(parseInt(result.stdout.trim())).toBe(3);
131
+ });
132
+
133
+ test('should pipe to wc for word counting', async () => {
134
+ const result = await $`echo "one two three four five" | wc -w`;
135
+
136
+ expect(result.code).toBe(0);
137
+ expect(parseInt(result.stdout.trim())).toBe(5);
138
+ });
139
+ });
140
+
141
+ describe('Piping to cut', () => {
142
+ test('should pipe to cut for field extraction', async () => {
143
+ const result = await $`echo "a:b:c:d" | cut -d: -f2`;
144
+
145
+ expect(result.code).toBe(0);
146
+ expect(result.stdout.trim()).toBe('b');
147
+ });
148
+
149
+ test('should handle cut with multiple fields', async () => {
150
+ const result = await $`echo "1,2,3,4,5" | cut -d, -f2,4`;
151
+
152
+ expect(result.code).toBe(0);
153
+ expect(result.stdout.trim()).toBe('2,4');
154
+ });
155
+ });
156
+
157
+ describe('Piping to sort', () => {
158
+ test('should pipe to sort for sorting lines', async () => {
159
+ const result = await $`printf "banana\\napple\\ncherry" | sort`;
160
+
161
+ expect(result.code).toBe(0);
162
+ const lines = result.stdout.trim().split('\n');
163
+ expect(lines[0]).toBe('apple');
164
+ expect(lines[1]).toBe('banana');
165
+ expect(lines[2]).toBe('cherry');
166
+ });
167
+
168
+ test('should handle sort with reverse flag', async () => {
169
+ const result = await $`printf "1\\n3\\n2" | sort -r`;
170
+
171
+ expect(result.code).toBe(0);
172
+ const lines = result.stdout.trim().split('\n');
173
+ expect(lines[0]).toBe('3');
174
+ expect(lines[1]).toBe('2');
175
+ expect(lines[2]).toBe('1');
176
+ });
177
+ });
178
+
179
+ describe('Piping to head/tail', () => {
180
+ test('should pipe to head for first lines', async () => {
181
+ const result = await $`printf "1\\n2\\n3\\n4\\n5" | head -n 2`;
182
+
183
+ expect(result.code).toBe(0);
184
+ const lines = result.stdout.trim().split('\n');
185
+ expect(lines.length).toBe(2);
186
+ expect(lines[0]).toBe('1');
187
+ expect(lines[1]).toBe('2');
188
+ });
189
+
190
+ test('should pipe to tail for last lines', async () => {
191
+ const result = await $`printf "1\\n2\\n3\\n4\\n5" | tail -n 2`;
192
+
193
+ expect(result.code).toBe(0);
194
+ const lines = result.stdout.trim().split('\n');
195
+ expect(lines.length).toBe(2);
196
+ expect(lines[0]).toBe('4');
197
+ expect(lines[1]).toBe('5');
198
+ });
199
+ });
200
+
201
+ describe('Complex multi-pipe operations', () => {
202
+ test('should handle multiple system command pipes', async () => {
203
+ const result =
204
+ await $`printf "apple\\nbanana\\ncherry\\napricot" | grep ^a | sort | head -n 1`;
205
+
206
+ expect(result.code).toBe(0);
207
+ expect(result.stdout.trim()).toBe('apple');
208
+ });
209
+
210
+ test.skipIf(!hasJq)('should combine jq with other tools', async () => {
211
+ const result =
212
+ await $`echo '[{"name":"alice"},{"name":"bob"},{"name":"charlie"}]' | jq -r '.[].name' | sort | tail -n 1`;
213
+
214
+ expect(result.code).toBe(0);
215
+ expect(result.stdout.trim()).toBe('charlie');
216
+ });
217
+
218
+ test('should handle pipes with text processing chain', async () => {
219
+ const result =
220
+ await $`echo "foo bar baz foo bar" | sed 's/foo/FOO/g' | awk '{print NF}'`;
221
+
222
+ expect(result.code).toBe(0);
223
+ expect(result.stdout.trim()).toBe('5');
224
+ });
225
+ });
226
+ });