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,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test cleanup utilities for command-stream tests
|
|
3
|
+
*
|
|
4
|
+
* Provides functions to be called in beforeEach/afterEach hooks
|
|
5
|
+
* within describe blocks.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* ```js
|
|
9
|
+
* import { beforeTestCleanup, afterTestCleanup } from './test-cleanup.mjs';
|
|
10
|
+
* import { describe, beforeEach, afterEach } from 'bun:test';
|
|
11
|
+
*
|
|
12
|
+
* describe('Your test suite', () => {
|
|
13
|
+
* beforeEach(beforeTestCleanup);
|
|
14
|
+
* afterEach(afterTestCleanup);
|
|
15
|
+
*
|
|
16
|
+
* // Your tests here
|
|
17
|
+
* });
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { resetGlobalState } from '../src/$.mjs';
|
|
22
|
+
import { existsSync } from 'fs';
|
|
23
|
+
|
|
24
|
+
// Save the original working directory when module loads
|
|
25
|
+
const originalCwd = process.cwd();
|
|
26
|
+
|
|
27
|
+
// Trace function for debugging
|
|
28
|
+
function trace(message) {
|
|
29
|
+
if (process.env.DEBUG || process.env.TRACE) {
|
|
30
|
+
const timestamp = new Date().toISOString();
|
|
31
|
+
console.error(`[TRACE ${timestamp}] [test-cleanup] ${message}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
trace(`Module loaded - original working directory: ${originalCwd}`);
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Cleanup function to call in beforeEach hook
|
|
39
|
+
*/
|
|
40
|
+
export async function beforeTestCleanup() {
|
|
41
|
+
trace('beforeTestCleanup running');
|
|
42
|
+
|
|
43
|
+
// CRITICAL: Restore working directory first - MUST succeed for spawn to work
|
|
44
|
+
const currentDir = process.cwd();
|
|
45
|
+
if (currentDir !== originalCwd) {
|
|
46
|
+
trace(`Restoring cwd from ${currentDir} to ${originalCwd}`);
|
|
47
|
+
try {
|
|
48
|
+
// Force restoration regardless of current state
|
|
49
|
+
process.chdir(originalCwd);
|
|
50
|
+
} catch (_e) {
|
|
51
|
+
// Original directory might be gone, try fallbacks
|
|
52
|
+
try {
|
|
53
|
+
if (existsSync(originalCwd)) {
|
|
54
|
+
process.chdir(originalCwd);
|
|
55
|
+
} else if (existsSync('/workspace/command-stream')) {
|
|
56
|
+
process.chdir('/workspace/command-stream');
|
|
57
|
+
} else if (process.env.HOME && existsSync(process.env.HOME)) {
|
|
58
|
+
process.chdir(process.env.HOME);
|
|
59
|
+
} else {
|
|
60
|
+
process.chdir('/');
|
|
61
|
+
}
|
|
62
|
+
} catch (_e2) {
|
|
63
|
+
console.error(
|
|
64
|
+
'[test-cleanup] FATAL: Cannot set working directory in beforeTestCleanup'
|
|
65
|
+
);
|
|
66
|
+
trace('FATAL: Cannot set working directory');
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Call the comprehensive reset
|
|
72
|
+
resetGlobalState();
|
|
73
|
+
|
|
74
|
+
// Extra safety: ensure we're in a valid directory after reset
|
|
75
|
+
try {
|
|
76
|
+
process.cwd(); // This will throw if we're in a bad state
|
|
77
|
+
} catch (_e) {
|
|
78
|
+
// Force to a known good directory
|
|
79
|
+
process.chdir(originalCwd);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// VERIFY: Ensure we actually restored to the original directory
|
|
83
|
+
const finalCwd = process.cwd();
|
|
84
|
+
if (finalCwd !== originalCwd && existsSync(originalCwd)) {
|
|
85
|
+
console.error(
|
|
86
|
+
`[test-cleanup] WARNING: Failed to restore cwd! Expected: ${originalCwd}, Got: ${finalCwd}`
|
|
87
|
+
);
|
|
88
|
+
// Try one more time
|
|
89
|
+
try {
|
|
90
|
+
process.chdir(originalCwd);
|
|
91
|
+
const verifiedCwd = process.cwd();
|
|
92
|
+
if (verifiedCwd === originalCwd) {
|
|
93
|
+
trace('Successfully restored on second attempt');
|
|
94
|
+
} else {
|
|
95
|
+
throw new Error(
|
|
96
|
+
`[test-cleanup] CRITICAL: Cannot restore to original directory ${originalCwd}, stuck in ${verifiedCwd}`
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
} catch (_e) {
|
|
100
|
+
throw new Error(
|
|
101
|
+
`[test-cleanup] CRITICAL: Cannot restore to original directory ${originalCwd}, stuck in ${finalCwd}`
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Give a tiny bit of time for any async cleanup to complete
|
|
107
|
+
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
108
|
+
trace('beforeTestCleanup completed');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Cleanup function to call in afterEach hook
|
|
113
|
+
*/
|
|
114
|
+
export async function afterTestCleanup() {
|
|
115
|
+
trace('afterTestCleanup running');
|
|
116
|
+
|
|
117
|
+
// CRITICAL: Clean up and restore state after each test
|
|
118
|
+
const currentDir = process.cwd();
|
|
119
|
+
if (currentDir !== originalCwd) {
|
|
120
|
+
trace(`Restoring cwd from ${currentDir} to ${originalCwd}`);
|
|
121
|
+
try {
|
|
122
|
+
// Force restoration regardless of current state
|
|
123
|
+
process.chdir(originalCwd);
|
|
124
|
+
} catch (_e) {
|
|
125
|
+
// Original directory might be gone, try fallbacks
|
|
126
|
+
try {
|
|
127
|
+
if (existsSync(originalCwd)) {
|
|
128
|
+
process.chdir(originalCwd);
|
|
129
|
+
} else if (existsSync('/workspace/command-stream')) {
|
|
130
|
+
process.chdir('/workspace/command-stream');
|
|
131
|
+
} else if (process.env.HOME && existsSync(process.env.HOME)) {
|
|
132
|
+
process.chdir(process.env.HOME);
|
|
133
|
+
} else {
|
|
134
|
+
process.chdir('/');
|
|
135
|
+
}
|
|
136
|
+
} catch (_e2) {
|
|
137
|
+
console.error(
|
|
138
|
+
'[test-cleanup] FATAL: Cannot set working directory in afterTestCleanup'
|
|
139
|
+
);
|
|
140
|
+
trace('FATAL: Cannot set working directory');
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Call the comprehensive reset
|
|
146
|
+
resetGlobalState();
|
|
147
|
+
|
|
148
|
+
// Extra safety: ensure we're in a valid directory after reset
|
|
149
|
+
try {
|
|
150
|
+
process.cwd(); // This will throw if we're in a bad state
|
|
151
|
+
} catch (_e) {
|
|
152
|
+
// Force to a known good directory
|
|
153
|
+
process.chdir(originalCwd);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// VERIFY: Ensure we actually restored to the original directory
|
|
157
|
+
const finalCwd = process.cwd();
|
|
158
|
+
if (finalCwd !== originalCwd && existsSync(originalCwd)) {
|
|
159
|
+
console.error(
|
|
160
|
+
`[test-cleanup] WARNING: Failed to restore cwd in afterEach! Expected: ${originalCwd}, Got: ${finalCwd}`
|
|
161
|
+
);
|
|
162
|
+
// Try one more time
|
|
163
|
+
try {
|
|
164
|
+
process.chdir(originalCwd);
|
|
165
|
+
const verifiedCwd = process.cwd();
|
|
166
|
+
if (verifiedCwd === originalCwd) {
|
|
167
|
+
trace('Successfully restored on second attempt in afterEach');
|
|
168
|
+
} else {
|
|
169
|
+
throw new Error(
|
|
170
|
+
`[test-cleanup] CRITICAL: Cannot restore to original directory ${originalCwd} in afterEach, stuck in ${verifiedCwd}`
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
} catch (_e) {
|
|
174
|
+
throw new Error(
|
|
175
|
+
`[test-cleanup] CRITICAL: Cannot restore to original directory ${originalCwd} in afterEach, stuck in ${finalCwd}`
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Give a tiny bit of time for any async cleanup to complete
|
|
181
|
+
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
182
|
+
trace('afterTestCleanup completed');
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Install a process exit handler to ensure cleanup even on crash
|
|
186
|
+
process.on('beforeExit', () => {
|
|
187
|
+
try {
|
|
188
|
+
if (process.cwd() !== originalCwd) {
|
|
189
|
+
process.chdir(originalCwd);
|
|
190
|
+
}
|
|
191
|
+
} catch (_e) {
|
|
192
|
+
// Ignore
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// Export resetGlobalState for direct use if needed
|
|
197
|
+
export { resetGlobalState };
|
|
198
|
+
|
|
199
|
+
// Export original cwd for verification in tests
|
|
200
|
+
export { originalCwd };
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Helper for command-stream tests
|
|
3
|
+
*
|
|
4
|
+
* IMPORTANT: Due to Bun's test runner limitations, beforeEach/afterEach hooks
|
|
5
|
+
* MUST be within describe() blocks to work properly.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* ```js
|
|
9
|
+
* import { setupTestHooks } from './test-helper-fixed.mjs';
|
|
10
|
+
* import { describe } from 'bun:test';
|
|
11
|
+
*
|
|
12
|
+
* describe('Your test suite', () => {
|
|
13
|
+
* setupTestHooks();
|
|
14
|
+
*
|
|
15
|
+
* // Your tests here
|
|
16
|
+
* });
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { beforeEach, afterEach } from 'bun:test';
|
|
21
|
+
import { resetGlobalState } from '../src/$.mjs';
|
|
22
|
+
import { existsSync } from 'fs';
|
|
23
|
+
|
|
24
|
+
// Save the original working directory when tests start
|
|
25
|
+
const originalCwd = process.cwd();
|
|
26
|
+
|
|
27
|
+
// Trace function for debugging
|
|
28
|
+
function trace(message) {
|
|
29
|
+
if (process.env.DEBUG || process.env.TRACE) {
|
|
30
|
+
const timestamp = new Date().toISOString();
|
|
31
|
+
console.error(`[TRACE ${timestamp}] [test-helper] ${message}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
trace(`Original working directory: ${originalCwd}`);
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Sets up beforeEach and afterEach hooks to restore working directory
|
|
39
|
+
* and reset global state between tests.
|
|
40
|
+
*
|
|
41
|
+
* MUST be called inside a describe() block!
|
|
42
|
+
*/
|
|
43
|
+
export function setupTestHooks() {
|
|
44
|
+
beforeEach(async () => {
|
|
45
|
+
trace('beforeEach hook running');
|
|
46
|
+
// CRITICAL: Restore working directory first - MUST succeed for spawn to work
|
|
47
|
+
const currentDir = process.cwd();
|
|
48
|
+
if (currentDir !== originalCwd) {
|
|
49
|
+
trace(`beforeEach: Restoring cwd from ${currentDir} to ${originalCwd}`);
|
|
50
|
+
try {
|
|
51
|
+
// Force restoration regardless of current state
|
|
52
|
+
process.chdir(originalCwd);
|
|
53
|
+
} catch (_e) {
|
|
54
|
+
// Original directory might be gone, try fallbacks
|
|
55
|
+
try {
|
|
56
|
+
if (existsSync(originalCwd)) {
|
|
57
|
+
process.chdir(originalCwd);
|
|
58
|
+
} else if (existsSync('/workspace/command-stream')) {
|
|
59
|
+
process.chdir('/workspace/command-stream');
|
|
60
|
+
} else if (process.env.HOME && existsSync(process.env.HOME)) {
|
|
61
|
+
process.chdir(process.env.HOME);
|
|
62
|
+
} else {
|
|
63
|
+
process.chdir('/');
|
|
64
|
+
}
|
|
65
|
+
} catch (_e2) {
|
|
66
|
+
console.error(
|
|
67
|
+
'[test-helper] FATAL: Cannot set working directory in beforeEach'
|
|
68
|
+
);
|
|
69
|
+
trace('FATAL: Cannot set working directory in beforeEach');
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Call the comprehensive reset
|
|
75
|
+
resetGlobalState();
|
|
76
|
+
|
|
77
|
+
// Extra safety: ensure we're in a valid directory after reset
|
|
78
|
+
try {
|
|
79
|
+
process.cwd(); // This will throw if we're in a bad state
|
|
80
|
+
} catch (_e) {
|
|
81
|
+
// Force to a known good directory
|
|
82
|
+
process.chdir(originalCwd);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Give a tiny bit of time for any async cleanup to complete
|
|
86
|
+
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
87
|
+
trace('beforeEach hook completed');
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
afterEach(async () => {
|
|
91
|
+
trace('afterEach hook running');
|
|
92
|
+
// CRITICAL: Clean up and restore state after each test
|
|
93
|
+
const currentDir = process.cwd();
|
|
94
|
+
if (currentDir !== originalCwd) {
|
|
95
|
+
trace(`afterEach: Restoring cwd from ${currentDir} to ${originalCwd}`);
|
|
96
|
+
try {
|
|
97
|
+
// Force restoration regardless of current state
|
|
98
|
+
process.chdir(originalCwd);
|
|
99
|
+
} catch (_e) {
|
|
100
|
+
// Original directory might be gone, try fallbacks
|
|
101
|
+
try {
|
|
102
|
+
if (existsSync(originalCwd)) {
|
|
103
|
+
process.chdir(originalCwd);
|
|
104
|
+
} else if (existsSync('/workspace/command-stream')) {
|
|
105
|
+
process.chdir('/workspace/command-stream');
|
|
106
|
+
} else if (process.env.HOME && existsSync(process.env.HOME)) {
|
|
107
|
+
process.chdir(process.env.HOME);
|
|
108
|
+
} else {
|
|
109
|
+
process.chdir('/');
|
|
110
|
+
}
|
|
111
|
+
} catch (_e2) {
|
|
112
|
+
console.error(
|
|
113
|
+
'[test-helper] FATAL: Cannot set working directory in afterEach'
|
|
114
|
+
);
|
|
115
|
+
trace('FATAL: Cannot set working directory in afterEach');
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Call the comprehensive reset
|
|
121
|
+
resetGlobalState();
|
|
122
|
+
|
|
123
|
+
// Extra safety: ensure we're in a valid directory after reset
|
|
124
|
+
try {
|
|
125
|
+
process.cwd(); // This will throw if we're in a bad state
|
|
126
|
+
} catch (_e) {
|
|
127
|
+
// Force to a known good directory
|
|
128
|
+
process.chdir(originalCwd);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Give a tiny bit of time for any async cleanup to complete
|
|
132
|
+
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
133
|
+
trace('afterEach hook completed');
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Install a process exit handler to ensure cleanup even on crash
|
|
138
|
+
process.on('beforeExit', () => {
|
|
139
|
+
try {
|
|
140
|
+
if (process.cwd() !== originalCwd) {
|
|
141
|
+
process.chdir(originalCwd);
|
|
142
|
+
}
|
|
143
|
+
} catch (_e) {
|
|
144
|
+
// Ignore
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
export { resetGlobalState };
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { beforeEach, afterEach } from 'bun:test';
|
|
2
|
+
import { resetGlobalState } from '../src/$.mjs';
|
|
3
|
+
import { existsSync } from 'fs';
|
|
4
|
+
|
|
5
|
+
// Save the original working directory when tests start
|
|
6
|
+
const originalCwd = process.cwd();
|
|
7
|
+
|
|
8
|
+
// Trace function for debugging
|
|
9
|
+
function trace(message) {
|
|
10
|
+
if (process.env.DEBUG || process.env.TRACE) {
|
|
11
|
+
const timestamp = new Date().toISOString();
|
|
12
|
+
console.error(`[TRACE ${timestamp}] [test-helper-v2] ${message}`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
trace(`Original working directory: ${originalCwd}`);
|
|
17
|
+
|
|
18
|
+
// Function to set up test hooks
|
|
19
|
+
export function setupTestHooks() {
|
|
20
|
+
trace('Setting up test hooks');
|
|
21
|
+
|
|
22
|
+
beforeEach(async () => {
|
|
23
|
+
trace('beforeEach hook running');
|
|
24
|
+
// CRITICAL: Restore working directory first - MUST succeed for spawn to work
|
|
25
|
+
const currentDir = process.cwd();
|
|
26
|
+
if (currentDir !== originalCwd) {
|
|
27
|
+
trace(`beforeEach: Restoring cwd from ${currentDir} to ${originalCwd}`);
|
|
28
|
+
try {
|
|
29
|
+
// Force restoration regardless of current state
|
|
30
|
+
process.chdir(originalCwd);
|
|
31
|
+
} catch (_e) {
|
|
32
|
+
// Original directory might be gone, try fallbacks
|
|
33
|
+
try {
|
|
34
|
+
if (existsSync(originalCwd)) {
|
|
35
|
+
process.chdir(originalCwd);
|
|
36
|
+
} else if (existsSync('/workspace/command-stream')) {
|
|
37
|
+
process.chdir('/workspace/command-stream');
|
|
38
|
+
} else if (process.env.HOME && existsSync(process.env.HOME)) {
|
|
39
|
+
process.chdir(process.env.HOME);
|
|
40
|
+
} else {
|
|
41
|
+
process.chdir('/');
|
|
42
|
+
}
|
|
43
|
+
} catch (_e2) {
|
|
44
|
+
console.error(
|
|
45
|
+
'[test-helper-v2] FATAL: Cannot set working directory in beforeEach'
|
|
46
|
+
);
|
|
47
|
+
trace('FATAL: Cannot set working directory in beforeEach');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Call the comprehensive reset
|
|
53
|
+
resetGlobalState();
|
|
54
|
+
|
|
55
|
+
// Extra safety: ensure we're in a valid directory after reset
|
|
56
|
+
try {
|
|
57
|
+
process.cwd(); // This will throw if we're in a bad state
|
|
58
|
+
} catch (_e) {
|
|
59
|
+
// Force to a known good directory
|
|
60
|
+
process.chdir(originalCwd);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Give a tiny bit of time for any async cleanup to complete
|
|
64
|
+
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
65
|
+
trace('beforeEach hook completed');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
afterEach(async () => {
|
|
69
|
+
trace('afterEach hook running');
|
|
70
|
+
// CRITICAL: Clean up and restore state after each test
|
|
71
|
+
const currentDir = process.cwd();
|
|
72
|
+
if (currentDir !== originalCwd) {
|
|
73
|
+
trace(`afterEach: Restoring cwd from ${currentDir} to ${originalCwd}`);
|
|
74
|
+
try {
|
|
75
|
+
// Force restoration regardless of current state
|
|
76
|
+
process.chdir(originalCwd);
|
|
77
|
+
} catch (_e) {
|
|
78
|
+
// Original directory might be gone, try fallbacks
|
|
79
|
+
try {
|
|
80
|
+
if (existsSync(originalCwd)) {
|
|
81
|
+
process.chdir(originalCwd);
|
|
82
|
+
} else if (existsSync('/workspace/command-stream')) {
|
|
83
|
+
process.chdir('/workspace/command-stream');
|
|
84
|
+
} else if (process.env.HOME && existsSync(process.env.HOME)) {
|
|
85
|
+
process.chdir(process.env.HOME);
|
|
86
|
+
} else {
|
|
87
|
+
process.chdir('/');
|
|
88
|
+
}
|
|
89
|
+
} catch (_e2) {
|
|
90
|
+
console.error(
|
|
91
|
+
'[test-helper-v2] FATAL: Cannot set working directory in afterEach'
|
|
92
|
+
);
|
|
93
|
+
trace('FATAL: Cannot set working directory in afterEach');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Call the comprehensive reset
|
|
99
|
+
resetGlobalState();
|
|
100
|
+
|
|
101
|
+
// Extra safety: ensure we're in a valid directory after reset
|
|
102
|
+
try {
|
|
103
|
+
process.cwd(); // This will throw if we're in a bad state
|
|
104
|
+
} catch (_e) {
|
|
105
|
+
// Force to a known good directory
|
|
106
|
+
process.chdir(originalCwd);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Give a tiny bit of time for any async cleanup to complete
|
|
110
|
+
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
111
|
+
trace('afterEach hook completed');
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Auto-setup hooks when imported
|
|
116
|
+
setupTestHooks();
|
|
117
|
+
|
|
118
|
+
export { resetGlobalState };
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { beforeEach, afterEach } from 'bun:test';
|
|
2
|
+
import { resetGlobalState } from '../src/$.mjs';
|
|
3
|
+
import { existsSync } from 'fs';
|
|
4
|
+
|
|
5
|
+
// Platform detection helpers
|
|
6
|
+
export const isWindows = process.platform === 'win32';
|
|
7
|
+
export const isUnix = process.platform !== 'win32';
|
|
8
|
+
|
|
9
|
+
// Save the original working directory when tests start
|
|
10
|
+
const originalCwd = process.cwd();
|
|
11
|
+
|
|
12
|
+
// Trace function for debugging
|
|
13
|
+
function trace(message) {
|
|
14
|
+
if (process.env.DEBUG || process.env.TRACE) {
|
|
15
|
+
const timestamp = new Date().toISOString();
|
|
16
|
+
console.error(`[TRACE ${timestamp}] [test-helper] ${message}`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
trace(`Original working directory: ${originalCwd}`);
|
|
21
|
+
|
|
22
|
+
// Install a process exit handler to ensure cleanup even on crash
|
|
23
|
+
process.on('beforeExit', () => {
|
|
24
|
+
try {
|
|
25
|
+
if (process.cwd() !== originalCwd) {
|
|
26
|
+
process.chdir(originalCwd);
|
|
27
|
+
}
|
|
28
|
+
} catch (_e) {
|
|
29
|
+
// Ignore
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Reset global state before and after each test to prevent interference
|
|
34
|
+
// Use async to ensure cleanup completes
|
|
35
|
+
beforeEach(async () => {
|
|
36
|
+
// CRITICAL: Restore working directory first - MUST succeed for spawn to work
|
|
37
|
+
const currentDir = process.cwd();
|
|
38
|
+
if (currentDir !== originalCwd) {
|
|
39
|
+
trace(`beforeEach: Restoring cwd from ${currentDir} to ${originalCwd}`);
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
// Force restoration regardless of current state
|
|
43
|
+
process.chdir(originalCwd);
|
|
44
|
+
} catch (_e) {
|
|
45
|
+
// Original directory might be gone, try fallbacks
|
|
46
|
+
try {
|
|
47
|
+
if (existsSync(originalCwd)) {
|
|
48
|
+
process.chdir(originalCwd);
|
|
49
|
+
} else if (existsSync('/workspace/command-stream')) {
|
|
50
|
+
process.chdir('/workspace/command-stream');
|
|
51
|
+
} else if (process.env.HOME && existsSync(process.env.HOME)) {
|
|
52
|
+
process.chdir(process.env.HOME);
|
|
53
|
+
} else {
|
|
54
|
+
process.chdir('/');
|
|
55
|
+
}
|
|
56
|
+
} catch (_e2) {
|
|
57
|
+
console.error(
|
|
58
|
+
'[test-helper] FATAL: Cannot set working directory in beforeEach'
|
|
59
|
+
);
|
|
60
|
+
trace('FATAL: Cannot set working directory in beforeEach');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Call the comprehensive reset
|
|
65
|
+
resetGlobalState();
|
|
66
|
+
|
|
67
|
+
// Extra safety: ensure we're in a valid directory after reset
|
|
68
|
+
try {
|
|
69
|
+
process.cwd(); // This will throw if we're in a bad state
|
|
70
|
+
} catch (_e) {
|
|
71
|
+
// Force to a known good directory
|
|
72
|
+
process.chdir(originalCwd);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// VERIFY: Ensure we actually restored to the original directory
|
|
76
|
+
const finalCwd = process.cwd();
|
|
77
|
+
if (finalCwd !== originalCwd && existsSync(originalCwd)) {
|
|
78
|
+
console.error(
|
|
79
|
+
`[test-helper] WARNING: Failed to restore cwd! Expected: ${originalCwd}, Got: ${finalCwd}`
|
|
80
|
+
);
|
|
81
|
+
// Try one more time
|
|
82
|
+
try {
|
|
83
|
+
process.chdir(originalCwd);
|
|
84
|
+
const verifiedCwd = process.cwd();
|
|
85
|
+
if (verifiedCwd === originalCwd) {
|
|
86
|
+
trace('Successfully restored on second attempt');
|
|
87
|
+
} else {
|
|
88
|
+
throw new Error(
|
|
89
|
+
`[test-helper] CRITICAL: Cannot restore to original directory ${originalCwd}, stuck in ${verifiedCwd}`
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
} catch (_e) {
|
|
93
|
+
throw new Error(
|
|
94
|
+
`[test-helper] CRITICAL: Cannot restore to original directory ${originalCwd}, stuck in ${finalCwd}`
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Give a tiny bit of time for any async cleanup to complete
|
|
100
|
+
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
afterEach(async () => {
|
|
104
|
+
// CRITICAL: Clean up and restore state after each test
|
|
105
|
+
const currentDir = process.cwd();
|
|
106
|
+
if (currentDir !== originalCwd) {
|
|
107
|
+
trace(`afterEach: Restoring cwd from ${currentDir} to ${originalCwd}`);
|
|
108
|
+
}
|
|
109
|
+
try {
|
|
110
|
+
// Force restoration regardless of current state
|
|
111
|
+
process.chdir(originalCwd);
|
|
112
|
+
} catch (_e) {
|
|
113
|
+
// Original directory might be gone, try fallbacks
|
|
114
|
+
try {
|
|
115
|
+
if (existsSync(originalCwd)) {
|
|
116
|
+
process.chdir(originalCwd);
|
|
117
|
+
} else if (existsSync('/workspace/command-stream')) {
|
|
118
|
+
process.chdir('/workspace/command-stream');
|
|
119
|
+
} else if (process.env.HOME && existsSync(process.env.HOME)) {
|
|
120
|
+
process.chdir(process.env.HOME);
|
|
121
|
+
} else {
|
|
122
|
+
process.chdir('/');
|
|
123
|
+
}
|
|
124
|
+
} catch (_e2) {
|
|
125
|
+
console.error(
|
|
126
|
+
'[test-helper] FATAL: Cannot set working directory in afterEach'
|
|
127
|
+
);
|
|
128
|
+
trace('FATAL: Cannot set working directory in afterEach');
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Call the comprehensive reset
|
|
133
|
+
resetGlobalState();
|
|
134
|
+
|
|
135
|
+
// Extra safety: ensure we're in a valid directory after reset
|
|
136
|
+
try {
|
|
137
|
+
process.cwd(); // This will throw if we're in a bad state
|
|
138
|
+
} catch (_e) {
|
|
139
|
+
// Force to a known good directory
|
|
140
|
+
process.chdir(originalCwd);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// VERIFY: Ensure we actually restored to the original directory
|
|
144
|
+
const finalCwd = process.cwd();
|
|
145
|
+
if (finalCwd !== originalCwd && existsSync(originalCwd)) {
|
|
146
|
+
console.error(
|
|
147
|
+
`[test-helper] WARNING: Failed to restore cwd! Expected: ${originalCwd}, Got: ${finalCwd}`
|
|
148
|
+
);
|
|
149
|
+
// Try one more time
|
|
150
|
+
try {
|
|
151
|
+
process.chdir(originalCwd);
|
|
152
|
+
const verifiedCwd = process.cwd();
|
|
153
|
+
if (verifiedCwd === originalCwd) {
|
|
154
|
+
trace('Successfully restored on second attempt');
|
|
155
|
+
} else {
|
|
156
|
+
throw new Error(
|
|
157
|
+
`[test-helper] CRITICAL: Cannot restore to original directory ${originalCwd}, stuck in ${verifiedCwd}`
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
} catch (_e) {
|
|
161
|
+
throw new Error(
|
|
162
|
+
`[test-helper] CRITICAL: Cannot restore to original directory ${originalCwd}, stuck in ${finalCwd}`
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Give a tiny bit of time for any async cleanup to complete
|
|
168
|
+
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
export { resetGlobalState };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
let sigintReceived = false;
|
|
3
|
+
process.on('SIGINT', () => {
|
|
4
|
+
console.log('CHILD_SIGINT_RECEIVED');
|
|
5
|
+
sigintReceived = true;
|
|
6
|
+
process.exit(130);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
// Keep running until interrupted
|
|
10
|
+
console.log('CHILD_STARTED');
|
|
11
|
+
setInterval(() => {
|
|
12
|
+
if (!sigintReceived) {
|
|
13
|
+
console.log('CHILD_RUNNING');
|
|
14
|
+
}
|
|
15
|
+
}, 100);
|