generated from NodeFactoryIo/node-ts-starter
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathApp.ts
129 lines (120 loc) · 3.69 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
117
118
119
120
121
122
123
124
125
126
127
128
129
import fastify, { FastifyInstance } from "fastify";
import fastifyCompress from "fastify-compress";
import fastifyCors from "fastify-cors";
import fastifyEnv from "fastify-env";
import fastifyFormBody from "fastify-formbody";
import fastifyHealthCheck from "fastify-healthcheck";
import { fastifyHelmet } from "fastify-helmet";
import fastifyMetrics from "fastify-metrics";
import fastifySensible from "fastify-sensible";
import fastifySwagger from "fastify-swagger";
import { Connection } from "typeorm";
import { config as envPluginConfig } from "./config";
import { getDatabaseConnection } from "./services/db";
import { logger } from "./services/logger";
import { routesPlugin } from "./services/plugins/routes";
import { SWAGGER_CONFIG } from "./services/swagger";
export class App {
public readonly instance: FastifyInstance;
protected constructor(instance: FastifyInstance) {
this.instance = instance;
}
/**
* Initializes fastify, env variables and register routes.
* Rest of plugins, db and port bind are initialized on start method.
*/
public static async init(): Promise<App> {
const instance = fastify({
logger: logger,
return503OnClosing: true,
});
const app = new App(instance);
await app.registerPlugins();
return app;
}
public async start(): Promise<void> {
try {
await this.initDb();
await this.instance.ready();
logger.info(this.instance.printRoutes());
return new Promise((resolve, reject) => {
this.instance.listen(
this.instance.config.SERVER_PORT,
this.instance.config.SERVER_ADDRESS,
(err) => {
if (err) {
logger.error("Failed to start server: ", err);
reject();
}
resolve();
}
);
});
} catch (error) {
logger.error(
`Error occurred during app startup because of: ${error.stack}`
);
this.stop(undefined);
}
}
public async stop(signal: string | undefined): Promise<void> {
await this.instance.db
.close()
.catch((error) =>
logger.error(
`Error occurred during database closing because: ${error.message}`
)
);
try {
await this.instance.close();
} catch (e) {
logger.error(
`Error occurred during server closing because: ${e.message}`
);
}
if (signal !== "TEST") {
process.kill(process.pid, signal);
}
}
private async initDb(): Promise<void> {
this.instance.decorate("db", await getDatabaseConnection());
await this.instance.db.runMigrations({ transaction: "all" });
}
private async registerPlugins(): Promise<void> {
this.instance.register(fastifyEnv, envPluginConfig);
await this.instance.after();
this.instance.register(fastifyCompress, {
global: true,
encodings: ["gzip", "deflate"],
});
this.instance.register(fastifyCors, {
origin: this.instance.config.CORS_ORIGIN,
});
this.instance.register(fastifyFormBody);
this.instance.register(fastifyHelmet);
this.instance.register(fastifySensible);
this.instance.register(fastifySwagger, SWAGGER_CONFIG);
this.instance.register(fastifyHealthCheck, {
healthcheckUrl: "/health",
exposeUptime: true,
underPressureOptions: {
healthCheckInterval: 5000,
healthCheck: async () => {
return true;
},
},
});
if (this.instance.config.NODE_ENV !== "test") {
this.instance.register(fastifyMetrics, {
blacklist: "/metrics",
enableDefaultMetrics: true,
});
}
this.instance.register(routesPlugin);
}
}
declare module "fastify" {
interface FastifyInstance {
db: Connection;
}
}