UNPKG

5.29 kBJavaScriptView Raw
1var child = require('child_process');
2var chokidar = require('chokidar');
3var fs = require('fs');
4var http = require('http');
5var mime = require('mime');
6var path = require('path');
7var rdbg = require('rdbg');
8var util = require('util');
9var temp = require('temp');
10var which = require('which');
11
12function serve(options, callback) {
13 var server = http.createServer(function(request, response) {
14 if (request.url == '/') {
15 response.setHeader('content-type', 'text/html');
16 response.write('<!doctype html><head><meta charset="utf-8"></head><body>');
17
18 for (var key in options.scripts) {
19 response.write('<script src="' + key + '"></script>');
20 }
21
22 response.end('</body>');
23 } else {
24 var filename = options.scripts[path.basename(request.url)];
25 if (!filename) {
26 var filename = path.join(options.cwd, request.url);
27 }
28
29 fs.exists(filename, function(exists) {
30 if (exists) {
31 response.setHeader('content-type', mime.lookup(filename));
32 response.writeHead(200);
33
34 var file = fs.createReadStream(filename);
35 file.pipe(response);
36 } else {
37 response.writeHead(404);
38 response.end('404');
39 }
40 });
41 }
42 });
43
44 server.listen(options.port, options.host, callback);
45 return server;
46}
47
48function compile(options, callback) {
49 if (options.output == undefined) {
50 var dirpath = temp.mkdirSync('amok-output');
51 options.output = path.join(dirpath, 'bundle.js');
52 }
53
54 switch (options.compiler) {
55 case 'browserify':
56 var command = which.sync('watchify');
57 var args = [
58 '-o',
59 options.output,
60 ];
61 break;
62
63 case 'webpack':
64 var command = which.sync('webpack');
65 var args = [
66 '--watch',
67 '--output-file',
68 options.output,
69 ];
70 break;
71
72 case 'typescript':
73 var command = which.sync('tsc');
74 var args = [
75 '--watch',
76 '--out',
77 options.output,
78 ];
79 break;
80
81 case 'coffeescript':
82 var command = which.sync('coffee');
83 var args = [
84 '--watch',
85 '--out',
86 options.output,
87 ];
88 break;
89
90 case 'babel':
91 var command = which.sync('babel');
92 var args = [
93 '--watch',
94 '--out-file',
95 options.output,
96 ];
97 break;
98
99 default:
100 var args = options.compiler.match(/'[^"]*'|"[^"]*"|\S+/g);
101 var command = args.shift();
102 break;
103 }
104
105 args = args.concat(options.args);
106
107 var compiler = child.spawn(command, args);
108 compiler.output = options.output;
109
110 process.nextTick(function tick() {
111 fs.exists(compiler.output, function(exists) {
112 if (exists) {
113 callback(null, compiler.stdout, compiler.stderr);
114 } else {
115 setTimeout(tick, 100);
116 }
117 });
118 });
119
120 return compiler;
121}
122
123function watch(options, callback) {
124 var files = Object.keys(options.scripts).map(function(key) {
125 return path.dirname(options.scripts[key]);
126 });
127
128 var watcher = chokidar.watch(files, {
129 persistent: true
130 });
131
132 if (callback) {
133 watcher.once('ready', callback);
134 }
135
136 return watcher;
137}
138
139function debug(options, callback) {
140 var bugger = rdbg.connect(options.debuggerPort, options.debuggerHost, function(target) {
141 callback(null, target);
142 });
143
144 bugger.targets(function(targets) {
145 var target = targets.filter(function(target) {
146 return target.url.indexOf(options.host) > -1 && target.webSocketDebuggerUrl;
147 })[0];
148
149 bugger.attach(target);
150 });
151
152 return bugger;
153}
154
155function open(options, callback) {
156 switch (options.client) {
157 case 'chrome':
158 var command = (function() {
159 if (process.platform == 'win32') {
160 var suffix = '\\Google\\Chrome\\Application\\chrome.exe';
161 var prefixes = [
162 process.env['LOCALAPPDATA'],
163 process.env['PROGRAMFILES'],
164 process.env['PROGRAMFILES(X86)'],
165 ];
166
167 var executables = prefixes.map(function(prefix) {
168 return prefix + suffix;
169 }).filter(function(path) {
170 return fs.existsSync(path);
171 });
172 return executables[0];
173 } else if (process.platform == 'darwin') {
174 return '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';
175 } else {
176 return which.sync('google-chrome');
177 }
178 }());
179
180 var args = [
181 '--remote-debugging-port=' + options.debuggerPort,
182 '--no-first-run',
183 '--no-default-browser-check',
184 '--disable-translate',
185 '--disable-default-apps',
186 '--disable-popup-blocking',
187 '--disable-zero-browsers-open-for-tests',
188 '--user-data-dir=' + temp.mkdirSync('amok-chrome'),
189 ];
190 break;
191
192 default:
193 var args = options.client.match(/'[^"]*'|"[^"]*"|\S+/g);
194 var command = args.shift();
195 break;
196 }
197
198 var url = util.format('http://%s:%d', options.host, options.port);
199 args.push(url);
200
201 var client = child.spawn(command, args);
202 setTimeout(function() {
203 callback(null, client.stdout, client.stderr);
204 }, 1000);
205
206 return client;
207}
208
209module.exports.serve = serve;
210module.exports.watch = watch;
211module.exports.compile = compile;
212module.exports.debug = debug;
213module.exports.open = open;