UNPKG

apemandb

Version:
198 lines (180 loc) 4.55 kB
/** * 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