From 912b7a20454c06ad63add61c25261f0b294e9446 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Hyyti=C3=A4l=C3=A4?= Date: Thu, 4 May 2017 18:06:17 +0300 Subject: [PATCH 1/3] feat(storages): pass only storageOptions to storage constructor Change Storage constructor to accept only storageOptions passed to Umzug constructor. In addition, try to figure out if created storage doesn't support this and use old format as fallback. Old style will be dropped in some major version in future, probably in version 3. This affetcs to all custom storages. DEPRECATED: - Storage constructors doesn't accept options that contains storageOptions any more. They accept only storageOptions directly. ```diff - let storage = new Storage(this.options) + let storage = new Storage(this.options.storageOptions) ``` --- src/index.js | 13 ++- src/storages/json.js | 24 ++--- src/storages/none.js | 8 -- src/storages/sequelize.js | 91 +++++++++-------- test/storages/json.test.js | 16 +-- test/storages/sequelize.test.js | 171 ++++++++++++-------------------- 6 files changed, 135 insertions(+), 188 deletions(-) diff --git a/src/index.js b/src/index.js index 47138baf..036996a4 100644 --- a/src/index.js +++ b/src/index.js @@ -407,7 +407,18 @@ module.exports = class Umzug extends EventEmitter { throw new Error('Unable to resolve the storage: ' + this.options.storage + ', ' + e); } - return new Storage(this.options); + let storage = new Storage(this.options.storageOptions); + if (_.has(storage, 'options.storageOptions')) { + console.warn( + 'Deprecated: Umzug Storage constructor has changed!', + 'old syntax: new Storage({ storageOptions: { ... } })', + 'new syntax: new Storage({ ... })', + 'where ... represents the same storageOptions passed to Umzug constructor.' + ); + storage = new Storage(this.options); + } + + return storage; } /** diff --git a/src/storages/json.js b/src/storages/json.js index 8375d359..09f72a4b 100644 --- a/src/storages/json.js +++ b/src/storages/json.js @@ -1,7 +1,7 @@ import _ from 'lodash'; import Bluebird from 'bluebird'; import fs from 'fs'; -import path from 'path'; +import _path from 'path'; /** * @class JSONStorage @@ -11,19 +11,11 @@ module.exports = class JSONStorage { * Constructs JSON file storage. * * @param {Object} [options] - * @param {Object} [options.storageOptions] - * @param {String} [options.storageOptions.path='./umzug.json'] - Path to JSON - * file where the log is stored. Defaults './umzug.json' relative to process' - * cwd. - * @constructs JSONStorage + * @param {String} [options.path='./umzug.json'] - Path to JSON file where + * the log is stored. Defaults './umzug.json' relative to process' cwd. */ - constructor(options = {}) { - this.options = options; - - this.options.storageOptions = { - path: path.resolve(process.cwd(), 'umzug.json'), - ...this.options.storageOptions || {}, - }; + constructor({ path = _path.resolve(process.cwd(), 'umzug.json') } = {}) { + this.path = path; } /** @@ -33,7 +25,7 @@ module.exports = class JSONStorage { * @returns {Promise} */ logMigration(migrationName) { - var filePath = this.options.storageOptions.path; + var filePath = this.path; var readfile = Bluebird.promisify(fs.readFile); var writefile = Bluebird.promisify(fs.writeFile); @@ -53,7 +45,7 @@ module.exports = class JSONStorage { * @returns {Promise} */ unlogMigration(migrationName) { - var filePath = this.options.storageOptions.path; + var filePath = this.path; var readfile = Bluebird.promisify(fs.readFile); var writefile = Bluebird.promisify(fs.writeFile); @@ -72,7 +64,7 @@ module.exports = class JSONStorage { * @returns {Promise.} */ executed() { - var filePath = this.options.storageOptions.path; + var filePath = this.path; var readfile = Bluebird.promisify(fs.readFile); return readfile(filePath) diff --git a/src/storages/none.js b/src/storages/none.js index 29eafa15..386c53bc 100644 --- a/src/storages/none.js +++ b/src/storages/none.js @@ -4,14 +4,6 @@ import Bluebird from 'bluebird'; * @class NoneStorage */ module.exports = class NoneStorage { - /** - * Constructs none storage. - * - * @param {Object} [options] - * @constructs NoneStorage - */ - constructor(options) {} - /** * Does nothing. * diff --git a/src/storages/sequelize.js b/src/storages/sequelize.js index 54ed8f42..29153844 100644 --- a/src/storages/sequelize.js +++ b/src/storages/sequelize.js @@ -42,54 +42,57 @@ module.exports = class SequelizeStorage { * * @constructs SequelizeStorage */ - constructor(options = {}) { - this.options = options; - this.options.storageOptions = { - // note 'sequelize' or 'model' is required - modelName: 'SequelizeMeta', - // note 'tableName' (optional) also supported - columnName: 'name', - timestamps: false, - ...this.options.storageOptions || {}, - }; - - if (!this.options.storageOptions.model && !this.options.storageOptions.sequelize) { + constructor({ + sequelize, + model, + modelName = 'SequelizeMeta', + tableName, + schema, + columnName = 'name', + columnType, + timestamps = false + } = {}) { + if (!model && !sequelize) { throw new Error('One of "sequelize" or "model" storage option is required'); } - // initialize model - if (!this.options.storageOptions.model) { - var sequelize = this.options.storageOptions.sequelize; - var modelName = this.options.storageOptions.modelName; - var Sequelize = sequelize.constructor; - var columnType = this.options.storageOptions.columnType || Sequelize.STRING; + this.sequelize = sequelize || model.sequelize; + + const Sequelize = this.sequelize.constructor; - if (sequelize.isDefined(modelName)) { - this.options.storageOptions.model = sequelize.model(modelName); - } else { - var attributes = {}; + this.columnType = columnType || Sequelize.STRING; + this.columnName = columnName; + this.timestamps = timestamps; + this.modelName = modelName; + this.tableName = tableName; + this.schema = schema; + this.model = model || this.getModel(); + } - attributes[this.options.storageOptions.columnName] = { - type: columnType, + getModel() { + if (this.sequelize.isDefined(this.modelName)) { + return this.sequelize.model(this.modelName); + } + + return this.sequelize.define( + this.modelName, + { + [this.columnName]: { + type: this.columnType, allowNull: false, unique: true, primaryKey: true, autoIncrement: false - }; - - this.options.storageOptions.model = sequelize.define( - modelName, - attributes, - { - tableName: this.options.storageOptions.tableName, - schema: this.options.storageOptions.schema, - timestamps: this.options.storageOptions.timestamps, - charset: 'utf8', - collate: 'utf8_unicode_ci' - } - ); + }, + }, + { + tableName: this.tableName, + schema: this.schema, + timestamps: this.timestamps, + charset: 'utf8', + collate: 'utf8_unicode_ci' } - } + ); } /** @@ -105,7 +108,7 @@ module.exports = class SequelizeStorage { .sync() .then(function(Model) { var migration = {}; - migration[self.options.storageOptions.columnName] = migrationName; + migration[self.columnName] = migrationName; return Model.create(migration); }); } @@ -118,14 +121,14 @@ module.exports = class SequelizeStorage { */ unlogMigration(migrationName) { var self = this; - var sequelize = this.options.storageOptions.sequelize; + var sequelize = this.sequelize; var sequelizeVersion = !!sequelize.modelManager ? 2 : 1; return this._model() .sync() .then(function(Model) { var where = {}; - where[self.options.storageOptions.columnName] = migrationName; + where[self.columnName] = migrationName; if (sequelizeVersion > 1) { // This is an ugly hack to find out which function signature we have to use. @@ -147,11 +150,11 @@ module.exports = class SequelizeStorage { return this._model() .sync() .then(function(Model) { - return Model.findAll({ order: [ [ self.options.storageOptions.columnName, 'ASC' ] ] }); + return Model.findAll({ order: [ [ self.columnName, 'ASC' ] ] }); }) .then(function(migrations) { return migrations.map(function(migration) { - return migration[self.options.storageOptions.columnName]; + return migration[self.columnName]; }); }); } @@ -163,6 +166,6 @@ module.exports = class SequelizeStorage { * @private */ _model() { - return this.options.storageOptions.model; + return this.model; } } diff --git a/test/storages/json.test.js b/test/storages/json.test.js index aec5361e..6442fc74 100644 --- a/test/storages/json.test.js +++ b/test/storages/json.test.js @@ -12,12 +12,12 @@ describe('JSON', function () { describe('constructor', function () { it('stores options', function () { var storage = new Storage(); - expect(storage).to.have.property('options'); + expect(storage).to.have.property('path'); }); it('sets the default storage path', function () { var storage = new Storage(); - expect(storage.options.storageOptions.path).to.equal( + expect(storage.path).to.equal( path.normalize(process.cwd() + '/umzug.json') ); }); @@ -26,9 +26,7 @@ describe('JSON', function () { describe('logMigration', function () { beforeEach(function () { this.path = __dirname + '/../tmp/umzug.json'; - this.storage = new Storage({ - storageOptions: { path: this.path } - }); + this.storage = new Storage({ path: this.path }); return helper.prepareMigrations(3); }); @@ -53,9 +51,7 @@ describe('JSON', function () { describe('unlogMigration', function () { beforeEach(function () { this.path = __dirname + '/../tmp/umzug.json'; - this.storage = new Storage({ - storageOptions: { path: this.path } - }); + this.storage = new Storage({ path: this.path }); return helper.prepareMigrations(3); }); @@ -88,9 +84,7 @@ describe('JSON', function () { describe('executed', function () { beforeEach(function () { this.path = __dirname + '/../tmp/umzug.json'; - this.storage = new Storage({ - storageOptions: { path: this.path } - }); + this.storage = new Storage({ path: this.path }); return helper.prepareMigrations(3); }); diff --git a/test/storages/sequelize.test.js b/test/storages/sequelize.test.js index f7854504..ff50bbcf 100644 --- a/test/storages/sequelize.test.js +++ b/test/storages/sequelize.test.js @@ -22,29 +22,22 @@ describe('sequelize', function () { }).to.throw('One of "sequelize" or "model" storage option is required'); }); - it('stores options', function () { - var storage = new Storage({ - storageOptions: { - sequelize: this.sequelize - } - }); - expect(storage).to.have.property('options'); - expect(storage.options).to.have.property('storageOptions'); + it('stores needed options', function () { + var storage = new Storage({ sequelize: this.sequelize }); + expect(storage).to.have.property('sequelize') + expect(storage).to.have.property('model'); + expect(storage).to.have.property('columnName') }); it('accepts a "sequelize" option and creates a model', function () { - var storage = new Storage({ - storageOptions: { - sequelize: this.sequelize - } - }); - expect(storage.options.storageOptions.model).to.equal( + var storage = new Storage({ sequelize: this.sequelize }); + expect(storage.model).to.equal( this.sequelize.model('SequelizeMeta') ); - expect(storage.options.storageOptions.model.getTableName()).to.equal( + expect(storage.model.getTableName()).to.equal( 'SequelizeMeta' ); - return storage.options.storageOptions.model.sync() + return storage.model.sync() .then((model) => { return model.describe(); }) @@ -61,42 +54,36 @@ describe('sequelize', function () { it('accepts a "modelName" option', function () { var storage = new Storage({ - storageOptions: { - sequelize: this.sequelize, - modelName: 'CustomModel' - } + sequelize: this.sequelize, + modelName: 'CustomModel' }); - expect(storage.options.storageOptions.model).to.equal( + expect(storage.model).to.equal( this.sequelize.model('CustomModel') ); - expect(storage.options.storageOptions.model.getTableName()).to.equal( + expect(storage.model.getTableName()).to.equal( 'CustomModels' ); }); it('accepts a "tableName" option', function () { var storage = new Storage({ - storageOptions: { - sequelize: this.sequelize, - tableName: 'CustomTable' - } + sequelize: this.sequelize, + tableName: 'CustomTable' }); - expect(storage.options.storageOptions.model).to.equal( + expect(storage.model).to.equal( this.sequelize.model('SequelizeMeta') ); - expect(storage.options.storageOptions.model.getTableName()).to.equal( + expect(storage.model.getTableName()).to.equal( 'CustomTable' ); }); it('accepts a "columnName" option', function () { var storage = new Storage({ - storageOptions: { - sequelize: this.sequelize, - columnName: 'customColumn' - } + sequelize: this.sequelize, + columnName: 'customColumn' }); - return storage.options.storageOptions.model.sync() + return storage.model.sync() .then((model) => { return model.describe(); }) @@ -107,12 +94,10 @@ describe('sequelize', function () { it('accepts a "timestamps" option', function () { var storage = new Storage({ - storageOptions: { - sequelize: this.sequelize, - timestamps: true - } + sequelize: this.sequelize, + timestamps: true }); - return storage.options.storageOptions.model.sync() + return storage.model.sync() .then((model) => { return model.describe(); }) @@ -123,12 +108,10 @@ describe('sequelize', function () { it('accepts a "columnType" option', function () { var storage = new Storage({ - storageOptions: { - sequelize: this.sequelize, - columnType: new Sequelize.STRING(190) - } + sequelize: this.sequelize, + columnType: new Sequelize.STRING(190) }); - return storage.options.storageOptions.model.sync() + return storage.model.sync() .then((model) => { return model.describe(); }) @@ -153,23 +136,19 @@ describe('sequelize', function () { }); var storage = new Storage({ - storageOptions: { - model: Model - } + model: Model }); - expect(storage.options.storageOptions.model).to.equal(Model); + expect(storage.model).to.equal(Model); }); }); describe('logMigration', function () { it('creates the table if it doesn\'t exist yet', function () { var storage = new Storage({ - storageOptions: { - sequelize: this.sequelize - } + sequelize: this.sequelize }); - return storage.options.storageOptions.model.sequelize.getQueryInterface().showAllTables() + return storage.model.sequelize.getQueryInterface().showAllTables() .then((allTables) => { expect(allTables).to.be.empty; }) @@ -177,7 +156,7 @@ describe('sequelize', function () { return storage.logMigration('asd.js'); }) .then(() => { - return storage.options.storageOptions.model.sequelize.getQueryInterface().showAllTables(); + return storage.model.sequelize.getQueryInterface().showAllTables(); }) .then((allTables) => { expect(allTables).to.eql(['SequelizeMeta']); @@ -186,14 +165,12 @@ describe('sequelize', function () { it('writes the migration to the database', function () { var storage = new Storage({ - storageOptions: { - sequelize: this.sequelize - } + sequelize: this.sequelize }); return storage.logMigration('asd.js') .then(() => { - return storage.options.storageOptions.model.findAll(); + return storage.model.findAll(); }) .then((migrations) => { expect(migrations.length).to.be.eql(1); @@ -203,15 +180,13 @@ describe('sequelize', function () { it('writes the migration to the database with a custom column name', function () { var storage = new Storage({ - storageOptions: { - sequelize: this.sequelize, - columnName: 'customColumnName' - } + sequelize: this.sequelize, + columnName: 'customColumnName' }); return storage.logMigration('asd.js') .then(() => { - return storage.options.storageOptions.model.findAll(); + return storage.model.findAll(); }) .then((migrations) => { expect(migrations.length).to.be.eql(1); @@ -221,10 +196,8 @@ describe('sequelize', function () { it('writes the migration to the database with timestamps', function () { var storage = new Storage({ - storageOptions: { - sequelize: this.sequelize, - timestamps: true - } + sequelize: this.sequelize, + timestamps: true }); // Sequelize | startTime | createdAt | endTime @@ -237,7 +210,7 @@ describe('sequelize', function () { return storage.logMigration('asd.js') .then(() => { - return storage.options.storageOptions.model.findAll(); + return storage.model.findAll(); }) .then((migrations) => { expect(migrations.length).to.be.eql(1); @@ -249,11 +222,9 @@ describe('sequelize', function () { describe('unlogMigration', function () { it('creates the table if it doesn\'t exist yet', function () { - var storage = new Storage({ - storageOptions: { sequelize: this.sequelize } - }); + var storage = new Storage({ sequelize: this.sequelize }); - return storage.options.storageOptions.model.sequelize.getQueryInterface().showAllTables() + return storage.model.sequelize.getQueryInterface().showAllTables() .then((allTables) => { expect(allTables).to.be.empty; }) @@ -261,7 +232,7 @@ describe('sequelize', function () { return storage.unlogMigration('asd.js'); }) .then(() => { - return storage.options.storageOptions.model.sequelize.getQueryInterface().showAllTables(); + return storage.model.sequelize.getQueryInterface().showAllTables(); }) .then((allTables) => { expect(allTables).to.eql(['SequelizeMeta']); @@ -269,13 +240,11 @@ describe('sequelize', function () { }); it('deletes the migration from the database', function () { - var storage = new Storage({ - storageOptions: { sequelize: this.sequelize } - }); + var storage = new Storage({ sequelize: this.sequelize }); return storage.logMigration('asd.js') .then(() => { - return storage.options.storageOptions.model.findAll(); + return storage.model.findAll(); }) .then((migrations) => { expect(migrations.length).to.be.eql(1); @@ -284,7 +253,7 @@ describe('sequelize', function () { return storage.unlogMigration('asd.js'); }) .then(() => { - return storage.options.storageOptions.model.findAll(); + return storage.model.findAll(); }) .then((migrations) => { expect(migrations).to.be.empty; @@ -292,7 +261,7 @@ describe('sequelize', function () { }); it('deletes only the passed migration', function () { - var storage = new Storage({ storageOptions: { sequelize: this.sequelize } }); + var storage = new Storage({ sequelize: this.sequelize }); return storage.logMigration('migration1.js') .then(() => { return storage.logMigration('migration2.js'); }) @@ -306,15 +275,13 @@ describe('sequelize', function () { it('deletes the migration from the database with a custom column name', function () { var storage = new Storage({ - storageOptions: { - sequelize: this.sequelize, - columnName: 'customColumnName' - } + sequelize: this.sequelize, + columnName: 'customColumnName' }); return storage.logMigration('asd.js') .then(() => { - return storage.options.storageOptions.model.findAll(); + return storage.model.findAll(); }) .then((migrations) => { expect(migrations.length).to.be.eql(1); @@ -323,7 +290,7 @@ describe('sequelize', function () { return storage.unlogMigration('asd.js'); }) .then(() => { - return storage.options.storageOptions.model.findAll(); + return storage.model.findAll(); }) .then((migrations) => { expect(migrations).to.be.empty; @@ -332,15 +299,13 @@ describe('sequelize', function () { it('deletes the migration from the database with timestamps', function () { var storage = new Storage({ - storageOptions: { - sequelize: this.sequelize, - timestamps: true - } + sequelize: this.sequelize, + timestamps: true }); return storage.logMigration('asd.js') .then(() => { - return storage.options.storageOptions.model.findAll(); + return storage.model.findAll(); }) .then((migrations) => { expect(migrations.length).to.be.eql(1); @@ -349,7 +314,7 @@ describe('sequelize', function () { return storage.unlogMigration('asd.js'); }) .then(() => { - return storage.options.storageOptions.model.findAll(); + return storage.model.findAll(); }) .then((migrations) => { expect(migrations).to.be.empty; @@ -361,12 +326,10 @@ describe('sequelize', function () { describe('executed', function () { it('creates the table if it doesn\'t exist yet', function () { var storage = new Storage({ - storageOptions: { - sequelize: this.sequelize - } + sequelize: this.sequelize }); - return storage.options.storageOptions.model.sequelize.getQueryInterface().showAllTables() + return storage.model.sequelize.getQueryInterface().showAllTables() .then((allTables) => { expect(allTables).to.be.empty; }) @@ -374,7 +337,7 @@ describe('sequelize', function () { return storage.executed(); }) .then(() => { - return storage.options.storageOptions.model.sequelize.getQueryInterface().showAllTables(); + return storage.model.sequelize.getQueryInterface().showAllTables(); }) .then((allTables) => { expect(allTables).to.eql(['SequelizeMeta']); @@ -383,9 +346,7 @@ describe('sequelize', function () { it('returns an empty array if no migrations were logged yet', function () { var storage = new Storage({ - storageOptions: { - sequelize: this.sequelize - } + sequelize: this.sequelize }); return storage.executed() @@ -396,9 +357,7 @@ describe('sequelize', function () { it('returns executed migrations', function () { var storage = new Storage({ - storageOptions: { - sequelize: this.sequelize - } + sequelize: this.sequelize }); return storage.logMigration('asd.js') @@ -412,10 +371,8 @@ describe('sequelize', function () { it('returns executed migrations with a custom column name', function () { var storage = new Storage({ - storageOptions: { - sequelize: this.sequelize, - columnName: 'customColumnName' - } + sequelize: this.sequelize, + columnName: 'customColumnName' }); return storage.logMigration('asd.js') @@ -429,10 +386,8 @@ describe('sequelize', function () { it('returns executed migrations with timestamps', function () { var storage = new Storage({ - storageOptions: { - sequelize: this.sequelize, - timestamps: true - } + sequelize: this.sequelize, + timestamps: true }); return storage.logMigration('asd.js') From 6b3d7998234dc6fe54e56f035855483bb5c91905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Hyyti=C3=A4l=C3=A4?= Date: Thu, 4 May 2017 19:22:20 +0300 Subject: [PATCH 2/3] feat(storages): add link to deprecation warning --- src/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index 036996a4..fd5a63ba 100644 --- a/src/index.js +++ b/src/index.js @@ -413,7 +413,8 @@ module.exports = class Umzug extends EventEmitter { 'Deprecated: Umzug Storage constructor has changed!', 'old syntax: new Storage({ storageOptions: { ... } })', 'new syntax: new Storage({ ... })', - 'where ... represents the same storageOptions passed to Umzug constructor.' + 'where ... represents the same storageOptions passed to Umzug constructor.', + 'For more information: https://github.com/sequelize/umzug/pull/137' ); storage = new Storage(this.options); } From b6dac257c4934083bb6accf90207f0e6e59a0ebd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Hyyti=C3=A4l=C3=A4?= Date: Thu, 4 May 2017 19:38:31 +0300 Subject: [PATCH 3/3] docs(storages): update docs to match new Storage API --- README.md | 7 ++----- src/storages/sequelize.js | 35 +++++++++++++++-------------------- 2 files changed, 17 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index a739e3ee..2b1b1dff 100644 --- a/README.md +++ b/README.md @@ -91,11 +91,8 @@ var Bluebird = require('bluebird'); var redefine = require('redefine'); module.exports = redefine.Class({ - constructor: function (options) { - this.options = options; - this.options.storageOptions = _.extend({ - option1: 'defaultValue1' - }, this.options.storageOptions) + constructor: function ({ option1: 'defaultValue1' } = {}) { + this.option1 = option1; }, logMigration: function (migrationName) { diff --git a/src/storages/sequelize.js b/src/storages/sequelize.js index 29153844..34a8e257 100644 --- a/src/storages/sequelize.js +++ b/src/storages/sequelize.js @@ -21,26 +21,21 @@ module.exports = class SequelizeStorage { * If the table does not exist it will be created automatically. * * @param {Object} [options] - * @param {Object} [options.storageOptions] - * @param {Object} [options.storageOptions.sequelize] - configured instance of - * Sequelize. - * @param {Object} [options.storageOptions.model] - Sequelize model - must - * have column name matching "columnName" option. - * @param {String} [options.storageOptions.modelName='SequelizeMeta'] - name - * of model to create if "model" option is not supplied. - * @param {String} [options.storageOptions.tableName=modelName] - name of - * table to create if "model" option is not supplied. - * @param {String} [options.storageOptions.schema=schema] - name of the schema - * to create the table under, defaults to undefined. - * @param {String} [options.storageOptions.columnName='name'] - name of table - * column holding migration name. - * @param {String} [options.storageOptions.columnType=Sequelize.STRING] - type - * of the column. For utf8mb4 charsets under InnoDB, you may need to set - * this <= 190. - * @param {Boolean} [options.storageOptions.timestamps=false] - option to add - * timestamps to model table - * - * @constructs SequelizeStorage + * @param {Object} [options.] + * @param {Object} [options.sequelize] - configured instance of Sequelize. + * @param {Object} [options.model] - Sequelize model - must have column name + * matching "columnName" option. + * @param {String} [options.modelName='SequelizeMeta'] - name of the model + * to create if "model" option is not supplied. + * @param {String} [options.tableName=modelName] - name of the table to create + * if "model" option is not supplied. + * @param {String} [options.schema=schema] - name of the schema to create + * the table under, defaults to undefined. + * @param {String} [options.columnName='name'] - name of the table column + * holding migration name. + * @param {String} [options.columnType=Sequelize.STRING] - type of the column. + * For utf8mb4 charsets under InnoDB, you may need to set this <= 190. + * @param {Boolean} [options.timestamps=false] - option to add timestamps to the model table */ constructor({ sequelize,