Passed
Push — main ( fcc09d...acdace )
by Lorenzo
01:47 queued 13s
created

ExpressBeans.initialize   A

Complexity

Conditions 4

Size

Total Lines 31
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 4

Importance

Changes 0
Metric Value
eloc 16
dl 0
loc 31
ccs 11
cts 11
cp 1
rs 9.6
c 0
b 0
f 0
cc 4
crap 4
1
import express, { Express } from 'express';
2
import { CreateExpressBeansOptions, ExpressBeansOptions, ExpressRouterBean } from '@/ExpressBeansTypes';
3
import { logger, registeredBeans } from '@/decorators';
4
5
export default class ExpressBeans {
6
  private readonly app: Express;
7
8
  private onInitialized: (() => void) | undefined;
9
10
  /**
11
   * Creates a new ExpressBeans application
12
   * @param options {ExpressBeansOptions}
13
   */
14
  static createApp(options?: Partial<CreateExpressBeansOptions>): Promise<ExpressBeans> {
15 4
    return new Promise((resolve, reject) => {
16
      let app: ExpressBeans;
17 4
      const onInitialized = () => {
18 1
        resolve(app);
19
      };
20 4
      app = new ExpressBeans({ ...options, onInitialized, onError: reject });
21
    });
22
  }
23
24
  /**
25
   * Constructor of ExpressBeans application
26
   * @constructor
27
   * @param options {ExpressBeansOptions}
28
   */
29
  constructor(options?: Partial<ExpressBeansOptions>) {
30 15
    this.app = express();
31 15
    this.app.disable('x-powered-by');
32 15
    this.initialize(options || {});
33
  }
34
35
  /**
36
   * Initializes the application and checks
37
   * if all beans are valid
38
   * @param listen {boolean}
39
   * @param port {number}
40
   * @param beans {Object[]}
41
   * @param onInitialized {Function}
42
   * @private
43
   */
44
  private initialize({
45
    listen = true,
46
    port = 8080,
47
    routerBeans = [],
48
    onInitialized,
49
    onError,
50
  }: Partial<ExpressBeansOptions>) {
51 15
    this.onInitialized = onInitialized;
52 15
    this.checkRouterBeans(routerBeans);
53 14
    setImmediate(async () => {
54 13
      try {
55 13
        this.registerRouters();
56 12
        if (listen) {
57 10
          this.listen(port);
58
        }
59
      } catch (err: any) {
60 4
        if (onError) {
61 3
          onError(err);
62
        } else {
63 1
          logger.error(new Error('Critical error', { cause: err }));
64 1
          process.exit(1);
65
        }
66
      }
67
    });
68
  }
69
70
  /**
71
   * Starts the server and calls onInitialized callback
72
   * @param {number} port
73
   */
74
  listen(port: number) {
75 11
    return this.app.listen(port, () => {
76 4
      logger.info(`Server listening on port ${port}`);
77 4
      if (this.onInitialized) {
78 2
        this.onInitialized();
79
      }
80
    });
81
  }
82
83
  private registerRouters() {
84 13
    Array.from(registeredBeans.values())
85 8
      .map((bean) => bean as ExpressRouterBean)
86 8
      .filter((bean) => bean.routerConfig)
87
      .forEach((bean) => {
88 8
        try {
89
          const {
90
            path,
91
            router,
92 8
          } = bean.routerConfig;
93 8
          logger.debug(`Registering router ${bean.className}`);
94 8
          this.app.use(path, router);
95
        } catch (e) {
96 1
          logger.error(e);
97 1
          throw new Error(`Router ${bean.className} not initialized correctly`);
98
        }
99
      });
100
  }
101
102
  private checkRouterBeans(routerBeans: Array<ExpressRouterBean>) {
103 15
    const invalidBeans = routerBeans
104 13
      .filter(((bean) => !bean.isExpressBean))
105 1
      .map((object: any) => object.prototype.constructor.name);
106 15
    if (invalidBeans.length > 0) {
107 1
      throw new Error(`Trying to use something that is not an ExpressBean: ${invalidBeans.join(', ')}`);
108
    }
109
  }
110
111
  /**
112
   * Gets Express application
113
   * @returns {Express}
114
   */
115
  getApp() {
116 2
    return this.app;
117
  }
118
119
  /**
120
   * Exposes use function of Express application
121
   * @param handlers
122
   */
123
  use(...handlers: any) {
124 1
    this.app.use(...handlers);
125
  }
126
}
127