-
Notifications
You must be signed in to change notification settings - Fork 9
/
dev-server.js
111 lines (93 loc) · 2.82 KB
/
dev-server.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
103
104
105
106
107
108
109
110
111
require('colors')
var socketIo = require('socket.io'),
curry = require('std/curry'),
fs = require('fs'),
path = require('path'),
time = require('std/time'),
http = require('http')
module.exports = {
compileFile: compileFile,
listen: listen,
mountAndWatchFile: mountAndWatchFile,
serveDevClient: serveDevClient,
respond: respond
}
function compileFile(filename, opts, callback) {
loadCompiler().compileFile(_resolveFilename(filename), opts, callback)
}
function listen(port, filenameRaw, opts) {
if (!port) { port = 8080 }
var filename = _resolveFilename(filenameRaw)
try {
var stat = fs.statSync(filename)
} catch(e) {
console.error('Error:', e.message ? e.message : e.toString())
return process.exit(-1)
}
if (!stat.isFile()) {
console.error('Error:', filename, 'is not a file.')
return process.exit(-1)
}
var server = http.createServer(function(req, res) {
if (req.url == '/favicon.ico') {
return send404(res)
} else {
serveDevClient(req, res)
}
})
function send404(res) {
res.writeHead(404)
res.end()
}
mountAndWatchFile(server, filename, opts)
server.listen(port)
console.log('Fun!'.magenta, 'Serving', filenameRaw.green, 'on', ('localhost:'+port).cyan, 'with these options:\n', opts)
}
function _resolveFilename(filename) {
return filename[0] == '/' ? filename : path.join(process.cwd(), filename)
}
function serveDevClient(req, res) {
fs.readFile(path.join(__dirname, './dev-client.html'), curry(respond, res))
}
function mountAndWatchFile(server, filename, opts) {
var serverIo = socketIo.listen(server)
serverIo.set('log level', 0)
serverIo.sockets.on('connection', function(socket) {
console.log("Dev client connected")
loadCompiler().compileFile(filename, opts, function broadcast(err, appHtml) {
socket.emit('change', { error:err, html:appHtml })
})
})
var lastChange = time.now()
fs.watch(filename, function(event, changedFilename) {
if (time.now() - lastChange < 1000) { return } // Node bug calls twice per change, see https://github.com/joyent/node/issues/2126
lastChange = time.now()
console.log(filename, "changed.", "Compiling and sending.")
loadCompiler().compileFile(filename, opts, function broadcast(err, appHtml) {
serverIo.sockets.emit('change', { error:err, html:appHtml })
})
})
}
function loadCompiler() {
for (var key in require.cache) {
delete require.cache[key]
}
return require('../src/compiler')
}
function respond(res, e, content) {
if (e) {
res.writeHead(500)
res.end(errorHtmlResponse(e))
} else {
res.writeHead(200)
res.end(content.toString())
}
}
function errorHtmlResponse(e) {
return ['<!doctype html>','<body>',
'<button ontouchstart="location.reload();" onclick="location.reload()">Reload</button>',
'<pre>',
e.stack ? e.stack : e.message ? e.message : e.toString ? e.toString() : e || 'Error',
'</pre>'
].join('\n')
}