const node_buffer = require('buffer'); const path = require('path'); const childProcess = require('child_process'); const process$2 = require('process'); const url = require('url'); const os = require('os'); const node_fs = require('fs'); const promises = require('timers/promises'); const require$$0 = require('stream'); const node_util = require('util'); function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } const path__default = /*#__PURE__*/_interopDefault(path); const childProcess__default = /*#__PURE__*/_interopDefault(childProcess); const process__default = /*#__PURE__*/_interopDefault(process$2); const url__default = /*#__PURE__*/_interopDefault(url); const os__default = /*#__PURE__*/_interopDefault(os); const require$$0__default = /*#__PURE__*/_interopDefault(require$$0); function stripFinalNewline(input) { const LF = typeof input === 'string' ? '\n' : '\n'.charCodeAt(); const CR = typeof input === 'string' ? '\r' : '\r'.charCodeAt(); if (input[input.length - 1] === LF) { input = input.slice(0, -1); } if (input[input.length - 1] === CR) { input = input.slice(0, -1); } return input; } function pathKey(options = {}) { const { env = process.env, platform = process.platform } = options; if (platform !== 'win32') { return 'PATH'; } return Object.keys(env).reverse().find(key => key.toUpperCase() === 'PATH') || 'Path'; } function npmRunPath(options = {}) { const { cwd = process__default.default.cwd(), path: path_ = process__default.default.env[pathKey()], execPath = process__default.default.execPath, } = options; let previous; const cwdString = cwd instanceof URL ? url__default.default.fileURLToPath(cwd) : cwd; let cwdPath = path__default.default.resolve(cwdString); const result = []; while (previous !== cwdPath) { result.push(path__default.default.join(cwdPath, 'node_modules/.bin')); previous = cwdPath; cwdPath = path__default.default.resolve(cwdPath, '..'); } // Ensure the running `node` binary is used. result.push(path__default.default.resolve(cwdString, execPath, '..')); return [...result, path_].join(path__default.default.delimiter); } function npmRunPathEnv({env = process__default.default.env, ...options} = {}) { env = {...env}; const path = pathKey({env}); options.path = env[path]; env[path] = npmRunPath(options); return env; } const copyProperty = (to, from, property, ignoreNonConfigurable) => { // `Function#length` should reflect the parameters of `to` not `from` since we keep its body. // `Function#prototype` is non-writable and non-configurable so can never be modified. if (property === 'length' || property === 'prototype') { return; } // `Function#arguments` and `Function#caller` should not be copied. They were reported to be present in `Reflect.ownKeys` for some devices in React Native (#41), so we explicitly ignore them here. if (property === 'arguments' || property === 'caller') { return; } const toDescriptor = Object.getOwnPropertyDescriptor(to, property); const fromDescriptor = Object.getOwnPropertyDescriptor(from, property); if (!canCopyProperty(toDescriptor, fromDescriptor) && ignoreNonConfigurable) { return; } Object.defineProperty(to, property, fromDescriptor); }; // `Object.defineProperty()` throws if the property exists, is not configurable and either: // - one its descriptors is changed // - it is non-writable and its value is changed const canCopyProperty = function (toDescriptor, fromDescriptor) { return toDescriptor === undefined || toDescriptor.configurable || ( toDescriptor.writable === fromDescriptor.writable && toDescriptor.enumerable === fromDescriptor.enumerable && toDescriptor.configurable === fromDescriptor.configurable && (toDescriptor.writable || toDescriptor.value === fromDescriptor.value) ); }; const changePrototype = (to, from) => { const fromPrototype = Object.getPrototypeOf(from); if (fromPrototype === Object.getPrototypeOf(to)) { return; } Object.setPrototypeOf(to, fromPrototype); }; const wrappedToString = (withName, fromBody) => `/* Wrapped ${withName}*/\n${fromBody}`; const toStringDescriptor = Object.getOwnPropertyDescriptor(Function.prototype, 'toString'); const toStringName = Object.getOwnPropertyDescriptor(Function.prototype.toString, 'name'); // We call `from.toString()` early (not lazily) to ensure `from` can be garbage collected. // We use `bind()` instead of a closure for the same reason. // Calling `from.toString()` early also allows caching it in case `to.toString()` is called several times. const changeToString = (to, from, name) => { const withName = name === '' ? '' : `with ${name.trim()}() `; const newToString = wrappedToString.bind(null, withName, from.toString()); // Ensure `to.toString.toString` is non-enumerable and has the same `same` Object.defineProperty(newToString, 'name', toStringName); Object.defineProperty(to, 'toString', {...toStringDescriptor, value: newToString}); }; function mimicFunction(to, from, {ignoreNonConfigurable = false} = {}) { const {name} = to; for (const property of Reflect.ownKeys(from)) { copyProperty(to, from, property, ignoreNonConfigurable); } changePrototype(to, from); changeToString(to, from, name); return to; } const calledFunctions = new WeakMap(); const onetime = (function_, options = {}) => { if (typeof function_ !== 'function') { throw new TypeError('Expected a function'); } let returnValue; let callCount = 0; const functionName = function_.displayName || function_.name || ''; const onetime = function (...arguments_) { calledFunctions.set(onetime, ++callCount); if (callCount === 1) { returnValue = function_.apply(this, arguments_); function_ = null; } else if (options.throw === true) { throw new Error(`Function \`${functionName}\` can only be called once`); } return returnValue; }; mimicFunction(onetime, function_); calledFunctions.set(onetime, callCount); return onetime; }; onetime.callCount = function_ => { if (!calledFunctions.has(function_)) { throw new Error(`The given function \`${function_.name}\` is not wrapped by the \`onetime\` package`); } return calledFunctions.get(function_); }; // List of realtime signals with information about them const getRealtimeSignals = () => { const length = SIGRTMAX - SIGRTMIN + 1; return Array.from({ length }, getRealtimeSignal) }; const getRealtimeSignal = (value, index) => ({ name: `SIGRT${index + 1}`, number: SIGRTMIN + index, action: 'terminate', description: 'Application-specific signal (realtime)', standard: 'posix', }); const SIGRTMIN = 34; const SIGRTMAX = 64; /* eslint-disable max-lines */ // List of known process signals with information about them const SIGNALS = [ { name: 'SIGHUP', number: 1, action: 'terminate', description: 'Terminal closed', standard: 'posix', }, { name: 'SIGINT', number: 2, action: 'terminate', description: 'User interruption with CTRL-C', standard: 'ansi', }, { name: 'SIGQUIT', number: 3, action: 'core', description: 'User interruption with CTRL-\\', standard: 'posix', }, { name: 'SIGILL', number: 4, action: 'core', description: 'Invalid machine instruction', standard: 'ansi', }, { name: 'SIGTRAP', number: 5, action: 'core', description: 'Debugger breakpoint', standard: 'posix', }, { name: 'SIGABRT', number: 6, action: 'core', description: 'Aborted', standard: 'ansi', }, { name: 'SIGIOT', number: 6, action: 'core', description: 'Aborted', standard: 'bsd', }, { name: 'SIGBUS', number: 7, action: 'core', description: 'Bus error due to misaligned, non-existing address or paging error', standard: 'bsd', }, { name: 'SIGEMT', number: 7, action: 'terminate', description: 'Command should be emulated but is not implemented', standard: 'other', }, { name: 'SIGFPE', number: 8, action: 'core', description: 'Floating point arithmetic error', standard: 'ansi', }, { name: 'SIGKILL', number: 9, action: 'terminate', description: 'Forced termination', standard: 'posix', forced: true, }, { name: 'SIGUSR1', number: 10, action: 'terminate', description: 'Application-specific signal', standard: 'posix', }, { name: 'SIGSEGV', number: 11, action: 'core', description: 'Segmentation fault', standard: 'ansi', }, { name: 'SIGUSR2', number: 12, action: 'terminate', description: 'Application-specific signal', standard: 'posix', }, { name: 'SIGPIPE', number: 13, action: 'terminate', description: 'Broken pipe or socket', standard: 'posix', }, { name: 'SIGALRM', number: 14, action: 'terminate', description: 'Timeout or timer', standard: 'posix', }, { name: 'SIGTERM', number: 15, action: 'terminate', description: 'Termination', standard: 'ansi', }, { name: 'SIGSTKFLT', number: 16, action: 'terminate', description: 'Stack is empty or overflowed', standard: 'other', }, { name: 'SIGCHLD', number: 17, action: 'ignore', description: 'Child process terminated, paused or unpaused', standard: 'posix', }, { name: 'SIGCLD', number: 17, action: 'ignore', description: 'Child process terminated, paused or unpaused', standard: 'other', }, { name: 'SIGCONT', number: 18, action: 'unpause', description: 'Unpaused', standard: 'posix', forced: true, }, { name: 'SIGSTOP', number: 19, action: 'pause', description: 'Paused', standard: 'posix', forced: true, }, { name: 'SIGTSTP', number: 20, action: 'pause', description: 'Paused using CTRL-Z or "suspend"', standard: 'posix', }, { name: 'SIGTTIN', number: 21, action: 'pause', description: 'Background process cannot read terminal input', standard: 'posix', }, { name: 'SIGBREAK', number: 21, action: 'terminate', description: 'User interruption with CTRL-BREAK', standard: 'other', }, { name: 'SIGTTOU', number: 22, action: 'pause', description: 'Background process cannot write to terminal output', standard: 'posix', }, { name: 'SIGURG', number: 23, action: 'ignore', description: 'Socket received out-of-band data', standard: 'bsd', }, { name: 'SIGXCPU', number: 24, action: 'core', description: 'Process timed out', standard: 'bsd', }, { name: 'SIGXFSZ', number: 25, action: 'core', description: 'File too big', standard: 'bsd', }, { name: 'SIGVTALRM', number: 26, action: 'terminate', description: 'Timeout or timer', standard: 'bsd', }, { name: 'SIGPROF', number: 27, action: 'terminate', description: 'Timeout or timer', standard: 'bsd', }, { name: 'SIGWINCH', number: 28, action: 'ignore', description: 'Terminal window size changed', standard: 'bsd', }, { name: 'SIGIO', number: 29, action: 'terminate', description: 'I/O is available', standard: 'other', }, { name: 'SIGPOLL', number: 29, action: 'terminate', description: 'Watched event', standard: 'other', }, { name: 'SIGINFO', number: 29, action: 'ignore', description: 'Request for process information', standard: 'other', }, { name: 'SIGPWR', number: 30, action: 'terminate', description: 'Device running out of power', standard: 'systemv', }, { name: 'SIGSYS', number: 31, action: 'core', description: 'Invalid system call', standard: 'other', }, { name: 'SIGUNUSED', number: 31, action: 'terminate', description: 'Invalid system call', standard: 'other', }, ]; /* eslint-enable max-lines */ // Retrieve list of know signals (including realtime) with information about // them const getSignals = () => { const realtimeSignals = getRealtimeSignals(); const signals = [...SIGNALS, ...realtimeSignals].map(normalizeSignal); return signals }; // Normalize signal: // - `number`: signal numbers are OS-specific. This is taken into account by // `os.constants.signals`. However we provide a default `number` since some // signals are not defined for some OS. // - `forced`: set default to `false` // - `supported`: set value const normalizeSignal = ({ name, number: defaultNumber, description, action, forced = false, standard, }) => { const { signals: { [name]: constantSignal }, } = os.constants; const supported = constantSignal !== undefined; const number = supported ? constantSignal : defaultNumber; return { name, number, description, supported, action, forced, standard } }; // Retrieve `signalsByName`, an object mapping signal name to signal properties. // We make sure the object is sorted by `number`. const getSignalsByName = () => { const signals = getSignals(); return Object.fromEntries(signals.map(getSignalByName)) }; const getSignalByName = ({ name, number, description, supported, action, forced, standard, }) => [name, { name, number, description, supported, action, forced, standard }]; const signalsByName = getSignalsByName(); // Retrieve `signalsByNumber`, an object mapping signal number to signal // properties. // We make sure the object is sorted by `number`. const getSignalsByNumber = () => { const signals = getSignals(); const length = SIGRTMAX + 1; const signalsA = Array.from({ length }, (value, number) => getSignalByNumber(number, signals), ); return Object.assign({}, ...signalsA) }; const getSignalByNumber = (number, signals) => { const signal = findSignalByNumber(number, signals); if (signal === undefined) { return {} } const { name, description, supported, action, forced, standard } = signal; return { [number]: { name, number, description, supported, action, forced, standard, }, } }; // Several signals might end up sharing the same number because of OS-specific // numbers, in which case those prevail. const findSignalByNumber = (number, signals) => { const signal = signals.find(({ name }) => os.constants.signals[name] === number); if (signal !== undefined) { return signal } return signals.find((signalA) => signalA.number === number) }; getSignalsByNumber(); const getErrorPrefix = ({timedOut, timeout, errorCode, signal, signalDescription, exitCode, isCanceled}) => { if (timedOut) { return `timed out after ${timeout} milliseconds`; } if (isCanceled) { return 'was canceled'; } if (errorCode !== undefined) { return `failed with ${errorCode}`; } if (signal !== undefined) { return `was killed with ${signal} (${signalDescription})`; } if (exitCode !== undefined) { return `failed with exit code ${exitCode}`; } return 'failed'; }; const makeError = ({ stdout, stderr, all, error, signal, exitCode, command, escapedCommand, timedOut, isCanceled, killed, parsed: {options: {timeout, cwd = process__default.default.cwd()}}, }) => { // `signal` and `exitCode` emitted on `spawned.on('exit')` event can be `null`. // We normalize them to `undefined` exitCode = exitCode === null ? undefined : exitCode; signal = signal === null ? undefined : signal; const signalDescription = signal === undefined ? undefined : signalsByName[signal].description; const errorCode = error && error.code; const prefix = getErrorPrefix({timedOut, timeout, errorCode, signal, signalDescription, exitCode, isCanceled}); const execaMessage = `Command ${prefix}: ${command}`; const isError = Object.prototype.toString.call(error) === '[object Error]'; const shortMessage = isError ? `${execaMessage}\n${error.message}` : execaMessage; const message = [shortMessage, stderr, stdout].filter(Boolean).join('\n'); if (isError) { error.originalMessage = error.message; error.message = message; } else { error = new Error(message); } error.shortMessage = shortMessage; error.command = command; error.escapedCommand = escapedCommand; error.exitCode = exitCode; error.signal = signal; error.signalDescription = signalDescription; error.stdout = stdout; error.stderr = stderr; error.cwd = cwd; if (all !== undefined) { error.all = all; } if ('bufferedData' in error) { delete error.bufferedData; } error.failed = true; error.timedOut = Boolean(timedOut); error.isCanceled = isCanceled; error.killed = killed && !timedOut; return error; }; const aliases = ['stdin', 'stdout', 'stderr']; const hasAlias = options => aliases.some(alias => options[alias] !== undefined); const normalizeStdio = options => { if (!options) { return; } const {stdio} = options; if (stdio === undefined) { return aliases.map(alias => options[alias]); } if (hasAlias(options)) { throw new Error(`It's not possible to provide \`stdio\` in combination with one of ${aliases.map(alias => `\`${alias}\``).join(', ')}`); } if (typeof stdio === 'string') { return stdio; } if (!Array.isArray(stdio)) { throw new TypeError(`Expected \`stdio\` to be of type \`string\` or \`Array\`, got \`${typeof stdio}\``); } const length = Math.max(stdio.length, aliases.length); return Array.from({length}, (value, index) => stdio[index]); }; // `ipc` is pushed unless it is already present const normalizeStdioNode = options => { const stdio = normalizeStdio(options); if (stdio === 'ipc') { return 'ipc'; } if (stdio === undefined || typeof stdio === 'string') { return [stdio, stdio, stdio, 'ipc']; } if (stdio.includes('ipc')) { return stdio; } return [...stdio, 'ipc']; }; /** * This is not the set of all possible signals. * * It IS, however, the set of all signals that trigger * an exit on either Linux or BSD systems. Linux is a * superset of the signal names supported on BSD, and * the unknown signals just fail to register, so we can * catch that easily enough. * * Windows signals are a different set, since there are * signals that terminate Windows processes, but don't * terminate (or don't even exist) on Posix systems. * * Don't bother with SIGKILL. It's uncatchable, which * means that we can't fire any callbacks anyway. * * If a user does happen to register a handler on a non- * fatal signal like SIGWINCH or something, and then * exit, it'll end up firing `process.emit('exit')`, so * the handler will be fired anyway. * * SIGBUS, SIGFPE, SIGSEGV and SIGILL, when not raised * artificially, inherently leave the process in a * state from which it is not safe to try and enter JS * listeners. */ const signals = []; signals.push('SIGHUP', 'SIGINT', 'SIGTERM'); if (process.platform !== 'win32') { signals.push('SIGALRM', 'SIGABRT', 'SIGVTALRM', 'SIGXCPU', 'SIGXFSZ', 'SIGUSR2', 'SIGTRAP', 'SIGSYS', 'SIGQUIT', 'SIGIOT' // should detect profiler and enable/disable accordingly. // see #21 // 'SIGPROF' ); } if (process.platform === 'linux') { signals.push('SIGIO', 'SIGPOLL', 'SIGPWR', 'SIGSTKFLT'); } // Note: since nyc uses this module to output coverage, any lines // that are in the direct sync flow of nyc's outputCoverage are // ignored, since we can never get coverage for them. // grab a reference to node's real process object right away const processOk = (process) => !!process && typeof process === 'object' && typeof process.removeListener === 'function' && typeof process.emit === 'function' && typeof process.reallyExit === 'function' && typeof process.listeners === 'function' && typeof process.kill === 'function' && typeof process.pid === 'number' && typeof process.on === 'function'; const kExitEmitter = Symbol.for('signal-exit emitter'); const global = globalThis; const ObjectDefineProperty = Object.defineProperty.bind(Object); // teeny special purpose ee class Emitter { emitted = { afterExit: false, exit: false, }; listeners = { afterExit: [], exit: [], }; count = 0; id = Math.random(); constructor() { if (global[kExitEmitter]) { return global[kExitEmitter]; } ObjectDefineProperty(global, kExitEmitter, { value: this, writable: false, enumerable: false, configurable: false, }); } on(ev, fn) { this.listeners[ev].push(fn); } removeListener(ev, fn) { const list = this.listeners[ev]; const i = list.indexOf(fn); /* c8 ignore start */ if (i === -1) { return; } /* c8 ignore stop */ if (i === 0 && list.length === 1) { list.length = 0; } else { list.splice(i, 1); } } emit(ev, code, signal) { if (this.emitted[ev]) { return false; } this.emitted[ev] = true; let ret = false; for (const fn of this.listeners[ev]) { ret = fn(code, signal) === true || ret; } if (ev === 'exit') { ret = this.emit('afterExit', code, signal) || ret; } return ret; } } class SignalExitBase { } const signalExitWrap = (handler) => { return { onExit(cb, opts) { return handler.onExit(cb, opts); }, load() { return handler.load(); }, unload() { return handler.unload(); }, }; }; class SignalExitFallback extends SignalExitBase { onExit() { return () => { }; } load() { } unload() { } } class SignalExit extends SignalExitBase { // "SIGHUP" throws an `ENOSYS` error on Windows, // so use a supported signal instead /* c8 ignore start */ #hupSig = process$1.platform === 'win32' ? 'SIGINT' : 'SIGHUP'; /* c8 ignore stop */ #emitter = new Emitter(); #process; #originalProcessEmit; #originalProcessReallyExit; #sigListeners = {}; #loaded = false; constructor(process) { super(); this.#process = process; // { : , ... } this.#sigListeners = {}; for (const sig of signals) { this.#sigListeners[sig] = () => { // If there are no other listeners, an exit is coming! // Simplest way: remove us and then re-send the signal. // We know that this will kill the process, so we can // safely emit now. const listeners = this.#process.listeners(sig); let { count } = this.#emitter; // This is a workaround for the fact that signal-exit v3 and signal // exit v4 are not aware of each other, and each will attempt to let // the other handle it, so neither of them do. To correct this, we // detect if we're the only handler *except* for previous versions // of signal-exit, and increment by the count of listeners it has // created. /* c8 ignore start */ const p = process; if (typeof p.__signal_exit_emitter__ === 'object' && typeof p.__signal_exit_emitter__.count === 'number') { count += p.__signal_exit_emitter__.count; } /* c8 ignore stop */ if (listeners.length === count) { this.unload(); const ret = this.#emitter.emit('exit', null, sig); /* c8 ignore start */ const s = sig === 'SIGHUP' ? this.#hupSig : sig; if (!ret) process.kill(process.pid, s); /* c8 ignore stop */ } }; } this.#originalProcessReallyExit = process.reallyExit; this.#originalProcessEmit = process.emit; } onExit(cb, opts) { /* c8 ignore start */ if (!processOk(this.#process)) { return () => { }; } /* c8 ignore stop */ if (this.#loaded === false) { this.load(); } const ev = opts?.alwaysLast ? 'afterExit' : 'exit'; this.#emitter.on(ev, cb); return () => { this.#emitter.removeListener(ev, cb); if (this.#emitter.listeners['exit'].length === 0 && this.#emitter.listeners['afterExit'].length === 0) { this.unload(); } }; } load() { if (this.#loaded) { return; } this.#loaded = true; // This is the number of onSignalExit's that are in play. // It's important so that we can count the correct number of // listeners on signals, and don't wait for the other one to // handle it instead of us. this.#emitter.count += 1; for (const sig of signals) { try { const fn = this.#sigListeners[sig]; if (fn) this.#process.on(sig, fn); } catch (_) { } } this.#process.emit = (ev, ...a) => { return this.#processEmit(ev, ...a); }; this.#process.reallyExit = (code) => { return this.#processReallyExit(code); }; } unload() { if (!this.#loaded) { return; } this.#loaded = false; signals.forEach(sig => { const listener = this.#sigListeners[sig]; /* c8 ignore start */ if (!listener) { throw new Error('Listener not defined for signal: ' + sig); } /* c8 ignore stop */ try { this.#process.removeListener(sig, listener); /* c8 ignore start */ } catch (_) { } /* c8 ignore stop */ }); this.#process.emit = this.#originalProcessEmit; this.#process.reallyExit = this.#originalProcessReallyExit; this.#emitter.count -= 1; } #processReallyExit(code) { /* c8 ignore start */ if (!processOk(this.#process)) { return 0; } this.#process.exitCode = code || 0; /* c8 ignore stop */ this.#emitter.emit('exit', this.#process.exitCode, null); return this.#originalProcessReallyExit.call(this.#process, this.#process.exitCode); } #processEmit(ev, ...args) { const og = this.#originalProcessEmit; if (ev === 'exit' && processOk(this.#process)) { if (typeof args[0] === 'number') { this.#process.exitCode = args[0]; /* c8 ignore start */ } /* c8 ignore start */ const ret = og.call(this.#process, ev, ...args); /* c8 ignore start */ this.#emitter.emit('exit', this.#process.exitCode, null); /* c8 ignore stop */ return ret; } else { return og.call(this.#process, ev, ...args); } } } const process$1 = globalThis.process; // wrap so that we call the method on the actual handler, without // exporting it directly. const { /** * Called when the process is exiting, whether via signal, explicit * exit, or running out of stuff to do. * * If the global process object is not suitable for instrumentation, * then this will be a no-op. * * Returns a function that may be used to unload signal-exit. */ onExit, /** * Load the listeners. Likely you never need to call this, unless * doing a rather deep integration with signal-exit functionality. * Mostly exposed for the benefit of testing. * * @internal */ load, /** * Unload the listeners. Likely you never need to call this, unless * doing a rather deep integration with signal-exit functionality. * Mostly exposed for the benefit of testing. * * @internal */ unload, } = signalExitWrap(processOk(process$1) ? new SignalExit(process$1) : new SignalExitFallback()); const DEFAULT_FORCE_KILL_TIMEOUT = 1000 * 5; // Monkey-patches `childProcess.kill()` to add `forceKillAfterTimeout` behavior const spawnedKill = (kill, signal = 'SIGTERM', options = {}) => { const killResult = kill(signal); setKillTimeout(kill, signal, options, killResult); return killResult; }; const setKillTimeout = (kill, signal, options, killResult) => { if (!shouldForceKill(signal, options, killResult)) { return; } const timeout = getForceKillAfterTimeout(options); const t = setTimeout(() => { kill('SIGKILL'); }, timeout); // Guarded because there's no `.unref()` when `execa` is used in the renderer // process in Electron. This cannot be tested since we don't run tests in // Electron. // istanbul ignore else if (t.unref) { t.unref(); } }; const shouldForceKill = (signal, {forceKillAfterTimeout}, killResult) => isSigterm(signal) && forceKillAfterTimeout !== false && killResult; const isSigterm = signal => signal === os__default.default.constants.signals.SIGTERM || (typeof signal === 'string' && signal.toUpperCase() === 'SIGTERM'); const getForceKillAfterTimeout = ({forceKillAfterTimeout = true}) => { if (forceKillAfterTimeout === true) { return DEFAULT_FORCE_KILL_TIMEOUT; } if (!Number.isFinite(forceKillAfterTimeout) || forceKillAfterTimeout < 0) { throw new TypeError(`Expected the \`forceKillAfterTimeout\` option to be a non-negative integer, got \`${forceKillAfterTimeout}\` (${typeof forceKillAfterTimeout})`); } return forceKillAfterTimeout; }; // `childProcess.cancel()` const spawnedCancel = (spawned, context) => { const killResult = spawned.kill(); if (killResult) { context.isCanceled = true; } }; const timeoutKill = (spawned, signal, reject) => { spawned.kill(signal); reject(Object.assign(new Error('Timed out'), {timedOut: true, signal})); }; // `timeout` option handling const setupTimeout = (spawned, {timeout, killSignal = 'SIGTERM'}, spawnedPromise) => { if (timeout === 0 || timeout === undefined) { return spawnedPromise; } let timeoutId; const timeoutPromise = new Promise((resolve, reject) => { timeoutId = setTimeout(() => { timeoutKill(spawned, killSignal, reject); }, timeout); }); const safeSpawnedPromise = spawnedPromise.finally(() => { clearTimeout(timeoutId); }); return Promise.race([timeoutPromise, safeSpawnedPromise]); }; const validateTimeout = ({timeout}) => { if (timeout !== undefined && (!Number.isFinite(timeout) || timeout < 0)) { throw new TypeError(`Expected the \`timeout\` option to be a non-negative integer, got \`${timeout}\` (${typeof timeout})`); } }; // `cleanup` option handling const setExitHandler = async (spawned, {cleanup, detached}, timedPromise) => { if (!cleanup || detached) { return timedPromise; } const removeExitHandler = onExit(() => { spawned.kill(); }); return timedPromise.finally(() => { removeExitHandler(); }); }; function isStream(stream) { return stream !== null && typeof stream === 'object' && typeof stream.pipe === 'function'; } function isWritableStream(stream) { return isStream(stream) && stream.writable !== false && typeof stream._write === 'function' && typeof stream._writableState === 'object'; } const isExecaChildProcess = target => target instanceof childProcess.ChildProcess && typeof target.then === 'function'; const pipeToTarget = (spawned, streamName, target) => { if (typeof target === 'string') { spawned[streamName].pipe(node_fs.createWriteStream(target)); return spawned; } if (isWritableStream(target)) { spawned[streamName].pipe(target); return spawned; } if (!isExecaChildProcess(target)) { throw new TypeError('The second argument must be a string, a stream or an Execa child process.'); } if (!isWritableStream(target.stdin)) { throw new TypeError('The target child process\'s stdin must be available.'); } spawned[streamName].pipe(target.stdin); return target; }; const addPipeMethods = spawned => { if (spawned.stdout !== null) { spawned.pipeStdout = pipeToTarget.bind(undefined, spawned, 'stdout'); } if (spawned.stderr !== null) { spawned.pipeStderr = pipeToTarget.bind(undefined, spawned, 'stderr'); } if (spawned.all !== undefined) { spawned.pipeAll = pipeToTarget.bind(undefined, spawned, 'all'); } }; const getStreamContents = async (stream, {init, convertChunk, getSize, truncateChunk, addChunk, getFinalChunk, finalize}, {maxBuffer = Number.POSITIVE_INFINITY} = {}) => { if (!isAsyncIterable(stream)) { throw new Error('The first argument must be a Readable, a ReadableStream, or an async iterable.'); } const state = init(); state.length = 0; try { for await (const chunk of stream) { const chunkType = getChunkType(chunk); const convertedChunk = convertChunk[chunkType](chunk, state); appendChunk({convertedChunk, state, getSize, truncateChunk, addChunk, maxBuffer}); } appendFinalChunk({state, convertChunk, getSize, truncateChunk, addChunk, getFinalChunk, maxBuffer}); return finalize(state); } catch (error) { error.bufferedData = finalize(state); throw error; } }; const appendFinalChunk = ({state, getSize, truncateChunk, addChunk, getFinalChunk, maxBuffer}) => { const convertedChunk = getFinalChunk(state); if (convertedChunk !== undefined) { appendChunk({convertedChunk, state, getSize, truncateChunk, addChunk, maxBuffer}); } }; const appendChunk = ({convertedChunk, state, getSize, truncateChunk, addChunk, maxBuffer}) => { const chunkSize = getSize(convertedChunk); const newLength = state.length + chunkSize; if (newLength <= maxBuffer) { addNewChunk(convertedChunk, state, addChunk, newLength); return; } const truncatedChunk = truncateChunk(convertedChunk, maxBuffer - state.length); if (truncatedChunk !== undefined) { addNewChunk(truncatedChunk, state, addChunk, maxBuffer); } throw new MaxBufferError(); }; const addNewChunk = (convertedChunk, state, addChunk, newLength) => { state.contents = addChunk(convertedChunk, state, newLength); state.length = newLength; }; const isAsyncIterable = stream => typeof stream === 'object' && stream !== null && typeof stream[Symbol.asyncIterator] === 'function'; const getChunkType = chunk => { const typeOfChunk = typeof chunk; if (typeOfChunk === 'string') { return 'string'; } if (typeOfChunk !== 'object' || chunk === null) { return 'others'; } // eslint-disable-next-line n/prefer-global/buffer if (globalThis.Buffer?.isBuffer(chunk)) { return 'buffer'; } const prototypeName = objectToString.call(chunk); if (prototypeName === '[object ArrayBuffer]') { return 'arrayBuffer'; } if (prototypeName === '[object DataView]') { return 'dataView'; } if ( Number.isInteger(chunk.byteLength) && Number.isInteger(chunk.byteOffset) && objectToString.call(chunk.buffer) === '[object ArrayBuffer]' ) { return 'typedArray'; } return 'others'; }; const {toString: objectToString} = Object.prototype; class MaxBufferError extends Error { name = 'MaxBufferError'; constructor() { super('maxBuffer exceeded'); } } const identity = value => value; const noop = () => undefined; const getContentsProp = ({contents}) => contents; const throwObjectStream = chunk => { throw new Error(`Streams in object mode are not supported: ${String(chunk)}`); }; const getLengthProp = convertedChunk => convertedChunk.length; async function getStreamAsArrayBuffer(stream, options) { return getStreamContents(stream, arrayBufferMethods, options); } const initArrayBuffer = () => ({contents: new ArrayBuffer(0)}); const useTextEncoder = chunk => textEncoder.encode(chunk); const textEncoder = new TextEncoder(); const useUint8Array = chunk => new Uint8Array(chunk); const useUint8ArrayWithOffset = chunk => new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength); const truncateArrayBufferChunk = (convertedChunk, chunkSize) => convertedChunk.slice(0, chunkSize); // `contents` is an increasingly growing `Uint8Array`. const addArrayBufferChunk = (convertedChunk, {contents, length: previousLength}, length) => { const newContents = hasArrayBufferResize() ? resizeArrayBuffer(contents, length) : resizeArrayBufferSlow(contents, length); new Uint8Array(newContents).set(convertedChunk, previousLength); return newContents; }; // Without `ArrayBuffer.resize()`, `contents` size is always a power of 2. // This means its last bytes are zeroes (not stream data), which need to be // trimmed at the end with `ArrayBuffer.slice()`. const resizeArrayBufferSlow = (contents, length) => { if (length <= contents.byteLength) { return contents; } const arrayBuffer = new ArrayBuffer(getNewContentsLength(length)); new Uint8Array(arrayBuffer).set(new Uint8Array(contents), 0); return arrayBuffer; }; // With `ArrayBuffer.resize()`, `contents` size matches exactly the size of // the stream data. It does not include extraneous zeroes to trim at the end. // The underlying `ArrayBuffer` does allocate a number of bytes that is a power // of 2, but those bytes are only visible after calling `ArrayBuffer.resize()`. const resizeArrayBuffer = (contents, length) => { if (length <= contents.maxByteLength) { contents.resize(length); return contents; } const arrayBuffer = new ArrayBuffer(length, {maxByteLength: getNewContentsLength(length)}); new Uint8Array(arrayBuffer).set(new Uint8Array(contents), 0); return arrayBuffer; }; // Retrieve the closest `length` that is both >= and a power of 2 const getNewContentsLength = length => SCALE_FACTOR ** Math.ceil(Math.log(length) / Math.log(SCALE_FACTOR)); const SCALE_FACTOR = 2; const finalizeArrayBuffer = ({contents, length}) => hasArrayBufferResize() ? contents : contents.slice(0, length); // `ArrayBuffer.slice()` is slow. When `ArrayBuffer.resize()` is available // (Node >=20.0.0, Safari >=16.4 and Chrome), we can use it instead. // eslint-disable-next-line no-warning-comments // TODO: remove after dropping support for Node 20. // eslint-disable-next-line no-warning-comments // TODO: use `ArrayBuffer.transferToFixedLength()` instead once it is available const hasArrayBufferResize = () => 'resize' in ArrayBuffer.prototype; const arrayBufferMethods = { init: initArrayBuffer, convertChunk: { string: useTextEncoder, buffer: useUint8Array, arrayBuffer: useUint8Array, dataView: useUint8ArrayWithOffset, typedArray: useUint8ArrayWithOffset, others: throwObjectStream, }, getSize: getLengthProp, truncateChunk: truncateArrayBufferChunk, addChunk: addArrayBufferChunk, getFinalChunk: noop, finalize: finalizeArrayBuffer, }; async function getStreamAsBuffer(stream, options) { if (!('Buffer' in globalThis)) { throw new Error('getStreamAsBuffer() is only supported in Node.js'); } try { return arrayBufferToNodeBuffer(await getStreamAsArrayBuffer(stream, options)); } catch (error) { if (error.bufferedData !== undefined) { error.bufferedData = arrayBufferToNodeBuffer(error.bufferedData); } throw error; } } // eslint-disable-next-line n/prefer-global/buffer const arrayBufferToNodeBuffer = arrayBuffer => globalThis.Buffer.from(arrayBuffer); async function getStreamAsString(stream, options) { return getStreamContents(stream, stringMethods, options); } const initString = () => ({contents: '', textDecoder: new TextDecoder()}); const useTextDecoder = (chunk, {textDecoder}) => textDecoder.decode(chunk, {stream: true}); const addStringChunk = (convertedChunk, {contents}) => contents + convertedChunk; const truncateStringChunk = (convertedChunk, chunkSize) => convertedChunk.slice(0, chunkSize); const getFinalStringChunk = ({textDecoder}) => { const finalChunk = textDecoder.decode(); return finalChunk === '' ? undefined : finalChunk; }; const stringMethods = { init: initString, convertChunk: { string: identity, buffer: useTextDecoder, arrayBuffer: useTextDecoder, dataView: useTextDecoder, typedArray: useTextDecoder, others: throwObjectStream, }, getSize: getLengthProp, truncateChunk: truncateStringChunk, addChunk: addStringChunk, getFinalChunk: getFinalStringChunk, finalize: getContentsProp, }; function getDefaultExportFromCjs (x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; } const PassThrough = require$$0__default.default.PassThrough; var mergeStream = function (/*streams...*/) { var sources = []; var output = new PassThrough({objectMode: true}); output.setMaxListeners(0); output.add = add; output.isEmpty = isEmpty; output.on('unpipe', remove); Array.prototype.slice.call(arguments).forEach(add); return output function add (source) { if (Array.isArray(source)) { source.forEach(add); return this } sources.push(source); source.once('end', remove.bind(null, source)); source.once('error', output.emit.bind(output, 'error')); source.pipe(output, {end: false}); return this } function isEmpty () { return sources.length == 0; } function remove (source) { sources = sources.filter(function (it) { return it !== source }); if (!sources.length && output.readable) { output.end(); } } }; const mergeStream$1 = /*@__PURE__*/getDefaultExportFromCjs(mergeStream); const validateInputOptions = input => { if (input !== undefined) { throw new TypeError('The `input` and `inputFile` options cannot be both set.'); } }; const getInputSync = ({input, inputFile}) => { if (typeof inputFile !== 'string') { return input; } validateInputOptions(input); return node_fs.readFileSync(inputFile); }; // `input` and `inputFile` option in sync mode const handleInputSync = options => { const input = getInputSync(options); if (isStream(input)) { throw new TypeError('The `input` option cannot be a stream in sync mode'); } return input; }; const getInput = ({input, inputFile}) => { if (typeof inputFile !== 'string') { return input; } validateInputOptions(input); return node_fs.createReadStream(inputFile); }; // `input` and `inputFile` option in async mode const handleInput = (spawned, options) => { const input = getInput(options); if (input === 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$1(); 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) => { // When `buffer` is `false`, `streamPromise` is `undefined` and there is no buffered data to retrieve if (!stream || streamPromise === undefined) { return; } // Wait for the `all` stream to receive the last chunk before destroying the stream await promises.setTimeout(0); stream.destroy(); try { return await streamPromise; } catch (error) { return error.bufferedData; } }; const getStreamPromise = (stream, {encoding, buffer, maxBuffer}) => { if (!stream || !buffer) { return; } // eslint-disable-next-line unicorn/text-encoding-identifier-case if (encoding === 'utf8' || encoding === 'utf-8') { return getStreamAsString(stream, {maxBuffer}); } if (encoding === null || encoding === 'buffer') { return getStreamAsBuffer(stream, {maxBuffer}); } return applyEncoding(stream, maxBuffer, encoding); }; const applyEncoding = async (stream, maxBuffer, encoding) => { const buffer = await getStreamAsBuffer(stream, {maxBuffer}); return buffer.toString(encoding); }; // 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), ]); } }; // eslint-disable-next-line unicorn/prefer-top-level-await const nativePromisePrototype = (async () => {})().constructor.prototype; const descriptors = ['then', 'catch', 'finally'].map(property => [ property, Reflect.getOwnPropertyDescriptor(nativePromisePrototype, property), ]); // The return value is a mixin of `childProcess` and `Promise` const mergePromise = (spawned, promise) => { for (const [property, descriptor] of descriptors) { // Starting the main `promise` is deferred to avoid consuming streams const value = typeof promise === 'function' ? (...args) => Reflect.apply(descriptor.value, promise(), args) : descriptor.value.bind(promise); Reflect.defineProperty(spawned, property, {...descriptor, value}); } }; // Use promises instead of `child_process` events const getSpawnedPromise = spawned => new Promise((resolve, reject) => { spawned.on('exit', (exitCode, signal) => { resolve({exitCode, signal}); }); spawned.on('error', error => { reject(error); }); if (spawned.stdin) { spawned.stdin.on('error', error => { reject(error); }); } }); const normalizeArgs = (file, args = []) => { if (!Array.isArray(args)) { return [file]; } return [file, ...args]; }; const NO_ESCAPE_REGEXP = /^[\w.-]+$/; const escapeArg = arg => { if (typeof arg !== 'string' || NO_ESCAPE_REGEXP.test(arg)) { return arg; } return `"${arg.replaceAll('"', '\\"')}"`; }; const joinCommand = (file, args) => normalizeArgs(file, args).join(' '); const getEscapedCommand = (file, args) => normalizeArgs(file, args).map(arg => escapeArg(arg)).join(' '); const SPACES_REGEXP = / +/g; // Handle `execaCommand()` const parseCommand = command => { const tokens = []; for (const token of command.trim().split(SPACES_REGEXP)) { // Allow spaces to be escaped by a backslash if not meant as a delimiter const previousToken = tokens.at(-1); if (previousToken && previousToken.endsWith('\\')) { // Merge previous token with current one tokens[tokens.length - 1] = `${previousToken.slice(0, -1)} ${token}`; } else { tokens.push(token); } } return tokens; }; const parseExpression = expression => { const typeOfExpression = typeof expression; if (typeOfExpression === 'string') { return expression; } if (typeOfExpression === 'number') { return String(expression); } if ( typeOfExpression === 'object' && expression !== null && !(expression instanceof childProcess.ChildProcess) && 'stdout' in expression ) { const typeOfStdout = typeof expression.stdout; if (typeOfStdout === 'string') { return expression.stdout; } if (node_buffer.Buffer.isBuffer(expression.stdout)) { return expression.stdout.toString(); } throw new TypeError(`Unexpected "${typeOfStdout}" stdout in template expression`); } throw new TypeError(`Unexpected "${typeOfExpression}" in template expression`); }; const concatTokens = (tokens, nextTokens, isNew) => isNew || tokens.length === 0 || nextTokens.length === 0 ? [...tokens, ...nextTokens] : [ ...tokens.slice(0, -1), `${tokens.at(-1)}${nextTokens[0]}`, ...nextTokens.slice(1), ]; const parseTemplate = ({templates, expressions, tokens, index, template}) => { const templateString = template ?? templates.raw[index]; const templateTokens = templateString.split(SPACES_REGEXP).filter(Boolean); const newTokens = concatTokens( tokens, templateTokens, templateString.startsWith(' '), ); if (index === expressions.length) { return newTokens; } const expression = expressions[index]; const expressionTokens = Array.isArray(expression) ? expression.map(expression => parseExpression(expression)) : [parseExpression(expression)]; return concatTokens( newTokens, expressionTokens, templateString.endsWith(' '), ); }; const parseTemplates = (templates, expressions) => { let tokens = []; for (const [index, template] of templates.entries()) { tokens = parseTemplate({templates, expressions, tokens, index, template}); } return tokens; }; const verboseDefault = node_util.debuglog('execa').enabled; const padField = (field, padding) => String(field).padStart(padding, '0'); const getTimestamp = () => { const date = new Date(); return `${padField(date.getHours(), 2)}:${padField(date.getMinutes(), 2)}:${padField(date.getSeconds(), 2)}.${padField(date.getMilliseconds(), 3)}`; }; const logCommand = (escapedCommand, {verbose}) => { if (!verbose) { return; } process__default.default.stderr.write(`[${getTimestamp()}] ${escapedCommand}\n`); }; const DEFAULT_MAX_BUFFER = 1000 * 1000 * 100; const getEnv = ({env: envOption, extendEnv, preferLocal, localDir, execPath}) => { const env = extendEnv ? {...process__default.default.env, ...envOption} : envOption; if (preferLocal) { return npmRunPathEnv({env, cwd: localDir, execPath}); } return env; }; function parse(command, args, options) { // Normalize arguments, similar to nodejs if (args && !Array.isArray(args)) { options = args; args = null; } args = args ? args.slice(0) : []; // Clone array to avoid changing the original options = Object.assign({}, options); // Clone object to avoid changing the original // Build our parsed object const parsed = { command, args, options, file: undefined, original: { command, args, }, }; return parsed } const handleArguments = (file, args, options = {}) => { const parsed = 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__default.default.cwd(), execPath: process__default.default.execPath, encoding: 'utf8', reject: true, cleanup: true, all: false, windowsHide: true, verbose: verboseDefault, ...options, }; options.env = getEnv(options); options.stdio = normalizeStdio(options); if (process__default.default.platform === 'win32' && path__default.default.basename(file, '.exe') === 'cmd') { // #116 args.unshift('/q'); } return {file, args, options, parsed}; }; const handleOutput = (options, value, error) => { if (typeof value !== 'string' && !node_buffer.Buffer.isBuffer(value)) { // When `execaSync()` errors, we normalize it to '' to mimic `execa()` return error === undefined ? undefined : ''; } if (options.stripFinalNewline) { return stripFinalNewline(value); } return value; }; function execa(file, args, options) { const parsed = handleArguments(file, args, options); const command = joinCommand(file, args); const escapedCommand = getEscapedCommand(file, args); logCommand(escapedCommand, parsed.options); validateTimeout(parsed.options); let spawned; try { spawned = childProcess__default.default.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__default.default.ChildProcess(); const errorPromise = Promise.reject(makeError({ error, stdout: '', stderr: '', all: '', command, escapedCommand, parsed, timedOut: false, isCanceled: false, killed: false, })); mergePromise(dummySpawned, errorPromise); return dummySpawned; } 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: (parsed.options.signal ? parsed.options.signal.aborted : false), 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); spawned.all = makeAllStream(spawned, parsed.options); addPipeMethods(spawned); mergePromise(spawned, handlePromiseOnce); return spawned; } function execaSync(file, args, options) { const parsed = handleArguments(file, args, options); const command = joinCommand(file, args); const escapedCommand = getEscapedCommand(file, args); logCommand(escapedCommand, parsed.options); const input = handleInputSync(parsed.options); let result; try { result = childProcess__default.default.spawnSync(parsed.file, parsed.args, {...parsed.options, input}); } 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, }; } const normalizeScriptStdin = ({input, inputFile, stdio}) => input === undefined && inputFile === undefined && stdio === undefined ? {stdin: 'inherit'} : {}; const normalizeScriptOptions = (options = {}) => ({ preferLocal: true, ...normalizeScriptStdin(options), ...options, }); function create$(options) { function $(templatesOrOptions, ...expressions) { if (!Array.isArray(templatesOrOptions)) { return create$({...options, ...templatesOrOptions}); } const [file, ...args] = parseTemplates(templatesOrOptions, expressions); return execa(file, args, normalizeScriptOptions(options)); } $.sync = (templates, ...expressions) => { if (!Array.isArray(templates)) { throw new TypeError('Please use $(options).sync`command` instead of $.sync(options)`command`.'); } const [file, ...args] = parseTemplates(templates, expressions); return execaSync(file, args, normalizeScriptOptions(options)); }; return $; } const $ = create$(); function execaCommand(command, options) { const [file, ...args] = parseCommand(command); return execa(file, args, options); } function execaCommandSync(command, options) { const [file, ...args] = parseCommand(command); return execaSync(file, args, options); } function execaNode(scriptPath, args, options = {}) { if (args && !Array.isArray(args) && typeof args === 'object') { options = args; args = []; } const stdio = normalizeStdioNode(options); const defaultExecArgv = process__default.default.execArgv.filter(arg => !arg.startsWith('--inspect')); const { nodePath = process__default.default.execPath, nodeOptions = defaultExecArgv, } = options; return execa( nodePath, [ ...nodeOptions, scriptPath, ...(Array.isArray(args) ? args : []), ], { ...options, stdin: undefined, stdout: undefined, stderr: undefined, stdio, shell: false, }, ); } exports.$ = $; exports.execa = execa; exports.execaCommand = execaCommand; exports.execaCommandSync = execaCommandSync; exports.execaNode = execaNode; exports.execaSync = execaSync;