aboutsummaryrefslogtreecommitdiff
path: root/node_modules/execa/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/execa/index.js')
-rw-r--r--node_modules/execa/index.js268
1 files changed, 268 insertions, 0 deletions
diff --git a/node_modules/execa/index.js b/node_modules/execa/index.js
new file mode 100644
index 0000000..6fc9f12
--- /dev/null
+++ b/node_modules/execa/index.js
@@ -0,0 +1,268 @@
+'use strict';
+const path = require('path');
+const childProcess = require('child_process');
+const crossSpawn = require('cross-spawn');
+const stripFinalNewline = require('strip-final-newline');
+const npmRunPath = require('npm-run-path');
+const onetime = require('onetime');
+const makeError = require('./lib/error');
+const normalizeStdio = require('./lib/stdio');
+const {spawnedKill, spawnedCancel, setupTimeout, validateTimeout, setExitHandler} = require('./lib/kill');
+const {handleInput, getSpawnedResult, makeAllStream, validateInputSync} = require('./lib/stream');
+const {mergePromise, getSpawnedPromise} = require('./lib/promise');
+const {joinCommand, parseCommand, getEscapedCommand} = require('./lib/command');
+
+const DEFAULT_MAX_BUFFER = 1000 * 1000 * 100;
+
+const getEnv = ({env: envOption, extendEnv, preferLocal, localDir, execPath}) => {
+ const env = extendEnv ? {...process.env, ...envOption} : envOption;
+
+ if (preferLocal) {
+ return npmRunPath.env({env, cwd: localDir, execPath});
+ }
+
+ return env;
+};
+
+const handleArguments = (file, args, options = {}) => {
+ const parsed = crossSpawn._parse(file, args, options);
+ file = parsed.command;
+ args = parsed.args;
+ options = parsed.options;
+
+ options = {
+ maxBuffer: DEFAULT_MAX_BUFFER,
+ buffer: true,
+ stripFinalNewline: true,
+ extendEnv: true,
+ preferLocal: false,
+ localDir: options.cwd || process.cwd(),
+ execPath: process.execPath,
+ encoding: 'utf8',
+ reject: true,
+ cleanup: true,
+ all: false,
+ windowsHide: true,
+ ...options
+ };
+
+ options.env = getEnv(options);
+
+ options.stdio = normalizeStdio(options);
+
+ if (process.platform === 'win32' && path.basename(file, '.exe') === 'cmd') {
+ // #116
+ args.unshift('/q');
+ }
+
+ return {file, args, options, parsed};
+};
+
+const handleOutput = (options, value, error) => {
+ if (typeof value !== 'string' && !Buffer.isBuffer(value)) {
+ // When `execa.sync()` errors, we normalize it to '' to mimic `execa()`
+ return error === undefined ? undefined : '';
+ }
+
+ if (options.stripFinalNewline) {
+ return stripFinalNewline(value);
+ }
+
+ return value;
+};
+
+const execa = (file, args, options) => {
+ const parsed = handleArguments(file, args, options);
+ const command = joinCommand(file, args);
+ const escapedCommand = getEscapedCommand(file, args);
+
+ validateTimeout(parsed.options);
+
+ let spawned;
+ try {
+ spawned = childProcess.spawn(parsed.file, parsed.args, parsed.options);
+ } catch (error) {
+ // Ensure the returned error is always both a promise and a child process
+ const dummySpawned = new childProcess.ChildProcess();
+ const errorPromise = Promise.reject(makeError({
+ error,
+ stdout: '',
+ stderr: '',
+ all: '',
+ command,
+ escapedCommand,
+ parsed,
+ timedOut: false,
+ isCanceled: false,
+ killed: false
+ }));
+ return mergePromise(dummySpawned, errorPromise);
+ }
+
+ const spawnedPromise = getSpawnedPromise(spawned);
+ const timedPromise = setupTimeout(spawned, parsed.options, spawnedPromise);
+ const processDone = setExitHandler(spawned, parsed.options, timedPromise);
+
+ const context = {isCanceled: false};
+
+ spawned.kill = spawnedKill.bind(null, spawned.kill.bind(spawned));
+ spawned.cancel = spawnedCancel.bind(null, spawned, context);
+
+ const handlePromise = async () => {
+ const [{error, exitCode, signal, timedOut}, stdoutResult, stderrResult, allResult] = await getSpawnedResult(spawned, parsed.options, processDone);
+ const stdout = handleOutput(parsed.options, stdoutResult);
+ const stderr = handleOutput(parsed.options, stderrResult);
+ const all = handleOutput(parsed.options, allResult);
+
+ if (error || exitCode !== 0 || signal !== null) {
+ const returnedError = makeError({
+ error,
+ exitCode,
+ signal,
+ stdout,
+ stderr,
+ all,
+ command,
+ escapedCommand,
+ parsed,
+ timedOut,
+ isCanceled: context.isCanceled,
+ killed: spawned.killed
+ });
+
+ if (!parsed.options.reject) {
+ return returnedError;
+ }
+
+ throw returnedError;
+ }
+
+ return {
+ command,
+ escapedCommand,
+ exitCode: 0,
+ stdout,
+ stderr,
+ all,
+ failed: false,
+ timedOut: false,
+ isCanceled: false,
+ killed: false
+ };
+ };
+
+ const handlePromiseOnce = onetime(handlePromise);
+
+ handleInput(spawned, parsed.options.input);
+
+ spawned.all = makeAllStream(spawned, parsed.options);
+
+ return mergePromise(spawned, handlePromiseOnce);
+};
+
+module.exports = execa;
+
+module.exports.sync = (file, args, options) => {
+ const parsed = handleArguments(file, args, options);
+ const command = joinCommand(file, args);
+ const escapedCommand = getEscapedCommand(file, args);
+
+ validateInputSync(parsed.options);
+
+ let result;
+ try {
+ result = childProcess.spawnSync(parsed.file, parsed.args, parsed.options);
+ } catch (error) {
+ throw makeError({
+ error,
+ stdout: '',
+ stderr: '',
+ all: '',
+ command,
+ escapedCommand,
+ parsed,
+ timedOut: false,
+ isCanceled: false,
+ killed: false
+ });
+ }
+
+ const stdout = handleOutput(parsed.options, result.stdout, result.error);
+ const stderr = handleOutput(parsed.options, result.stderr, result.error);
+
+ if (result.error || result.status !== 0 || result.signal !== null) {
+ const error = makeError({
+ stdout,
+ stderr,
+ error: result.error,
+ signal: result.signal,
+ exitCode: result.status,
+ command,
+ escapedCommand,
+ parsed,
+ timedOut: result.error && result.error.code === 'ETIMEDOUT',
+ isCanceled: false,
+ killed: result.signal !== null
+ });
+
+ if (!parsed.options.reject) {
+ return error;
+ }
+
+ throw error;
+ }
+
+ return {
+ command,
+ escapedCommand,
+ exitCode: 0,
+ stdout,
+ stderr,
+ failed: false,
+ timedOut: false,
+ isCanceled: false,
+ killed: false
+ };
+};
+
+module.exports.command = (command, options) => {
+ const [file, ...args] = parseCommand(command);
+ return execa(file, args, options);
+};
+
+module.exports.commandSync = (command, options) => {
+ const [file, ...args] = parseCommand(command);
+ return execa.sync(file, args, options);
+};
+
+module.exports.node = (scriptPath, args, options = {}) => {
+ if (args && !Array.isArray(args) && typeof args === 'object') {
+ options = args;
+ args = [];
+ }
+
+ const stdio = normalizeStdio.node(options);
+ const defaultExecArgv = process.execArgv.filter(arg => !arg.startsWith('--inspect'));
+
+ const {
+ nodePath = process.execPath,
+ nodeOptions = defaultExecArgv
+ } = options;
+
+ return execa(
+ nodePath,
+ [
+ ...nodeOptions,
+ scriptPath,
+ ...(Array.isArray(args) ? args : [])
+ ],
+ {
+ ...options,
+ stdin: undefined,
+ stdout: undefined,
+ stderr: undefined,
+ stdio,
+ shell: false
+ }
+ );
+};