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,53 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { $, shell, enableVirtualCommands } from '../src/$.mjs';
4
+
5
+ enableVirtualCommands();
6
+ shell.verbose(true);
7
+
8
+ console.log('=== Testing Shell Operators with cd ===\n');
9
+
10
+ const originalCwd = process.cwd();
11
+
12
+ console.log('Test 1: && operator (AND - run next if previous succeeds)');
13
+ console.log('Command: cd /tmp && pwd');
14
+ const result1 = await $`cd /tmp && pwd`;
15
+ console.log('Output:', result1.stdout);
16
+ console.log('After command, cwd is:', process.cwd());
17
+ console.log();
18
+
19
+ // Reset
20
+ process.chdir(originalCwd);
21
+
22
+ console.log('Test 2: || operator (OR - run next if previous fails)');
23
+ console.log('Command: cd /nonexistent || echo "failed to cd"');
24
+ const result2 = await $`cd /nonexistent || echo "failed to cd"`;
25
+ console.log('Output:', result2.stdout);
26
+ console.log();
27
+
28
+ console.log('Test 3: ; operator (semicolon - run regardless)');
29
+ console.log('Command: cd /tmp ; pwd ; cd /usr ; pwd');
30
+ const result3 = await $`cd /tmp ; pwd ; cd /usr ; pwd`;
31
+ console.log('Output:', result3.stdout);
32
+ console.log('After command, cwd is:', process.cwd());
33
+ console.log();
34
+
35
+ // Reset
36
+ process.chdir(originalCwd);
37
+
38
+ console.log('Test 4: Subshell with ()');
39
+ console.log('Command: (cd /tmp && pwd) ; pwd');
40
+ const result4 = await $`(cd /tmp && pwd) ; pwd`;
41
+ console.log('Output:', result4.stdout);
42
+ console.log('After command, cwd is:', process.cwd());
43
+ console.log();
44
+
45
+ console.log('Test 5: Complex chain');
46
+ console.log('Command: cd /tmp && echo "in tmp" && cd /usr && echo "in usr"');
47
+ const result5 = await $`cd /tmp && echo "in tmp" && cd /usr && echo "in usr"`;
48
+ console.log('Output:', result5.stdout);
49
+ console.log('After command, cwd is:', process.cwd());
50
+
51
+ // Reset to original
52
+ process.chdir(originalCwd);
53
+ console.log('\n=== Tests Complete ===');
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Test that parent process continues after child is interrupted
4
+
5
+ import { $ } from '../src/$.mjs';
6
+
7
+ async function test() {
8
+ console.log('Testing that parent continues after child interruption...\n');
9
+
10
+ // Start first command
11
+ console.log('1. Starting first sleep command...');
12
+ const runner1 = $`sleep 5`;
13
+ const promise1 = runner1.start();
14
+
15
+ // Kill it after 500ms
16
+ setTimeout(() => {
17
+ console.log(' Killing first command...');
18
+ runner1.kill();
19
+ }, 500);
20
+
21
+ const result1 = await promise1;
22
+ console.log(` First command finished with code: ${result1.code}`);
23
+
24
+ // Parent continues - start another command
25
+ console.log('\n2. Parent continues - starting second command...');
26
+ const runner2 = $`echo "Parent is still alive!"`;
27
+ const result2 = await runner2;
28
+ console.log(` Second command output: ${result2.stdout.trim()}`);
29
+ console.log(` Second command finished with code: ${result2.code}`);
30
+
31
+ // Start a third command to prove we're still running
32
+ console.log('\n3. Starting third command...');
33
+ const result3 = await $`echo "Still running after interruption"`;
34
+ console.log(` Third command output: ${result3.stdout.trim()}`);
35
+
36
+ console.log(
37
+ '\n✓ SUCCESS: Parent process continued running after child interruption'
38
+ );
39
+ console.log(
40
+ "This is the correct behavior - parent doesn't exit on child SIGINT"
41
+ );
42
+ }
43
+
44
+ test().catch(console.error);
@@ -0,0 +1,86 @@
1
+ import { $ } from '../src/$.mjs';
2
+
3
+ console.log('=== Testing Path Interpolation Issues ===\n');
4
+
5
+ async function testPathInterpolation() {
6
+ // Test 1: Simple path with no spaces
7
+ console.log('1. Testing simple path interpolation:');
8
+ const simplePath = '/bin/echo';
9
+ try {
10
+ const result1 = await $`${simplePath} "simple test"`;
11
+ console.log('✅ Simple path works:', result1.stdout.trim());
12
+ } catch (error) {
13
+ console.log('❌ Simple path failed:', error.message);
14
+ }
15
+
16
+ // Test 2: Path with spaces (like the .claude directory)
17
+ console.log('\n2. Testing path with spaces:');
18
+ const pathWithSpaces = '/usr/bin/env';
19
+ try {
20
+ const result2 = await $`${pathWithSpaces} echo "space test"`;
21
+ console.log('✅ Path with env works:', result2.stdout.trim());
22
+ } catch (error) {
23
+ console.log('❌ Path with env failed:', error.message);
24
+ }
25
+
26
+ // Test 3: Simulate the exact issue - path that might have quotes
27
+ console.log('\n3. Testing problematic path structure:');
28
+ const problematicPath = '/nonexistent/path/to/claude';
29
+ try {
30
+ const result3 = await $`${problematicPath} --version`;
31
+ console.log('✅ Problematic path works:', result3.stdout.trim());
32
+ } catch (error) {
33
+ console.log('❌ Problematic path failed:', error.message);
34
+ console.log('Error details:', error);
35
+ }
36
+
37
+ // Test 4: Check what command gets built
38
+ console.log('\n4. Testing command building:');
39
+ const testPath = '/Users/test/.claude/local/claude';
40
+ console.log('Variable value:', JSON.stringify(testPath));
41
+
42
+ try {
43
+ // Create command but don't execute
44
+ const cmd = $`${testPath} --help`;
45
+ console.log('Command spec:', cmd.spec);
46
+ } catch (error) {
47
+ console.log('❌ Command building failed:', error.message);
48
+ }
49
+
50
+ // Test 5: Environment variable usage
51
+ console.log('\n5. Testing environment variable:');
52
+ process.env.TEST_CLAUDE_PATH = '/usr/bin/echo';
53
+ const claudeFromEnv = process.env.TEST_CLAUDE_PATH;
54
+ console.log('Env var value:', JSON.stringify(claudeFromEnv));
55
+
56
+ try {
57
+ const result5 = await $`${claudeFromEnv} "env test"`;
58
+ console.log('✅ Env var path works:', result5.stdout.trim());
59
+ } catch (error) {
60
+ console.log('❌ Env var path failed:', error.message);
61
+ }
62
+
63
+ // Test 6: Test with stdin like the failing script
64
+ console.log('\n6. Testing with stdin (like failing script):');
65
+ try {
66
+ const result6 = await $({ stdin: 'test input\n', mirror: false })`/bin/cat`;
67
+ console.log('✅ Stdin test works:', result6.stdout.trim());
68
+ } catch (error) {
69
+ console.log('❌ Stdin test failed:', error.message);
70
+ }
71
+
72
+ // Test 7: Check raw command string
73
+ console.log('\n7. Checking command string generation:');
74
+ const testCmd = '/usr/bin/which';
75
+ console.log('Raw variable:', JSON.stringify(testCmd));
76
+ try {
77
+ const cmd = $`${testCmd} node`;
78
+ console.log('Generated command:', cmd.spec?.command || 'Not available');
79
+ const result = await cmd;
80
+ console.log('✅ Command string test works');
81
+ } catch (error) {
82
+ console.log('❌ Command string test failed:', error.message);
83
+ }
84
+ }
85
+
86
+ testPathInterpolation().catch(console.error);
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Simple test to verify:
5
+ * 1. streams.stdin can be used to send data to commands that read stdin
6
+ * 2. kill() method works to interrupt ping commands
7
+ */
8
+
9
+ import { $ } from '../src/$.mjs';
10
+
11
+ console.log('=== Testing ping kill() and streams.stdin ===');
12
+ console.log('');
13
+
14
+ async function testPingKillAndStdin() {
15
+ try {
16
+ console.log('TEST 1: Use kill() method to interrupt ping 8.8.8.8');
17
+
18
+ const pingCommand = $`ping 8.8.8.8`;
19
+
20
+ // Access streams.stdout to auto-start the command
21
+ const stdout = pingCommand.streams.stdout;
22
+ console.log('✓ Accessed streams.stdout - ping should start');
23
+ console.log(' Started?', pingCommand.started);
24
+
25
+ // Wait for ping to produce some output
26
+ await new Promise((resolve) => setTimeout(resolve, 1500));
27
+
28
+ // Kill the ping command
29
+ console.log('✓ Killing ping command...');
30
+ pingCommand.kill();
31
+
32
+ const result = await pingCommand;
33
+ console.log('✓ Ping killed with exit code:', result.code);
34
+ console.log('✓ Output received (length):', result.stdout.length);
35
+ console.log(
36
+ '✓ First 100 chars:',
37
+ JSON.stringify(result.stdout.slice(0, 100))
38
+ );
39
+
40
+ console.log('');
41
+ console.log('TEST 2: Send data via streams.stdin to cat');
42
+
43
+ const catCommand = $`cat`;
44
+
45
+ // Access stdin to auto-start and get the stream
46
+ const stdin = catCommand.streams.stdin;
47
+ console.log('✓ Accessed streams.stdin - cat should start');
48
+ console.log(' Started?', catCommand.started);
49
+
50
+ // Send data to cat
51
+ if (stdin) {
52
+ console.log('✓ Writing data to stdin...');
53
+ stdin.write('Hello from stdin!\\n');
54
+ stdin.write('Second line\\n');
55
+ stdin.end(); // Close stdin so cat finishes
56
+ }
57
+
58
+ const catResult = await catCommand;
59
+ console.log('✓ Cat completed with exit code:', catResult.code);
60
+ console.log('✓ Cat output:', JSON.stringify(catResult.stdout));
61
+
62
+ console.log('');
63
+ console.log(
64
+ 'TEST 3: Verify stdin is available but process not started initially'
65
+ );
66
+
67
+ const echoCommand = $`cat`;
68
+ console.log('✓ Command created, started?', echoCommand.started);
69
+
70
+ // Just access streams object (should not auto-start)
71
+ const streams = echoCommand.streams;
72
+ console.log('✓ Accessed .streams object, started?', echoCommand.started);
73
+
74
+ // Now access stdin (should auto-start)
75
+ const echoStdin = echoCommand.streams.stdin;
76
+ console.log('✓ Accessed .streams.stdin, started?', echoCommand.started);
77
+
78
+ if (echoStdin) {
79
+ echoStdin.write('Auto-start test\\n');
80
+ echoStdin.end();
81
+ }
82
+
83
+ const echoResult = await echoCommand;
84
+ console.log('✓ Result:', JSON.stringify(echoResult.stdout));
85
+
86
+ console.log('');
87
+ console.log(
88
+ '✅ ALL TESTS PASSED - ping kill() and streams.stdin work correctly!'
89
+ );
90
+ } catch (error) {
91
+ console.log('');
92
+ console.error('❌ TEST FAILED:', error.message);
93
+ console.error(error.stack);
94
+ process.exit(1);
95
+ }
96
+ }
97
+
98
+ testPingKillAndStdin();
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Test ping example similar to hive-mind/claude-pipe/test-ping.mjs
4
+ import { $ } from '../src/$.mjs';
5
+
6
+ console.log('STARTING_PING');
7
+ try {
8
+ await $`ping 8.8.8.8`;
9
+ } catch (error) {
10
+ console.error('❌ Test failed:', error.message);
11
+ process.exit(1);
12
+ }
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env bun
2
+
3
+ // Test if Bun has PTY support or if we can fake it
4
+
5
+ console.log('=== Testing PTY/TTY Solutions ===\n');
6
+
7
+ // Check if Bun has PTY support
8
+ console.log('Checking Bun APIs for PTY support:');
9
+ console.log(
10
+ ' Bun.spawn options:',
11
+ Object.keys(Bun.spawn(['echo'], { stdout: 'pipe' }))
12
+ );
13
+
14
+ // Try using script command as a PTY wrapper
15
+ console.log('\nUsing script command as PTY wrapper:');
16
+ {
17
+ const start = Date.now();
18
+ let chunkCount = 0;
19
+
20
+ // Use script to create a PTY
21
+ // -q: quiet mode (no script started/done messages)
22
+ // /dev/null: don't save typescript file
23
+ const proc = Bun.spawn(
24
+ [
25
+ 'script',
26
+ '-q',
27
+ '/dev/null',
28
+ 'sh',
29
+ '-c',
30
+ 'bun run js/examples/emulate-claude-stream.mjs | jq .',
31
+ ],
32
+ {
33
+ stdout: 'pipe',
34
+ stderr: 'pipe',
35
+ env: {
36
+ ...process.env,
37
+ // Force color/TTY detection
38
+ FORCE_COLOR: '1',
39
+ TERM: 'xterm-256color',
40
+ },
41
+ }
42
+ );
43
+
44
+ for await (const chunk of proc.stdout) {
45
+ chunkCount++;
46
+ const elapsed = Date.now() - start;
47
+ const text = Buffer.from(chunk).toString();
48
+
49
+ // Script adds control characters, let's see what we get
50
+ const cleanText = text.replace(/\x1b\[[0-9;]*m/g, ''); // Remove ANSI codes
51
+ const lines = cleanText
52
+ .split('\n')
53
+ .filter((l) => l.trim())
54
+ .slice(0, 2);
55
+
56
+ console.log(` [${elapsed}ms] Chunk ${chunkCount}: ${chunk.length} bytes`);
57
+ if (lines.length > 0) {
58
+ console.log(` First lines:`, lines);
59
+ }
60
+ }
61
+
62
+ await proc.exited;
63
+ console.log(` Total chunks: ${chunkCount}`);
64
+ }
65
+
66
+ // Alternative: Try to use COLUMNS/LINES env vars to fake TTY
67
+ console.log('\nTrying with TTY environment variables:');
68
+ {
69
+ const start = Date.now();
70
+ let chunkCount = 0;
71
+
72
+ const proc = Bun.spawn(
73
+ ['sh', '-c', 'bun run js/examples/emulate-claude-stream.mjs | jq .'],
74
+ {
75
+ stdout: 'pipe',
76
+ stderr: 'pipe',
77
+ env: {
78
+ ...process.env,
79
+ COLUMNS: '80',
80
+ LINES: '24',
81
+ TERM: 'xterm-256color',
82
+ FORCE_COLOR: '1',
83
+ },
84
+ }
85
+ );
86
+
87
+ for await (const chunk of proc.stdout) {
88
+ chunkCount++;
89
+ const elapsed = Date.now() - start;
90
+ const text = Buffer.from(chunk).toString();
91
+ const lines = text
92
+ .split('\n')
93
+ .filter((l) => l.trim())
94
+ .slice(0, 2);
95
+
96
+ console.log(` [${elapsed}ms] Chunk ${chunkCount}: first lines:`, lines);
97
+ }
98
+
99
+ await proc.exited;
100
+ console.log(` Total chunks: ${chunkCount}`);
101
+ }
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env bun
2
+
3
+ // Test using unbuffer or script to create a pseudo-TTY
4
+
5
+ console.log('Test: Using unbuffer to force line buffering\n');
6
+
7
+ const proc1 = Bun.spawn(['./js/examples/emulate-claude-stream.mjs'], {
8
+ stdout: 'pipe',
9
+ stderr: 'pipe',
10
+ });
11
+
12
+ // Try using unbuffer (if available) to force line buffering
13
+ // unbuffer is part of the expect package
14
+ const proc2 = Bun.spawn(['unbuffer', 'jq', '.'], {
15
+ stdin: proc1.stdout,
16
+ stdout: 'pipe',
17
+ stderr: 'pipe',
18
+ });
19
+
20
+ const start = Date.now();
21
+ let chunkCount = 0;
22
+
23
+ for await (const chunk of proc2.stdout) {
24
+ chunkCount++;
25
+ const elapsed = Date.now() - start;
26
+ const text = Buffer.from(chunk).toString();
27
+ const lines = text
28
+ .split('\n')
29
+ .filter((l) => l.trim())
30
+ .slice(0, 2);
31
+
32
+ console.log(`[${elapsed}ms] Chunk ${chunkCount}: First lines:`, lines);
33
+ }
34
+
35
+ console.log(`\nTotal chunks received: ${chunkCount}`);
36
+
37
+ await proc1.exited;
38
+ await proc2.exited;
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Comprehensive test of the smart quoting behavior
4
+ import { $ } from '../src/$.mjs';
5
+
6
+ console.log('=== Smart Quoting Behavior Summary ===\n');
7
+
8
+ const tests = [
9
+ {
10
+ category: 'SAFE STRINGS (No quotes needed)',
11
+ tests: [
12
+ { input: 'hello', expected: 'hello' },
13
+ { input: '/usr/bin/echo', expected: '/usr/bin/echo' },
14
+ { input: 'file.txt', expected: 'file.txt' },
15
+ { input: 'user@host.com', expected: 'user@host.com' },
16
+ { input: 'key=value', expected: 'key=value' },
17
+ { input: '192.168.1.1', expected: '192.168.1.1' },
18
+ { input: 'v1.2.3-beta', expected: 'v1.2.3-beta' },
19
+ ],
20
+ },
21
+
22
+ {
23
+ category: 'UNSAFE STRINGS (Auto-quoted)',
24
+ tests: [
25
+ { input: 'hello world', expected: "'hello world'" },
26
+ { input: '$HOME', expected: "'$HOME'" },
27
+ { input: '$(whoami)', expected: "'$(whoami)'" },
28
+ { input: '`date`', expected: "'`date`'" },
29
+ { input: 'test; ls', expected: "'test; ls'" },
30
+ { input: 'a|b', expected: "'a|b'" },
31
+ { input: 'a&b', expected: "'a&b'" },
32
+ { input: 'a>b', expected: "'a>b'" },
33
+ { input: '*.txt', expected: "'*.txt'" },
34
+ { input: 'a b c', expected: "'a b c'" },
35
+ ],
36
+ },
37
+
38
+ {
39
+ category: 'USER-PROVIDED SINGLE QUOTES (Preserved)',
40
+ tests: [
41
+ { input: "'hello'", expected: "'hello'" },
42
+ { input: "'hello world'", expected: "'hello world'" },
43
+ { input: "'$HOME'", expected: "'$HOME'" },
44
+ { input: "'/path with spaces/cmd'", expected: "'/path with spaces/cmd'" },
45
+ { input: "'test; echo BAD'", expected: "'test; echo BAD'" },
46
+ ],
47
+ },
48
+
49
+ {
50
+ category: 'USER-PROVIDED DOUBLE QUOTES (Wrapped)',
51
+ tests: [
52
+ { input: '"hello"', expected: '\'"hello"\'' },
53
+ { input: '"hello world"', expected: '\'"hello world"\'' },
54
+ { input: '"$HOME"', expected: '\'"$HOME"\'' },
55
+ {
56
+ input: '"/path with spaces/cmd"',
57
+ expected: '\'"/path with spaces/cmd"\'',
58
+ },
59
+ { input: '"test; echo BAD"', expected: '\'"test; echo BAD"\'' },
60
+ ],
61
+ },
62
+
63
+ {
64
+ category: 'COMPLEX CASES',
65
+ tests: [
66
+ { input: "it's", expected: "'it'\\''s'" },
67
+ { input: "'it's'", expected: "''\\''it'\\''s'\\'''" }, // Invalid quoted string, needs re-escaping
68
+ { input: '""', expected: '\'""\'' },
69
+ { input: "''", expected: "''" },
70
+ { input: "'", expected: "''\\'''" },
71
+ { input: '"', expected: "'\"'" },
72
+ ],
73
+ },
74
+ ];
75
+
76
+ let totalPassed = 0;
77
+ let totalFailed = 0;
78
+
79
+ tests.forEach(({ category, tests: categoryTests }) => {
80
+ console.log(`\n${category}`);
81
+ console.log('='.repeat(category.length));
82
+
83
+ categoryTests.forEach(({ input, expected }) => {
84
+ const cmd = $({ mirror: false })`echo ${input}`;
85
+ const actual = cmd.spec.command.replace('echo ', '');
86
+ const passed = actual === expected;
87
+
88
+ if (passed) {
89
+ console.log(`✅ ${input.padEnd(25)} → ${actual}`);
90
+ totalPassed++;
91
+ } else {
92
+ console.log(`❌ ${input.padEnd(25)} → ${actual} (expected: ${expected})`);
93
+ totalFailed++;
94
+ }
95
+ });
96
+ });
97
+
98
+ console.log(`\n${'='.repeat(50)}`);
99
+ console.log(`TOTAL: ${totalPassed} passed, ${totalFailed} failed`);
100
+
101
+ if (totalFailed === 0) {
102
+ console.log('\n🎉 All quoting behaviors work as expected!');
103
+ console.log('\nKey features:');
104
+ console.log('✓ No unnecessary quoting for safe strings');
105
+ console.log('✓ Automatic quoting for strings with special characters');
106
+ console.log('✓ User-provided single quotes are preserved');
107
+ console.log('✓ User-provided double quotes are preserved (wrapped)');
108
+ console.log('✓ No double-quoting when user already quoted');
109
+ console.log('✓ Shell injection protection maintained');
110
+ }
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Test quoting edge cases for issue #12
4
+ import { $ } from '../src/$.mjs';
5
+
6
+ console.log('=== Testing Quote Edge Cases for Issue #12 ===\n');
7
+
8
+ async function testCommands() {
9
+ // Test 1: Path as command (should NOT be quoted)
10
+ console.log('1. Testing path as command:');
11
+ const path = '/bin/echo';
12
+ try {
13
+ const result = await $`${path} "hello from echo"`;
14
+ console.log('✓ Success:', String(result).trim());
15
+ } catch (error) {
16
+ console.error('✗ Failed:', error.message);
17
+ }
18
+
19
+ // Test 2: Path with spaces (needs special handling)
20
+ console.log('\n2. Testing path with spaces:');
21
+ const spacePath = '/path with spaces/bin/echo';
22
+ try {
23
+ // This should fail since the path doesn't exist, but check the error message
24
+ const result = await $`${spacePath} "test"`;
25
+ console.log('Result:', String(result).trim());
26
+ } catch (error) {
27
+ console.error('Expected failure:', error.message);
28
+ // Check if quotes are doubled in the error
29
+ if (error.message.includes("''")) {
30
+ console.log('⚠️ Double quotes detected in error!');
31
+ }
32
+ }
33
+
34
+ // Test 3: Command with arguments
35
+ console.log('\n3. Testing command with multiple interpolations:');
36
+ const cmd = 'echo';
37
+ const arg1 = 'hello';
38
+ const arg2 = 'world';
39
+ try {
40
+ const result = await $`${cmd} ${arg1} ${arg2}`;
41
+ console.log('✓ Success:', String(result).trim());
42
+ } catch (error) {
43
+ console.error('✗ Failed:', error.message);
44
+ }
45
+
46
+ // Test 4: First interpolation is command, should not be quoted
47
+ console.log('\n4. Testing first interpolation as command:');
48
+ const ls = 'ls';
49
+ try {
50
+ const result = await $`${ls} -la`.pipe($`head -n 3`);
51
+ console.log('✓ Success, got listing');
52
+ } catch (error) {
53
+ console.error('✗ Failed:', error.message);
54
+ }
55
+
56
+ // Test 5: Complex command construction
57
+ console.log('\n5. Testing complex command:');
58
+ const executable = '/usr/bin/env';
59
+ const program = 'node';
60
+ const flag = '--version';
61
+ try {
62
+ const result = await $`${executable} ${program} ${flag}`;
63
+ console.log('✓ Success:', String(result).trim());
64
+ } catch (error) {
65
+ console.error('✗ Failed:', error.message);
66
+ }
67
+ }
68
+
69
+ testCommands().catch(console.error);
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { parseShellCommand } from '../src/shell-parser.mjs';
4
+
5
+ const tests = [
6
+ 'cd "/tmp/my dir"',
7
+ 'cd /tmp/my\\ dir',
8
+ "cd '/tmp/my dir'",
9
+ 'echo "hello world"',
10
+ ];
11
+
12
+ console.log('=== Testing quote parsing ===\n');
13
+
14
+ for (const cmd of tests) {
15
+ console.log(`Command: ${cmd}`);
16
+ const parsed = parseShellCommand(cmd);
17
+ console.log('Parsed:', JSON.stringify(parsed, null, 2));
18
+
19
+ if (parsed && parsed.type === 'simple' && parsed.args.length > 0) {
20
+ console.log('First arg value:', parsed.args[0].value);
21
+ }
22
+ console.log();
23
+ }