apemandb
Version:
Database for apeman project.
169 lines (152 loc) • 4.23 kB
JavaScript
/**
* Database for apeman.
* @constructor Apemandb
*/
const argx = require('argx')
const { singularize } = require('inflection')
const { pascalcase } = require('stringcase')
const co = require('co')
const asleep = require('asleep')
const deleteEmptyProps = require('./helpers/delete_empty_props')
const prepareStorage = require('./storaging/prepare_storage')
const TransactionExtension = require('./extensions/transaction_extension')
const Sequelize = require('sequelize')
const setupDatabase = require('./preparing/setup_database')
const debug = require('debug')('apeman:db')
/** @lends Apemandb */
function Apemandb (database, username, password, options) {
let args = argx(arguments)
options = Object.assign({
logging: false
}, args.pop('object') || {})
database = args.shift('string') || null
username = args.shift('string') || null
password = args.shift('string') || null
const s = this
debug(`database: ${database}`)
debug(`username: ${username}`)
debug(`password: ${password}`)
debug(`options: ${JSON.stringify(options)}`)
deleteEmptyProps(options)
prepareStorage(options.storage)
// noinspection Eslint
s.__proto__ = new Sequelize(database, username, password, options)
Object.assign(s, Apemandb.prototype)
Object.assign(s, TransactionExtension)
}
Apemandb.prototype = {
/**
* Setup database
* @param {string} [rootUsername] - Username of root
* @param {string} [rootPassword] - Password of root
*/
setup (rootUsername, rootPassword) {
const s = this
let { config } = s
return co(function * () {
let dialect = s.getDialect()
yield setupDatabase(dialect, rootUsername, rootPassword, config)
})
},
/**
* Define a model.
* @param {string} name
* @param {Object} attributes - Model attributes.
* @param {Object} options - Optional settings.
* @returns {Model}
*/
define (name, attributes, options) {
let args = argx(arguments)
name = args.shift('string')
attributes = deleteEmptyProps(args.shift('object') || {})
options = deleteEmptyProps(args.shift('object') || {})
const s = this
// noinspection Eslint
return s.__proto__.define(name, attributes, options)
},
/**
* Get a model.
* @param {string} name - Name of the model.
* @returns {Model}
* @throws {Error} - Throw when not found.
*/
model (name) {
const s = this
let keys = Object.keys(s.models || {})
let _formatName = (name) => pascalcase(singularize(name))
for (let i = 0, len = keys.length; i < len; i++) {
let hit = _formatName(keys[ i ]) === _formatName(name)
if (hit) {
return s.models[ keys[ i ] ]
}
}
throw new Error('Model not found with name: ' + name)
},
/**
* Reset all tables.
* @returns {Promise}
*/
reset () {
const s = this
let drop = () => co(function * () {
return yield s.drop()
})
let sync = () => co(function * () {
return yield s.sync({ force: true })
})
return co(function * () {
yield drop()
yield sync()
return s
})
},
/**
* Describe all tables.
* @returns {Promise}
*/
describe () {
const s = this
let { models } = s
let describe = (model) => co(function * () {
return yield model.describe()
})
return co(function * () {
let result = {}
for (let name of Object.keys(models || {})) {
result[ name ] = yield describe(models[ name ])
}
return result
})
},
/**
* Apply seed files.
* @param {object} [options] - Optional settings.
* @returns {Promise}
*/
seed (options) {
const s = this
let { seeds } = s
let names = Object.keys(seeds)
debug(`Seeding model names: ${names.join(', ')}`)
return co(function * () {
for (let name of names) {
let seed = seeds[ name ]
yield seed(s.model(name.replace(/^\d+\./, '')), options)
yield asleep(10)
}
})
},
close () {
const s = this
return new Promise((resolve, reject) => {
try {
Sequelize.prototype.close.call(s)
resolve()
} catch (e) {
reject(e)
}
})
}
}
module.exports = Apemandb