forked from algorithm-visualizer/server
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathServer.ts
136 lines (123 loc) · 4.24 KB
/
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
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
131
132
133
134
135
136
import express, { NextFunction, Request, Response } from 'express';
import morgan from 'morgan';
import bodyParser from 'body-parser';
import * as Controllers from 'controllers';
import { NotFound } from 'ts-httpexceptions';
import compression from 'compression';
import { __PROD__, credentials, httpPort, httpsPort, webhookOptions } from 'config/environments';
import http from 'http';
import https from 'https';
import cron from 'node-cron';
import { Hierarchy } from 'models';
import * as Tracers from 'tracers';
import { errorHandlerMiddleware, frontendMiddleware, redirectMiddleware } from 'middlewares';
import { execute, issueHttpsCertificate, pull } from 'utils/misc';
import { frontendBuildDir, frontendBuiltDir, frontendDir, rootDir } from 'config/paths';
import fs from 'fs-extra';
const Webhook = require('express-github-webhook');
export default class Server {
readonly hierarchy = new Hierarchy();
readonly tracers = Object.values(Tracers).map(Tracer => new Tracer());
private readonly app = express();
private readonly webhook = webhookOptions && Webhook(webhookOptions);
constructor() {
this.app
.use(compression())
.use(morgan(__PROD__ ? 'tiny' : 'dev'))
.use(redirectMiddleware())
.use(bodyParser.json())
.use(bodyParser.urlencoded({ extended: true }))
.use('/api', this.getApiRouter())
.use(frontendMiddleware(this));
if (this.webhook) {
this.app.use(this.webhook);
}
this.app.use(errorHandlerMiddleware());
if (this.webhook) {
this.webhook.on('push', async (repo: string, data: any) => {
const { ref, head_commit } = data;
if (ref !== 'refs/heads/master') return;
if (!head_commit) throw new Error('The `head_commit` is empty.');
switch (repo) {
case 'server':
await this.update(head_commit.id);
break;
case 'algorithm-visualizer':
await this.updateFrontend(head_commit.id);
break;
case 'algorithms':
await this.hierarchy.update(head_commit.id);
break;
default:
throw new Error(`Webhook from unknown repository '${repo}'.`);
}
});
this.webhook.on('release', async (repo: string, data: any) => {
const tracer = this.tracers.find(tracer => repo === `tracers.${tracer.lang}`);
if (!tracer) throw new Error(`Tracer not found for repository '${repo}'.`);
await tracer.update(data.release);
});
}
if (credentials) {
cron.schedule('0 0 1 * *', () => {
issueHttpsCertificate();
});
}
}
getApiRouter() {
const router = express.Router();
Object.values(Controllers).forEach(Controller => new Controller(this).route(router));
router.use((req: Request, res: Response, next: NextFunction) => {
next(new NotFound('API not found.'));
});
return router;
};
async update(commit?: string) {
await pull(rootDir, 'server', commit);
await execute('npm install', {
cwd: rootDir,
stdout: process.stdout,
stderr: process.stderr,
});
process.exit(0);
};
async updateFrontend(commit?: string) {
if (fs.pathExistsSync(frontendDir)) {
await execute(`git fetch`, {
cwd: frontendDir,
stdout: process.stdout,
stderr: process.stderr,
});
} else {
await execute(`git clone https://github.com/likewu/algorithm-visualizer.git ${frontendDir}`, {
stdout: process.stdout,
stderr: process.stderr,
});
}
await execute(`git reset --hard origin/master`, {
cwd: frontendDir,
stdout: process.stdout,
stderr: process.stderr,
});
await execute([
'npm install',
'npm run build',
`rm -rf ${frontendBuiltDir}`,
`mv ${frontendBuildDir} ${frontendBuiltDir}`,
].join(' && '), {
cwd: frontendDir,
stdout: process.stdout,
stderr: process.stderr,
});
}
start() {
const httpServer = http.createServer(this.app);
httpServer.listen(httpPort);
console.info(`http: listening on port ${httpPort}`);
if (credentials) {
const httpsServer = https.createServer(credentials, this.app);
httpsServer.listen(httpsPort);
console.info(`https: listening on port ${httpsPort}`);
}
}
}