/**
* @module libflitter/database/DatabaseUnit
*/
const path = require('path')
const Unit = require('../Unit')
const ScaffoldService = require('flitter-orm/src/services/Connection')
/**
* The database unit loads the model schemas from the specified directory
* and creates Mongoose models from them. Then, using the specified values
* it connects to the MongoDB database and continues initializing the stack
* from within the context of a guaranteed connection to the database.
*
* @extends module:libflitter/Unit~Unit
*/
class DatabaseUnit extends Unit {
/**
* Defines the services required by this unit.
* @returns {Array<string>}
*/
static get services() {
return [...super.services, 'output', 'configs']
}
/**
* Gets the name of the service provided by this unit: 'database'
* @returns {string} - 'database'
*/
static get name() {
return 'database'
}
/**
* Return the services provided by this unit. In this case, the ORM
* scaffold service is registered.
* @return {Array<string>}
*/
static get provides() {
return ['scaffold']
}
/**
* Instantiate the unit. Resolve the path to the directory with the model definition schemata.
* @param {string} [models_directory = './app/models'] - path to the directory with the model definition schemata
*/
constructor(models_directory = './app/models'){
super()
/**
* The fully-qualified path to the directory with the model definition schemata.
* @type {string}
* @name DatabaseUnit#directory
*/
this.directory = path.resolve(models_directory)
}
/**
* Get the standard formatted MongoDB connect string using the configured information.
* e.g. 'mongodb://user:pass@host:port/db' &c.
* @returns {string}
*/
get connect_string() {
/*
* Get the database information from the config.
*/
const db_host = this.configs.get('database.host')
const db_port = this.configs.get('database.port')
const db_name = this.configs.get('database.name')
const db_proto = this.configs.get('database.protocol') || 'mongodb'
const db_flags = this.configs.get('database.connect_flags') || ''
/*
* Form the connect string, which is the address of
* the MongoDB server including the name of the
* database and authentication, if it has been specified.
*/
let connect_string = ""
if ( this.configs.get('database.auth.require') === 'true' ){
const db_user = this.configs.get('database.auth.username')
const db_pass = this.configs.get('database.auth.password')
connect_string = `${db_proto}://${db_user}:${db_pass}@${db_host}${db_port ? ':' + db_port : ''}/${db_name}${db_flags}`
}
else {
connect_string = `${db_proto}://${db_host}${db_port ? ':' + db_port : ''}/${db_name}${db_flags}`
}
return connect_string
}
/**
* Loads the unit. Loads the model definition schemata from {@link module:libflitter/database/DatabaseUnit~DatabaseUnit#directory}
* and creates Mongoose models from them. Then, it binds the models, schemata, and helper functions to the appropriate
* contexts. Opens the database connection using the values configured in the 'database' configuration.
* @param {module:libflitter/app/FlitterApp~FlitterApp} app - the Flitter app
* @param {module:libflitter/Context~Context} context - the Unit's context
* @returns {Promise<void>}
*/
async go(app){
const connect_string = this.connect_string
this.output.debug('Database connection string: '+connect_string)
// Register the ORM service into the DI container
app.di().container.register_service(ScaffoldService.name, ScaffoldService)
// Get an instance of the service
const scaffold = app.di().get(ScaffoldService.name)
await scaffold.open(connect_string)
}
/**
* Cleans up the unit's resources before Flitter exits. Closes the MongoDB connection cleanly.
* @param {module:libflitter/app/FlitterApp~FlitterApp} app - the Flitter app
* @returns {Promise<void>}
*/
async cleanup(app){
const scaffold = app.di().get(ScaffoldService.name)
await scaffold.close()
}
/**
* Get the directories provided by this unit.
* Currently, {@link module:libflitter/database/DatabaseUnit~DatabaseUnit#directory}
* @returns {{models: string}}
*/
directories() {
return {
models: this.directory,
}
}
/**
* Get the templates provided by the unit.
* Currently, "model" provided by {@link module:libflitter/templates/model}
* @returns {{model: {template: (model|(function(string): string)|*), extension: string, directory: string}}}
*/
templates(){
return {
model: {
template: require('../templates/model'),
directory: this.directory,
extension: '.model.js'
}
}
}
/**
* Get the fully-qualified path to the migrations provided by this unit.
* @returns {string}
*/
migrations(){
return path.resolve(__dirname, 'migrations')
}
}
module.exports = DatabaseUnit