UNPKG

api-rest-entrypoint-generator-from-mysql

Version:
199 lines (185 loc) 6.69 kB
'use strict' const { Sequelize, Op, Model, DataTypes } = require('sequelize'); const CONF = require('./config') const utils = require('../../utils') class Attribute { table = null; dbattr = {} name = ''; type = null; nullable = false; default = null; constructor(){ } /** * Creates an Attribute object from database column info * @param {Table} parent * @param {string} dbattr * @returns {Attribute} */ static async create(parent,dbattr) { let attr = new Attribute(); attr.table = parent; attr.setAttributeDataFromDB(dbattr); return attr; return false; } /** Maps database columno object to Attribute properties */ setAttributeDataFromDB(dbattr) { this.dbattr = dbattr; this.name = dbattr.Field; this.type = dbattr.Type; this.nullable = (dbattr.Null == "YES") this.default = dbattr.Default; } isPrimaryKey() { return this.name === CONF.ATTR_ID; } isForeingKey() { return this.name.startsWith(CONF.ATTR_ID + CONF.SPACE_REPLACE); } isCreatedAt() { return this.name === CONF.ATTR_CREATEDAT; } isModifiedAt() { return this.name === CONF.ATTR_MODIFIEDAT; } /** * Build Sequelize field definition from current attribute * including validation and default values * @returns Sequelize definition */ getSequelizeDefinition() { let _def = {}; _def['field'] = this.name; _def['type'] = this.getSequelizeType() if (this.isPrimaryKey()) { _def['primaryKey'] = true; _def['autoIncrement'] = true; } _def['allowNull'] = this.nullable; let _v = this.getSequelizeValidation(_def['type']) if (utils.nonEmptyObject(_v)) _def['validate'] = _v; let _d = this.getSequelizeDefault(_def['type']) if (_d !== null) _def['defaultValue'] = _d; return _def; } /** Get Sequelize validation definition */ getSequelizeValidation(sqztype) { let _v = {} if (sqztype instanceof DataTypes.INTEGER) _v['isInt'] = true; if (!this.nullable) _v['notNull'] = true; return _v; } /** Get Sequelize default definition */ getSequelizeDefault(sqztype) { if (this.default !== null) { if (this.isCreatedAt() || this.default.toLowerCase().startsWith('current_timestamp')) return DataTypes.NOW; if ([DataTypes.INTEGER,DataTypes.BIGINT].includes(sqztype) || sqztype instanceof DataTypes.BIGINT) return parseInt(this.default); if (sqztype == DataTypes.BOOLEAN) return (this.default == '1') return this.default } return null; } /** * Get Sequelize DataType from attribute database type * @returns {DataTypes} */ getSequelizeType() { return Attribute.getSequelizeTypeFromMySql(this.type); } /** * Maps MySql column datatype to Sequelize DataTypes * It also cares of datatype modifiers. * @param {string} dbtype full database column type * @returns {DataTypes} */ static getSequelizeTypeFromMySql(dbtype) { let type = dbtype.toLowerCase().split(/[ ()]+/); var _t = null; switch (type[0]) { case 'date': return DataTypes.DATEONLY; case 'time': case 'datetime': if(type.length > 1 && !isNaN(type[1])) return DataTypes.DATE(parseInt(type[1])) else return DataTypes.DATE; case 'tinyint': if(type.length > 1 && !isNaN(type[1]) && parseInt(type[1]) == 1) return DataTypes.BOOLEAN; case 'int': case 'smallint': case 'mediumint': _t = DataTypes.INTEGER; break case 'bigint': if(type.length > 1 && !isNaN(type[1])) _t = DataTypes.BIGINT(parseInt(type[1])) else _t = DataTypes.BIGINT; break; case 'float': if(type.length > 1 && !isNaN(type[1])) if(type.length > 2 && !isNaN(type[2])) _t = DataTypes.FLOAT(parseInt(type[1]),parseInt(type[2])) else _t = DataTypes.FLOAT(parseInt(type[1])) else _t = DataTypes.FLOAT; break; case 'double': if(type.length > 1 && !isNaN(type[1])) if(type.length > 2 && !isNaN(type[2])) _t = DataTypes.FLOAT(parseInt(type[1]),parseInt(type[2])) else _t = DataTypes.FLOAT(parseInt(type[1])) else _t = DataTypes.FLOAT; break; case 'decimal': if(type.length > 1 && !isNaN(type[1])) if(type.length > 2 && !isNaN(type[2])) return DataTypes.FLOAT(parseInt(type[1]),parseInt(type[2])) else return DataTypes.FLOAT(parseInt(type[1])) else return DataTypes.FLOAT; case 'varchar': if(type.length > 1 && !isNaN(type[1])) if(type.length > 2 && !isNaN(type[2])) return DataTypes.STRING(parseInt(type[1]),parseInt(type[2])) else return DataTypes.STRING(parseInt(type[1])) else return DataTypes.STRING; case 'text': return DataTypes.TEXT; case 'blob': return DataTypes.BLOB; case 'json': return DataTypes.JSON; case 'jsonb': return DataTypes.JSONB; default: return DataTypes.STRING; } // check unsigned for int, bigint, double, float if (_t && type.includes('unsigned')) return _t.UNSIGNED; else return _t; } } module.exports = Attribute const Database = require('./database') const Relation = require('./relation') const Table = require('./table')