-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdev-server.js
More file actions
110 lines (99 loc) · 2.86 KB
/
Copy pathdev-server.js
File metadata and controls
110 lines (99 loc) · 2.86 KB
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
#!/usr/bin/env node
const http = require('http');
const fs = require('fs');
const path = require('path');
const { spawn } = require('child_process');
const PORT = 3000;
const OUTDIR = path.join(__dirname, 'result', 'examples', 'todo-app');
const WATCH_DIRS = [
path.join(__dirname, 'src'),
path.join(__dirname, 'examples', 'todo-app'),
path.join(__dirname, 'flake.nix'),
];
let clients = [];
function serveFile(filePath, res) {
fs.readFile(filePath, (err, data) => {
if (err) {
res.writeHead(404);
res.end('Not found');
} else {
if (filePath.endsWith('.css')) res.setHeader('Content-Type', 'text/css');
else if (filePath.endsWith('.js')) res.setHeader('Content-Type', 'application/javascript');
else if (filePath.endsWith('.html')) res.setHeader('Content-Type', 'text/html');
res.end(data);
}
});
}
const server = http.createServer((req, res) => {
let reqPath = req.url.split('?')[0];
if (reqPath === '/') reqPath = '/index.html';
const filePath = path.join(OUTDIR, reqPath);
if (reqPath === '/__livereload') {
clients.push(res);
req.on('close', () => {
clients = clients.filter(c => c !== res);
});
return;
}
serveFile(filePath, res);
});
server.listen(PORT, () => {
console.log(`NixUI dev server running at http://localhost:${PORT}`);
});
function notifyClients() {
clients.forEach(res => {
res.write('data: reload\n\n');
res.end();
});
clients = [];
}
function buildAndReload() {
console.log('Rebuilding...');
const build = spawn('nix', ['build', '.#nixui']);
build.stdout.on('data', d => process.stdout.write(d));
build.stderr.on('data', d => process.stderr.write(d));
build.on('close', code => {
if (code === 0) {
console.log('Build succeeded. Reloading browser.');
notifyClients();
} else {
console.log('Build failed.');
}
});
}
let debounceTimer = null;
function watchDirs() {
WATCH_DIRS.forEach(dir => {
if (fs.existsSync(dir)) {
fs.watch(dir, { recursive: true }, (event, filename) => {
if (debounceTimer) clearTimeout(debounceTimer);
debounceTimer = setTimeout(buildAndReload, 300);
});
}
});
}
watchDirs();
// Inject live reload script into index.html
const origServeFile = serveFile;
serveFile = function(filePath, res) {
if (filePath.endsWith('index.html')) {
fs.readFile(filePath, 'utf8', (err, data) => {
if (err) {
res.writeHead(404);
res.end('Not found');
} else {
// Inject live reload script
const injected = data.replace('</body>', `<script>
const es = new EventSource('/__livereload');
es.onmessage = () => location.reload();
</script></body>`);
res.setHeader('Content-Type', 'text/html');
res.end(injected);
}
});
} else {
origServeFile(filePath, res);
}
};
// Initial build
buildAndReload();