-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
108 lines (94 loc) · 3.06 KB
/
index.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
import http from 'node:http';
import url from 'node:url';
import EventEmitter from 'node:events';
export function startServer({ name, port }) {
const template = `
<html>
<head>
<title>${name}</title>
<style>
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
display: flex;
height: 100%;
width: 100%;
justify-content: center;
align-items: center;
font-family: sans-serif;
color: #4b4b4b;
}
.metric__label {
margin-bottom: 0.3em;
font-size: 3vw;
text-align: center;
color: #505050;
}
.metric__value {
font-size: 8vw;
text-align: center;
}
</style>
</head>
<body>
<div class="metric">
<div class="metric__label">${name}</div>
<div class="metric__value">–</div>
</div>
<script>
const metricElement = document.getElementsByClassName('metric__value')[0];
const source = new EventSource('/events');
source.onmessage = function(e) {
metricElement.innerText = e.data
};
</script>
</bod>
</html>
`;
const channel = createChannel();
const server = http.createServer((request, response) => {
const { pathname } = url.parse(request.url);
if (pathname === '/') {
response.writeHead(200, {
'Content-Type': 'text/html'
});
response.end(template);
} else if (pathname === '/events') {
response.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
Connection: 'keepalive'
});
response.write('\n');
const unsubscribe = channel.subscribe((metric) => {
response.write(`data: ${metric}\n\n`);
});
request.on('close', () => unsubscribe());
} else {
response.writeHead(404, {
'Content-Type': 'text/plain'
});
response.end('Not found');
}
});
server.listen(port);
return {
update: channel.update
};
}
function createChannel() {
const emitter = new EventEmitter();
const subscribe = (callback) => {
emitter.on('value', callback);
return () => {
emitter.removeListener('value', callback);
};
};
const update = (value) => {
emitter.emit('value', value);
};
return {
subscribe,
update
};
}