-
Notifications
You must be signed in to change notification settings - Fork 2
/
index.js
102 lines (84 loc) · 2.81 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
92
93
94
95
96
97
98
99
100
101
102
/**
* Created by wehjin on 5/23/14.
*/
var util = require('util');
var stream = require('stream');
var Transform = stream.Transform;
var spawn = require('child_process').spawn;
util.inherits(SpawnStream, Transform);
module.exports = SpawnStream;
function SpawnStream(command, commandArguments, options) {
if (!(this instanceof SpawnStream))
return new SpawnStream(command, commandArguments, options);
options = options || {};
this.options = options;
var streamOptions = options['stream'] || {};
Transform.call(this, streamOptions);
var spawnOptions = options['spawn'] || {};
spawnOptions.stdio = ['pipe', 'pipe', 'ignore'];
this.command = command;
this.commandArguments = commandArguments;
this.spawnOptions = spawnOptions;
}
SpawnStream.prototype._transform = function (chunk, encoding, callback) {
var options = this.options;
if (options.debug) {
console.error('_transform');
}
if (!this.child) {
var transform = this;
var child = spawn(this.command, this.commandArguments, this.spawnOptions);
this.child = child;
this.stdoutDidEnd = false;
if (options.debug) {
console.error('build child process');
}
// When we get data on stdout, push it downstream. But if we get an end, do
// not push it downstream stream yet. Mark it so that we know it occurred in
// _flush. Pass through any error.
child.stdout
.on('data', function (data) {
if (options.debug) {
console.error('received data from stdout');
}
transform.push(data);
})
.on('end', function (data) {
if (options.debug) {
console.error('received end from stdout');
}
if (data) {
transform.push(data);
}
transform.stdoutDidEnd = true;
})
.on('error', this.emit.bind(this, 'error'));
// Pass through errors from stdin and the child.
child.stdin.on('error', this.emit.bind(this, 'error'));
child.on('error', this.emit.bind(this, 'error'));
}
// Pass data from upstream to the child.
this.child.stdin.write(chunk, encoding);
callback();
};
SpawnStream.prototype._flush = function (callback) {
var transform = this;
var debug = this.options.debug;
if (debug) {
console.error("_flush");
}
function onEnd() {
transform.child.kill();
delete transform.child;
callback();
}
if (!this.child) {
callback();
} else if (this.stdoutDidEnd) {
this.child.stdin.end();
onEnd();
} else {
this.child.stdin.end();
this.child.stdout.once('end', onEnd);
}
};