1 | "use strict";
|
2 | var __rest = (this && this.__rest) || function (s, e) {
|
3 | var t = {};
|
4 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
5 | t[p] = s[p];
|
6 | if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
7 | for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
|
8 | t[p[i]] = s[p[i]];
|
9 | return t;
|
10 | };
|
11 | Object.defineProperty(exports, "__esModule", { value: true });
|
12 | var path = require("path");
|
13 | var net = require("net");
|
14 | var sfs = require("fs");
|
15 | var assign = require("lodash.assign");
|
16 | var rxjs_1 = require("rxjs");
|
17 | var operators_1 = require("rxjs/operators");
|
18 | var spawnOg = require('child_process').spawn;
|
19 | var isWindows = process.platform === 'win32';
|
20 | var d = require('debug')('spawn-rx');
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 | function statSyncNoException(file) {
|
30 | try {
|
31 | return sfs.statSync(file);
|
32 | }
|
33 | catch (e) {
|
34 | return null;
|
35 | }
|
36 | }
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 | function runDownPath(exe) {
|
47 |
|
48 |
|
49 |
|
50 | if (exe.match(/[\\\/]/)) {
|
51 | d('Path has slash in directory, bailing');
|
52 | return exe;
|
53 | }
|
54 | var target = path.join('.', exe);
|
55 | if (statSyncNoException(target)) {
|
56 | d("Found executable in currect directory: " + target);
|
57 | return target;
|
58 | }
|
59 | var haystack = process.env.PATH.split(isWindows ? ';' : ':');
|
60 | for (var _i = 0, haystack_1 = haystack; _i < haystack_1.length; _i++) {
|
61 | var p = haystack_1[_i];
|
62 | var needle = path.join(p, exe);
|
63 | if (statSyncNoException(needle)) {
|
64 | return needle;
|
65 | }
|
66 | }
|
67 | d('Failed to find executable anywhere in path');
|
68 | return exe;
|
69 | }
|
70 |
|
71 |
|
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 |
|
80 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 |
|
86 | function findActualExecutable(exe, args) {
|
87 |
|
88 | if (process.platform !== 'win32') {
|
89 | return { cmd: runDownPath(exe), args: args };
|
90 | }
|
91 | if (!sfs.existsSync(exe)) {
|
92 |
|
93 |
|
94 |
|
95 | var possibleExts = ['.exe', '.bat', '.cmd', '.ps1'];
|
96 | for (var _i = 0, possibleExts_1 = possibleExts; _i < possibleExts_1.length; _i++) {
|
97 | var ext = possibleExts_1[_i];
|
98 | var possibleFullPath = runDownPath("" + exe + ext);
|
99 | if (sfs.existsSync(possibleFullPath)) {
|
100 | return findActualExecutable(possibleFullPath, args);
|
101 | }
|
102 | }
|
103 | }
|
104 | if (exe.match(/\.ps1$/i)) {
|
105 | var cmd = path.join(process.env.SYSTEMROOT, 'System32', 'WindowsPowerShell', 'v1.0', 'PowerShell.exe');
|
106 | var psargs = ['-ExecutionPolicy', 'Unrestricted', '-NoLogo', '-NonInteractive', '-File', exe];
|
107 | return { cmd: cmd, args: psargs.concat(args) };
|
108 | }
|
109 | if (exe.match(/\.(bat|cmd)$/i)) {
|
110 | var cmd = path.join(process.env.SYSTEMROOT, 'System32', 'cmd.exe');
|
111 | var cmdArgs = ['/C', exe].concat(args);
|
112 | return { cmd: cmd, args: cmdArgs };
|
113 | }
|
114 | if (exe.match(/\.(js)$/i)) {
|
115 | var cmd = process.execPath;
|
116 | var nodeArgs = [exe];
|
117 | return { cmd: cmd, args: nodeArgs.concat(args) };
|
118 | }
|
119 |
|
120 | return { cmd: exe, args: args };
|
121 | }
|
122 | exports.findActualExecutable = findActualExecutable;
|
123 |
|
124 |
|
125 |
|
126 |
|
127 |
|
128 |
|
129 |
|
130 |
|
131 |
|
132 |
|
133 |
|
134 |
|
135 |
|
136 |
|
137 |
|
138 |
|
139 |
|
140 | function spawnDetached(exe, params, opts) {
|
141 | if (opts === void 0) { opts = null; }
|
142 | var _a = findActualExecutable(exe, params), cmd = _a.cmd, args = _a.args;
|
143 | if (!isWindows) {
|
144 | return spawn(cmd, args, assign({}, opts || {}, { detached: true }));
|
145 | }
|
146 | var newParams = [cmd].concat(args);
|
147 | var target = path.join(__dirname, '..', '..', 'vendor', 'jobber', 'Jobber.exe');
|
148 | var options = assign({}, opts || {}, { detached: true, jobber: true });
|
149 | d("spawnDetached: " + target + ", " + newParams);
|
150 | return spawn(target, newParams, options);
|
151 | }
|
152 | exports.spawnDetached = spawnDetached;
|
153 |
|
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 |
|
165 |
|
166 |
|
167 |
|
168 | function spawn(exe, params, opts) {
|
169 | if (params === void 0) { params = []; }
|
170 | if (opts === void 0) { opts = null; }
|
171 | opts = opts || {};
|
172 | var spawnObs = rxjs_1.Observable.create(function (subj) {
|
173 | var stdin = opts.stdin, optsWithoutStdIn = __rest(opts, ["stdin"]);
|
174 | var _a = findActualExecutable(exe, params), cmd = _a.cmd, args = _a.args;
|
175 | d("spawning process: " + cmd + " " + args.join() + ", " + JSON.stringify(optsWithoutStdIn));
|
176 | var origOpts = assign({}, optsWithoutStdIn);
|
177 | if ('jobber' in origOpts) {
|
178 | delete origOpts.jobber;
|
179 | }
|
180 | if ('split' in origOpts) {
|
181 | delete origOpts.split;
|
182 | }
|
183 | var proc = spawnOg(cmd, args, origOpts);
|
184 | var bufHandler = function (source) { return function (b) {
|
185 | if (b.length < 1) {
|
186 | return;
|
187 | }
|
188 | var chunk = '<< String sent back was too long >>';
|
189 | try {
|
190 | if (typeof b === 'string') {
|
191 | chunk = b.toString();
|
192 | }
|
193 | else {
|
194 | chunk = b.toString(origOpts.encoding || 'utf8');
|
195 | }
|
196 | }
|
197 | catch (e) {
|
198 | chunk = "<< Lost chunk of process output for " + exe + " - length was " + b.length + ">>";
|
199 | }
|
200 | subj.next({ source: source, text: chunk });
|
201 | }; };
|
202 | var ret = new rxjs_1.Subscription();
|
203 | if (opts.stdin) {
|
204 | if (proc.stdin) {
|
205 | ret.add(opts.stdin.subscribe(function (x) { return proc.stdin.write(x); }, subj.error.bind(subj), function () { return proc.stdin.end(); }));
|
206 | }
|
207 | else {
|
208 | subj.error(new Error("opts.stdio conflicts with provided spawn opts.stdin observable, 'pipe' is required"));
|
209 | }
|
210 | }
|
211 | var stderrCompleted = null;
|
212 | var stdoutCompleted = null;
|
213 | var noClose = false;
|
214 | if (proc.stdout) {
|
215 | stdoutCompleted = new rxjs_1.AsyncSubject();
|
216 | proc.stdout.on('data', bufHandler('stdout'));
|
217 | proc.stdout.on('close', function () { stdoutCompleted.next(true); stdoutCompleted.complete(); });
|
218 | }
|
219 | else {
|
220 | stdoutCompleted = rxjs_1.of(true);
|
221 | }
|
222 | if (proc.stderr) {
|
223 | stderrCompleted = new rxjs_1.AsyncSubject();
|
224 | proc.stderr.on('data', bufHandler('stderr'));
|
225 | proc.stderr.on('close', function () { stderrCompleted.next(true); stderrCompleted.complete(); });
|
226 | }
|
227 | else {
|
228 | stderrCompleted = rxjs_1.of(true);
|
229 | }
|
230 | proc.on('error', function (e) {
|
231 | noClose = true;
|
232 | subj.error(e);
|
233 | });
|
234 | proc.on('close', function (code) {
|
235 | noClose = true;
|
236 | var pipesClosed = rxjs_1.merge(stdoutCompleted, stderrCompleted)
|
237 | .pipe(operators_1.reduce(function (acc) { return acc; }, true));
|
238 | if (code === 0) {
|
239 | pipesClosed.subscribe(function () { return subj.complete(); });
|
240 | }
|
241 | else {
|
242 | pipesClosed.subscribe(function () { return subj.error(new Error("Failed with exit code: " + code)); });
|
243 | }
|
244 | });
|
245 | ret.add(new rxjs_1.Subscription(function () {
|
246 | if (noClose) {
|
247 | return;
|
248 | }
|
249 | d("Killing process: " + cmd + " " + args.join());
|
250 | if (opts.jobber) {
|
251 |
|
252 | net.connect("\\\\.\\pipe\\jobber-" + proc.pid);
|
253 | setTimeout(function () { return proc.kill(); }, 5 * 1000);
|
254 | }
|
255 | else {
|
256 | proc.kill();
|
257 | }
|
258 | }));
|
259 | return ret;
|
260 | });
|
261 | return opts.split ? spawnObs : spawnObs.pipe(operators_1.pluck('text'));
|
262 | }
|
263 | exports.spawn = spawn;
|
264 | function wrapObservableInPromise(obs) {
|
265 | return new Promise(function (res, rej) {
|
266 | var out = '';
|
267 | obs.subscribe(function (x) { return out += x; }, function (e) { return rej(new Error(out + "\n" + e.message)); }, function () { return res(out); });
|
268 | });
|
269 | }
|
270 |
|
271 |
|
272 |
|
273 |
|
274 |
|
275 |
|
276 |
|
277 |
|
278 |
|
279 |
|
280 |
|
281 |
|
282 |
|
283 |
|
284 | function spawnDetachedPromise(exe, params, opts) {
|
285 | if (opts === void 0) { opts = null; }
|
286 | return wrapObservableInPromise(spawnDetached(exe, params, opts));
|
287 | }
|
288 | exports.spawnDetachedPromise = spawnDetachedPromise;
|
289 |
|
290 |
|
291 |
|
292 |
|
293 |
|
294 |
|
295 |
|
296 |
|
297 |
|
298 |
|
299 |
|
300 |
|
301 |
|
302 | function spawnPromise(exe, params, opts) {
|
303 | if (opts === void 0) { opts = null; }
|
304 | return wrapObservableInPromise(spawn(exe, params, opts));
|
305 | }
|
306 | exports.spawnPromise = spawnPromise;
|
307 |
|
\ | No newline at end of file |