apemandb
Version:
Database for apeman project.
198 lines (180 loc) • 4.55 kB
JavaScript
/**
* Create a database model attribute
* @function createAttribute
*/
'use strict'
const { snakecase } = require('stringcase')
/** @lends createAttribute */
function createAttribute (config) {
if (config.$dynamic) {
return null
}
let {
$comment,
$type,
$nullable,
$validate,
$unique,
$name,
$default,
$get,
$set,
$convert
} = config
return {
comment: createAttribute.parseComment($comment),
type: createAttribute.parseType($type),
defaultValue: createAttribute.parseDefaultValue(typeof $default === 'undefined' ? config.$defaultValue : $default),
allowNull: createAttribute.parseAllowNull($nullable),
validate: createAttribute.parseValidate($validate),
unique: createAttribute.parseUnique($unique),
get: createAttribute.parseGet($name, $get, $convert),
set: createAttribute.parseSet($name, $set, $convert),
field: createAttribute.parseField($name)
}
}
Object.assign(createAttribute, {
_types: {},
_converters: {},
converterModules: {
$json: require('../converting/json_converter'),
$trim: require('../converting/trim_converter')
},
/**
* Parse comment.
* @param {string} $comment
* @returns {string}
*/
parseComment ($comment) {
return String($comment).trim()
},
/**
* Parse type.
* @param {string} $type
* @returns {Object}
*/
parseType ($type) {
if (typeof $type !== 'string') {
return $type
}
let cache = createAttribute._types[ $type ]
if (cache) {
return cache
}
let parsed = createAttribute._getType($type)
createAttribute._types[ $type ] = parsed
return parsed
},
/**
* Parse default value
* @param {boolean} $default
* @returns {boolean}
*/
parseDefaultValue ($default) {
return $default
},
/**
* Parse allow null setting.
* @param {boolean?} $nullable
* @returns {boolean}
*/
parseAllowNull ($nullable) {
return !!$nullable
},
/**
* Parse validation settings.
* @param {Object} $validation
* @returns {Object}
*/
parseValidate ($validation) {
return Object.keys($validation || {})
.reduce((validate, name) => Object.assign({
[name.replace(/^\$/, '')]: $validation[ name ]
}), {})
},
/**
* Parse unique constrain.
* @param {boolean?} $unique
* @returns {boolean}
*/
parseUnique ($unique) {
return !!$unique
},
/**
* Parse getter.
* @param {string} $name
* @param {?string} [$get]
* @param {Object} $convert
* @returns {function}
*/
parseGet ($name, $get, $convert) {
if ($get) {
// noinspection Eslint
return new Function(`return ${$get}`)
}
let converters = createAttribute._defineConverters($convert)
return function get () {
const s = this
let value = s.getDataValue($name)
for (let converter of converters) {
value = converter.convertToGet(value)
}
return value
}
},
/**
* Parse setter.
* @param {string} $name
* @param {?string} [$set]
* @param {Object} $convert
* @param {boolean} $readonly
* @returns {function}
*/
parseSet ($name, $set, $convert, $readonly) {
if ($readonly) {
return function setToReadonly (value) {
throw new Error(`[apemandb] Failed to set attribute "${$name}" since it is readonly.`)
}
}
if ($set) {
// noinspection Eslint
return new Function($set)
}
let converters = createAttribute._defineConverters($convert)
return function set (value) {
const s = this
for (let converter of converters) {
value = converter.convertToSet(value)
}
s.setDataValue($name, value)
}
},
/**
* Parse field name
* @param {string} $name - Attribute name.
* @returns {string} - Field name in database.
*/
parseField ($name) {
return snakecase($name)
},
_getType ($type) {
// noinspection Eslint
const Sequelize = require('sequelize')
// noinspection Eslint
return eval(`Sequelize.${$type}`) // Evaluate dynamic getter.
},
_defineConverters ($convert) {
$convert = $convert || {}
let converters = []
let { converterModules } = createAttribute
Object.keys($convert).forEach((name) => {
let Converter = converterModules[ name ]
if (!Converter) {
throw new Error(`Unknown converter: ${name}`)
}
converters.push(new Converter($convert[ name ]))
})
return converters
}
})
module.exports = createAttribute