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