command-stream 0.0.1 → 0.0.3
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/$.mjs +43 -21
- package/README.md +73 -43
- package/package.json +1 -1
package/$.mjs
CHANGED
|
@@ -16,6 +16,20 @@ let globalShellSettings = {
|
|
|
16
16
|
nounset: false // set -u equivalent: error on undefined variables
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
+
// Helper function to create result objects with Bun.$ compatibility
|
|
20
|
+
function createResult({ code, stdout = '', stderr = '', stdin = '' }) {
|
|
21
|
+
return {
|
|
22
|
+
code,
|
|
23
|
+
stdout,
|
|
24
|
+
stderr,
|
|
25
|
+
stdin,
|
|
26
|
+
// Bun.$ compatibility method
|
|
27
|
+
async text() {
|
|
28
|
+
return stdout;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
19
33
|
// Virtual command registry - unified system for all commands
|
|
20
34
|
const virtualCommands = new Map();
|
|
21
35
|
|
|
@@ -219,13 +233,21 @@ class ProcessRunner extends StreamEmitter {
|
|
|
219
233
|
const code = await exited;
|
|
220
234
|
await Promise.all([outPump, errPump, stdinPumpPromise]);
|
|
221
235
|
|
|
222
|
-
|
|
236
|
+
const resultData = {
|
|
223
237
|
code,
|
|
224
238
|
stdout: this.options.capture ? Buffer.concat(this.outChunks).toString('utf8') : undefined,
|
|
225
239
|
stderr: this.options.capture ? Buffer.concat(this.errChunks).toString('utf8') : undefined,
|
|
226
240
|
stdin: this.options.capture && this.inChunks ? Buffer.concat(this.inChunks).toString('utf8') : undefined,
|
|
227
241
|
child: this.child
|
|
228
242
|
};
|
|
243
|
+
|
|
244
|
+
this.result = {
|
|
245
|
+
...resultData,
|
|
246
|
+
// Bun.$ compatibility method
|
|
247
|
+
async text() {
|
|
248
|
+
return resultData.stdout || '';
|
|
249
|
+
}
|
|
250
|
+
};
|
|
229
251
|
|
|
230
252
|
this.finished = true;
|
|
231
253
|
this.emit('end', this.result);
|
|
@@ -481,7 +503,7 @@ class ProcessRunner extends StreamEmitter {
|
|
|
481
503
|
|
|
482
504
|
async _runPipeline(commands) {
|
|
483
505
|
if (commands.length === 0) {
|
|
484
|
-
return { code: 1, stdout: '', stderr: 'No commands in pipeline', stdin: '' };
|
|
506
|
+
return createResult({ code: 1, stdout: '', stderr: 'No commands in pipeline', stdin: '' });
|
|
485
507
|
}
|
|
486
508
|
|
|
487
509
|
let currentOutput = '';
|
|
@@ -565,14 +587,14 @@ class ProcessRunner extends StreamEmitter {
|
|
|
565
587
|
this.emit('data', { type: 'stderr', data: buf });
|
|
566
588
|
}
|
|
567
589
|
|
|
568
|
-
// Store final result
|
|
569
|
-
const finalResult = {
|
|
590
|
+
// Store final result using createResult helper for .text() method compatibility
|
|
591
|
+
const finalResult = createResult({
|
|
570
592
|
code: result.code,
|
|
571
593
|
stdout: currentOutput,
|
|
572
594
|
stderr: result.stderr,
|
|
573
595
|
stdin: this.options.stdin && typeof this.options.stdin === 'string' ? this.options.stdin :
|
|
574
596
|
this.options.stdin && Buffer.isBuffer(this.options.stdin) ? this.options.stdin.toString('utf8') : ''
|
|
575
|
-
};
|
|
597
|
+
});
|
|
576
598
|
|
|
577
599
|
this.result = finalResult;
|
|
578
600
|
this.finished = true;
|
|
@@ -605,13 +627,13 @@ class ProcessRunner extends StreamEmitter {
|
|
|
605
627
|
}
|
|
606
628
|
} catch (error) {
|
|
607
629
|
// Handle errors from virtual commands in pipeline
|
|
608
|
-
const result = {
|
|
630
|
+
const result = createResult({
|
|
609
631
|
code: error.code ?? 1,
|
|
610
632
|
stdout: currentOutput,
|
|
611
633
|
stderr: error.stderr ?? error.message,
|
|
612
634
|
stdin: this.options.stdin && typeof this.options.stdin === 'string' ? this.options.stdin :
|
|
613
635
|
this.options.stdin && Buffer.isBuffer(this.options.stdin) ? this.options.stdin.toString('utf8') : ''
|
|
614
|
-
};
|
|
636
|
+
});
|
|
615
637
|
|
|
616
638
|
this.result = result;
|
|
617
639
|
this.finished = true;
|
|
@@ -637,13 +659,13 @@ class ProcessRunner extends StreamEmitter {
|
|
|
637
659
|
} else {
|
|
638
660
|
// For system commands in pipeline, we would need to spawn processes
|
|
639
661
|
// For now, return an error indicating this isn't supported
|
|
640
|
-
const result = {
|
|
662
|
+
const result = createResult({
|
|
641
663
|
code: 1,
|
|
642
664
|
stdout: currentOutput,
|
|
643
665
|
stderr: `Pipeline with system command '${cmd}' not yet supported`,
|
|
644
666
|
stdin: this.options.stdin && typeof this.options.stdin === 'string' ? this.options.stdin :
|
|
645
667
|
this.options.stdin && Buffer.isBuffer(this.options.stdin) ? this.options.stdin.toString('utf8') : ''
|
|
646
|
-
};
|
|
668
|
+
});
|
|
647
669
|
|
|
648
670
|
this.result = result;
|
|
649
671
|
this.finished = true;
|
|
@@ -684,21 +706,21 @@ class ProcessRunner extends StreamEmitter {
|
|
|
684
706
|
const destResult = await destination;
|
|
685
707
|
|
|
686
708
|
// Return the final result with combined information
|
|
687
|
-
return {
|
|
709
|
+
return createResult({
|
|
688
710
|
code: destResult.code,
|
|
689
711
|
stdout: destResult.stdout,
|
|
690
712
|
stderr: sourceResult.stderr + destResult.stderr,
|
|
691
713
|
stdin: sourceResult.stdin
|
|
692
|
-
};
|
|
714
|
+
});
|
|
693
715
|
|
|
694
716
|
} catch (error) {
|
|
695
|
-
const result = {
|
|
717
|
+
const result = createResult({
|
|
696
718
|
code: error.code ?? 1,
|
|
697
719
|
stdout: '',
|
|
698
720
|
stderr: error.message || 'Pipeline execution failed',
|
|
699
721
|
stdin: this.options.stdin && typeof this.options.stdin === 'string' ? this.options.stdin :
|
|
700
722
|
this.options.stdin && Buffer.isBuffer(this.options.stdin) ? this.options.stdin.toString('utf8') : ''
|
|
701
|
-
};
|
|
723
|
+
});
|
|
702
724
|
|
|
703
725
|
this.result = result;
|
|
704
726
|
this.finished = true;
|
|
@@ -846,14 +868,14 @@ class ProcessRunner extends StreamEmitter {
|
|
|
846
868
|
stderr: 'pipe'
|
|
847
869
|
});
|
|
848
870
|
|
|
849
|
-
result = {
|
|
871
|
+
result = createResult({
|
|
850
872
|
code: proc.exitCode || 0,
|
|
851
873
|
stdout: proc.stdout?.toString('utf8') || '',
|
|
852
874
|
stderr: proc.stderr?.toString('utf8') || '',
|
|
853
875
|
stdin: typeof stdin === 'string' ? stdin :
|
|
854
|
-
Buffer.isBuffer(stdin) ? stdin.toString('utf8') : ''
|
|
855
|
-
|
|
856
|
-
|
|
876
|
+
Buffer.isBuffer(stdin) ? stdin.toString('utf8') : ''
|
|
877
|
+
});
|
|
878
|
+
result.child = proc;
|
|
857
879
|
} else {
|
|
858
880
|
// Use Node's synchronous spawn
|
|
859
881
|
const cp = require('child_process');
|
|
@@ -866,14 +888,14 @@ class ProcessRunner extends StreamEmitter {
|
|
|
866
888
|
stdio: ['pipe', 'pipe', 'pipe']
|
|
867
889
|
});
|
|
868
890
|
|
|
869
|
-
result = {
|
|
891
|
+
result = createResult({
|
|
870
892
|
code: proc.status || 0,
|
|
871
893
|
stdout: proc.stdout || '',
|
|
872
894
|
stderr: proc.stderr || '',
|
|
873
895
|
stdin: typeof stdin === 'string' ? stdin :
|
|
874
|
-
Buffer.isBuffer(stdin) ? stdin.toString('utf8') : ''
|
|
875
|
-
|
|
876
|
-
|
|
896
|
+
Buffer.isBuffer(stdin) ? stdin.toString('utf8') : ''
|
|
897
|
+
});
|
|
898
|
+
result.child = proc;
|
|
877
899
|
}
|
|
878
900
|
|
|
879
901
|
// Mirror output if requested (but always capture for result)
|
package/README.md
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
# command-$tream
|
|
1
|
+
# [command-$tream](https://github.com/link-foundation/command-stream)
|
|
2
2
|
|
|
3
3
|
$treamable commands executor
|
|
4
4
|
|
|
5
5
|
A modern $ shell utility library with streaming, async iteration, and EventEmitter support, optimized for Bun runtime.
|
|
6
6
|
|
|
7
|
+
<img width="2624" height="1320" alt="carbon" src="https://github.com/user-attachments/assets/41cccd6a-f029-4206-b3bc-a85c5dbcf2cf" />
|
|
8
|
+
|
|
7
9
|
## Features
|
|
8
10
|
|
|
9
11
|
- 🐚 **Shell-like by Default**: Commands behave exactly like running in terminal (stdout→stdout, stderr→stderr, stdin→stdin)
|
|
@@ -12,10 +14,51 @@ A modern $ shell utility library with streaming, async iteration, and EventEmitt
|
|
|
12
14
|
- 📡 **Real-time Streaming**: Process command output as it arrives, not after completion
|
|
13
15
|
- 🔄 **Bun Optimized**: Designed for Bun runtime with Node.js compatibility
|
|
14
16
|
- ⚡ **Performance**: Memory-efficient streaming prevents large buffer accumulation
|
|
15
|
-
- 🎯 **Backward Compatible**: Existing `await $` syntax continues to work
|
|
17
|
+
- 🎯 **Backward Compatible**: Existing `await $` syntax continues to work + Bun.$ `.text()` method
|
|
16
18
|
- 🛡️ **Type Safe**: Full TypeScript support (coming soon)
|
|
17
19
|
- 🔧 **Built-in Commands**: 18 essential commands work identically across platforms
|
|
18
20
|
|
|
21
|
+
## Comparison with Other Libraries
|
|
22
|
+
|
|
23
|
+
| Feature | [command-stream](https://github.com/link-foundation/command-stream) | [Bun.$](https://bun.sh/docs/runtime/shell) | [execa](https://github.com/sindresorhus/execa) | [zx](https://github.com/google/zx) |
|
|
24
|
+
|---------|----------------|-------|-------|-----|
|
|
25
|
+
| **Runtime Support** | ✅ Bun + Node.js | 🟡 Bun only | ✅ Node.js | ✅ Node.js |
|
|
26
|
+
| **Template Literals** | ✅ `` $`cmd` `` | ✅ `` $`cmd` `` | ✅ `` $`cmd` `` | ✅ `` $`cmd` `` |
|
|
27
|
+
| **Real-time Streaming** | ✅ Live output | ❌ Buffer only | 🟡 Limited | ❌ Buffer only |
|
|
28
|
+
| **Synchronous Execution** | ✅ `.sync()` with events | ❌ No | ✅ `execaSync` | ❌ No |
|
|
29
|
+
| **Async Iteration** | ✅ `for await (chunk of $.stream())` | ❌ No | ❌ No | ❌ No |
|
|
30
|
+
| **EventEmitter Pattern** | ✅ `.on('data', ...)` | ❌ No | 🟡 Limited events | ❌ No |
|
|
31
|
+
| **Mixed Patterns** | ✅ Events + await/sync | ❌ No | ❌ No | ❌ No |
|
|
32
|
+
| **Bun.$ Compatibility** | ✅ `.text()` method support | ✅ Native API | ❌ No | ❌ No |
|
|
33
|
+
| **Shell Injection Protection** | ✅ Auto-quoting | ✅ Built-in | ✅ Safe by default | ✅ Safe by default |
|
|
34
|
+
| **Cross-platform** | ✅ macOS/Linux/Windows | ✅ Yes | ✅ Yes | ✅ Yes |
|
|
35
|
+
| **Performance** | ⚡ Fast (Bun optimized) | ⚡ Very fast | 🐌 Moderate | 🐌 Slow |
|
|
36
|
+
| **Memory Efficiency** | ✅ Streaming prevents buildup | 🟡 Buffers in memory | 🟡 Buffers in memory | 🟡 Buffers in memory |
|
|
37
|
+
| **Error Handling** | ✅ Configurable (`set -e`/`set +e`, non-zero OK by default) | ✅ Throws on error | ✅ Throws on error | ✅ Throws on error |
|
|
38
|
+
| **Shell Settings** | ✅ `set -e`/`set +e` equivalent | ❌ No | ❌ No | ❌ No |
|
|
39
|
+
| **Stdout Support** | ✅ Real-time streaming + events | ✅ Shell redirection + buffered | ✅ Node.js streams + interleaved | ✅ Readable streams + `.pipe.stdout` |
|
|
40
|
+
| **Stderr Support** | ✅ Real-time streaming + events | ✅ Redirection + `.quiet()` access | ✅ Streams + interleaved output | ✅ Readable streams + `.pipe.stderr` |
|
|
41
|
+
| **Stdin Support** | ✅ string/Buffer/inherit/ignore | ✅ Pipe operations | ✅ Input/output streams | ✅ Basic stdin |
|
|
42
|
+
| **Built-in Commands** | ✅ **18 commands**: cat, ls, mkdir, rm, mv, cp, touch, basename, dirname, seq, yes + all Bun.$ commands | ✅ echo, cd, etc. | ❌ Uses system | ❌ Uses system |
|
|
43
|
+
| **Virtual Commands Engine** | ✅ **Revolutionary**: Register JavaScript functions as shell commands with full pipeline support | ❌ No extensibility | ❌ No custom commands | ❌ No custom commands |
|
|
44
|
+
| **Pipeline/Piping Support** | ✅ **Advanced**: System + Built-ins + Virtual + Mixed + `.pipe()` method | ✅ Standard shell piping | ✅ Programmatic `.pipe()` + multi-destination | ✅ Shell piping + `.pipe()` method |
|
|
45
|
+
| **Bundle Size** | 📦 ~15KB | 🎯 0KB (built-in) | 📦 ~25KB | 📦 ~50KB |
|
|
46
|
+
| **TypeScript** | 🔄 Coming soon | ✅ Built-in | ✅ Full support | ✅ Full support |
|
|
47
|
+
| **License** | ✅ **Unlicense (Public Domain)** | 🟡 MIT (+ LGPL dependencies) | 🟡 MIT | 🟡 Apache 2.0 |
|
|
48
|
+
|
|
49
|
+
### Why Choose command-stream?
|
|
50
|
+
|
|
51
|
+
- **🆓 Truly Free**: **Unlicense (Public Domain)** - No restrictions, no attribution required, use however you want
|
|
52
|
+
- **🚀 Revolutionary Virtual Commands**: **World's first** fully customizable virtual commands engine - register JavaScript functions as shell commands!
|
|
53
|
+
- **🔗 Advanced Pipeline System**: **Only library** where virtual commands work seamlessly in pipelines with built-ins and system commands
|
|
54
|
+
- **🔧 Built-in Commands**: **18 essential commands** work identically across all platforms - no system dependencies!
|
|
55
|
+
- **📡 Real-time Processing**: Only library with true streaming and async iteration
|
|
56
|
+
- **🔄 Flexible Patterns**: Multiple usage patterns (await, events, iteration, mixed)
|
|
57
|
+
- **🐚 Shell Replacement**: Dynamic error handling with `set -e`/`set +e` equivalents for .sh file replacement
|
|
58
|
+
- **⚡ Bun Optimized**: Designed for Bun with Node.js fallback compatibility
|
|
59
|
+
- **💾 Memory Efficient**: Streaming prevents large buffer accumulation
|
|
60
|
+
- **🛡️ Production Ready**: 266+ tests with comprehensive coverage
|
|
61
|
+
|
|
19
62
|
## Built-in Commands (🚀 NEW!)
|
|
20
63
|
|
|
21
64
|
command-stream now includes **18 built-in commands** that work identically to their bash/sh counterparts, providing true cross-platform shell scripting without system dependencies:
|
|
@@ -72,46 +115,6 @@ await $`seq 1 5 | cat > numbers.txt`;
|
|
|
72
115
|
await $`basename /path/to/file.txt .txt`; // → "file"
|
|
73
116
|
```
|
|
74
117
|
|
|
75
|
-
## Comparison with Other Libraries
|
|
76
|
-
|
|
77
|
-
| Feature | [command-stream](https://github.com/link-foundation/command-stream) | [Bun.$](https://bun.sh/docs/runtime/shell) | [execa](https://github.com/sindresorhus/execa) | [zx](https://github.com/google/zx) |
|
|
78
|
-
|---------|----------------|-------|-------|-----|
|
|
79
|
-
| **Runtime Support** | ✅ Bun + Node.js | 🟡 Bun only | ✅ Node.js | ✅ Node.js |
|
|
80
|
-
| **Template Literals** | ✅ `` $`cmd` `` | ✅ `` $`cmd` `` | ✅ `` $`cmd` `` | ✅ `` $`cmd` `` |
|
|
81
|
-
| **Real-time Streaming** | ✅ Live output | ❌ Buffer only | 🟡 Limited | ❌ Buffer only |
|
|
82
|
-
| **Synchronous Execution** | ✅ `.sync()` with events | ❌ No | ✅ `execaSync` | ❌ No |
|
|
83
|
-
| **Async Iteration** | ✅ `for await (chunk of $.stream())` | ❌ No | ❌ No | ❌ No |
|
|
84
|
-
| **EventEmitter Pattern** | ✅ `.on('data', ...)` | ❌ No | 🟡 Limited events | ❌ No |
|
|
85
|
-
| **Mixed Patterns** | ✅ Events + await/sync | ❌ No | ❌ No | ❌ No |
|
|
86
|
-
| **Shell Injection Protection** | ✅ Auto-quoting | ✅ Built-in | ✅ Safe by default | ✅ Safe by default |
|
|
87
|
-
| **Cross-platform** | ✅ macOS/Linux/Windows | ✅ Yes | ✅ Yes | ✅ Yes |
|
|
88
|
-
| **Performance** | ⚡ Fast (Bun optimized) | ⚡ Very fast | 🐌 Moderate | 🐌 Slow |
|
|
89
|
-
| **Memory Efficiency** | ✅ Streaming prevents buildup | 🟡 Buffers in memory | 🟡 Buffers in memory | 🟡 Buffers in memory |
|
|
90
|
-
| **Error Handling** | ✅ Configurable (`set -e`/`set +e`, non-zero OK by default) | ✅ Throws on error | ✅ Throws on error | ✅ Throws on error |
|
|
91
|
-
| **Shell Settings** | ✅ `set -e`/`set +e` equivalent | ❌ No | ❌ No | ❌ No |
|
|
92
|
-
| **Stdout Support** | ✅ Real-time streaming + events | ✅ Shell redirection + buffered | ✅ Node.js streams + interleaved | ✅ Readable streams + `.pipe.stdout` |
|
|
93
|
-
| **Stderr Support** | ✅ Real-time streaming + events | ✅ Redirection + `.quiet()` access | ✅ Streams + interleaved output | ✅ Readable streams + `.pipe.stderr` |
|
|
94
|
-
| **Stdin Support** | ✅ string/Buffer/inherit/ignore | ✅ Pipe operations | ✅ Input/output streams | ✅ Basic stdin |
|
|
95
|
-
| **Built-in Commands** | ✅ **18 commands**: cat, ls, mkdir, rm, mv, cp, touch, basename, dirname, seq, yes + all Bun.$ commands | ✅ echo, cd, etc. | ❌ Uses system | ❌ Uses system |
|
|
96
|
-
| **Virtual Commands Engine** | ✅ **Revolutionary**: Register JavaScript functions as shell commands with full pipeline support | ❌ No extensibility | ❌ No custom commands | ❌ No custom commands |
|
|
97
|
-
| **Pipeline/Piping Support** | ✅ **Advanced**: System + Built-ins + Virtual + Mixed + `.pipe()` method | ✅ Standard shell piping | ✅ Programmatic `.pipe()` + multi-destination | ✅ Shell piping + `.pipe()` method |
|
|
98
|
-
| **Bundle Size** | 📦 ~15KB | 🎯 0KB (built-in) | 📦 ~25KB | 📦 ~50KB |
|
|
99
|
-
| **TypeScript** | 🔄 Coming soon | ✅ Built-in | ✅ Full support | ✅ Full support |
|
|
100
|
-
| **License** | ✅ **Unlicense (Public Domain)** | 🟡 MIT (+ LGPL dependencies) | 🟡 MIT | 🟡 Apache 2.0 |
|
|
101
|
-
|
|
102
|
-
### Why Choose command-stream?
|
|
103
|
-
|
|
104
|
-
- **🆓 Truly Free**: **Unlicense (Public Domain)** - No restrictions, no attribution required, use however you want
|
|
105
|
-
- **🚀 Revolutionary Virtual Commands**: **World's first** fully customizable virtual commands engine - register JavaScript functions as shell commands!
|
|
106
|
-
- **🔗 Advanced Pipeline System**: **Only library** where virtual commands work seamlessly in pipelines with built-ins and system commands
|
|
107
|
-
- **🔧 Built-in Commands**: **18 essential commands** work identically across all platforms - no system dependencies!
|
|
108
|
-
- **📡 Real-time Processing**: Only library with true streaming and async iteration
|
|
109
|
-
- **🔄 Flexible Patterns**: Multiple usage patterns (await, events, iteration, mixed)
|
|
110
|
-
- **🐚 Shell Replacement**: Dynamic error handling with `set -e`/`set +e` equivalents for .sh file replacement
|
|
111
|
-
- **⚡ Bun Optimized**: Designed for Bun with Node.js fallback compatibility
|
|
112
|
-
- **💾 Memory Efficient**: Streaming prevents large buffer accumulation
|
|
113
|
-
- **🛡️ Production Ready**: 266+ tests with comprehensive coverage
|
|
114
|
-
|
|
115
118
|
## Installation
|
|
116
119
|
|
|
117
120
|
```bash
|
|
@@ -693,10 +696,37 @@ All built-in commands support:
|
|
|
693
696
|
stdout: string, // Complete stdout output
|
|
694
697
|
stderr: string, // Complete stderr output
|
|
695
698
|
stdin: string, // Input sent to process
|
|
696
|
-
child: ChildProcess
|
|
699
|
+
child: ChildProcess, // Original child process object
|
|
700
|
+
async text() // Bun.$ compatibility method - returns stdout as string
|
|
697
701
|
}
|
|
698
702
|
```
|
|
699
703
|
|
|
704
|
+
#### `.text()` Method (Bun.$ Compatibility)
|
|
705
|
+
|
|
706
|
+
For compatibility with Bun.$, all result objects include an async `.text()` method:
|
|
707
|
+
|
|
708
|
+
```javascript
|
|
709
|
+
import { $ } from 'command-stream';
|
|
710
|
+
|
|
711
|
+
// Both sync and async execution support .text()
|
|
712
|
+
const result1 = await $`echo "hello world"`;
|
|
713
|
+
const text1 = await result1.text(); // "hello world\n"
|
|
714
|
+
|
|
715
|
+
const result2 = $`echo "sync example"`.sync();
|
|
716
|
+
const text2 = await result2.text(); // "sync example\n"
|
|
717
|
+
|
|
718
|
+
// .text() is equivalent to accessing .stdout
|
|
719
|
+
expect(await result.text()).toBe(result.stdout);
|
|
720
|
+
|
|
721
|
+
// Works with built-in commands
|
|
722
|
+
const result3 = await $`seq 1 3`;
|
|
723
|
+
const text3 = await result3.text(); // "1\n2\n3\n"
|
|
724
|
+
|
|
725
|
+
// Works with .pipe() method
|
|
726
|
+
const result4 = await $`echo "pipe test"`.pipe($`cat`);
|
|
727
|
+
const text4 = await result4.text(); // "pipe test\n"
|
|
728
|
+
```
|
|
729
|
+
|
|
700
730
|
## Testing
|
|
701
731
|
|
|
702
732
|
```bash
|
package/package.json
CHANGED