-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
130 lines (109 loc) · 3.29 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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import fs from 'fs';
import fsp from 'fs/promises';
import http from 'http';
import path from 'path';
import WebSocket from 'ws';
import chokidar from 'chokidar';
const FgCyan = '\x1b[36m';
const FgGreen = '\x1b[32m';
const FgRed = '\x1b[31m';
const FgYellow = '\x1b[33m';
const cwd = path.resolve(process.cwd());
const jsConfigFile = path.resolve(cwd, 'd-d.config.js');
try {
await fsp.access(jsConfigFile);
} catch (error) {
console.log(FgYellow, `You have to create a d-d.config.js file`);
process.exit(1);
}
const { default: config } = await import(jsConfigFile);
const dist = config.dist || '/dist';
const src = config.src || '/src';
const port = config.port || 1234;
const socketPort = config.socketPort || 1235;
const MIME = config.mime || {
css: 'text/css',
gif: 'image/gif',
html: 'text/html',
ico: 'image/x-icon',
jpeg: 'image/jpeg',
jpg: 'image/jpeg',
js: 'text/javascript',
json: 'application/json',
map: 'application/json',
pdf: 'application/pdf',
png: 'image/png',
svg: 'image/svg+xml',
xml: 'text/xml'
};
function createHandler(method) {
return (req, res) => method.apply(this, [req, res]);
}
function route(url) {
const path = `${cwd}${dist}${url}`;
try {
const content = fs.readFileSync(path).toString();
console.log(
FgYellow,
`[${new Date().toLocaleTimeString()}]`,
'200',
url
);
return createHandler(write(content, 200, path));
} catch (e) {
console.log(FgRed, `[${new Date().toLocaleTimeString()}]`, '404', url);
return createHandler(write(`File not found: ${url}`, 404));
}
}
function write(content, code, pathname) {
const contentTransformed = content.replace(
'</body>',
`<script>
(function() {
const ws = new WebSocket('ws://localhost:${socketPort}');
const onChange = ${config.onChangeClient && config.onChangeClient.toString()};
ws.onmessage = ({ data }) => {
onChange && onChange(data);
!onChange && window.location.reload();
};
})();
</script>
</body>`
);
return function (req, res) {
res.writeHead(code || 200, {
'Access-Control-Allow-Origin': '*',
'Content-Type': pathname
? MIME[pathname.split('.').pop()]
: 'text/plain'
});
res.write(contentTransformed);
res.end();
};
}
function watch(ws) {
chokidar.watch(src).on('change', (pathname) => {
if (ws.readyState === 1) {
console.log('\n', FgGreen, 'File changed: ' + pathname, '\n');
config.onChangeServer(pathname);
ws.send(pathname);
}
});
}
function server() {
return http.createServer((req, res) => {
route(req.url)(req, res);
});
}
const wss = new WebSocket.Server({ port: socketPort });
wss.on('connection', function connection(ws) {
console.log('\n');
console.log(FgCyan, 'WebSocket connection');
console.log('\n');
ws.on('error', (error) => console.log(error));
watch(ws);
});
server().listen(port);
console.log('\n');
console.log(FgCyan, `Server: http://localhost:${port}/index.html`);
console.log('\n');