From 507e53992d43ac5f1324178fbc90dfd68402d3d5 Mon Sep 17 00:00:00 2001 From: Andy Edwards Date: Fri, 8 May 2020 01:03:28 -0500 Subject: [PATCH] feat: always include code/signal in output --- index.d.ts | 19 ++++++-------- src/index.js | 26 +++++++++++--------- test/index.js | 68 ++++++++++++++++++++++++++++++++++----------------- 3 files changed, 68 insertions(+), 45 deletions(-) diff --git a/index.d.ts b/index.d.ts index 569c07e..5f61c8b 100644 --- a/index.d.ts +++ b/index.d.ts @@ -6,29 +6,26 @@ import { ForkOptions, } from 'child_process' -interface Output { +export interface Output { stdout?: string | Buffer | null | undefined stderr?: string | Buffer | null | undefined + code?: number | null + signal?: string | null } -interface ExitReason { - code?: number - signal?: string -} - -type ErrorWithOutput = Error & Output & ExitReason +export type ErrorWithOutput = Error & Output -type ChildProcessPromise = ChildProcess & Promise +export type ChildProcessPromise = ChildProcess & Promise -interface PromisifyChildProcessOptions { +export interface PromisifyChildProcessOptions { encoding?: string killSignal?: string maxBuffer?: number } -type PromisifySpawnOptions = SpawnOptions & PromisifyChildProcessOptions +export type PromisifySpawnOptions = SpawnOptions & PromisifyChildProcessOptions -type PromisifyForkOptions = ForkOptions & PromisifyChildProcessOptions +export type PromisifyForkOptions = ForkOptions & PromisifyChildProcessOptions export function promisifyChildProcess( child: ChildProcess, diff --git a/src/index.js b/src/index.js index cfa422b..5b7898d 100644 --- a/src/index.js +++ b/src/index.js @@ -4,17 +4,19 @@ import type { ChildProcess } from 'child_process' const child_process = require('child_process') export type ChildProcessOutput = { - stdout: ?(string | Buffer), - stderr: ?(string | Buffer), -} - -export type ErrorWithOutput = Error & { stdout?: ?(string | Buffer), stderr?: ?(string | Buffer), - code?: ?number, - signal?: ?string, + code?: number | null, + signal?: string | null, } +export interface ExitReason { + code?: number | null; + signal?: string | null; +} + +export type ErrorWithOutput = Error & ChildProcessOutput + export type ChildProcessPromise = ChildProcess & Promise type PromisifyChildProcessBaseOpts = { @@ -100,6 +102,8 @@ export function promisifyChildProcess( } } function defineOutputs(obj: Object) { + obj.code = code + obj.signal = signal if (captureStdio) { obj.stdout = joinChunks(stdoutChunks, encoding) obj.stderr = joinChunks(stderrChunks, encoding) @@ -124,15 +128,13 @@ export function promisifyChildProcess( }) } } - const output: ChildProcessOutput = ({}: any) - defineOutputs(output) const finalError: ?ErrorWithOutput = error if (finalError) { - finalError.code = code - finalError.signal = signal defineOutputs(finalError) reject(finalError) } else { + const output: ChildProcessOutput = ({}: any) + defineOutputs(output) resolve(output) } } @@ -190,7 +192,7 @@ function promisifyExecMethod(method: any): any { err.stderr = stderr reject(err) } else { - resolve({ stdout, stderr }) + resolve({ code: 0, signal: null, stdout, stderr }) } } ) diff --git a/test/index.js b/test/index.js index 4fd06e4..8e857a0 100644 --- a/test/index.js +++ b/test/index.js @@ -52,7 +52,7 @@ describe('spawn', function() { it('resolves with process output', async () => { let finallyDone = false - const { stdout, stderr } = await spawn( + const { code, signal, stdout, stderr } = await spawn( process.execPath, [require.resolve('./resolvesWithProcessOutput')], { maxBuffer: 200 * 1024 } @@ -61,6 +61,8 @@ describe('spawn', function() { finallyDone = true }) expect(finallyDone, 'finally handler finished').to.be.true + expect(code, 'code').to.equal(0) + expect(signal, 'signal').to.equal(null) if (stdout == null || stderr == null) throw new Error('missing output') if (!(stdout instanceof Buffer)) throw new Error('expected stdout to be a buffer') @@ -85,7 +87,11 @@ describe('spawn', function() { { maxBuffer: 1 } ).catch(err => (error = err)) if (error == null) throw new Error('missing error') - const { stdout, stderr } = error + const { code, signal, stdout, stderr } = error + if (process.env.BABEL_ENV !== 'coverage') + expect(code, 'code').to.equal(null) + if (process.env.BABEL_ENV !== 'coverage') + expect(signal, 'signal').to.equal('SIGTERM') expect(stdout.toString('utf8')).to.equal('h') expect(stderr.toString('utf8')).to.equal('') }) @@ -112,9 +118,10 @@ describe('spawn', function() { .catch(err => (error = err)) expect(finallyDone, 'finally handler finished').to.be.true if (error == null) throw new Error('missing error') - const { code, message, stdout, stderr } = error + const { code, signal, message, stdout, stderr } = error expect(message).to.equal('Process exited with code 2') - expect(code).to.equal(2) + expect(code, 'code').to.equal(2) + expect(signal, 'signal').to.equal(null) if (!(stdout instanceof Buffer)) throw new Error('expected stdout to be a buffer') if (!(stderr instanceof Buffer)) @@ -145,9 +152,10 @@ describe('spawn', function() { }) await child.catch(err => (error = err)) if (error == null) throw new Error('missing error') - const { signal, message, stdout, stderr } = error + const { code, signal, message, stdout, stderr } = error expect(message).to.equal('Process was killed with SIGINT') - expect(signal).to.equal('SIGINT') + expect(code, 'code').to.equal(null) + expect(signal, 'signal').to.equal('SIGINT') if (!(stdout instanceof Buffer)) throw new Error('expected stdout to be a buffer') if (!(stderr instanceof Buffer)) @@ -171,13 +179,15 @@ describe('fork', function() { it('resolves with process output', async () => { let finallyDone = false - const { stdout, stderr } = await fork( + const { code, signal, stdout, stderr } = await fork( require.resolve('./resolvesWithProcessOutput'), { silent: true, maxBuffer: 200 * 1024 } ).finally(async () => { await delay(50) finallyDone = true }) + expect(code, 'code').to.equal(0) + expect(signal, 'signal').to.equal(null) expect(finallyDone, 'finally handler finished').to.be.true if (stdout == null || stderr == null) throw new Error('missing output') if (!(stdout instanceof Buffer)) @@ -202,7 +212,11 @@ describe('fork', function() { maxBuffer: 1, }).catch(err => (error = err)) if (error == null) throw new Error('missing error') - const { stdout, stderr } = error + const { code, signal, stdout, stderr } = error + if (process.env.BABEL_ENV !== 'coverage') + expect(code, 'code').to.equal(null) + if (process.env.BABEL_ENV !== 'coverage') + expect(signal, 'signal').to.equal('SIGTERM') expect(stdout.toString('utf8')).to.equal('h') expect(stderr.toString('utf8')).to.equal('') }) @@ -229,9 +243,10 @@ describe('fork', function() { .catch(err => (error = err)) expect(finallyDone, 'finally handler finished').to.be.true if (error == null) throw new Error('missing error') - const { code, message, stdout, stderr } = error + const { code, signal, message, stdout, stderr } = error expect(message).to.equal('Process exited with code 2') - expect(code).to.equal(2) + expect(code, 'code').to.equal(2) + expect(signal, 'signal').to.equal(null) if (!(stdout instanceof Buffer)) throw new Error('expected stdout to be a buffer') if (!(stderr instanceof Buffer)) @@ -259,9 +274,10 @@ describe('fork', function() { }) await child.catch(err => (error = err)) if (error == null) throw new Error('missing error') - const { signal, message, stdout, stderr } = error + const { code, signal, message, stdout, stderr } = error expect(message).to.equal('Process was killed with SIGINT') - expect(signal).to.equal('SIGINT') + expect(code, 'code').to.equal(null) + expect(signal, 'signal').to.equal('SIGINT') if (!(stdout instanceof Buffer)) throw new Error('expected stdout to be a buffer') if (!(stderr instanceof Buffer)) @@ -281,10 +297,12 @@ describe('exec', function() { this.timeout(30000) it('resolves with process output', async () => { - const { stdout, stderr } = await exec( + const { code, signal, stdout, stderr } = await exec( `${process.execPath} ${require.resolve('./resolvesWithProcessOutput')}` ) if (stdout == null || stderr == null) throw new Error('missing output') + expect(code, 'code').to.equal(0) + expect(signal, 'signal').to.equal(null) expect(stdout).to.equal('hello') expect(stderr).to.equal('world') }) @@ -294,8 +312,9 @@ describe('exec', function() { `${process.execPath} ${require.resolve('./rejectsWithExitCode')}` ).catch(err => (error = err)) if (error == null) throw new Error('missing error') - const { code, stdout, stderr } = error - expect(code).to.equal(2) + const { code, signal, stdout, stderr } = error + expect(code, 'code').to.equal(2) + expect(signal, 'signal').to.equal(null) expect(stdout).to.equal('hello') expect(stderr).to.equal('world') }) @@ -318,8 +337,9 @@ describe('exec', function() { }) await child.catch(err => (error = err)) if (error == null) throw new Error('missing error') - const { signal, stdout, stderr } = error - expect(signal).to.equal('SIGINT') + const { code, signal, stdout, stderr } = error + expect(code, 'code').to.equal(null) + expect(signal, 'signal').to.equal('SIGINT') expect(stdout).to.equal('hello') expect(stderr).to.equal('world') }) @@ -329,10 +349,12 @@ describe('execFile', function() { this.timeout(30000) it('resolves with process output', async () => { - const { stdout, stderr } = await execFile( + const { code, signal, stdout, stderr } = await execFile( require.resolve('./resolvesWithProcessOutput') ) if (stdout == null || stderr == null) throw new Error('missing output') + expect(code, 'code').to.equal(0) + expect(signal, 'signal').to.equal(null) expect(stdout).to.equal('hello') expect(stderr).to.equal('world') }) @@ -342,8 +364,9 @@ describe('execFile', function() { err => (error = err) ) if (error == null) throw new Error('missing error') - const { code, stdout, stderr } = error - expect(code).to.equal(2) + const { code, signal, stdout, stderr } = error + expect(code, 'code').to.equal(2) + expect(signal, 'signal').to.equal(null) expect(stdout).to.equal('hello') expect(stderr).to.equal('world') }) @@ -364,8 +387,9 @@ describe('execFile', function() { }) await child.catch(err => (error = err)) if (error == null) throw new Error('missing error') - const { signal, stdout, stderr } = error - expect(signal).to.equal('SIGINT') + const { code, signal, stdout, stderr } = error + expect(code, 'code').to.equal(null) + expect(signal, 'signal').to.equal('SIGINT') expect(stdout).to.equal('hello') expect(stderr).to.equal('world') })