Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save jgeewax/e9e6ffa3a3b260da2b2879ecebe1e879 to your computer and use it in GitHub Desktop.
Save jgeewax/e9e6ffa3a3b260da2b2879ecebe1e879 to your computer and use it in GitHub Desktop.
Automatically generates migration files from your sequelize models
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