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,265 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Example: Testing baseline spawn behavior vs command-stream library
|
|
5
|
+
*
|
|
6
|
+
* Problem: When tests fail in CI, it's important to determine if the issue
|
|
7
|
+
* is with the library or with the underlying Node.js spawn behavior.
|
|
8
|
+
*
|
|
9
|
+
* Solution: Test both baseline (raw spawn) and library functionality to compare.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { spawn } from 'child_process';
|
|
13
|
+
import { $ } from '../src/$.mjs';
|
|
14
|
+
|
|
15
|
+
console.log('Testing baseline vs library behavior');
|
|
16
|
+
|
|
17
|
+
// Example 1: Baseline spawn test (no library)
|
|
18
|
+
async function testBaselineSpawn() {
|
|
19
|
+
console.log('\nTEST 1: Baseline spawn (no command-stream)');
|
|
20
|
+
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
const child = spawn('echo', ['baseline test'], {
|
|
23
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
let stdout = '';
|
|
27
|
+
let stderr = '';
|
|
28
|
+
|
|
29
|
+
child.stdout.on('data', (data) => {
|
|
30
|
+
stdout += data.toString();
|
|
31
|
+
console.log('Baseline stdout:', data.toString().trim());
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
child.stderr.on('data', (data) => {
|
|
35
|
+
stderr += data.toString();
|
|
36
|
+
console.log('Baseline stderr:', data.toString().trim());
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
child.on('exit', (code, signal) => {
|
|
40
|
+
console.log(`Baseline exit: code=${code}, signal=${signal}`);
|
|
41
|
+
if (code === 0) {
|
|
42
|
+
resolve({ stdout, stderr, code });
|
|
43
|
+
} else {
|
|
44
|
+
reject(new Error(`Baseline failed: ${code}/${signal}`));
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
child.on('error', (error) => {
|
|
49
|
+
console.log('Baseline error:', error.message);
|
|
50
|
+
reject(error);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Example 2: Library test (using command-stream)
|
|
56
|
+
async function testLibrary() {
|
|
57
|
+
console.log('\nTEST 2: Library test (using command-stream)');
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
const result = await $`echo "library test"`;
|
|
61
|
+
console.log('Library stdout:', result.stdout.trim());
|
|
62
|
+
console.log(`Library exit: code=${result.code}`);
|
|
63
|
+
return result;
|
|
64
|
+
} catch (error) {
|
|
65
|
+
console.log('Library error:', error.message);
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Example 3: Signal handling comparison
|
|
71
|
+
async function testSignalHandlingComparison() {
|
|
72
|
+
console.log('\nTEST 3: Signal handling comparison');
|
|
73
|
+
|
|
74
|
+
// Baseline signal handling
|
|
75
|
+
console.log('3a. Baseline signal handling:');
|
|
76
|
+
const baselineChild = spawn('sleep', ['30'], {
|
|
77
|
+
stdio: 'inherit',
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
setTimeout(() => {
|
|
81
|
+
console.log('Sending SIGTERM to baseline child...');
|
|
82
|
+
baselineChild.kill('SIGTERM');
|
|
83
|
+
}, 1000);
|
|
84
|
+
|
|
85
|
+
await new Promise((resolve) => {
|
|
86
|
+
baselineChild.on('exit', (code, signal) => {
|
|
87
|
+
console.log(`Baseline exited: code=${code}, signal=${signal}`);
|
|
88
|
+
resolve();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Library signal handling
|
|
93
|
+
console.log('3b. Library signal handling:');
|
|
94
|
+
const runner = $`sleep 30`;
|
|
95
|
+
const promise = runner.start();
|
|
96
|
+
|
|
97
|
+
setTimeout(() => {
|
|
98
|
+
console.log('Sending kill to library runner...');
|
|
99
|
+
runner.kill();
|
|
100
|
+
}, 1000);
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
await promise;
|
|
104
|
+
} catch (error) {
|
|
105
|
+
console.log(`Library exited: ${error.message}`);
|
|
106
|
+
}
|
|
107
|
+
console.log(`Library finished: ${runner.finished}`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Example 4: Streaming comparison
|
|
111
|
+
async function testStreamingComparison() {
|
|
112
|
+
console.log('\nTEST 4: Streaming output comparison');
|
|
113
|
+
|
|
114
|
+
// Baseline streaming
|
|
115
|
+
console.log('4a. Baseline streaming:');
|
|
116
|
+
await new Promise((resolve) => {
|
|
117
|
+
const child = spawn(
|
|
118
|
+
'sh',
|
|
119
|
+
['-c', 'for i in 1 2 3; do echo "baseline $i"; sleep 0.1; done'],
|
|
120
|
+
{
|
|
121
|
+
stdio: 'pipe',
|
|
122
|
+
}
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
child.stdout.on('data', (chunk) => {
|
|
126
|
+
process.stdout.write(`[Baseline chunk]: ${chunk}`);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
child.on('exit', resolve);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// Library streaming
|
|
133
|
+
console.log('4b. Library streaming:');
|
|
134
|
+
const runner = $`sh -c 'for i in 1 2 3; do echo "library $i"; sleep 0.1; done'`;
|
|
135
|
+
|
|
136
|
+
for await (const chunk of runner.stream()) {
|
|
137
|
+
process.stdout.write(`[Library chunk]: ${chunk.data}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Example 5: Error handling comparison
|
|
142
|
+
async function testErrorHandlingComparison() {
|
|
143
|
+
console.log('\nTEST 5: Error handling comparison');
|
|
144
|
+
|
|
145
|
+
// Baseline error handling
|
|
146
|
+
console.log('5a. Baseline error handling:');
|
|
147
|
+
try {
|
|
148
|
+
await new Promise((resolve, reject) => {
|
|
149
|
+
const child = spawn('false', [], { stdio: 'inherit' });
|
|
150
|
+
child.on('exit', (code) => {
|
|
151
|
+
if (code !== 0) {
|
|
152
|
+
reject(new Error(`Command failed with code ${code}`));
|
|
153
|
+
} else {
|
|
154
|
+
resolve();
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
} catch (error) {
|
|
159
|
+
console.log('Baseline error caught:', error.message);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Library error handling
|
|
163
|
+
console.log('5b. Library error handling:');
|
|
164
|
+
try {
|
|
165
|
+
await $`false`;
|
|
166
|
+
} catch (error) {
|
|
167
|
+
console.log('Library error caught:', error.message);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Example 6: CI-specific differences
|
|
172
|
+
async function testCISpecificDifferences() {
|
|
173
|
+
console.log('\nTEST 6: CI-specific behavior differences');
|
|
174
|
+
|
|
175
|
+
const isCI = process.env.CI === 'true';
|
|
176
|
+
const isTTY = process.stdout.isTTY;
|
|
177
|
+
|
|
178
|
+
console.log(`Environment: CI=${isCI}, TTY=${isTTY}`);
|
|
179
|
+
|
|
180
|
+
// Test that might behave differently in CI
|
|
181
|
+
const testScript = `
|
|
182
|
+
if [ -t 0 ]; then
|
|
183
|
+
echo "TTY detected"
|
|
184
|
+
else
|
|
185
|
+
echo "No TTY (typical in CI)"
|
|
186
|
+
fi
|
|
187
|
+
`;
|
|
188
|
+
|
|
189
|
+
// Baseline
|
|
190
|
+
console.log('6a. Baseline TTY detection:');
|
|
191
|
+
await new Promise((resolve) => {
|
|
192
|
+
const child = spawn('sh', ['-c', testScript], {
|
|
193
|
+
stdio: 'inherit',
|
|
194
|
+
});
|
|
195
|
+
child.on('exit', resolve);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
// Library
|
|
199
|
+
console.log('6b. Library TTY detection:');
|
|
200
|
+
const result = await $`sh -c ${testScript}`;
|
|
201
|
+
console.log(result.stdout.trim());
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Example 7: Performance comparison
|
|
205
|
+
async function testPerformanceComparison() {
|
|
206
|
+
console.log('\nTEST 7: Performance comparison');
|
|
207
|
+
|
|
208
|
+
const iterations = 10;
|
|
209
|
+
|
|
210
|
+
// Baseline performance
|
|
211
|
+
console.log(`7a. Baseline performance (${iterations} iterations):`);
|
|
212
|
+
const baselineStart = Date.now();
|
|
213
|
+
for (let i = 0; i < iterations; i++) {
|
|
214
|
+
await new Promise((resolve) => {
|
|
215
|
+
const child = spawn('echo', [`test ${i}`], {
|
|
216
|
+
stdio: 'ignore',
|
|
217
|
+
});
|
|
218
|
+
child.on('exit', resolve);
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
const baselineTime = Date.now() - baselineStart;
|
|
222
|
+
console.log(`Baseline time: ${baselineTime}ms`);
|
|
223
|
+
|
|
224
|
+
// Library performance
|
|
225
|
+
console.log(`7b. Library performance (${iterations} iterations):`);
|
|
226
|
+
const libraryStart = Date.now();
|
|
227
|
+
for (let i = 0; i < iterations; i++) {
|
|
228
|
+
await $({ quiet: true })`echo "test ${i}"`;
|
|
229
|
+
}
|
|
230
|
+
const libraryTime = Date.now() - libraryStart;
|
|
231
|
+
console.log(`Library time: ${libraryTime}ms`);
|
|
232
|
+
|
|
233
|
+
console.log(`Overhead: ${libraryTime - baselineTime}ms`);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Run all comparisons
|
|
237
|
+
async function main() {
|
|
238
|
+
console.log('Environment info:');
|
|
239
|
+
console.log(`- Node: ${process.version}`);
|
|
240
|
+
console.log(`- Platform: ${process.platform}`);
|
|
241
|
+
console.log(`- CI: ${process.env.CI || 'false'}`);
|
|
242
|
+
console.log(`- TTY: ${process.stdout.isTTY || false}`);
|
|
243
|
+
|
|
244
|
+
try {
|
|
245
|
+
await testBaselineSpawn();
|
|
246
|
+
await testLibrary();
|
|
247
|
+
await testSignalHandlingComparison();
|
|
248
|
+
await testStreamingComparison();
|
|
249
|
+
await testErrorHandlingComparison();
|
|
250
|
+
await testCISpecificDifferences();
|
|
251
|
+
await testPerformanceComparison();
|
|
252
|
+
|
|
253
|
+
console.log('\n✅ All comparison tests completed successfully');
|
|
254
|
+
console.log('Both baseline and library are working correctly');
|
|
255
|
+
} catch (error) {
|
|
256
|
+
console.error('\n❌ Test failed:', error);
|
|
257
|
+
console.error('This helps identify if the issue is with:');
|
|
258
|
+
console.error('- The library implementation');
|
|
259
|
+
console.error('- The underlying Node.js spawn behavior');
|
|
260
|
+
console.error('- CI environment configuration');
|
|
261
|
+
process.exit(1);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
main();
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Example: Debugging ES module loading failures in CI
|
|
5
|
+
*
|
|
6
|
+
* Problem: In CI environments, child processes spawned with ES module imports
|
|
7
|
+
* sometimes fail immediately with SIGINT or other signals.
|
|
8
|
+
*
|
|
9
|
+
* Solution: Use different approaches for loading modules in child processes.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { spawn } from 'child_process';
|
|
13
|
+
import { $ } from '../src/$.mjs';
|
|
14
|
+
|
|
15
|
+
console.log('Testing ES module loading in child processes');
|
|
16
|
+
|
|
17
|
+
// Example 1: Direct ES module import (may fail in CI)
|
|
18
|
+
async function testDirectESModule() {
|
|
19
|
+
console.log('\nTEST 1: Direct ES module import in child process');
|
|
20
|
+
|
|
21
|
+
const script = `
|
|
22
|
+
import { $ } from '../src/$.mjs';
|
|
23
|
+
console.log('Module loaded successfully');
|
|
24
|
+
const result = await $\`echo "ES module test"\`;
|
|
25
|
+
console.log('Result:', result.stdout);
|
|
26
|
+
`;
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
// This might fail in CI with immediate SIGINT
|
|
30
|
+
const child = spawn('node', ['--input-type=module', '-e', script], {
|
|
31
|
+
stdio: 'inherit',
|
|
32
|
+
cwd: process.cwd(),
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
await new Promise((resolve, reject) => {
|
|
36
|
+
child.on('exit', (code, signal) => {
|
|
37
|
+
if (code === 0) {
|
|
38
|
+
console.log('✓ ES module loaded successfully');
|
|
39
|
+
resolve();
|
|
40
|
+
} else {
|
|
41
|
+
console.log(`✗ Failed with code ${code}, signal ${signal}`);
|
|
42
|
+
reject(new Error(`Process failed: ${code}/${signal}`));
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.log('Expected failure in CI:', error.message);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Example 2: CommonJS fallback approach
|
|
52
|
+
async function testCommonJSFallback() {
|
|
53
|
+
console.log('\nTEST 2: CommonJS-style dynamic import');
|
|
54
|
+
|
|
55
|
+
const script = `
|
|
56
|
+
(async () => {
|
|
57
|
+
try {
|
|
58
|
+
const module = await import('../src/$.mjs');
|
|
59
|
+
const $ = module.$;
|
|
60
|
+
console.log('Module loaded via dynamic import');
|
|
61
|
+
const result = await $\`echo "Dynamic import test"\`;
|
|
62
|
+
console.log('Result:', result.stdout);
|
|
63
|
+
} catch (error) {
|
|
64
|
+
console.error('Import failed:', error.message);
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
})();
|
|
68
|
+
`;
|
|
69
|
+
|
|
70
|
+
const child = spawn('node', ['--input-type=module', '-e', script], {
|
|
71
|
+
stdio: 'inherit',
|
|
72
|
+
cwd: process.cwd(),
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
await new Promise((resolve) => {
|
|
76
|
+
child.on('exit', (code, signal) => {
|
|
77
|
+
console.log(`Process exited with code ${code}, signal ${signal}`);
|
|
78
|
+
resolve();
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Example 3: Simple inline script without imports (most reliable in CI)
|
|
84
|
+
async function testInlineScript() {
|
|
85
|
+
console.log('\nTEST 3: Inline script without ES module imports');
|
|
86
|
+
|
|
87
|
+
const child = spawn(
|
|
88
|
+
'node',
|
|
89
|
+
[
|
|
90
|
+
'-e',
|
|
91
|
+
`
|
|
92
|
+
console.log('INLINE_START');
|
|
93
|
+
setTimeout(() => {
|
|
94
|
+
console.log('INLINE_END');
|
|
95
|
+
process.exit(0);
|
|
96
|
+
}, 100);
|
|
97
|
+
`,
|
|
98
|
+
],
|
|
99
|
+
{
|
|
100
|
+
stdio: 'inherit',
|
|
101
|
+
}
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
await new Promise((resolve) => {
|
|
105
|
+
child.on('exit', (code) => {
|
|
106
|
+
console.log(`✓ Inline script completed with code ${code}`);
|
|
107
|
+
resolve();
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Example 4: Shell command fallback (most compatible)
|
|
113
|
+
async function testShellFallback() {
|
|
114
|
+
console.log('\nTEST 4: Shell command fallback');
|
|
115
|
+
|
|
116
|
+
// Use shell commands directly when ES modules fail
|
|
117
|
+
const child = spawn(
|
|
118
|
+
'sh',
|
|
119
|
+
['-c', 'echo "SHELL_START" && sleep 0.1 && echo "SHELL_END"'],
|
|
120
|
+
{
|
|
121
|
+
stdio: 'inherit',
|
|
122
|
+
}
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
await new Promise((resolve) => {
|
|
126
|
+
child.on('exit', (code) => {
|
|
127
|
+
console.log(`✓ Shell command completed with code ${code}`);
|
|
128
|
+
resolve();
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Example 5: Error handling with detailed diagnostics
|
|
134
|
+
async function testWithDiagnostics() {
|
|
135
|
+
console.log('\nTEST 5: Child process with detailed diagnostics');
|
|
136
|
+
|
|
137
|
+
const script = `
|
|
138
|
+
console.error('[DIAG] Node version:', process.version);
|
|
139
|
+
console.error('[DIAG] Platform:', process.platform);
|
|
140
|
+
console.error('[DIAG] CWD:', process.cwd());
|
|
141
|
+
console.error('[DIAG] Module paths:', module.paths);
|
|
142
|
+
|
|
143
|
+
import('../src/$.mjs').then(
|
|
144
|
+
(module) => {
|
|
145
|
+
console.log('SUCCESS: Module loaded');
|
|
146
|
+
process.exit(0);
|
|
147
|
+
},
|
|
148
|
+
(error) => {
|
|
149
|
+
console.error('FAILURE: Cannot load module');
|
|
150
|
+
console.error('Error:', error.message);
|
|
151
|
+
console.error('Stack:', error.stack);
|
|
152
|
+
process.exit(1);
|
|
153
|
+
}
|
|
154
|
+
);
|
|
155
|
+
`;
|
|
156
|
+
|
|
157
|
+
const child = spawn('node', ['--input-type=module', '-e', script], {
|
|
158
|
+
stdio: 'inherit',
|
|
159
|
+
cwd: process.cwd(),
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
await new Promise((resolve) => {
|
|
163
|
+
child.on('exit', resolve);
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Run all tests
|
|
168
|
+
async function main() {
|
|
169
|
+
console.log('Environment info:');
|
|
170
|
+
console.log('- Node version:', process.version);
|
|
171
|
+
console.log('- Platform:', process.platform);
|
|
172
|
+
console.log('- CI:', process.env.CI || 'false');
|
|
173
|
+
console.log('- GitHub Actions:', process.env.GITHUB_ACTIONS || 'false');
|
|
174
|
+
|
|
175
|
+
await testDirectESModule();
|
|
176
|
+
await testCommonJSFallback();
|
|
177
|
+
await testInlineScript();
|
|
178
|
+
await testShellFallback();
|
|
179
|
+
await testWithDiagnostics();
|
|
180
|
+
|
|
181
|
+
console.log('\nAll tests completed');
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Example: Debugging signal handling issues in CI
|
|
5
|
+
*
|
|
6
|
+
* Problem: SIGINT/SIGTERM signals behave differently in CI environments,
|
|
7
|
+
* especially with process groups and detached processes.
|
|
8
|
+
*
|
|
9
|
+
* Solution: Proper signal forwarding and cleanup strategies.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { spawn } from 'child_process';
|
|
13
|
+
import { $ } from '../src/$.mjs';
|
|
14
|
+
|
|
15
|
+
console.log('Testing signal handling in CI environment');
|
|
16
|
+
|
|
17
|
+
// Example 1: Basic signal forwarding
|
|
18
|
+
async function testBasicSignalForwarding() {
|
|
19
|
+
console.log('\nTEST 1: Basic signal forwarding');
|
|
20
|
+
|
|
21
|
+
const child = spawn('sh', ['-c', 'echo "Starting sleep" && sleep 30'], {
|
|
22
|
+
stdio: 'inherit',
|
|
23
|
+
detached: false, // Not detached, stays in same process group
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
console.log(`Child PID: ${child.pid}`);
|
|
27
|
+
|
|
28
|
+
// Forward SIGINT to child
|
|
29
|
+
const signalHandler = () => {
|
|
30
|
+
console.log('Parent received SIGINT, forwarding to child...');
|
|
31
|
+
child.kill('SIGINT');
|
|
32
|
+
};
|
|
33
|
+
process.on('SIGINT', signalHandler);
|
|
34
|
+
|
|
35
|
+
// Simulate SIGINT after 1 second
|
|
36
|
+
setTimeout(() => {
|
|
37
|
+
console.log('Simulating SIGINT...');
|
|
38
|
+
process.kill(process.pid, 'SIGINT');
|
|
39
|
+
}, 1000);
|
|
40
|
+
|
|
41
|
+
await new Promise((resolve) => {
|
|
42
|
+
child.on('exit', (code, signal) => {
|
|
43
|
+
console.log(`Child exited with code ${code}, signal ${signal}`);
|
|
44
|
+
process.removeListener('SIGINT', signalHandler);
|
|
45
|
+
resolve();
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Example 2: Detached process group handling
|
|
51
|
+
async function testDetachedProcessGroup() {
|
|
52
|
+
console.log('\nTEST 2: Detached process group');
|
|
53
|
+
|
|
54
|
+
const child = spawn('sh', ['-c', 'echo "Detached start" && sleep 30'], {
|
|
55
|
+
stdio: 'inherit',
|
|
56
|
+
detached: true, // Creates new process group
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const pgid = -child.pid; // Negative PID targets the process group
|
|
60
|
+
console.log(`Child PID: ${child.pid}, PGID: ${pgid}`);
|
|
61
|
+
|
|
62
|
+
// Kill entire process group
|
|
63
|
+
setTimeout(() => {
|
|
64
|
+
console.log('Killing process group...');
|
|
65
|
+
try {
|
|
66
|
+
process.kill(pgid, 'SIGTERM');
|
|
67
|
+
} catch (error) {
|
|
68
|
+
console.log('Error killing process group:', error.message);
|
|
69
|
+
// Fallback to killing just the child
|
|
70
|
+
child.kill('SIGTERM');
|
|
71
|
+
}
|
|
72
|
+
}, 1000);
|
|
73
|
+
|
|
74
|
+
await new Promise((resolve) => {
|
|
75
|
+
child.on('exit', (code, signal) => {
|
|
76
|
+
console.log(`Child exited with code ${code}, signal ${signal}`);
|
|
77
|
+
resolve();
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Example 3: Signal handling with command-stream
|
|
83
|
+
async function testCommandStreamSignals() {
|
|
84
|
+
console.log('\nTEST 3: Command-stream signal handling');
|
|
85
|
+
|
|
86
|
+
const runner = $`sleep 30`;
|
|
87
|
+
const promise = runner.start();
|
|
88
|
+
|
|
89
|
+
// Log when command starts
|
|
90
|
+
runner.on('start', () => {
|
|
91
|
+
console.log('Command started');
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Simulate interrupt after 1 second
|
|
95
|
+
setTimeout(() => {
|
|
96
|
+
console.log('Sending kill signal to runner...');
|
|
97
|
+
runner.kill();
|
|
98
|
+
}, 1000);
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
await promise;
|
|
102
|
+
console.log('Command completed normally');
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.log('Command was interrupted:', error.message);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
console.log('Runner finished:', runner.finished);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Example 4: Cleanup on unexpected exit
|
|
111
|
+
async function testCleanupOnExit() {
|
|
112
|
+
console.log('\nTEST 4: Cleanup on unexpected exit');
|
|
113
|
+
|
|
114
|
+
const children = [];
|
|
115
|
+
|
|
116
|
+
// Cleanup function
|
|
117
|
+
const cleanup = () => {
|
|
118
|
+
console.log('Cleaning up child processes...');
|
|
119
|
+
children.forEach((child) => {
|
|
120
|
+
if (!child.killed) {
|
|
121
|
+
console.log(`Killing child ${child.pid}`);
|
|
122
|
+
child.kill('SIGTERM');
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
// Register cleanup handlers
|
|
128
|
+
process.on('exit', cleanup);
|
|
129
|
+
process.on('SIGINT', () => {
|
|
130
|
+
console.log('Received SIGINT');
|
|
131
|
+
cleanup();
|
|
132
|
+
process.exit(130); // Standard exit code for SIGINT
|
|
133
|
+
});
|
|
134
|
+
process.on('SIGTERM', () => {
|
|
135
|
+
console.log('Received SIGTERM');
|
|
136
|
+
cleanup();
|
|
137
|
+
process.exit(143); // Standard exit code for SIGTERM
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// Start some child processes
|
|
141
|
+
for (let i = 0; i < 3; i++) {
|
|
142
|
+
const child = spawn('sleep', ['30'], {
|
|
143
|
+
stdio: 'ignore',
|
|
144
|
+
});
|
|
145
|
+
children.push(child);
|
|
146
|
+
console.log(`Started child ${i + 1} with PID ${child.pid}`);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Simulate cleanup after 1 second
|
|
150
|
+
setTimeout(() => {
|
|
151
|
+
console.log('Triggering cleanup...');
|
|
152
|
+
cleanup();
|
|
153
|
+
}, 1000);
|
|
154
|
+
|
|
155
|
+
// Wait for all children to exit
|
|
156
|
+
await Promise.all(
|
|
157
|
+
children.map((child) => new Promise((resolve) => child.on('exit', resolve)))
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
console.log('All children cleaned up');
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Example 5: Signal handling in CI vs local environment
|
|
164
|
+
async function testEnvironmentDifferences() {
|
|
165
|
+
console.log('\nTEST 5: Environment-specific signal handling');
|
|
166
|
+
|
|
167
|
+
const isCI = process.env.CI === 'true';
|
|
168
|
+
const isGitHubActions = process.env.GITHUB_ACTIONS === 'true';
|
|
169
|
+
const isTTY = process.stdout.isTTY;
|
|
170
|
+
|
|
171
|
+
console.log('Environment:');
|
|
172
|
+
console.log(`- CI: ${isCI}`);
|
|
173
|
+
console.log(`- GitHub Actions: ${isGitHubActions}`);
|
|
174
|
+
console.log(`- TTY: ${isTTY}`);
|
|
175
|
+
console.log(`- Process group: ${process.pid}`);
|
|
176
|
+
|
|
177
|
+
// Different strategies based on environment
|
|
178
|
+
if (isCI) {
|
|
179
|
+
console.log('Using CI-optimized signal handling');
|
|
180
|
+
// In CI, we might need more aggressive cleanup
|
|
181
|
+
const child = spawn('sleep', ['30'], {
|
|
182
|
+
stdio: 'inherit',
|
|
183
|
+
detached: false, // Keep in same process group for CI
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
setTimeout(() => {
|
|
187
|
+
// Use SIGKILL as last resort in CI
|
|
188
|
+
child.kill('SIGKILL');
|
|
189
|
+
}, 1000);
|
|
190
|
+
|
|
191
|
+
await new Promise((resolve) => child.on('exit', resolve));
|
|
192
|
+
} else {
|
|
193
|
+
console.log('Using local development signal handling');
|
|
194
|
+
// In local dev, we can be more graceful
|
|
195
|
+
const child = spawn('sleep', ['30'], {
|
|
196
|
+
stdio: 'inherit',
|
|
197
|
+
detached: true, // Can detach in local environment
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
setTimeout(() => {
|
|
201
|
+
// Use SIGTERM for graceful shutdown
|
|
202
|
+
child.kill('SIGTERM');
|
|
203
|
+
}, 1000);
|
|
204
|
+
|
|
205
|
+
await new Promise((resolve) => child.on('exit', resolve));
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Run tests
|
|
210
|
+
async function main() {
|
|
211
|
+
try {
|
|
212
|
+
await testBasicSignalForwarding();
|
|
213
|
+
await testDetachedProcessGroup();
|
|
214
|
+
await testCommandStreamSignals();
|
|
215
|
+
await testCleanupOnExit();
|
|
216
|
+
await testEnvironmentDifferences();
|
|
217
|
+
|
|
218
|
+
console.log('\nAll signal handling tests completed');
|
|
219
|
+
} catch (error) {
|
|
220
|
+
console.error('Test failed:', error);
|
|
221
|
+
process.exit(1);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
main();
|