• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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