UNPKG

2.21 kBJavaScriptView Raw
1const cp = require('child_process')
2
3const defSpawnOptions = { stdio: 'inherit' }
4
5/**
6 * @summary Get shell program meta for current platform
7 * @private
8 * @returns {Object}
9 */
10function getShell () {
11 if (process.platform === 'win32') {
12 return { cmd: 'cmd', arg: '/C' }
13 } else {
14 return { cmd: 'sh', arg: '-c' }
15 }
16}
17
18/**
19 * Callback is called with the output when the process terminates. Output is
20 * available when true is passed as options argument or stdio: null set
21 * within given options.
22 *
23 * @summary Execute shell command forwarding all stdio
24 * @param {String|Array} command
25 * @param {Object|TRUE} [options] spawn() options or TRUE to set stdio: null
26 * @param {Function} [callback]
27 * @returns {ChildProcess}
28 */
29function execSh (command, options, callback) {
30 if (Array.isArray(command)) {
31 command = command.join(';')
32 }
33
34 if (options === true) {
35 options = { stdio: null }
36 }
37
38 if (typeof options === 'function') {
39 callback = options
40 options = defSpawnOptions
41 } else {
42 options = options || {}
43 options = Object.assign({}, defSpawnOptions, options)
44 callback = callback || function () {}
45 }
46
47 let child
48 let stdout = ''
49 let stderr = ''
50 const shell = getShell()
51
52 try {
53 child = cp.spawn(shell.cmd, [shell.arg, command], options)
54 } catch (e) {
55 callback(e, stdout, stderr)
56 return
57 }
58
59 if (child.stdout) {
60 child.stdout.on('data', function (data) {
61 stdout += data
62 })
63 }
64
65 if (child.stderr) {
66 child.stderr.on('data', function (data) {
67 stderr += data
68 })
69 }
70
71 child.on('close', function (code) {
72 if (code) {
73 const e = new Error('Shell command exit with non zero code: ' + code)
74 e.code = code
75 callback(e, stdout, stderr)
76 } else {
77 callback(null, stdout, stderr)
78 }
79 })
80
81 return child
82}
83
84execSh.promise = function (command, options) {
85 return new Promise(function (resolve, reject) {
86 execSh(command, options, function (err, stdout, stderr) {
87 if (err) {
88 err.stdout = stdout
89 err.stderr = stderr
90 return reject(err)
91 }
92
93 resolve({
94 stderr: stderr,
95 stdout: stdout
96 })
97 })
98 })
99}
100
101module.exports = execSh