-
Notifications
You must be signed in to change notification settings - Fork 23
/
server.ts
101 lines (81 loc) · 3.09 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
import 'zone.js/dist/zone-node';
import 'reflect-metadata';
import { enableProdMode } from '@angular/core';
import { ngExpressEngine } from '@nguniversal/express-engine';
import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';
import { Request, Response } from 'express-serve-static-core';
import * as express from 'express';
import * as WSS from 'ws';
import * as http from 'http';
import { join } from 'path';
import { readFileSync } from 'fs';
import { queryDataByFieldCollection, queryDataByFieldExpression, queryDropdownFilterDataByField } from './server/query';
process.on('uncaughtException', (exception) => {
console.log('node process crashed: ', exception);
});
// Faster server renders w/ Prod mode (dev mode never needed)
enableProdMode();
// Express server
const app = express();
const server = http.createServer(app);
const wss = new WSS.Server({ server });
const PORT = process.env.PORT || 8080;
const DIST_FOLDER = process.env.DIST_FOLDER ? join(process.cwd(), process.env.DIST_FOLDER) : process.cwd();
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/ornamentum-demo/server/main');
// Fetch data and cache
const data: Array<any> = JSON.parse(readFileSync(join(DIST_FOLDER, 'server/data.json'), 'utf8'));
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
app.engine(
'html',
ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [provideModuleMap(LAZY_MODULE_MAP)]
})
);
app.set('view engine', 'html');
app.set('views', join(DIST_FOLDER, 'browser'));
// Example data route
app.get('/api/data', (req: Request, res: Response) => {
const { offset = 0, limit = 10, ...fields } = req.query;
const parsedOffset = Number(offset);
const parsedLimit = Number(limit);
res.status(200).json(queryDataByFieldExpression(data, parsedOffset || 0, parsedLimit || 10, fields));
});
// Column filtering options
app.get('/api/data/filter', (req: Request, res: Response) => {
const { ...field } = req.query;
res.status(200).json(queryDropdownFilterDataByField(data, field));
});
// Server static files from /browser
app.get(
'*.*',
express.static(join(DIST_FOLDER, 'browser'), {
maxAge: '30d'
})
);
// All regular routes use the Universal engine
app.get('*', (req: Request, res: Response) => {
res.render('index', { req });
});
// Web socket endpoint
wss.on('connection', (ws: WSS) => {
try {
ws.on('message', (message: string) => {
const query = JSON.parse(message);
if (query && query['type'] === 'data-fetch') {
const result = queryDataByFieldCollection(data, query['offset'] || 0, query['limit'] || 10, query['fields'] || query['filter']);
ws.send(JSON.stringify(result));
}
});
ws.on('close', () => {
console.log('[WS] closing connection');
});
} catch (e) {
console.log('[WS] connection crash');
}
});
// Start up the Node server
server.listen(PORT, () => {
console.log(`Node Express server listening on http://localhost:${PORT}`);
});