/
app.ts
116 lines (103 loc) · 3.73 KB
/
app.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
import en from '@assets/languages/en.json';
import { ErrorHandling, stage, StageLevel } from '@core/helpers';
import { Logger } from '@core/utils';
import { Wrapper } from '@core/wrapper';
import { translation } from '@lib/translation';
import Sentry = require('@sentry/node');
import compression = require('compression');
import express = require('express');
import monitor = require('express-status-monitor');
import helmet = require('helmet');
import morgan = require('morgan');
// https://github.com/RafalWilinski/express-status-monitor
import path from 'path';
const log = new Logger('Application instance');
// Stage.tests(StageLevel.DEV, () => {
// Sentry.init({ dsn: 'https://57572231908b4ef0bde6a7328e71cfcf@sentry.io/1462257' });
// });
export class Application {
private _application = express();
private staticDirectory = path.join(process.cwd(), 'src', 'public');
private uploadDirectory = path.join(process.cwd(), 'uploads');
constructor() {
this.configure();
this.allowCors();
this.setupLocalization();
}
get application() {
return this._application;
}
/**
* allow cross origin restriction
* see the difference in cors package
*/
private allowCors() {
this.application.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE');
res.header('Access-Control-Allow-Headers', 'Origin, Authorization, X-Requested-With, Content-Type, Accept');
next();
});
}
/**
* configure the app instance
* set app variables
*/
private configure() {
stage.test(StageLevel.PROD, () => {
this.application
.use(Sentry.Handlers.requestHandler())
.use(Sentry.Handlers.errorHandler());
});
this.application
.use(monitor())
.use(express.json())
.use(express.urlencoded({ extended: true }))
.use(morgan('dev'))
.use(helmet())
.use(compression())
.use(express.static(this.staticDirectory))
.use(express.static(this.uploadDirectory));
// TODO Security
// 1_ sql injection
// 2_ csrf
// 3_ xss
}
protected populateRoutes() {
return new Promise((resolve) => {
// SECTION routes resolving event
Wrapper.routerList.forEach(({ router, uri }) => {
this.application.use(path.join('/api', uri), router);
});
this.application.get('/api', (req, res) => res.status(200).json({ work: '/API hitted' }));
this.application.get('/', (req, res) => res.sendFile('index.html'));
this.application.use((req, res, next) => {
const acceptLanguage = req.acceptsLanguages();
log.warn(acceptLanguage);
if (acceptLanguage) {
// use localization here
}
});
// * catch favIcon request
this.application.use(ErrorHandling.favIcon);
// * catch not found error
this.application.use(ErrorHandling.notFound);
// * Globally catch error
this.application.use(ErrorHandling.catchError);
resolve(this.application);
});
}
private setupLocalization() {
translation.add('en', en);
// localization.add('ar', ar);
translation.use('en');
}
public get(key: string): string {
return this.application.get(key);
}
public set<T>(key: string, value: T): T {
this.application.set(key, value);
return value;
}
}
// TODO add lusca lib