Forked from manuelbieh/sequelize-schema-file-generator.js
Last active
August 24, 2016 14:16
-
-
Save jgeewax/e9e6ffa3a3b260da2b2879ecebe1e879 to your computer and use it in GitHub Desktop.
Automatically generates migration files from your sequelize 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
import fs from 'fs'; | |
import { js_beautify as beautify } from 'js-beautify'; | |
import Sequelize from 'sequelize'; | |
import * as models from "../models"; | |
const sequelize = new Sequelize({ | |
host: '', | |
port: '', | |
database: '', | |
username: '', | |
password: '', | |
dialect: 'mysql', | |
}); | |
const indent_size = 2; | |
function toJson (value) { | |
let result = JSON.stringify(value, null, indent_size); | |
// If it's an object, take quotes off the properties. | |
if (value === Object(value)) { | |
result = result.replace(/\"([^(\")"]+)\":/g,"$1:"); | |
} | |
return result; | |
} | |
class Migration { | |
constructor(model) { | |
if (!(model instanceof Sequelize.Model)) | |
throw new TypeError('Invalid model'); | |
this.model = model; | |
} | |
get tableName() { | |
return this.model.tableName; | |
} | |
toString () { | |
let table = this.model.tableName; | |
let schema = this.getParsedColumns(); | |
let indexes = this.getParsedIndexes(); | |
let template = ` | |
'use strict'; | |
module.exports = { | |
up: function(queryInterface, Sequelize) { | |
return queryInterface.sequelize.query("SET FOREIGN_KEY_CHECKS = 0") | |
.then(() => { | |
return queryInterface.createTable(${toJson(table)}, | |
${toJson(schema)}) | |
})${indexes.map((index) => { | |
let params = [table, index.fields, index.options]; | |
return `.then(() => { | |
return queryInterface.addIndex(${params.map(toJson).join(', ')}); | |
})`; | |
}).reduce((prev, cur) => { | |
// We use this instead of .join('\n') due to always wanting a first | |
// newline (join doesn't have a leading newline). | |
return prev + '\n' + cur; | |
}, '')} | |
.then(() => { | |
return queryInterface.sequelize.query( | |
"SET FOREIGN_KEY_CHECKS = 1"); | |
}); | |
}, | |
down: function(queryInterface, Sequelize) { | |
return queryInterface.sequelize.query("SET FOREIGN_KEY_CHECKS = 0") | |
.then(() => { | |
return queryInterface.dropTable(${toJson(table)}"); | |
}) | |
.then(() => { | |
return queryInterface.sequelize.query( | |
"SET FOREIGN_KEY_CHECKS = 1"); | |
}); | |
} | |
};` | |
return beautify(template, { indent_size }); | |
} | |
getParsedColumns() { | |
const extraFields = ['Model', 'fieldName', 'field']; | |
let attributes = this.model.attributes; | |
let parsedColumns = {}; | |
for (let [columnName, column] of Object.entries(attributes)) { | |
let parsedColumn = {}; | |
// If there's no type defined, we can't do anything here. | |
if (column.type === undefined) continue; | |
// Only keep propeties that we need. | |
for (let [k, v] of Object.entries(column)) { | |
if (!k.startsWith('_') && !extraFields.includes(k)) { | |
parsedColumn[k] = v; | |
} | |
} | |
// Deal with type (it's special). | |
if (column.type.options !== undefined) | |
column.type.options = column.type.options.toString(sequelize); | |
parsedColumn.type = column.type.toString(); | |
// Add the parsed column to the map. | |
parsedColumns[columnName] = parsedColumn; | |
} | |
return parsedColumns; | |
} | |
getParsedIndexes() { | |
let parsedIndexes = []; | |
let indexes = this.model.options.indexes; | |
for (let index of indexes) { | |
let parsedIndex = { fields: index.fields }; | |
let options = {}; | |
if (index.name) options.indexName = index.name; | |
if (index.unique === true) options.indicesType = 'UNIQUE'; | |
if (index.indexType || index.method) | |
options.using = index.indexType || index.method; | |
if (index.prefix) options.prefix = index.prefix; | |
if (Object.keys(options).length) | |
parsedIndex.options = options; | |
parsedIndexes.push(parsedIndex); | |
} | |
return parsedIndexes; | |
} | |
} | |
for(let model in models) { | |
if (!(models[model] instanceof Sequelize.Model)) continue; | |
let m = new Migration(models[model]); | |
console.log('\n\n--\nmigration is: ', m.toString()); | |
break; | |
let d = new Date(); | |
let filename = [d.getFullYear(), d.getMonth()+1, d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds()] | |
.map((num) => num <= 60 && (num + 100).toString().substring(1) || num) | |
.join('') + `-${models[model].tableName}`; | |
console.log(beautify(template, { indent_size })); | |
break; | |
//fs.writeFileSync(`./${filename}.js`, template); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment