-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkoa-server.ts
105 lines (89 loc) · 2.36 KB
/
koa-server.ts
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
import chokidar from "chokidar";
import { readFileSync } from "fs";
import Koa from "koa";
import mime from "mime-types";
import Stream from "stream";
import { SERVER_PORT, WATCH_DIRECTORY } from "./constants";
import { getAllFiles } from "./common";
// Server setup
const app = new Koa();
// Directory watcher setup
const watcher = chokidar.watch(`${WATCH_DIRECTORY}/**`, {
persistent: true,
interval: 300,
});
// Hot-reload feature over Server-sent events (SSE)
app.use((ctx, next) => {
console.log(`requested ${ctx.path}`);
if ("/events" == ctx.path) {
ctx.set({
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive",
});
ctx.status = 200;
const stream = new Stream.PassThrough();
ctx.body = stream;
stream.write(`data: init\n\n`);
const sseHandler = (path) => {
stream.write(`data: reload\n\n`);
console.log(`hot-reload on ${path}`);
};
watcher
.on("add", sseHandler)
.on("change", sseHandler)
.on("unlink", sseHandler)
.on("addDir", sseHandler)
.on("unlinkDir", sseHandler);
ctx.req.on("close", () => {
stream.end();
});
} else {
next();
}
});
// Root URL processor and static serve
app.use((ctx, next) => {
try {
const files = getAllFiles(WATCH_DIRECTORY);
if (ctx.path === "/") {
ctx.body = readFileSync(`${WATCH_DIRECTORY}/index.html`).toString();
next();
} else if (files.includes(ctx.path)) {
const path = `${WATCH_DIRECTORY}${ctx.path}`;
ctx.body = readFileSync(path);
ctx.type = mime.lookup(path).toString();
} else {
ctx.status = 404;
}
} catch (err) {
ctx.status = 500;
ctx.body = err.message;
}
});
// Inject template variable
app.use((ctx, next) => {
if (ctx.body) {
ctx.body = ctx.body.replace(/<\/(body)>/gi, "%$1-injection%</$1>");
next();
} else {
ctx.status = 204;
}
});
// Inject sse-template to the body
app.use((ctx, next) => {
if (ctx.body) {
try {
const sseInjection = readFileSync("./sse-injection.html").toString();
ctx.body = ctx.body.replace("%body-injection%", sseInjection);
next();
} catch (err) {
ctx.status = 500;
ctx.body = err.message;
}
} else {
ctx.status = 204;
}
});
app.listen(SERVER_PORT);
console.log(`hot-reload server was started on port ${SERVER_PORT}`);