-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathapplication.ts
103 lines (90 loc) · 3.11 KB
/
application.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
// Copyright 2020 Liam Tan. All rights reserved. MIT license.
import { Application as OakApplication, Response, Context, blue, bgBlue } from "./deps.ts";
import { Router } from "./router.ts";
import { ApplicationConfig, EInjectionScope, ControllerMetadata } from "./types.ts";
import DIContainer from "./dependency_container.ts";
import { getInjectableMetadata, getControllerOwnMeta } from "./metadata.ts";
import { logger, cors, timing } from "./middleware.ts";
/**
* Bootstrap class responsible for registering controllers
* onto Router, and starting the Oak webserver
*/
export class Application {
#router: Router;
#app: OakApplication;
#middleware: Array<Function>;
public constructor(appConfig: ApplicationConfig) {
// register injectables and controllers into `DIContainer` singleton
for (const newable of appConfig.injectables) {
const scope: EInjectionScope = getInjectableMetadata(newable);
DIContainer.register(newable, scope, newable.name);
}
for (const controller of appConfig.controllers) {
const meta: ControllerMetadata | undefined = getControllerOwnMeta(controller);
if (!meta) {
throw new Error("Attempted to register non-controller class");
}
DIContainer.register(controller, meta.scope, controller.name);
}
this.#router = new Router();
this.#app = new OakApplication();
for (const controller of appConfig.controllers) {
this.#router.register(controller);
}
this.#middleware = [];
}
/**
* Function for user to add `logger` middleware. Builder
* pattern so returns ref to `this`
*/
public useLogger(): Application {
this.#middleware.push(logger);
return this;
}
/**
* Function for user to add `timing` middleware. Builder
* pattern so returns ref to `this`
*/
public useTiming(): Application {
this.#middleware.push(timing);
return this;
}
/**
* Function for user to add `cors` middleware. Builder
* pattern so returns ref to `this`
*/
public useCors(): Application {
this.#middleware.push(cors);
return this;
}
/**
* 404 middleware, enabled by default and not disableable
*/
private async handleNotFound(context: Context): Promise<void> {
const response: Response = context.response;
response.status = 404;
response.body = {
error: "Not Found",
status: 404,
};
}
/**
* Function responsible for begin listen of oak webserver.
* Console notified when webserver begins.
*
* The webserver will start on port `port` as provided as
* an argument.
*/
public async run(port: number): Promise<void> {
this.#middleware.forEach((middleware: any): any => this.#app.use(middleware));
// apply routes
this.#app.use(this.#router.middleware());
// if routes passes through, handle not found with 404 response.
this.#app.use(this.handleNotFound);
const bootstrapMsg: string = this.#router.getBootstrapMsg();
console.log(blue(bootstrapMsg));
console.info(bgBlue(`Dactyl running - please visit http://localhost:${port}/`));
DIContainer.instantiateAllSingletons();
this.#app.listen({ port });
}
}