UNPKG

5.06 kBJavaScriptView Raw
1'use strict';
2
3var async = require('async');
4var fs = require('fs');
5var os = require('os');
6var path = require('path');
7var spawn = require('child_process').spawn;
8var downloader = require('./downloader');
9var tunnelLocation = void 0;
10var activeTunnel = void 0;
11var started = false;
12
13function logger(msg) {
14 console.log.apply(console, arguments);
15}
16
17function download(options, callback) {
18 tunnelLocation = path.normalize(path.join(__dirname, '../testingbot-tunnel.jar'));
19
20 var url = 'https://testingbot.com/tunnel/testingbot-tunnel.jar';
21
22 if (options.tunnelVersion) {
23 tunnelLocation = path.normalize(path.join(__dirname, '../testingbot-tunnel-' + options.tunnelVersion + '.jar'));
24 url = 'https://testingbot.com/tunnel/testingbot-tunnel-' + options.tunnelVersion + '.jar';
25 }
26
27 try {
28 var tunnelFile = fs.statSync(tunnelLocation);
29 if (tunnelFile['size'] > 1024) {
30 return callback(null);
31 }
32 } catch (ignore) {}
33
34 downloader.get(url, { fileName: 'testingbot-tunnel', destination: tunnelLocation }, function (err, destination) {
35 if (err) {
36 return callback(new Error('Could not download the tunnel from TestingBot - please check your connection. ' + err.message));
37 }
38
39 return callback(null);
40 });
41}
42
43function run(options, callback) {
44 if (!fs.existsSync(tunnelLocation)) {
45 return callback(new Error('Tunnel jar file is not present in ' + tunnelLocation));
46 }
47
48 var checkJava = spawn('java');
49 checkJava.on('error', function (err) {
50 return callback(new Error('Java might not be installed, necessary to use testingbot-tunnel ' + err.message));
51 });
52
53 var onReady = function onReady() {
54 started = true;
55 logger('Tunnel is ready');
56 callback(null, activeTunnel);
57 };
58
59 var args = [];
60
61 args.push('-jar');
62 args.push(tunnelLocation);
63
64 if (options.apiKey) {
65 args.push(options.apiKey);
66 }
67
68 if (options.apiSecret) {
69 args.push(options.apiSecret);
70 }
71
72 for (var option in options) {
73 if (option === 'apiKey' || option === 'apiSecret' || option === 'verbose' || option === 'tunnelVersion') {
74 continue;
75 }
76
77 if (options[option]) {
78 args.push('--' + option);
79 args.push(options[option]);
80 } else {
81 args.push('--' + option);
82 }
83 }
84
85 var readyFile = path.join(os.tmpdir(), 'testingbot.ready');
86 try {
87 if (fs.statSync(readyFile).isFile()) {
88 logger('Tunnel Readyfile already exists, removing');
89 fs.unlinkSync(readyFile);
90 }
91 } catch (ignore) {}
92
93 args.push('-f');
94 args.push(readyFile);
95
96 var readyFileChecker = setInterval(function () {
97 fs.stat(readyFile, function (error, stat) {
98 if (!error) {
99 clearInterval(readyFileChecker);
100 onReady();
101 }
102 });
103 }, 800);
104
105 if (options.verbose) {
106 logger('Starting tunnel with options', args);
107 }
108 activeTunnel = spawn('java', args, {});
109
110 activeTunnel.stderr.on('data', function (data) {
111 data = data.toString().trim();
112 if (options.verbose && data !== '') {
113 logger(data);
114 }
115 if (data.indexOf('is available for download') > -1) {
116 logger(data);
117 }
118 if (data.indexOf('error code : 401') > -1) {
119 activeTunnel.error = 'Invalid credentials. Please supply the correct key/secret obtained from TestingBot.com';
120 activeTunnel.close();
121 }
122 });
123
124 activeTunnel.stdout.on('data', function (data) {
125 data = data.toString().trim();
126 if (options.verbose && data !== '') {
127 logger(data);
128 }
129 });
130
131 activeTunnel.close = function (closeCallback) {
132 if (closeCallback) {
133 if (!activeTunnel) {
134 closeCallback();
135 } else {
136 activeTunnel.on('close', function () {
137 closeCallback();
138 });
139 }
140 }
141 activeTunnel.kill('SIGINT');
142 };
143
144 activeTunnel.on('exit', function (code, signal) {
145 logger('Closing TestingBot Tunnel');
146 if (!started) {
147 callback(new Error(activeTunnel.error ? activeTunnel.error : 'Could not start TestingBot Tunnel. Exit code ' + code + ' signal: ' + signal));
148 }
149
150 started = false;
151 activeTunnel = null;
152 });
153}
154
155function killTunnel(callback) {
156 if (!callback) {
157 callback = function callback() {};
158 }
159
160 if (!activeTunnel) {
161 return callback(new Error('no active tunnel'));
162 }
163
164 activeTunnel.kill('SIGINT');
165 callback(null);
166}
167
168function downloadAndRun(options, callback) {
169 if (!options) {
170 options = {};
171 }
172
173 if (!callback) {
174 callback = function callback() {};
175 }
176
177 async.waterfall([async.apply(download, options), async.apply(run, options)], callback);
178}
179
180module.exports = downloadAndRun;
181module.exports.kill = killTunnel;
\No newline at end of file