Skip to content

Commit 7566081

Browse files
1e9yantongolub
andauthored
feat: direct piping to file shortcut (google#1001)
* feat: pipe to file shortcut * docs: update doc to reflect the new pipe signature --------- Co-authored-by: Anton Golub <antongolub@antongolub.com>
1 parent 2a3b19d commit 7566081

File tree

3 files changed

+25
-17
lines changed

3 files changed

+25
-17
lines changed

docs/process-promise.md

+7
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,13 @@ await $`echo "Hello, stdout!"`
7070
await $`cat /tmp/output.txt`
7171
```
7272

73+
You can pass a string to `pipe()` to implicitly create a receiving file. The previous example is equivalent to:
74+
75+
```js
76+
await $`echo "Hello, stdout!"`
77+
.pipe('/tmp/output.txt')
78+
```
79+
7380
Pipes can be used to show a real-time output of the process:
7481

7582
```js

src/core.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ export class ProcessPromise extends Promise<ProcessOutput> {
335335
pipe<D extends Writable>(dest: D): D & PromiseLike<ProcessOutput & D>
336336
pipe<D extends ProcessPromise>(dest: D): D
337337
pipe(
338-
dest: Writable | ProcessPromise | TemplateStringsArray,
338+
dest: Writable | ProcessPromise | TemplateStringsArray | string,
339339
...args: any[]
340340
): (Writable & PromiseLike<ProcessPromise & Writable>) | ProcessPromise {
341341
if (isStringLiteral(dest, ...args))
@@ -347,9 +347,6 @@ export class ProcessPromise extends Promise<ProcessOutput> {
347347
})(dest as TemplateStringsArray, ...args)
348348
)
349349

350-
if (isString(dest))
351-
throw new Error('The pipe() method does not take strings. Forgot $?')
352-
353350
this._piped = true
354351
const ee = this._ee
355352
const from = new VoidStream()
@@ -371,6 +368,8 @@ export class ProcessPromise extends Promise<ProcessOutput> {
371368
})
372369
}
373370

371+
if (isString(dest)) dest = fs.createWriteStream(dest)
372+
374373
if (dest instanceof ProcessPromise) {
375374
dest._pipedFrom = this
376375

@@ -382,6 +381,7 @@ export class ProcessPromise extends Promise<ProcessOutput> {
382381
}
383382
return dest
384383
}
384+
385385
from.once('end', () => dest.emit('end-piped-from')).pipe(dest)
386386
return promisifyStream(dest, this) as Writable &
387387
PromiseLike<ProcessPromise & Writable>

test/core.test.js

+14-13
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,20 @@ describe('core', () => {
421421
}
422422
})
423423

424+
test('accepts file', async () => {
425+
const file = tempfile()
426+
try {
427+
await $`echo foo`.pipe(file)
428+
assert.equal((await fs.readFile(file)).toString(), 'foo\n')
429+
430+
const r = $`cat`
431+
fs.createReadStream(file).pipe(r.stdin)
432+
assert.equal((await r).stdout, 'foo\n')
433+
} finally {
434+
await fs.rm(file)
435+
}
436+
})
437+
424438
test('accepts ProcessPromise', async () => {
425439
const p = await $`echo foo`.pipe($`cat`)
426440
assert.equal(p.stdout.trim(), 'foo')
@@ -437,19 +451,6 @@ describe('core', () => {
437451
assert.equal((await p1).stdout.trim(), 'pipe-to-stdout')
438452
})
439453

440-
test('checks argument type', async () => {
441-
let err
442-
try {
443-
$`echo 'test'`.pipe('str')
444-
} catch (p) {
445-
err = p
446-
}
447-
assert.equal(
448-
err.message,
449-
'The pipe() method does not take strings. Forgot $?'
450-
)
451-
})
452-
453454
describe('supports chaining', () => {
454455
const getUpperCaseTransform = () =>
455456
new Transform({

0 commit comments

Comments
 (0)