Last active
December 21, 2018 07:12
-
-
Save paulmowat/1999c07a10f068d11d8bc7614d214c4e to your computer and use it in GitHub Desktop.
Sequelize Migration Generator from Models
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// //////////////////////////////// | |
// How to use? | |
// 1. Make sure you've ran the `sequelize init` before (It should create `config`,`seeders`,`migrations` folders). | |
// 2. Run it with `node sequelize-schema-file-generator.js` | |
// 3. Review the generated migrations inside of the `migrations` folder. | |
// //////////////////////////////// | |
/* jscs:disable */ | |
/* jshint ignore:start */ | |
var path = require('path') | |
var models = require(path.join(__dirname, '/models')).sequelize.models | |
var Sequelize = require('sequelize') | |
var fs = require('fs') | |
// Logger | |
var logger = require(path.join(__dirname, '../', 'lib/log/logger')) | |
delete models.default | |
var env = require(path.join(__dirname, '/../config/config')).env | |
var config = require(path.join(__dirname, '/../config/dbconfig'))[env] | |
var sequelize = {} | |
if (config.use_env_variable) { | |
sequelize = new Sequelize(process.env[config.use_env_variable]) | |
} else { | |
sequelize = new Sequelize(config.database, config.username, config.password, config) | |
} | |
// fix date for all files | |
const d = new Date(2017, 8, 16, 22, 18, 57) | |
// The priority is to create first tables that others by restriction to create an association first, before the table is created. | |
// is write in name of file migration. example : 201703291645-01-user.js this file run first that 201703291645-02-user-grant.js | |
for (const model in models) { // jshint ignore:line | |
if (models.hasOwnProperty(model)) { | |
process.stdout.write(models[model].name + 'Singular=' + models[model].options.name.singular + ' Plural=' + models[model].options.name.plural) | |
var priority = '00' | |
const attributes = models[model].attributes | |
priority = setPriority(attributes, model) | |
process.stdout.write(' Priority=' + priority) | |
var processedattributes = processAttributes(attributes) | |
var schema = JSON.stringify(processedattributes, null, 2) | |
schema = schema.replace(/"([^"]+)":/g, '$1:') | |
schema = schema.replace(/"Sequelize([^"]+)"/g, 'Sequelize$1') | |
schema = schema.replace(/["]+/g, '\'') | |
const tableName = models[model].tableName | |
var indexes = buildIndexes(models, model, tableName) | |
schema = schema.split('\n').map((line) => ' ' + line).join('\n') | |
// with respect original file remove return queryInterface.sequelize.query('SET FOREIGN_KEY_CHECKS = 0') | |
// and return queryInterface.sequelize.query('SET FOREIGN_KEY_CHECKS = 1') because postgres dont work only for mysql | |
const template = `'use strict' | |
module.exports = { | |
up: function (queryInterface, Sequelize) { | |
return queryInterface.createTable('${tableName}', | |
${schema})${indexes.join('\n')} | |
}, | |
down: function (queryInterface, Sequelize) { | |
return queryInterface.dropTable('${tableName}') | |
} | |
} | |
` | |
const filename = [d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds()] | |
.map((num) => (num <= 60 && (num + 100).toString().substring(1)) || num) | |
.join('') + `-` + priority + `-${models[model].tableName}` | |
fs.writeFileSync(path.join(__dirname, `/migrations/${filename}.js`), template) | |
process.stdout.write(' Migration=' + filename + '.js\n') | |
} | |
} | |
logger.debug('Completed') | |
process.exit(0) | |
function processAttributes (attributes) { | |
for (const column in attributes) { | |
if (attributes.hasOwnProperty(column)) { | |
delete attributes[column].Model | |
delete attributes[column].fieldName | |
delete attributes[column].field | |
attributes = processAttributesColumnProperty(attributes, column) | |
if (typeof attributes[column]['type'] !== 'undefined') { | |
attributes = processAttributesColumnTypeOptions(attributes, column) | |
attributes = processAttributesColumnType(attributes, column) | |
} | |
if (typeof attributes[column]['defaultValue'] !== 'undefined') { | |
attributes = processAttributesDefaultValue(attributes, column) | |
} | |
} | |
} | |
return attributes | |
} | |
function processAttributesColumnProperty (attributes, column) { | |
for (const property in attributes[column]) { | |
if (property.startsWith('_')) { | |
delete attributes[column][property] | |
} | |
} | |
return attributes | |
} | |
function processAttributesColumnTypeOptions (attributes, column) { | |
if (typeof attributes[column]['type']['options'] !== 'undefined' && typeof attributes[column]['type']['options'].toString === 'function') { | |
attributes[column]['type']['options'] = attributes[column]['type']['options'].toString(sequelize) | |
} | |
return attributes | |
} | |
function processAttributesColumnType (attributes, column) { | |
if (typeof attributes[column]['type'].toString === 'function') { | |
if (attributes[column].type.key === 'DOUBLE PRECISION') { | |
attributes[column]['type'] = 'Sequelize.DOUBLE' | |
} else { | |
attributes[column]['type'] = 'Sequelize.' + attributes[column].type.key | |
} | |
} | |
return attributes | |
} | |
function processAttributesDefaultValue (attributes, column) { | |
if (attributes[column].defaultValue !== null) { | |
if (attributes[column].defaultValue.key === 'UUIDV4') { | |
attributes[column]['defaultValue'] = 'Sequelize.UUIDV4' | |
} | |
} | |
return attributes | |
} | |
function setPriority (attributes, model) { | |
var priority = '00' | |
// put all tables with reference 2nd | |
for (const column in attributes) { | |
if ((attributes.hasOwnProperty(column)) && (models[model].attributes[column].references !== undefined)) { | |
priority = '01' | |
break | |
} | |
} | |
// handle tables that need to be defined later | |
if (['authaccesstoken', 'authrefreshtoken', 'passwordemailtoken', 'userpasswordhistory', 'bankaccount', 'dsconfig', 'fmsagreementtype', 'fmsbudgetaccount', 'fmscommitmenttype', 'fmsdocument', 'layout', | |
'userdataversion'].includes(models[model].options.name.singular)) { | |
priority = '02' | |
} else if (['databankbalance', 'datasummary', 'dsconfigstat', 'datatransaction', 'dsagreementtype', 'dsbudgetmodel', 'dsbudgetaccount', 'dsbudgetparameter', 'dscommitmenttype', | |
'dscompany', 'dsdocument', 'dsledger', 'dstransactiontype', 'layoutdetail', 'userdatarevision', 'pendingimport' | |
].includes(models[model].options.name.singular)) { | |
priority = '03' | |
} else if (['userdatastate', 'userdatasummary' | |
].includes(models[model].options.name.singular)) { | |
priority = '04' | |
} | |
return priority | |
} | |
function buildIndexes (models, model, tableName) { | |
const indexes = [] | |
// any indexes? | |
if (models[model].options.indexes.length) { | |
indexes.push('\n') | |
for (var index = 0; index <= models[model].options.indexes.length - 1; index++) { | |
var obj = models[model].options.indexes[index] | |
indexes.push(' .then(() => {') | |
indexes.push(' return queryInterface.addIndex(') | |
indexes.push(` '${tableName}',`) | |
const opts = {} | |
if (obj.name) { | |
opts.indexName = obj.name | |
} | |
if (obj.unique === true) { | |
opts.indicesType = 'UNIQUE' | |
} | |
if (obj.method === true) { | |
opts.indexType = obj.method | |
} | |
if (Object.keys(opts).length) { | |
indexes.push(` ['${obj.fields.join("', '")}'],`) | |
// Deals with using single quotes to match our standards | |
var indexString = JSON.stringify(opts) | |
indexString = indexString.replace(/"/g, '\'') | |
indexString = indexString.replace(/:/g, ': ') | |
indexes.push(` ${indexString}`) | |
} else { | |
indexes.push(` ['${obj.fields.join("', '")}']`) | |
} | |
indexes.push(' )') | |
if (index === (models[model].options.indexes.length - 1)) { | |
indexes.push(' })') | |
} else { | |
indexes.push(' })') | |
} | |
} | |
} else { | |
indexes.push('') | |
} | |
return indexes | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment