Skip to content

Conversation

@konard
Copy link
Member

@konard konard commented Sep 9, 2025

Summary

This PR implements issue #19 by replacing plain string properties in result objects with real Node.js stream wrappers, while maintaining full backward compatibility.

🔧 Implementation

Stream Wrappers:

  • ReadableStreamWrapper for stdout and stderr
  • WritableStreamWrapper for stdin
  • Both extend Node.js native streams (Readable/Writable)
  • Full stream functionality: pipe(), read(), write(), events, etc.

Core Changes:

  • Modified createResult() to return stream wrappers instead of strings
  • Updated virtual command processing to use the unified result creation
  • Fixed stdin data handling for inherit mode
  • Added proper capture mode support

Backward Compatibility:

  • All string methods work unchanged: trim(), slice(), includes(), etc.
  • String coercion: String(result.stdout)
  • JSON serialization: JSON.stringify(result.stdout)
  • Template literals: Output: ${result.stdout}

💥 Breaking Changes

  • typeof result.stdout changes from 'string' to 'object'
  • This is intentional per the issue requirements for "real streams"
  • Functionality remains compatible, only type inspection changes

🧪 Test Plan

  • Comprehensive test suite for stream functionality
  • Backward compatibility verification
  • Both virtual and non-virtual commands tested
  • Stream lifecycle and events tested
  • Edge cases (empty streams, capture modes) covered

📖 Example Usage

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

// New stream functionality
result.stdout.on('data', chunk => console.log('Got:', chunk));
result.stdout.pipe(process.stdout);
result.stdin.write('input data');

// Existing string usage (still works)
console.log(result.stdout.trim());     // "hello world" 
console.log(result.stdout.length);     // 12
console.log(result.stdout.includes('hello')); // true

🏁 Status

Ready for Review - Implementation complete with full test coverage


🤖 Generated with Claude Code


Resolves #19

Adding CLAUDE.md with task information for AI processing.
This file will be removed when the task is complete.

Issue: #19
@konard konard self-assigned this Sep 9, 2025
konard and others added 2 commits September 9, 2025 22:48
This commit implements the requested feature to return real streams
or stream wrappers instead of plain strings for result.stdout,
result.stderr, and result.stdin.

## Implementation Details

### Stream Wrappers
- Created `ReadableStreamWrapper` class extending Node.js `Readable`
- Created `WritableStreamWrapper` class extending Node.js `Writable`
- Both classes provide full backward compatibility with string methods
- Support all common string operations: trim(), slice(), includes(), etc.
- Proper JSON serialization via toJSON() method
- Custom inspection for console.log

### Core Changes
- Modified `createResult()` function to return stream wrappers
- Updated virtual command result processing to use createResult
- Fixed stdin data handling for virtual commands
- Added proper capture/non-capture mode handling

### Stream Functionality
- Full Node.js stream compatibility (pipe, read, write, on, etc.)
- Readable streams for stdout and stderr
- Writable streams for stdin
- Stream events (data, end, finish) work correctly
- Proper stream lifecycle management

### Backward Compatibility
- All string methods work unchanged: result.stdout.trim()
- String coercion works: String(result.stdout)
- JSON serialization preserved: JSON.stringify(result.stdout)
- Template literal interpolation: `Output: ${result.stdout}`

### Breaking Changes
- typeof result.stdout changed from 'string' to 'object'
- This is intentional and matches the issue requirements
- Stream objects behave like strings but are technically objects

### Testing
- Added comprehensive test suite for stream functionality
- Tests verify stream behavior, backward compatibility, and edge cases
- All new stream-specific functionality is fully tested

## Example Usage

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

// Stream usage (new functionality)
result.stdout.on('data', chunk => console.log(chunk));
result.stdout.pipe(process.stdout);

// String usage (backward compatible)
console.log(result.stdout.trim()); // "hello world"
console.log(result.stdout.length); // 12
```

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
@konard konard changed the title [WIP] Return real streams or stream wrappers Implement real streams or stream wrappers for result objects Sep 9, 2025
@konard konard marked this pull request as ready for review September 9, 2025 20:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Return real streams or stream wrappers

2 participants