Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions examples/debug-issue-19.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/usr/bin/env node

/**
* Debug script to understand issue #19 - Return real streams or stream wrappers
* Current behavior: result.stdout/stderr/stdin are strings
* Desired behavior: They should be readable/writable streams
*/

import { $ } from '../src/$.mjs';

console.log('=== Issue #19 Debug - Current vs Desired Behavior ===\n');

async function testCurrentBehavior() {
console.log('1. Current behavior - result contains strings:');

const result = await $`echo "hello world"`;

console.log(' result.stdout type:', typeof result.stdout);
console.log(' result.stdout constructor:', result.stdout?.constructor?.name);
console.log(' result.stdout instanceof Object:', result.stdout instanceof Object);
console.log(' result.stdout value:', result.stdout);
console.log(' result.stdout JSON:', JSON.stringify(result.stdout));
console.log(' result.stderr type:', typeof result.stderr);
console.log(' result.stderr constructor:', result.stderr.constructor.name);
console.log(' result.stdin type:', typeof result.stdin);
console.log(' result.stdin constructor:', result.stdin.constructor.name);
console.log(' Is result.stdout a stream?', result.stdout && typeof result.stdout.pipe === 'function');
console.log(' Is result.stdout readable?', result.stdout && typeof result.stdout.read === 'function');
console.log(' Is result.stdin writable?', result.stdin && typeof result.stdin.write === 'function');

// Test stream functionality
console.log(' Testing stream methods:');
console.log(' result.stdout.trim():', JSON.stringify(result.stdout.trim()));
console.log(' result.stdout.length:', result.stdout.length);

console.log('\n2. Current streams interface (works correctly):');

const cmd = $`echo "hello from streams"`;
const stdout = await cmd.streams.stdout;
console.log(' cmd.streams.stdout type:', typeof stdout);
console.log(' Is cmd.streams.stdout a stream?', stdout && typeof stdout.pipe === 'function');
console.log(' Is cmd.streams.stdout readable?', stdout && typeof stdout.read === 'function');

await cmd; // Wait for completion
}

testCurrentBehavior().catch(console.error);
27 changes: 27 additions & 0 deletions examples/debug-jest-compatibility.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env node

import { $ } from '../src/$.mjs';

async function test() {
const result = await $`echo "test content"`;

console.log('Testing Jest/Bun compatibility:');
console.log('result.stdout:', result.stdout);
console.log('typeof result.stdout:', typeof result.stdout);
console.log('result.stdout.toString():', result.stdout.toString());
console.log('result.stdout.includes("test"):', result.stdout.includes("test"));
console.log('String(result.stdout):', String(result.stdout));
console.log('JSON.stringify(result.stdout):', JSON.stringify(result.stdout));

// Test what happens when we try to use includes
try {
console.log('Direct includes call:', result.stdout.includes('test'));
} catch (e) {
console.log('Error with includes:', e.message);
}

// Test with conversion
console.log('Convert to string first:', String(result.stdout).includes('test'));
}

test().catch(console.error);
30 changes: 30 additions & 0 deletions examples/debug-result-flow.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env node

import { $ } from '../src/$.mjs';

console.log('=== Debug Result Flow ===');

// Add debug to console.log to see what gets returned
const originalLog = console.log;
console.log = (...args) => {
if (args[0] && args[0].includes && args[0].includes('[DEBUG]')) {
originalLog('[TRACED]', ...args);
} else {
originalLog(...args);
}
};

async function test() {
console.log('About to run echo command...');
const result = await $`echo "test"`;

console.log('Result received:');
console.log(' result:', result);
console.log(' result keys:', Object.keys(result));
console.log(' result.code:', result.code);
console.log(' result.stdout:', result.stdout);
console.log(' result.stderr:', result.stderr);
console.log(' result.stdin:', result.stdin);
}

test().catch(console.error);
69 changes: 69 additions & 0 deletions examples/issue-19-final-demo.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/usr/bin/env node

/**
* Issue #19 Final Demo - Real streams or stream wrappers
*
* This demonstrates the solution: result.stdout, result.stderr, and result.stdin
* are now real Node.js streams (ReadableStreamWrapper and WritableStreamWrapper)
* that maintain backward compatibility with string usage.
*/

import { $ } from '../src/$.mjs';
import { Readable, Writable } from 'stream';

console.log('πŸŽ‰ Issue #19 Solution Demo: Real Streams or Stream Wrappers\n');

async function demo() {
console.log('1️⃣ Stream Type Verification:');
const result = await $`echo "Hello, streams!"`;

console.log(` βœ… result.stdout instanceof Readable: ${result.stdout instanceof Readable}`);
console.log(` βœ… result.stderr instanceof Readable: ${result.stderr instanceof Readable}`);
console.log(` βœ… result.stdin instanceof Writable: ${result.stdin instanceof Writable}`);
console.log(` βœ… Has pipe method: ${typeof result.stdout.pipe === 'function'}`);
console.log(` βœ… Has read method: ${typeof result.stdout.read === 'function'}`);
console.log(` βœ… Has write method: ${typeof result.stdin.write === 'function'}`);

console.log('\n2️⃣ Stream Reading Functionality:');
return new Promise((resolve) => {
const chunks = [];

result.stdout.on('data', (chunk) => {
chunks.push(chunk.toString());
console.log(` πŸ“₯ Received chunk: ${JSON.stringify(chunk.toString())}`);
});

result.stdout.on('end', () => {
const combined = chunks.join('');
console.log(` βœ… Stream ended. Combined data: ${JSON.stringify(combined)}`);

console.log('\n3️⃣ Backward Compatibility:');
console.log(` βœ… toString(): ${JSON.stringify(result.stdout.toString())}`);
console.log(` βœ… trim(): ${JSON.stringify(result.stdout.trim())}`);
console.log(` βœ… length: ${result.stdout.length}`);
console.log(` βœ… includes(): ${result.stdout.includes('streams')}`);
console.log(` βœ… slice(): ${JSON.stringify(result.stdout.slice(0, 5))}`);

console.log('\n4️⃣ JSON Serialization:');
console.log(` βœ… JSON.stringify(stdout): ${JSON.stringify(result.stdout)}`);

console.log('\n5️⃣ Type Information:');
console.log(` πŸ“ typeof result.stdout: ${typeof result.stdout} (now 'object' instead of 'string')`);
console.log(` πŸ“ result.stdout.constructor.name: ${result.stdout.constructor.name}`);

console.log('\n🎯 Summary:');
console.log(' β€’ stdout, stderr, stdin are now real Node.js streams');
console.log(' β€’ They maintain full backward compatibility with string methods');
console.log(' β€’ They support all stream operations (pipe, read, write, etc.)');
console.log(' β€’ Breaking change: typeof is now "object" instead of "string"');
console.log(' β€’ This matches the requirement for "real streams or stream wrappers"');

resolve();
});

// Trigger reading
result.stdout.read();
});
}

demo().catch(console.error);
21 changes: 21 additions & 0 deletions examples/minimal-test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env node

import { $ } from '../src/$.mjs';

console.log('=== Minimal Test ===');

async function test() {
const result = await $`echo "test"`;

console.log('result:', result);
console.log('result.stdout:', result.stdout);
console.log('typeof result.stdout:', typeof result.stdout);
console.log('result.stdout.constructor:', result.stdout.constructor);
console.log('result.stdout instanceof Object:', result.stdout instanceof Object);

// Let's try to access the object directly
console.log('Object.getPrototypeOf(result.stdout):', Object.getPrototypeOf(result.stdout));
console.log('result.stdout.__proto__:', result.stdout.__proto__);
}

test().catch(console.error);
76 changes: 76 additions & 0 deletions examples/test-issue-19-streams.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/usr/bin/env node

/**
* Test script for issue #19 - Return real streams or stream wrappers
* Tests that result.stdout, result.stderr, and result.stdin are proper streams
*/

import { $ } from '../src/$.mjs';
import { Readable, Writable } from 'stream';

console.log('=== Issue #19 Stream Functionality Test ===\n');

async function testStreamFunctionality() {
console.log('1. Testing basic stream properties:');

const result = await $`echo "hello world"`;

// Check if they are actually stream instances
console.log(' result.stdout instanceof Readable:', result.stdout instanceof Readable);
console.log(' result.stderr instanceof Readable:', result.stderr instanceof Readable);
console.log(' result.stdin instanceof Writable:', result.stdin instanceof Writable);

// Check stream methods exist
console.log(' result.stdout has pipe method:', typeof result.stdout.pipe === 'function');
console.log(' result.stdout has read method:', typeof result.stdout.read === 'function');
console.log(' result.stdin has write method:', typeof result.stdin.write === 'function');

console.log('\n2. Testing stream reading:');

// Test reading from stdout stream
let chunks = [];
result.stdout.on('data', (chunk) => {
chunks.push(chunk.toString());
console.log(' Received chunk:', JSON.stringify(chunk.toString()));
});

result.stdout.on('end', () => {
console.log(' Stream ended');
console.log(' Combined data:', JSON.stringify(chunks.join('')));
});

// Start reading
result.stdout.read();

console.log('\n3. Testing backward compatibility:');

// Test string-like behavior
console.log(' result.stdout as string:', JSON.stringify(result.stdout.toString()));
console.log(' result.stdout.trim():', JSON.stringify(result.stdout.trim()));
console.log(' result.stdout.length:', result.stdout.length);
console.log(' result.stdout.includes("hello"):', result.stdout.includes("hello"));

console.log('\n4. Testing writable stream (stdin):');

// Test writing to stdin stream
const result2 = await $`cat`;
const chunks2 = [];

result2.stdin.on('data', (chunk) => {
chunks2.push(chunk.toString());
console.log(' Written data received:', JSON.stringify(chunk.toString()));
});

result2.stdin.write('test data\n');
result2.stdin.write('more test data\n');
result2.stdin.end();

// Wait a bit for stream processing
await new Promise(resolve => setTimeout(resolve, 100));

console.log(' All written data:', JSON.stringify(chunks2.join('')));

console.log('\nβœ… All stream tests completed');
}

testStreamFunctionality().catch(console.error);
52 changes: 12 additions & 40 deletions examples/test-non-virtual.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,18 @@

import { $ } from '../src/$.mjs';

async function testNonVirtual() {
console.log('πŸ§ͺ Testing with definitely non-virtual command');

// Use wc which should not be virtual
const wcCmd = $`wc -l`;
console.log('1. Created wc command');

// Check if process spawns properly with regular async execution
console.log('2. Testing normal execution first...');
const testCmd = $`wc -l`;
const testResult = await testCmd.start({ stdin: 'test\nline2\n' });
console.log(' Normal execution result:', testResult.stdout.trim());

// Now test streams
console.log('3. Testing streams...');
await wcCmd.start({ mode: 'async', stdin: 'pipe', stdout: 'pipe', stderr: 'pipe' });

console.log('4. After start:');
console.log(' started:', wcCmd.started);
console.log(' child exists:', !!wcCmd.child);
console.log(' finished:', wcCmd.finished);

if (wcCmd.child) {
console.log(' child.pid:', wcCmd.child.pid);
console.log(' child.stdin:', typeof wcCmd.child.stdin);
}
console.log('=== Testing Non-Virtual Command ===');

async function test() {
// Use a command that's likely not virtualized (like node)
const result = await $`node -e "console.log('hello')"`;

// Try direct access to child stdin if available
if (wcCmd.child && wcCmd.child.stdin) {
console.log('5. Direct child.stdin access works!');
wcCmd.child.stdin.write('line1\n');
wcCmd.child.stdin.write('line2\n');
wcCmd.child.stdin.end();

const result = await wcCmd;
console.log(' Direct access result:', result.stdout.trim());
} else {
console.log('5. No child.stdin available');
wcCmd.kill();
}
console.log('Result received:');
console.log(' result:', result);
console.log(' result keys:', Object.keys(result));
console.log(' result.stdout type:', typeof result.stdout);
console.log(' result.stdout constructor:', result.stdout?.constructor?.name);
console.log(' result.stdin type:', typeof result.stdin);
}

testNonVirtual();
test().catch(console.error);
Loading
Loading