import {Inject, Singleton} from "../../di"; import {DatabaseService} from "../DatabaseService"; import {PostgresConnection} from "../connection/PostgresConnection"; import {ErrorWithContext} from "../../util"; import {Unit} from "../../lifecycle/Unit"; import {Config} from "../../service/Config"; import {Logging} from "../../service/Logging"; /** * Application unit responsible for loading and creating database connections from config. */ @Singleton() export class Database extends Unit { @Inject() protected readonly config!: Config; @Inject() protected readonly dbService!: DatabaseService; @Inject() protected readonly logging!: Logging; /** * Load the `database.connections` config and register Connection instances for each config. * Automatically initializes the connections. */ public async up() { const connections = this.config.get('database.connections') const promises = [] for ( const key in connections ) { if ( !connections.hasOwnProperty(key) ) continue const config = connections[key] this.logging.info(`Initializing database connection: ${key}`) this.logging.verbose(config) let conn if ( config?.dialect === 'postgres' ) { conn = this.app().make(PostgresConnection, key, config) } else { const e = new ErrorWithContext(`Invalid or missing database dialect: ${config.dialect}. Should be one of: postgres`) e.context = { connectionName: key } throw e } this.dbService.register(key, conn) promises.push(conn.init()) } await Promise.all(promises) this.logging.info('Database connections opened.') } /** * Close the configured connections cleanly before exit. */ public async down() { await Promise.all(this.dbService.names() .map(name => this.dbService.get(name).close())) } }