1'use strict' 2 3const cp = require('child_process') 4const path = require('path') 5 6module.exports.runCommand = runCommand 7function runCommand (command, opts) { 8 const cmd = opts.call || command || opts.command 9 const copts = (opts.call ? [] : opts.cmdOpts) || [] 10 return spawn(cmd, copts, { 11 shell: opts.shell || !!opts.call, 12 stdio: opts.stdio || 'inherit' 13 }).catch(err => { 14 if (err.code === 'ENOENT') { 15 err = new Error( 16 `npx: ${ 17 require('./y.js')`command not found: ${path.basename(cmd)}` 18 }` 19 ) 20 err.exitCode = 127 21 } else { 22 err.message = require('./y.js')`Command failed: ${cmd} ${err.message}` 23 } 24 throw err 25 }) 26} 27 28module.exports.spawn = spawn 29function spawn (cmd, args, opts) { 30 opts = opts || {} 31 opts.shell = opts.shell || process.platform === 'win32' 32 return new Promise((resolve, reject) => { 33 const child = cp.spawn(cmd, args, opts) 34 let stdout = '' 35 let stderr = '' 36 child.stdout && child.stdout.on('data', d => { stdout += d }) 37 child.stderr && child.stderr.on('data', d => { stderr += d }) 38 child.on('error', reject) 39 child.on('close', code => { 40 if (code) { 41 const err = new Error( 42 require('./y.js')`Command failed: ${cmd} ${args.join(' ')}` 43 ) 44 err.isOperational = true 45 err.stderr = stderr 46 err.exitCode = code 47 reject(err) 48 } else { 49 resolve({code, stdout, stderr}) 50 } 51 }) 52 }) 53} 54 55module.exports.exec = exec 56function exec (cmd, args, opts) { 57 opts = opts || {} 58 return new Promise((resolve, reject) => { 59 cp.exec(`${escapeArg(cmd, true)} ${ 60 args.join(' ') 61 }`, opts, (err, stdout) => { 62 if (err) { 63 if (typeof err.code === 'number') { 64 err.exitCode = err.code 65 } 66 reject(err) 67 } else { 68 resolve(stdout) 69 } 70 }) 71 }) 72} 73 74module.exports.escapeArg = escapeArg 75function escapeArg (str, asPath) { 76 return process.platform === 'win32' && asPath 77 ? path.normalize(str) 78 .split(/\\/) 79 .map(s => s.match(/\s+/) ? `"${s}"` : s) 80 .join('\\') 81 : process.platform === 'win32' 82 ? `"${str}"` 83 : str.match(/[^-_.~/\w]/) 84 ? `'${str.replace(/'/g, "'\"'\"'")}'` 85 : str 86} 87