import {Express, Router} from "express"; import Logger from "./Logger"; import {sleep} from "./Utils"; import Application from "./Application"; import config from "config"; import SecurityError from "./SecurityError"; export default abstract class ApplicationComponent { private val?: T; protected app?: Application; public async checkSecuritySettings(): Promise { } public async start(app: Express): Promise { } public async init(router: Router): Promise { } public async handle(router: Router): Promise { } public async stop(): Promise { } protected export(val: T) { this.val = val; } public import(): T { if (!this.val) throw 'Cannot import if nothing was exported.'; return this.val; } public setApp(app: Application) { this.app = app; } protected async prepare(name: string, prepare: () => Promise): Promise { let err; do { try { await prepare(); err = null; } catch (e) { err = e; Logger.error(err, `${name} failed to prepare; retrying in 5s...`) await sleep(5000); } } while (err); Logger.info(`${name} ready!`); } protected async close(thingName: string, thing: any, fn: Function): Promise { try { await new Promise((resolve, reject) => fn.call(thing, (err: any) => { if (err) reject(err); else resolve(); })); Logger.info(`${thingName} closed.`); } catch (e) { Logger.error(e, `An error occurred while closing the ${thingName}.`); } } protected checkSecurityConfigField(field: string) { if (!config.has(field) || config.get(field) === 'default') { throw new SecurityError('field not configured.'); } } }