diff --git a/docs/process-promise.md b/docs/process-promise.md index d34e0a7b49..bf68383daa 100644 --- a/docs/process-promise.md +++ b/docs/process-promise.md @@ -70,6 +70,13 @@ await $`echo "Hello, stdout!"` await $`cat /tmp/output.txt` ``` +You can pass a string to `pipe()` to implicitly create a receiving file. The previous example is equivalent to: + +```js +await $`echo "Hello, stdout!"` + .pipe('/tmp/output.txt') +``` + Pipes can be used to show a real-time output of the process: ```js diff --git a/src/core.ts b/src/core.ts index 840b0110b5..34afe47d81 100644 --- a/src/core.ts +++ b/src/core.ts @@ -335,7 +335,7 @@ export class ProcessPromise extends Promise { pipe(dest: D): D & PromiseLike pipe(dest: D): D pipe( - dest: Writable | ProcessPromise | TemplateStringsArray, + dest: Writable | ProcessPromise | TemplateStringsArray | string, ...args: any[] ): (Writable & PromiseLike) | ProcessPromise { if (isStringLiteral(dest, ...args)) @@ -347,9 +347,6 @@ export class ProcessPromise extends Promise { })(dest as TemplateStringsArray, ...args) ) - if (isString(dest)) - throw new Error('The pipe() method does not take strings. Forgot $?') - this._piped = true const ee = this._ee const from = new VoidStream() @@ -371,6 +368,8 @@ export class ProcessPromise extends Promise { }) } + if (isString(dest)) dest = fs.createWriteStream(dest) + if (dest instanceof ProcessPromise) { dest._pipedFrom = this @@ -382,6 +381,7 @@ export class ProcessPromise extends Promise { } return dest } + from.once('end', () => dest.emit('end-piped-from')).pipe(dest) return promisifyStream(dest, this) as Writable & PromiseLike diff --git a/test/core.test.js b/test/core.test.js index 46b48d99ef..1dcebf7ce1 100644 --- a/test/core.test.js +++ b/test/core.test.js @@ -421,6 +421,20 @@ describe('core', () => { } }) + test('accepts file', async () => { + const file = tempfile() + try { + await $`echo foo`.pipe(file) + assert.equal((await fs.readFile(file)).toString(), 'foo\n') + + const r = $`cat` + fs.createReadStream(file).pipe(r.stdin) + assert.equal((await r).stdout, 'foo\n') + } finally { + await fs.rm(file) + } + }) + test('accepts ProcessPromise', async () => { const p = await $`echo foo`.pipe($`cat`) assert.equal(p.stdout.trim(), 'foo') @@ -437,19 +451,6 @@ describe('core', () => { assert.equal((await p1).stdout.trim(), 'pipe-to-stdout') }) - test('checks argument type', async () => { - let err - try { - $`echo 'test'`.pipe('str') - } catch (p) { - err = p - } - assert.equal( - err.message, - 'The pipe() method does not take strings. Forgot $?' - ) - }) - describe('supports chaining', () => { const getUpperCaseTransform = () => new Transform({