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,80 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Simple test runner that runs all tests individually and reports results
5
+ */
6
+
7
+ import { execSync } from 'child_process';
8
+ import { readdirSync } from 'fs';
9
+ import { join } from 'path';
10
+
11
+ const testsDir = join(process.cwd(), 'tests');
12
+ const testFiles = readdirSync(testsDir)
13
+ .filter((f) => f.endsWith('.test.mjs'))
14
+ .sort();
15
+
16
+ console.log(`🧪 Running ${testFiles.length} test files individually...\n`);
17
+
18
+ let totalPass = 0;
19
+ let totalFail = 0;
20
+ const failedFiles = [];
21
+
22
+ for (const file of testFiles) {
23
+ const filePath = join(testsDir, file);
24
+
25
+ try {
26
+ // Run test synchronously and capture output
27
+ const output = execSync(`bun test ${filePath} 2>&1`, { encoding: 'utf-8' });
28
+
29
+ // Parse the output to find pass/fail counts
30
+ const passMatch = output.match(/(\d+)\s+pass/);
31
+ const failMatch = output.match(/(\d+)\s+fail/);
32
+
33
+ const pass = passMatch ? parseInt(passMatch[1]) : 0;
34
+ const fail = failMatch ? parseInt(failMatch[1]) : 0;
35
+
36
+ totalPass += pass;
37
+ totalFail += fail;
38
+
39
+ if (fail > 0) {
40
+ console.log(`❌ ${file}: ${pass} pass, ${fail} fail`);
41
+ failedFiles.push(file);
42
+ } else {
43
+ console.log(`✅ ${file}: ${pass} pass`);
44
+ }
45
+ } catch (error) {
46
+ // Test failed to run or had non-zero exit
47
+ const output = error.stdout || '';
48
+ const passMatch = output.match(/(\d+)\s+pass/);
49
+ const failMatch = output.match(/(\d+)\s+fail/);
50
+
51
+ const pass = passMatch ? parseInt(passMatch[1]) : 0;
52
+ const fail = failMatch ? parseInt(failMatch[1]) : 0;
53
+
54
+ totalPass += pass;
55
+ totalFail += fail;
56
+
57
+ if (fail > 0) {
58
+ console.log(`❌ ${file}: ${pass} pass, ${fail} fail`);
59
+ failedFiles.push(file);
60
+ } else {
61
+ console.log(`⚠️ ${file}: Error running test`);
62
+ failedFiles.push(file);
63
+ }
64
+ }
65
+ }
66
+
67
+ console.log(`\n${'='.repeat(60)}`);
68
+ console.log('📊 Summary:');
69
+ console.log(` Total tests passed: ${totalPass}`);
70
+ console.log(` Total tests failed: ${totalFail}`);
71
+ console.log(` Files with failures: ${failedFiles.length}`);
72
+
73
+ if (failedFiles.length > 0) {
74
+ console.log('\n❌ Failed test files:');
75
+ failedFiles.forEach((f) => console.log(` - ${f}`));
76
+ process.exit(1);
77
+ } else {
78
+ console.log('\n✅ All tests passed!');
79
+ process.exit(0);
80
+ }
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Test runner that runs all tests individually and reports results
5
+ * This helps identify test issues and ensures all tests pass in isolation
6
+ */
7
+
8
+ import { $ } from '../src/$.mjs';
9
+ import { readdirSync } from 'fs';
10
+ import { join, basename } from 'path';
11
+
12
+ const testsDir = join(process.cwd(), 'tests');
13
+ const testFiles = readdirSync(testsDir)
14
+ .filter((f) => f.endsWith('.test.mjs'))
15
+ .sort();
16
+
17
+ console.log(`\n🧪 Running ${testFiles.length} test files individually...\n`);
18
+
19
+ let totalPass = 0;
20
+ let totalFail = 0;
21
+ const failedFiles = [];
22
+
23
+ for (const file of testFiles) {
24
+ const filePath = join(testsDir, file);
25
+
26
+ try {
27
+ // Run the test and capture output
28
+ const result = await $`bun test ${filePath}`;
29
+
30
+ // Parse the output to find pass/fail counts
31
+ const output = result.stdout;
32
+ const passMatch = output.match(/(\d+)\s+pass/);
33
+ const failMatch = output.match(/(\d+)\s+fail/);
34
+
35
+ const pass = passMatch ? parseInt(passMatch[1]) : 0;
36
+ const fail = failMatch ? parseInt(failMatch[1]) : 0;
37
+
38
+ totalPass += pass;
39
+ totalFail += fail;
40
+
41
+ if (fail > 0) {
42
+ console.log(`❌ ${file}: ${pass} pass, ${fail} fail`);
43
+ failedFiles.push(file);
44
+ } else {
45
+ console.log(`✅ ${file}: ${pass} pass`);
46
+ }
47
+ } catch (error) {
48
+ console.log(`⚠️ ${file}: Error running test`);
49
+ console.error(` ${error.message}`);
50
+ failedFiles.push(file);
51
+ }
52
+ }
53
+
54
+ console.log(`\n${'='.repeat(60)}`);
55
+ console.log('📊 Summary:');
56
+ console.log(` Total tests passed: ${totalPass}`);
57
+ console.log(` Total tests failed: ${totalFail}`);
58
+ console.log(` Files with failures: ${failedFiles.length}`);
59
+
60
+ if (failedFiles.length > 0) {
61
+ console.log('\n❌ Failed test files:');
62
+ failedFiles.forEach((f) => console.log(` - ${f}`));
63
+ process.exit(1);
64
+ } else {
65
+ console.log('\n✅ All tests passed!');
66
+ process.exit(0);
67
+ }
@@ -0,0 +1,31 @@
1
+ const testOutput = "Token scopes: 'gist', 'read:org', 'repo'";
2
+
3
+ // Try the current regex
4
+ const scopesMatch = testOutput.match(
5
+ /Token scopes:\s*'([^']+)'|Token scopes:\s*([^\n]+)/
6
+ );
7
+ console.log('Match result:', scopesMatch);
8
+
9
+ if (scopesMatch) {
10
+ const scopesStr = scopesMatch[1] || scopesMatch[2];
11
+ console.log('Captured string:', scopesStr);
12
+
13
+ // The issue: we're only capturing the first quoted item
14
+ // We need to capture the entire line after "Token scopes:"
15
+ }
16
+
17
+ // Better approach - capture everything after Token scopes:
18
+ const betterMatch = testOutput.match(/Token scopes:\s*(.+)/);
19
+ console.log('\nBetter match:', betterMatch);
20
+ if (betterMatch) {
21
+ const scopesLine = betterMatch[1];
22
+ console.log('Full scopes line:', scopesLine);
23
+
24
+ // Extract all quoted strings
25
+ const scopes = scopesLine.match(/'([^']+)'/g);
26
+ console.log('All quoted strings:', scopes);
27
+
28
+ // Clean them up
29
+ const cleanScopes = scopes ? scopes.map((s) => s.replace(/'/g, '')) : [];
30
+ console.log('Clean scopes:', cleanScopes);
31
+ }
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env bun
2
+
3
+ import { $ } from '../src/$.mjs';
4
+
5
+ console.log('Testing pipeline executed via sh -c:');
6
+ console.log('This should stream in real-time\n');
7
+
8
+ const start = Date.now();
9
+
10
+ // Execute the entire pipeline as a single shell command
11
+ const cmd = $`sh -c 'bun run js/examples/emulate-claude-stream.mjs | jq .'`;
12
+
13
+ for await (const chunk of cmd.stream()) {
14
+ if (chunk.type === 'stdout') {
15
+ const elapsed = Date.now() - start;
16
+ const lines = chunk.data
17
+ .toString()
18
+ .split('\n')
19
+ .filter((l) => l.trim());
20
+ for (const line of lines) {
21
+ console.log(`[${elapsed}ms] ${line}`);
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Test script to reproduce Bun shell path detection issues
4
+ import { $ } from '../src/$.mjs';
5
+
6
+ console.log('=== Shell Detection Test ===');
7
+ console.log(
8
+ `Runtime: ${typeof globalThis.Bun !== 'undefined' ? 'Bun' : 'Node.js'}`
9
+ );
10
+ console.log(`Platform: ${process.platform}`);
11
+
12
+ const testCommands = [
13
+ { cmd: 'echo "Hello, World!"', desc: 'Simple echo' },
14
+ { cmd: 'pwd', desc: 'Print working directory' },
15
+ { cmd: 'date', desc: 'Current date' },
16
+ { cmd: 'which sh', desc: 'Find sh location' },
17
+ { cmd: 'which bash', desc: 'Find bash location' },
18
+ ];
19
+
20
+ console.log('\n=== Testing Commands ===');
21
+ for (const { cmd, desc } of testCommands) {
22
+ console.log(`\nTest: ${desc}`);
23
+ console.log(`Command: ${cmd}`);
24
+ try {
25
+ const result = await $`${cmd}`;
26
+ console.log('✓ Success:', result.stdout.toString().trim());
27
+ } catch (error) {
28
+ console.log('✗ Failed:', error.message);
29
+ if (error.code === 'ENOENT') {
30
+ console.log(' Error: ENOENT - Command/Shell not found');
31
+ console.log(' This indicates shell path resolution issues!');
32
+ }
33
+ if (error.stderr) {
34
+ console.log(' Stderr:', error.stderr.toString().trim());
35
+ }
36
+ }
37
+ }
38
+
39
+ console.log('\n=== Testing Shell Detection Directly ===');
40
+ // Test shell detection by importing the function directly
41
+ import fs from 'fs';
42
+ import cp from 'child_process';
43
+
44
+ const isBun = typeof globalThis.Bun !== 'undefined';
45
+
46
+ console.log('\nTesting individual shell paths:');
47
+ const shellsToTest = ['/bin/sh', '/usr/bin/sh', '/bin/bash', '/usr/bin/bash'];
48
+
49
+ for (const shellPath of shellsToTest) {
50
+ const exists = fs.existsSync(shellPath);
51
+ console.log(`${shellPath}: ${exists ? '✓ exists' : '✗ not found'}`);
52
+ }
53
+
54
+ console.log('\nTesting `which` command in both runtimes:');
55
+ const shellNames = ['sh', 'bash', 'zsh'];
56
+
57
+ for (const shellName of shellNames) {
58
+ try {
59
+ const result = cp.spawnSync('which', [shellName], { encoding: 'utf-8' });
60
+ if (result.status === 0 && result.stdout) {
61
+ console.log(`which ${shellName}: ✓ ${result.stdout.trim()}`);
62
+ } else {
63
+ console.log(`which ${shellName}: ✗ not found (status: ${result.status})`);
64
+ if (result.stderr) {
65
+ console.log(` stderr: ${result.stderr.trim()}`);
66
+ }
67
+ }
68
+ } catch (error) {
69
+ console.log(`which ${shellName}: ✗ error - ${error.message}`);
70
+ }
71
+ }
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { parseShellCommand, needsRealShell } from '../src/shell-parser.mjs';
4
+
5
+ const testCases = [
6
+ 'cd /tmp',
7
+ 'cd /tmp && pwd',
8
+ 'cd /tmp || echo "failed"',
9
+ 'cd /tmp ; pwd ; cd /usr',
10
+ '(cd /tmp && pwd)',
11
+ '(cd /tmp && pwd) ; pwd',
12
+ 'cd /tmp && echo "hello" && cd /usr',
13
+ 'ls -la | grep test | wc -l',
14
+ 'cd "/path with spaces" && pwd',
15
+ 'echo "hello world" > file.txt',
16
+ 'cat < input.txt > output.txt',
17
+ 'cd /tmp && (cd /usr && pwd) && pwd',
18
+ 'false || echo "failed" && echo "success"',
19
+ ];
20
+
21
+ console.log('=== Shell Parser Test ===\n');
22
+
23
+ for (const cmd of testCases) {
24
+ console.log(`Command: ${cmd}`);
25
+
26
+ if (needsRealShell(cmd)) {
27
+ console.log(' Needs real shell: YES');
28
+ } else {
29
+ console.log(' Needs real shell: NO');
30
+ }
31
+
32
+ const parsed = parseShellCommand(cmd);
33
+ console.log(' Parsed:', JSON.stringify(parsed, null, 2));
34
+ console.log();
35
+ }
36
+
37
+ console.log('=== Test Complete ===');
@@ -0,0 +1,241 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Example: Testing SIGINT behavior across different scenarios
5
+ *
6
+ * This helps debug why SIGINT tests might fail in different environments
7
+ */
8
+
9
+ import { spawn } from 'child_process';
10
+ import { $ } from '../src/$.mjs';
11
+
12
+ console.log('Testing SIGINT behavior');
13
+
14
+ // Test 1: Basic shell command with SIGINT
15
+ async function testBasicShellSigint() {
16
+ console.log('\nTEST 1: Basic shell command with SIGINT');
17
+
18
+ return new Promise((resolve) => {
19
+ const child = spawn('sh', ['-c', 'echo "START" && sleep 30'], {
20
+ stdio: ['pipe', 'pipe', 'pipe'],
21
+ detached: true,
22
+ });
23
+
24
+ console.log(`Started process with PID: ${child.pid}`);
25
+
26
+ let stdout = '';
27
+ child.stdout.on('data', (data) => {
28
+ stdout += data.toString();
29
+ console.log('Received stdout:', data.toString().trim());
30
+ });
31
+
32
+ // Wait for initial output
33
+ setTimeout(() => {
34
+ console.log('Sending SIGINT...');
35
+ child.kill('SIGINT');
36
+ }, 500);
37
+
38
+ child.on('exit', (code, signal) => {
39
+ console.log(`Process exited with code: ${code}, signal: ${signal}`);
40
+ console.log(`Total stdout received: ${stdout}`);
41
+
42
+ // Expected: code=null, signal='SIGINT' OR code=130, signal=null
43
+ const exitCode = code !== null ? code : signal === 'SIGINT' ? 130 : 1;
44
+ console.log(`Effective exit code: ${exitCode}`);
45
+
46
+ resolve({ stdout, exitCode, signal });
47
+ });
48
+ });
49
+ }
50
+
51
+ // Test 2: Shell with trap for SIGINT
52
+ async function testShellWithTrap() {
53
+ console.log('\nTEST 2: Shell with trap for SIGINT');
54
+
55
+ const script = `
56
+ echo "START_WITH_TRAP"
57
+ trap 'echo "Caught SIGINT"; exit 130' INT
58
+ sleep 30
59
+ `;
60
+
61
+ return new Promise((resolve) => {
62
+ const child = spawn('sh', ['-c', script], {
63
+ stdio: ['pipe', 'pipe', 'pipe'],
64
+ detached: true,
65
+ });
66
+
67
+ console.log(`Started process with PID: ${child.pid}`);
68
+
69
+ let stdout = '';
70
+ child.stdout.on('data', (data) => {
71
+ stdout += data.toString();
72
+ console.log('Received stdout:', data.toString().trim());
73
+ });
74
+
75
+ setTimeout(() => {
76
+ console.log('Sending SIGINT...');
77
+ child.kill('SIGINT');
78
+ }, 500);
79
+
80
+ child.on('exit', (code, signal) => {
81
+ console.log(`Process exited with code: ${code}, signal: ${signal}`);
82
+ resolve({ stdout, code, signal });
83
+ });
84
+ });
85
+ }
86
+
87
+ // Test 3: Process group handling
88
+ async function testProcessGroup() {
89
+ console.log('\nTEST 3: Process group SIGINT');
90
+
91
+ return new Promise((resolve) => {
92
+ const child = spawn('sh', ['-c', 'echo "GROUP_START" && sleep 30'], {
93
+ stdio: ['pipe', 'pipe', 'pipe'],
94
+ detached: true, // Creates new process group
95
+ });
96
+
97
+ const pgid = -child.pid;
98
+ console.log(`Started process with PID: ${child.pid}, PGID: ${pgid}`);
99
+
100
+ let stdout = '';
101
+ child.stdout.on('data', (data) => {
102
+ stdout += data.toString();
103
+ console.log('Received stdout:', data.toString().trim());
104
+ });
105
+
106
+ setTimeout(() => {
107
+ console.log('Killing entire process group...');
108
+ try {
109
+ process.kill(pgid, 'SIGINT');
110
+ } catch (err) {
111
+ console.log('Failed to kill process group, killing child directly');
112
+ child.kill('SIGINT');
113
+ }
114
+ }, 500);
115
+
116
+ child.on('exit', (code, signal) => {
117
+ console.log(`Process exited with code: ${code}, signal: ${signal}`);
118
+ resolve({ stdout, code, signal });
119
+ });
120
+ });
121
+ }
122
+
123
+ // Test 4: Command-stream library SIGINT handling
124
+ async function testCommandStreamSigint() {
125
+ console.log('\nTEST 4: Command-stream library SIGINT');
126
+
127
+ const runner = $`echo "LIBRARY_START" && sleep 30`;
128
+ const promise = runner.start();
129
+
130
+ let output = '';
131
+ runner.on('data', (chunk) => {
132
+ output += chunk.data.toString();
133
+ console.log('Received data:', chunk.data.toString().trim());
134
+ });
135
+
136
+ setTimeout(() => {
137
+ console.log('Killing runner...');
138
+ runner.kill();
139
+ }, 500);
140
+
141
+ try {
142
+ const result = await promise;
143
+ console.log('Command completed normally:', result);
144
+ return { output, result };
145
+ } catch (error) {
146
+ console.log('Command was interrupted:', error.message);
147
+ return { output, error: error.message };
148
+ }
149
+ }
150
+
151
+ // Test 5: Different kill signals
152
+ async function testDifferentSignals() {
153
+ console.log('\nTEST 5: Different signals (SIGINT vs SIGTERM vs SIGKILL)');
154
+
155
+ const signals = ['SIGINT', 'SIGTERM', 'SIGKILL'];
156
+
157
+ for (const signal of signals) {
158
+ console.log(`\nTesting ${signal}:`);
159
+
160
+ await new Promise((resolve) => {
161
+ const child = spawn('sh', ['-c', 'sleep 30'], {
162
+ stdio: 'ignore',
163
+ detached: true,
164
+ });
165
+
166
+ console.log(`Started PID ${child.pid}`);
167
+
168
+ setTimeout(() => {
169
+ console.log(`Sending ${signal}...`);
170
+ child.kill(signal);
171
+ }, 100);
172
+
173
+ child.on('exit', (code, sig) => {
174
+ console.log(`Exit: code=${code}, signal=${sig}`);
175
+ resolve();
176
+ });
177
+ });
178
+ }
179
+ }
180
+
181
+ // Test 6: Platform-specific behavior
182
+ async function testPlatformSpecific() {
183
+ console.log('\nTEST 6: Platform-specific SIGINT behavior');
184
+
185
+ console.log('Platform:', process.platform);
186
+ console.log('Node version:', process.version);
187
+
188
+ // macOS vs Linux might handle signals differently
189
+ if (process.platform === 'darwin') {
190
+ console.log('macOS: Testing with /bin/sleep');
191
+ const child = spawn('/bin/sleep', ['30'], {
192
+ stdio: 'ignore',
193
+ });
194
+
195
+ setTimeout(() => {
196
+ child.kill('SIGINT');
197
+ }, 100);
198
+
199
+ await new Promise((resolve) => {
200
+ child.on('exit', (code, signal) => {
201
+ console.log(`macOS /bin/sleep exit: code=${code}, signal=${signal}`);
202
+ resolve();
203
+ });
204
+ });
205
+ } else {
206
+ console.log('Linux: Testing with sleep command');
207
+ const child = spawn('sleep', ['30'], {
208
+ stdio: 'ignore',
209
+ });
210
+
211
+ setTimeout(() => {
212
+ child.kill('SIGINT');
213
+ }, 100);
214
+
215
+ await new Promise((resolve) => {
216
+ child.on('exit', (code, signal) => {
217
+ console.log(`Linux sleep exit: code=${code}, signal=${signal}`);
218
+ resolve();
219
+ });
220
+ });
221
+ }
222
+ }
223
+
224
+ // Main execution
225
+ async function main() {
226
+ try {
227
+ await testBasicShellSigint();
228
+ await testShellWithTrap();
229
+ await testProcessGroup();
230
+ await testCommandStreamSigint();
231
+ await testDifferentSignals();
232
+ await testPlatformSpecific();
233
+
234
+ console.log('\n✅ All SIGINT tests completed');
235
+ } catch (error) {
236
+ console.error('❌ Test failed:', error);
237
+ process.exit(1);
238
+ }
239
+ }
240
+
241
+ main();
@@ -0,0 +1,14 @@
1
+ #!/bin/sh
2
+
3
+ # Example: Test SIGINT handling in shell scripts
4
+ # This script demonstrates proper SIGINT handling with trap
5
+
6
+ echo "BASELINE_START"
7
+
8
+ # Set up signal handler
9
+ trap 'echo "Got SIGINT"; exit 130' INT
10
+
11
+ echo "Sleeping for 30 seconds (send SIGINT to interrupt)..."
12
+ sleep 30
13
+
14
+ echo "Sleep completed normally"
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env bun
2
+
3
+ import { $ } from '../src/$.mjs';
4
+
5
+ console.log('Simple pipe test:');
6
+
7
+ const result = await $`echo hello | cat`;
8
+ console.log('Result:', result.stdout);
9
+
10
+ console.log('\nPipe with jq:');
11
+ const result2 = await $`echo '{"x":1}' | jq .`;
12
+ console.log('Result:', result2.stdout);
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { $ } from '../src/$.mjs';
4
+ import { trace } from '../src/$.utils.mjs';
5
+
6
+ async function testSimpleStreaming() {
7
+ trace('TestExample', '🧪 Testing simple streaming after fix');
8
+
9
+ // Test 1: Basic stdin control
10
+ const sortCmd = $`sort`;
11
+ const stdin = await sortCmd.streams.stdin;
12
+
13
+ stdin.write('zebra\n');
14
+ stdin.write('apple\n');
15
+ stdin.end();
16
+
17
+ const result = await sortCmd;
18
+ trace('TestExample', () => `✅ Sort result: ${result.stdout}`);
19
+
20
+ // Test 2: Grep filter
21
+ const grepCmd = $`grep "test"`;
22
+ const grepStdin = await grepCmd.streams.stdin;
23
+
24
+ grepStdin.write('no match\n');
25
+ grepStdin.write('this is test\n');
26
+ grepStdin.end();
27
+
28
+ const grepResult = await grepCmd;
29
+ trace('TestExample', () => `✅ Grep result: ${grepResult.stdout}`);
30
+ }
31
+
32
+ testSimpleStreaming();
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Test script that reads the module code from stdin
4
+ // This avoids ES module import issues in CI
5
+
6
+ console.error('[test-sleep-stdin] Process started, PID:', process.pid);
7
+ console.error('[test-sleep-stdin] Node version:', process.version);
8
+
9
+ // Read the module code to eval from stdin
10
+ let moduleCode = '';
11
+ process.stdin.on('data', (chunk) => {
12
+ moduleCode += chunk.toString();
13
+ });
14
+
15
+ process.stdin.on('end', async () => {
16
+ try {
17
+ console.error('[test-sleep-stdin] Evaluating module code...');
18
+ // Create an async function to evaluate the code
19
+ const AsyncFunction = Object.getPrototypeOf(async () => {}).constructor;
20
+ const runTest = new AsyncFunction('require', 'process', moduleCode);
21
+ await runTest(require, process);
22
+ } catch (error) {
23
+ console.error('[test-sleep-stdin] Error:', error.message);
24
+ console.log('STARTING_SLEEP'); // Still output for test
25
+ process.exit(1);
26
+ }
27
+ });