execa
Version:
Process execution for humans
187 lines (180 loc) • 3.69 kB
JavaScript
import {getSignalDescription} from '../terminate/signal.js';
import {getDurationMs} from './duration.js';
import {getFinalError} from './final-error.js';
import {createMessages} from './message.js';
// Object returned on subprocess success
export const makeSuccessResult = ({
command,
escapedCommand,
stdio,
all,
ipcOutput,
options: {cwd},
startTime,
}) => omitUndefinedProperties({
command,
escapedCommand,
cwd,
durationMs: getDurationMs(startTime),
failed: false,
timedOut: false,
isCanceled: false,
isGracefullyCanceled: false,
isTerminated: false,
isMaxBuffer: false,
isForcefullyTerminated: false,
exitCode: 0,
stdout: stdio[1],
stderr: stdio[2],
all,
stdio,
ipcOutput,
pipedFrom: [],
});
// Object returned on subprocess failure before spawning
export const makeEarlyError = ({
error,
command,
escapedCommand,
fileDescriptors,
options,
startTime,
isSync,
}) => makeError({
error,
command,
escapedCommand,
startTime,
timedOut: false,
isCanceled: false,
isGracefullyCanceled: false,
isMaxBuffer: false,
isForcefullyTerminated: false,
stdio: Array.from({length: fileDescriptors.length}),
ipcOutput: [],
options,
isSync,
});
// Object returned on subprocess failure
export const makeError = ({
error: originalError,
command,
escapedCommand,
startTime,
timedOut,
isCanceled,
isGracefullyCanceled,
isMaxBuffer,
isForcefullyTerminated,
exitCode: rawExitCode,
signal: rawSignal,
stdio,
all,
ipcOutput,
options: {
timeoutDuration,
timeout = timeoutDuration,
forceKillAfterDelay,
killSignal,
cwd,
maxBuffer,
},
isSync,
}) => {
const {exitCode, signal, signalDescription} = normalizeExitPayload(rawExitCode, rawSignal);
const {originalMessage, shortMessage, message} = createMessages({
stdio,
all,
ipcOutput,
originalError,
signal,
signalDescription,
exitCode,
escapedCommand,
timedOut,
isCanceled,
isGracefullyCanceled,
isMaxBuffer,
isForcefullyTerminated,
forceKillAfterDelay,
killSignal,
maxBuffer,
timeout,
cwd,
});
const error = getFinalError(originalError, message, isSync);
Object.assign(error, getErrorProperties({
error,
command,
escapedCommand,
startTime,
timedOut,
isCanceled,
isGracefullyCanceled,
isMaxBuffer,
isForcefullyTerminated,
exitCode,
signal,
signalDescription,
stdio,
all,
ipcOutput,
cwd,
originalMessage,
shortMessage,
}));
return error;
};
const getErrorProperties = ({
error,
command,
escapedCommand,
startTime,
timedOut,
isCanceled,
isGracefullyCanceled,
isMaxBuffer,
isForcefullyTerminated,
exitCode,
signal,
signalDescription,
stdio,
all,
ipcOutput,
cwd,
originalMessage,
shortMessage,
}) => omitUndefinedProperties({
shortMessage,
originalMessage,
command,
escapedCommand,
cwd,
durationMs: getDurationMs(startTime),
failed: true,
timedOut,
isCanceled,
isGracefullyCanceled,
isTerminated: signal !== undefined,
isMaxBuffer,
isForcefullyTerminated,
exitCode,
signal,
signalDescription,
code: error.cause?.code,
stdout: stdio[1],
stderr: stdio[2],
all,
stdio,
ipcOutput,
pipedFrom: [],
});
const omitUndefinedProperties = result => Object.fromEntries(Object.entries(result).filter(([, value]) => value !== undefined));
// `signal` and `exitCode` emitted on `subprocess.on('exit')` event can be `null`.
// We normalize them to `undefined`
const normalizeExitPayload = (rawExitCode, rawSignal) => {
const exitCode = rawExitCode === null ? undefined : rawExitCode;
const signal = rawSignal === null ? undefined : rawSignal;
const signalDescription = signal === undefined ? undefined : getSignalDescription(rawSignal);
return {exitCode, signal, signalDescription};
};