forked from IndigoUnited/node-buffered-spawn
/
index.js
91 lines (74 loc) · 2.36 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
var spawn = require('cross-spawn');
var createError = require('err-code');
var Q = require('q');
function execute(command, args, options) {
var process;
var stderr = new Buffer('');
var stdout = new Buffer('');
var deferred = Q.defer();
// Buffer output, reporting progress
process = spawn(command, args, options);
process.stdout.on('data', function (data) {
stdout = Buffer.concat([stdout, data]);
data.type = 'stdout';
deferred.notify(data);
});
process.stderr.on('data', function (data) {
stderr = Buffer.concat([stderr, data]);
data.type = 'stderr';
deferred.notify(data);
});
// If there is an error spawning the command, reject the promise
process.on('error', function (error) {
return deferred.reject(error);
});
// Listen to the close event instead of exit
// They are similar but close ensures that streams are flushed
process.on('close', function (code) {
var fullCommand;
var error;
stdout = stdout.toString();
stderr = stderr.toString();
if (!code) {
return deferred.resolve([stdout, stderr]);
}
// Generate the full command to be presented in the error message
args = args || [];
fullCommand = command;
fullCommand += args.length ? ' ' + args.join(' ') : '';
// Build the error instance
error = createError('Failed to execute "' + fullCommand + '", exit code of #' + code, 'ECMDERR', {
stderr: stderr,
stdout: stdout,
details: stderr,
status: code
});
return deferred.reject(error);
});
deferred.promise.cp = process;
return deferred.promise;
}
function buffered(command, args, options, callback) {
if (typeof options === 'function') {
callback = options;
options = null;
}
if (typeof args === 'function') {
callback = args;
args = options = null;
}
var promise = execute(command, args, options);
// Manual nodeify because of .spread :(
if (!callback) {
return promise;
}
promise
.spread(function (stdout, stderr) {
callback(null, stdout, stderr);
}, function (err) {
callback(err, err.stdout, err.stderr);
})
.done();
return promise.cp;
}
module.exports = buffered;