117 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			117 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import {setImmediate} from 'node:timers/promises';
 | |
| import getStream, {getStreamAsArrayBuffer, getStreamAsArray} from 'get-stream';
 | |
| import {isArrayBuffer} from '../utils/uint-array.js';
 | |
| import {shouldLogOutput, logLines} from '../verbose/output.js';
 | |
| import {iterateForResult} from './iterate.js';
 | |
| import {handleMaxBuffer} from './max-buffer.js';
 | |
| import {getStripFinalNewline} from './strip-newline.js';
 | |
| 
 | |
| // Retrieve `result.stdout|stderr|all|stdio[*]`
 | |
| export const getStreamOutput = async ({stream, onStreamEnd, fdNumber, encoding, buffer, maxBuffer, lines, allMixed, stripFinalNewline, verboseInfo, streamInfo}) => {
 | |
| 	const logPromise = logOutputAsync({
 | |
| 		stream,
 | |
| 		onStreamEnd,
 | |
| 		fdNumber,
 | |
| 		encoding,
 | |
| 		allMixed,
 | |
| 		verboseInfo,
 | |
| 		streamInfo,
 | |
| 	});
 | |
| 
 | |
| 	if (!buffer) {
 | |
| 		await Promise.all([resumeStream(stream), logPromise]);
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	const stripFinalNewlineValue = getStripFinalNewline(stripFinalNewline, fdNumber);
 | |
| 	const iterable = iterateForResult({
 | |
| 		stream,
 | |
| 		onStreamEnd,
 | |
| 		lines,
 | |
| 		encoding,
 | |
| 		stripFinalNewline: stripFinalNewlineValue,
 | |
| 		allMixed,
 | |
| 	});
 | |
| 	const [output] = await Promise.all([
 | |
| 		getStreamContents({
 | |
| 			stream,
 | |
| 			iterable,
 | |
| 			fdNumber,
 | |
| 			encoding,
 | |
| 			maxBuffer,
 | |
| 			lines,
 | |
| 		}),
 | |
| 		logPromise,
 | |
| 	]);
 | |
| 	return output;
 | |
| };
 | |
| 
 | |
| const logOutputAsync = async ({stream, onStreamEnd, fdNumber, encoding, allMixed, verboseInfo, streamInfo: {fileDescriptors}}) => {
 | |
| 	if (!shouldLogOutput({
 | |
| 		stdioItems: fileDescriptors[fdNumber]?.stdioItems,
 | |
| 		encoding,
 | |
| 		verboseInfo,
 | |
| 		fdNumber,
 | |
| 	})) {
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	const linesIterable = iterateForResult({
 | |
| 		stream,
 | |
| 		onStreamEnd,
 | |
| 		lines: true,
 | |
| 		encoding,
 | |
| 		stripFinalNewline: true,
 | |
| 		allMixed,
 | |
| 	});
 | |
| 	await logLines(linesIterable, stream, fdNumber, verboseInfo);
 | |
| };
 | |
| 
 | |
| // When using `buffer: false`, users need to read `subprocess.stdout|stderr|all` right away
 | |
| // See https://github.com/sindresorhus/execa/issues/730 and https://github.com/sindresorhus/execa/pull/729#discussion_r1465496310
 | |
| const resumeStream = async stream => {
 | |
| 	await setImmediate();
 | |
| 	if (stream.readableFlowing === null) {
 | |
| 		stream.resume();
 | |
| 	}
 | |
| };
 | |
| 
 | |
| const getStreamContents = async ({stream, stream: {readableObjectMode}, iterable, fdNumber, encoding, maxBuffer, lines}) => {
 | |
| 	try {
 | |
| 		if (readableObjectMode || lines) {
 | |
| 			return await getStreamAsArray(iterable, {maxBuffer});
 | |
| 		}
 | |
| 
 | |
| 		if (encoding === 'buffer') {
 | |
| 			return new Uint8Array(await getStreamAsArrayBuffer(iterable, {maxBuffer}));
 | |
| 		}
 | |
| 
 | |
| 		return await getStream(iterable, {maxBuffer});
 | |
| 	} catch (error) {
 | |
| 		return handleBufferedData(handleMaxBuffer({
 | |
| 			error,
 | |
| 			stream,
 | |
| 			readableObjectMode,
 | |
| 			lines,
 | |
| 			encoding,
 | |
| 			fdNumber,
 | |
| 		}));
 | |
| 	}
 | |
| };
 | |
| 
 | |
| // On failure, `result.stdout|stderr|all` should contain the currently buffered stream
 | |
| // They are automatically closed and flushed by Node.js when the subprocess exits
 | |
| // When `buffer` is `false`, `streamPromise` is `undefined` and there is no buffered data to retrieve
 | |
| export const getBufferedData = async streamPromise => {
 | |
| 	try {
 | |
| 		return await streamPromise;
 | |
| 	} catch (error) {
 | |
| 		return handleBufferedData(error);
 | |
| 	}
 | |
| };
 | |
| 
 | |
| // Ensure we are returning Uint8Arrays when using `encoding: 'buffer'`
 | |
| const handleBufferedData = ({bufferedData}) => isArrayBuffer(bufferedData)
 | |
| 	? new Uint8Array(bufferedData)
 | |
| 	: bufferedData;
 |