Skip to content

Commit 1e8698e

Browse files
author
hirsch88
committed
refactor bootstrap
1 parent 30bf9c7 commit 1e8698e

File tree

4 files changed

+276
-169
lines changed

4 files changed

+276
-169
lines changed

src/app.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,11 @@ import * as favicon from 'serve-favicon';
1515
import * as bodyParser from 'body-parser';
1616
import * as compression from 'compression';
1717
import * as monitor from 'express-status-monitor';
18-
import { Bootstrap } from './core/Bootstrap';
18+
import { bootstrap } from './core/Bootstrap';
1919
import { Log } from './core/log';
20-
import container from './container';
2120

2221

23-
const app = Bootstrap.getApp()
22+
bootstrap.configureExpress((app: express.Application) => app
2423
// Report real time server metrics for Express-based node servers
2524
.use(monitor())
2625

@@ -56,7 +55,5 @@ const app = Bootstrap.getApp()
5655
stream: {
5756
write: Log.info
5857
}
59-
}));
60-
61-
62-
export default Bootstrap.build(app, container);
58+
}))
59+
);

src/core/Bootstrap.1.ts

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
/**
2+
* core.Bootstrap
3+
* ------------------------------------
4+
*
5+
* This class helps us to create an express app very easy and moreover
6+
* to give us a better possibility to extend the bootstrap process.
7+
*
8+
* We also setup the swagger documentation, api info route and the
9+
* small monitor app.
10+
*/
11+
12+
import * as fs from 'fs';
13+
import * as http from 'http';
14+
import * as express from 'express';
15+
import * as monitor from 'express-status-monitor';
16+
import { Container } from 'inversify';
17+
import { InversifyExpressServer } from 'inversify-express-utils';
18+
import { Environment } from './Environment';
19+
import { my } from 'my-express';
20+
import { exceptionHandler, extendExpressResponse } from './api';
21+
import { events } from './api/events';
22+
import { Log } from './log';
23+
24+
const log = new Log('core:Bootstrap');
25+
26+
27+
export class Bootstrap {
28+
29+
/**
30+
* Returns a basic express application with some configurations
31+
* like host and port.
32+
*
33+
* @static
34+
* @returns {express.Application}
35+
*
36+
* @memberof Bootstrap
37+
*/
38+
static getApp(): express.Application {
39+
const app = express();
40+
app.set('host', Environment.get('APP_HOST'));
41+
app.set('port', Bootstrap.normalizePort(Environment.get<string>('PORT') || Environment.get<string>('APP_PORT')));
42+
log.info('Starting app...');
43+
return app;
44+
}
45+
46+
/**
47+
* Binds the express application and the ioc container together,
48+
* so we can use the awesome annotations of the inversify library.
49+
*
50+
* @static
51+
* @param {express.Application} app
52+
* @param {Container} container
53+
* @returns {express.Application}
54+
*
55+
* @memberof Bootstrap
56+
*/
57+
static startUp(app: express.Application, container: Container): Promise<{ app: express.Application, server: http.Server }> {
58+
app = Bootstrap.setupApiInfo(app);
59+
app = Bootstrap.setupSwagger(app);
60+
app = Bootstrap.setupApiMonitor(app);
61+
62+
let inversifyExpressServer = new InversifyExpressServer(container, undefined, { rootPath: Environment.get<string>('APP_URL_PREFIX') }, app);
63+
inversifyExpressServer = Bootstrap.setupConfigurations(inversifyExpressServer);
64+
65+
const inversifyExpressApp = inversifyExpressServer.build();
66+
const server = () => inversifyExpressApp.listen(app.get('port'));
67+
68+
return new Promise((resolve, reject) => {
69+
resolve({
70+
app: inversifyExpressApp,
71+
server: server
72+
});
73+
});
74+
75+
// const server = app.listen(app.get('port'));
76+
// return server.build();
77+
78+
}
79+
80+
/**
81+
* Sets up the express middlewares witch are last in the chain
82+
*
83+
* @static
84+
* @param {InversifyExpressServer} server
85+
* @returns {InversifyExpressServer}
86+
*
87+
* @memberof Bootstrap
88+
*/
89+
static setupConfigurations(server: InversifyExpressServer): InversifyExpressServer {
90+
server.setConfig((a) => a.use(extendExpressResponse));
91+
server.setErrorConfig((a) => a.use(exceptionHandler));
92+
return server;
93+
}
94+
95+
/**
96+
* Sets up a route for all the api info
97+
*
98+
* @static
99+
* @param {express.Application} app
100+
* @returns {express.Application}
101+
*
102+
* @memberof Bootstrap
103+
*/
104+
static setupApiInfo(app: express.Application): express.Application {
105+
if (Environment.get<string>('API_INFO_ENABLED') === 'true') {
106+
app.get(Environment.get<string>('APP_URL_PREFIX') + Environment.get<string>('API_INFO_ROUTE'), (req: my.Request, res: my.Response) => {
107+
const pkg = Environment.getPkg();
108+
const links = {
109+
links: {}
110+
};
111+
if (Environment.get<string>('SWAGGER_ENABLED') === 'true') {
112+
links.links['swagger'] = `${app.get('host')}:${app.get('port')}${process.env.APP_URL_PREFIX}${process.env.SWAGGER_ROUTE}`;
113+
}
114+
if (Environment.get<string>('MONITOR_ENABLED') === 'true') {
115+
links.links['monitor'] = `${app.get('host')}:${app.get('port')}${process.env.APP_URL_PREFIX}${process.env.MONITOR_ROUTE}`;
116+
}
117+
return res.json({
118+
name: pkg.name,
119+
version: pkg.version,
120+
description: pkg.description,
121+
...links
122+
});
123+
});
124+
}
125+
return app;
126+
}
127+
128+
/**
129+
* Sets up the swagger documentation
130+
*
131+
* @static
132+
* @param {express.Application} app
133+
* @returns {express.Application}
134+
*
135+
* @memberof Bootstrap
136+
*/
137+
static setupSwagger(app: express.Application): express.Application {
138+
if (Environment.get<string>('SWAGGER_ENABLED') === 'true') {
139+
const baseFolder = __dirname.indexOf('/src/') >= 0 ? '/src/' : '/dist/';
140+
const basePath = __dirname.substring(0, __dirname.indexOf(baseFolder));
141+
const swaggerFile = require(basePath + Environment.get<string>('SWAGGER_FILE'));
142+
const packageJson = require(basePath + '/package.json');
143+
144+
// Add npm infos to the swagger doc
145+
swaggerFile.info = {
146+
title: packageJson.name,
147+
description: packageJson.description,
148+
version: packageJson.version
149+
};
150+
151+
// Initialize swagger-jsdoc -> returns validated swagger spec in json format
152+
const swaggerUi = require('swagger-ui-express');
153+
const route = Environment.get<string>('APP_URL_PREFIX') + Environment.get<string>('SWAGGER_ROUTE');
154+
app.use(route, swaggerUi.serve, swaggerUi.setup(swaggerFile));
155+
}
156+
return app;
157+
}
158+
159+
/**
160+
* Sets up a small monitor app
161+
*
162+
* @static
163+
* @param {express.Application} app
164+
* @returns {express.Application}
165+
*
166+
* @memberof Bootstrap
167+
*/
168+
static setupApiMonitor(app: express.Application): express.Application {
169+
if (Environment.get<string>('MONITOR_ENABLED') === 'true') {
170+
app.get(Environment.get<string>('APP_URL_PREFIX') + Environment.get<string>('MONITOR_ROUTE'), monitor().pageRoute);
171+
}
172+
return app;
173+
}
174+
175+
/**
176+
* Sets up the event listeners and registers them.
177+
*
178+
* @static
179+
*
180+
* @memberof Bootstrap
181+
*/
182+
static setupEventListeners(): void {
183+
const baseFolder = __dirname.indexOf('/src/') >= 0 ? '/src/' : '/dist/';
184+
const basePath = __dirname.substring(0, __dirname.indexOf(baseFolder));
185+
const path = `${basePath}${baseFolder}api/listeners`;
186+
fs.readdir(path, (err: any, items: string[]): void => {
187+
for (let i = 0; i < items.length; i++) {
188+
const name = items[i].substring(0, items[i].length - 3);
189+
const Listener = require(`${path}/${items[i]}`)[name];
190+
const listener = new Listener();
191+
events.on(Listener.Event, (...args) => listener.run(...args));
192+
}
193+
});
194+
}
195+
196+
/**
197+
* Well this method just normalizes the given port :-)
198+
*
199+
* @static
200+
* @param {string} port
201+
* @returns {(number | string | boolean)}
202+
*
203+
* @memberof Bootstrap
204+
*/
205+
static normalizePort(port: string): number | string | boolean {
206+
const parsedPort = parseInt(port, 10);
207+
if (isNaN(parsedPort)) { // named pipe
208+
return port;
209+
}
210+
if (parsedPort >= 0) { // port number
211+
return parsedPort;
212+
}
213+
return false;
214+
}
215+
216+
}

0 commit comments

Comments
 (0)