| 'use strict'; | 
| const isStream = require('is-stream'); | 
| const getStream = require('get-stream'); | 
| const mergeStream = require('merge-stream'); | 
|   | 
| // `input` option | 
| const handleInput = (spawned, input) => { | 
|     // Checking for stdin is workaround for https://github.com/nodejs/node/issues/26852 | 
|     // TODO: Remove `|| spawned.stdin === undefined` once we drop support for Node.js <=12.2.0 | 
|     if (input === undefined || spawned.stdin === undefined) { | 
|         return; | 
|     } | 
|   | 
|     if (isStream(input)) { | 
|         input.pipe(spawned.stdin); | 
|     } else { | 
|         spawned.stdin.end(input); | 
|     } | 
| }; | 
|   | 
| // `all` interleaves `stdout` and `stderr` | 
| const makeAllStream = (spawned, {all}) => { | 
|     if (!all || (!spawned.stdout && !spawned.stderr)) { | 
|         return; | 
|     } | 
|   | 
|     const mixed = mergeStream(); | 
|   | 
|     if (spawned.stdout) { | 
|         mixed.add(spawned.stdout); | 
|     } | 
|   | 
|     if (spawned.stderr) { | 
|         mixed.add(spawned.stderr); | 
|     } | 
|   | 
|     return mixed; | 
| }; | 
|   | 
| // On failure, `result.stdout|stderr|all` should contain the currently buffered stream | 
| const getBufferedData = async (stream, streamPromise) => { | 
|     if (!stream) { | 
|         return; | 
|     } | 
|   | 
|     stream.destroy(); | 
|   | 
|     try { | 
|         return await streamPromise; | 
|     } catch (error) { | 
|         return error.bufferedData; | 
|     } | 
| }; | 
|   | 
| const getStreamPromise = (stream, {encoding, buffer, maxBuffer}) => { | 
|     if (!stream || !buffer) { | 
|         return; | 
|     } | 
|   | 
|     if (encoding) { | 
|         return getStream(stream, {encoding, maxBuffer}); | 
|     } | 
|   | 
|     return getStream.buffer(stream, {maxBuffer}); | 
| }; | 
|   | 
| // Retrieve result of child process: exit code, signal, error, streams (stdout/stderr/all) | 
| const getSpawnedResult = async ({stdout, stderr, all}, {encoding, buffer, maxBuffer}, processDone) => { | 
|     const stdoutPromise = getStreamPromise(stdout, {encoding, buffer, maxBuffer}); | 
|     const stderrPromise = getStreamPromise(stderr, {encoding, buffer, maxBuffer}); | 
|     const allPromise = getStreamPromise(all, {encoding, buffer, maxBuffer: maxBuffer * 2}); | 
|   | 
|     try { | 
|         return await Promise.all([processDone, stdoutPromise, stderrPromise, allPromise]); | 
|     } catch (error) { | 
|         return Promise.all([ | 
|             {error, signal: error.signal, timedOut: error.timedOut}, | 
|             getBufferedData(stdout, stdoutPromise), | 
|             getBufferedData(stderr, stderrPromise), | 
|             getBufferedData(all, allPromise) | 
|         ]); | 
|     } | 
| }; | 
|   | 
| const validateInputSync = ({input}) => { | 
|     if (isStream(input)) { | 
|         throw new TypeError('The `input` option cannot be a stream in sync mode'); | 
|     } | 
| }; | 
|   | 
| module.exports = { | 
|     handleInput, | 
|     makeAllStream, | 
|     getSpawnedResult, | 
|     validateInputSync | 
| }; |