Comparing version 2.2.0 to 2.3.0
@@ -0,0 +0,0 @@ { |
# Change Log | ||
All notable changes to this project will be documented in this file. | ||
## v2.3.0 - 2020-03-22 | ||
### Added | ||
- `migrationsList` helper to easily build a valid list of migrations | ||
[#199](https://github.com/sequelize/umzug/pull/199) | ||
### Changed | ||
- Documentation updates | ||
[#198](https://github.com/sequelize/umzug/pull/198) | ||
- Updated dependencies | ||
[#203](https://github.com/sequelize/umzug/pull/203) | ||
- Configure babel to not rely on babel-runtime | ||
[#202](https://github.com/sequelize/umzug/pull/202) | ||
- Skip logging non-migration files | ||
[#190](https://github.com/sequelize/umzug/pull/190) | ||
## v2.2.0 - 2018-11-18 | ||
@@ -5,0 +21,0 @@ |
@@ -15,3 +15,5 @@ "use strict"; | ||
try { | ||
result = require.resolve(packageName, { basedir: process.cwd() }); | ||
result = require.resolve(packageName, { | ||
basedir: process.cwd() | ||
}); | ||
result = require(result); | ||
@@ -18,0 +20,0 @@ } catch (e) { |
205
lib/index.js
@@ -1,47 +0,31 @@ | ||
'use strict'; | ||
"use strict"; | ||
var _keys = require('babel-runtime/core-js/object/keys'); | ||
var _bluebird = _interopRequireDefault(require("bluebird")); | ||
var _keys2 = _interopRequireDefault(_keys); | ||
var _fs = _interopRequireDefault(require("fs")); | ||
var _extends2 = require('babel-runtime/helpers/extends'); | ||
var _migration2 = _interopRequireDefault(require("./migration")); | ||
var _extends3 = _interopRequireDefault(_extends2); | ||
var _path = _interopRequireDefault(require("path")); | ||
var _bluebird = require('bluebird'); | ||
var _events = require("events"); | ||
var _bluebird2 = _interopRequireDefault(_bluebird); | ||
var _migrationsList = _interopRequireDefault(require("./migrationsList")); | ||
var _fs = require('fs'); | ||
var _Storage = _interopRequireDefault(require("./storages/Storage")); | ||
var _fs2 = _interopRequireDefault(_fs); | ||
var _JSONStorage = _interopRequireDefault(require("./storages/JSONStorage")); | ||
var _migration2 = require('./migration'); | ||
var _MongoDBStorage = _interopRequireDefault(require("./storages/MongoDBStorage")); | ||
var _migration3 = _interopRequireDefault(_migration2); | ||
var _SequelizeStorage = _interopRequireDefault(require("./storages/SequelizeStorage")); | ||
var _path = require('path'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var _path2 = _interopRequireDefault(_path); | ||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } | ||
var _events = require('events'); | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
var _Storage = require('./storages/Storage'); | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
var _Storage2 = _interopRequireDefault(_Storage); | ||
var _JSONStorage = require('./storages/JSONStorage'); | ||
var _JSONStorage2 = _interopRequireDefault(_JSONStorage); | ||
var _MongoDBStorage = require('./storages/MongoDBStorage'); | ||
var _MongoDBStorage2 = _interopRequireDefault(_MongoDBStorage); | ||
var _SequelizeStorage = require('./storages/SequelizeStorage'); | ||
var _SequelizeStorage2 = _interopRequireDefault(_SequelizeStorage); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
/** | ||
@@ -86,4 +70,3 @@ * @class Umzug | ||
super(); | ||
this.options = (0, _extends3.default)({ | ||
this.options = _objectSpread({ | ||
storage: 'json', | ||
@@ -101,5 +84,5 @@ storageOptions: {}, | ||
if (!Array.isArray(this.options.migrations)) { | ||
this.options.migrations = (0, _extends3.default)({ | ||
this.options.migrations = _objectSpread({ | ||
params: [], | ||
path: _path2.default.resolve(process.cwd(), 'migrations'), | ||
path: _path.default.resolve(process.cwd(), 'migrations'), | ||
pattern: /^\d+[\w-]+\.js$/, | ||
@@ -113,3 +96,2 @@ traverseDirectories: false, | ||
} | ||
/** | ||
@@ -123,18 +105,19 @@ * Executes given migrations with a given method. | ||
*/ | ||
execute(options = {}) { | ||
const self = this; | ||
options = (0, _extends3.default)({ | ||
options = _objectSpread({ | ||
migrations: [], | ||
method: 'up' | ||
}, options); | ||
return _bluebird.default.map(options.migrations, migration => self._findMigration(migration)).then(migrations => _objectSpread({}, options, { | ||
migrations | ||
})).then(options => _bluebird.default.each(options.migrations, migration => { | ||
const name = _path.default.basename(migration.file, _path.default.extname(migration.file)); | ||
return _bluebird2.default.map(options.migrations, migration => self._findMigration(migration)).then(migrations => (0, _extends3.default)({}, options, { | ||
migrations | ||
})).then(options => _bluebird2.default.each(options.migrations, migration => { | ||
const name = _path2.default.basename(migration.file, _path2.default.extname(migration.file)); | ||
let startTime; | ||
return self._wasExecuted(migration).catch(() => false).then(executed => typeof executed === 'undefined' ? true : executed).tap(executed => { | ||
if (!executed || options.method === 'down') { | ||
const fun = migration[options.method] || _bluebird2.default.resolve; | ||
const fun = migration[options.method] || _bluebird.default.resolve; | ||
let params = self.options.migrations.params; | ||
@@ -155,3 +138,2 @@ | ||
startTime = new Date(); | ||
return fun.apply(migration, params); | ||
@@ -161,8 +143,9 @@ } | ||
if (!executed && options.method === 'up') { | ||
return _bluebird2.default.resolve(self.storage.logMigration(migration.file)); | ||
return _bluebird.default.resolve(self.storage.logMigration(migration.file)); | ||
} else if (options.method === 'down') { | ||
return _bluebird2.default.resolve(self.storage.unlogMigration(migration.file)); | ||
return _bluebird.default.resolve(self.storage.unlogMigration(migration.file)); | ||
} | ||
}).tap(() => { | ||
const duration = ((new Date() - startTime) / 1000).toFixed(3); | ||
if (options.method === 'up') { | ||
@@ -178,3 +161,2 @@ self.log('== ' + name + ': migrated (' + duration + 's)\n'); | ||
} | ||
/** | ||
@@ -185,6 +167,7 @@ * Lists executed migrations. | ||
*/ | ||
executed() { | ||
return _bluebird2.default.resolve(this.storage.executed()).bind(this).map(file => new _migration3.default(file)); | ||
return _bluebird.default.resolve(this.storage.executed()).bind(this).map(file => new _migration2.default(file)); | ||
} | ||
/** | ||
@@ -195,12 +178,12 @@ * Lists pending migrations. | ||
*/ | ||
pending() { | ||
return this._findMigrations().bind(this).then(function (all) { | ||
return _bluebird2.default.join(all, this.executed()); | ||
return _bluebird.default.join(all, this.executed()); | ||
}).spread((all, executed) => { | ||
const executedFiles = executed.map(migration => migration.file); | ||
return all.filter(migration => executedFiles.indexOf(migration.file) === -1); | ||
}); | ||
} | ||
/** | ||
@@ -221,6 +204,7 @@ * Execute migrations up. | ||
*/ | ||
up(options) { | ||
return this._run('up', options, this.pending.bind(this)); | ||
} | ||
/** | ||
@@ -241,2 +225,4 @@ * Execute migrations down. | ||
*/ | ||
down(options) { | ||
@@ -247,5 +233,5 @@ const getExecuted = function () { | ||
if (typeof options === 'undefined' || !(0, _keys2.default)(options).length) { | ||
if (typeof options === 'undefined' || !Object.keys(options).length) { | ||
return getExecuted().bind(this).then(function (migrations) { | ||
return migrations[0] ? this.down(migrations[0].file) : _bluebird2.default.resolve([]); | ||
return migrations[0] ? this.down(migrations[0].file) : _bluebird.default.resolve([]); | ||
}); | ||
@@ -256,3 +242,2 @@ } else { | ||
} | ||
/** | ||
@@ -283,2 +268,4 @@ * Callback function to get migrations in right order. | ||
*/ | ||
_run(method, options, rest) { | ||
@@ -288,3 +275,3 @@ if (typeof options === 'string') { | ||
} else if (Array.isArray(options)) { | ||
return _bluebird2.default.resolve(options).bind(this).map(function (migration) { | ||
return _bluebird.default.resolve(options).bind(this).map(function (migration) { | ||
return this._findMigration(migration); | ||
@@ -294,7 +281,9 @@ }).then(function (migrations) { | ||
}).then(function () { | ||
return this._run(method, { migrations: options }); | ||
return this._run(method, { | ||
migrations: options | ||
}); | ||
}); | ||
} | ||
options = (0, _extends3.default)({ | ||
options = _objectSpread({ | ||
to: null, | ||
@@ -312,3 +301,3 @@ from: null, | ||
return rest().bind(this).then(function (migrations) { | ||
let result = _bluebird2.default.resolve().bind(this); | ||
let result = _bluebird.default.resolve().bind(this); | ||
@@ -325,3 +314,3 @@ if (options.to) { | ||
return result.then(() => _bluebird2.default.resolve(migrations)); | ||
return result.then(() => _bluebird.default.resolve(migrations)); | ||
}).then(function (migrations) { | ||
@@ -336,7 +325,8 @@ if (options.from) { | ||
}).then(function (migrationFiles) { | ||
return this._run(method, { migrations: migrationFiles }); | ||
return this._run(method, { | ||
migrations: migrationFiles | ||
}); | ||
}); | ||
} | ||
} | ||
/** | ||
@@ -353,2 +343,4 @@ * Lists pending/executed migrations depending on method from a given | ||
*/ | ||
_findMigrationsFromMatch(from, method) { | ||
@@ -363,2 +355,3 @@ // We'll fetch all migrations and work our way from start to finish | ||
} | ||
return found; | ||
@@ -383,3 +376,2 @@ }); | ||
} | ||
/** | ||
@@ -390,2 +382,4 @@ * Pass message to logger if logging is enabled. | ||
*/ | ||
log(message) { | ||
@@ -396,3 +390,2 @@ if (this.options.logging) { | ||
} | ||
/** | ||
@@ -404,2 +397,4 @@ * Try to require and initialize storage. | ||
*/ | ||
_initStorage() { | ||
@@ -411,2 +406,3 @@ if (typeof this.options.storage !== 'string') { | ||
let StorageClass; | ||
try { | ||
@@ -419,2 +415,3 @@ StorageClass = this._getStorageClass(); | ||
let storage = new StorageClass(this.options.storageOptions); | ||
if (storage && storage.options && storage.options.storageOptions) { | ||
@@ -431,9 +428,13 @@ 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.', 'For more information: https://github.com/sequelize/umzug/pull/137'); | ||
case 'none': | ||
return _Storage2.default; | ||
return _Storage.default; | ||
case 'json': | ||
return _JSONStorage2.default; | ||
return _JSONStorage.default; | ||
case 'mongodb': | ||
return _MongoDBStorage2.default; | ||
return _MongoDBStorage.default; | ||
case 'sequelize': | ||
return _SequelizeStorage2.default; | ||
return _SequelizeStorage.default; | ||
default: | ||
@@ -443,3 +444,2 @@ return require(this.options.storage); | ||
} | ||
/** | ||
@@ -451,24 +451,31 @@ * Loads all migrations in ascending order. | ||
*/ | ||
_findMigrations(migrationPath) { | ||
if (Array.isArray(this.options.migrations)) { | ||
return _bluebird2.default.resolve(this.options.migrations); | ||
return _bluebird.default.resolve(this.options.migrations); | ||
} | ||
const isRoot = !migrationPath; | ||
if (isRoot) { | ||
migrationPath = this.options.migrations.path; | ||
} | ||
return _bluebird2.default.promisify(_fs2.default.readdir)(migrationPath).bind(this).map(function (file) { | ||
const filePath = _path2.default.resolve(migrationPath, file); | ||
return _bluebird.default.promisify(_fs.default.readdir)(migrationPath).bind(this).map(function (file) { | ||
const filePath = _path.default.resolve(migrationPath, file); | ||
if (this.options.migrations.traverseDirectories) { | ||
if (_fs2.default.lstatSync(filePath).isDirectory()) { | ||
if (_fs.default.lstatSync(filePath).isDirectory()) { | ||
return this._findMigrations(filePath).then(migrations => migrations); | ||
} | ||
} | ||
if (this.options.migrations.pattern.test(file)) { | ||
return new _migration3.default(filePath, this.options); | ||
return new _migration2.default(filePath, this.options); | ||
} | ||
this.log('File: ' + file + ' does not match pattern: ' + this.options.migrations.pattern); | ||
return file; | ||
}).reduce((a, b) => a.concat(b), []) // flatten the result to an array | ||
.filter(file => file instanceof _migration3.default // only care about Migration | ||
.filter(file => file instanceof _migration2.default // only care about Migration | ||
).then(migrations => { | ||
@@ -487,6 +494,6 @@ if (isRoot) { | ||
} | ||
return migrations; | ||
}); | ||
} | ||
/** | ||
@@ -499,2 +506,4 @@ * Gets a migration with a given name. | ||
*/ | ||
_findMigration(needle) { | ||
@@ -505,7 +514,6 @@ return this._findMigrations().then(migrations => migrations.filter(migration => migration.testFileName(needle))[0]).then(migration => { | ||
} else { | ||
return _bluebird2.default.reject(new Error('Unable to find migration: ' + needle)); | ||
return _bluebird.default.reject(new Error('Unable to find migration: ' + needle)); | ||
} | ||
}); | ||
} | ||
/** | ||
@@ -519,12 +527,13 @@ * Checks if migration is executed. It will success if and only if there is | ||
*/ | ||
_wasExecuted(_migration) { | ||
return this.executed().filter(migration => migration.testFileName(_migration.file)).then(migrations => { | ||
if (migrations[0]) { | ||
return _bluebird2.default.resolve(); | ||
return _bluebird.default.resolve(); | ||
} else { | ||
return _bluebird2.default.reject(new Error('Migration was not executed: ' + _migration.file)); | ||
return _bluebird.default.reject(new Error('Migration was not executed: ' + _migration.file)); | ||
} | ||
}); | ||
} | ||
/** | ||
@@ -538,8 +547,9 @@ * Checks if a list of migrations are all executed. It will success if and | ||
*/ | ||
_wereExecuted(migrationNames) { | ||
return _bluebird2.default.resolve(migrationNames).bind(this).map(function (migration) { | ||
return _bluebird.default.resolve(migrationNames).bind(this).map(function (migration) { | ||
return this._wasExecuted(migration); | ||
}); | ||
} | ||
/** | ||
@@ -553,12 +563,13 @@ * Checks if migration is pending. It will success if and only if there is | ||
*/ | ||
_isPending(_migration) { | ||
return this.pending().filter(migration => migration.testFileName(_migration.file)).then(migrations => { | ||
if (migrations[0]) { | ||
return _bluebird2.default.resolve(); | ||
return _bluebird.default.resolve(); | ||
} else { | ||
return _bluebird2.default.reject(new Error('Migration is not pending: ' + _migration.file)); | ||
return _bluebird.default.reject(new Error('Migration is not pending: ' + _migration.file)); | ||
} | ||
}); | ||
} | ||
/** | ||
@@ -572,8 +583,9 @@ * Checks if a list of migrations are all pending. It will success if and only | ||
*/ | ||
_arePending(migrationNames) { | ||
return _bluebird2.default.resolve(migrationNames).bind(this).map(function (migration) { | ||
return _bluebird.default.resolve(migrationNames).bind(this).map(function (migration) { | ||
return this._isPending(migration); | ||
}); | ||
} | ||
/** | ||
@@ -587,4 +599,6 @@ * Skip migrations in a given migration list after `to` migration. | ||
*/ | ||
_findMigrationsUntilMatch(to, migrations) { | ||
return _bluebird2.default.resolve(migrations).map(migration => migration.file).reduce((acc, migration) => { | ||
return _bluebird.default.resolve(migrations).map(migration => migration.file).reduce((acc, migration) => { | ||
if (acc.add) { | ||
@@ -601,4 +615,9 @@ acc.migrations.push(migration); | ||
return acc; | ||
}, { migrations: [], add: true }).get('migrations'); | ||
}, { | ||
migrations: [], | ||
add: true | ||
}).get('migrations'); | ||
} | ||
}; | ||
}; | ||
module.exports.migrationsList = _migrationsList.default; |
@@ -1,17 +0,13 @@ | ||
'use strict'; | ||
"use strict"; | ||
var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator'); | ||
var _path2 = _interopRequireDefault(require("path")); | ||
var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); | ||
var _helper = _interopRequireDefault(require("./helper")); | ||
var _path2 = require('path'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var _path3 = _interopRequireDefault(_path2); | ||
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } | ||
var _helper = require('./helper'); | ||
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } | ||
var _helper2 = _interopRequireDefault(_helper); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
/** | ||
@@ -48,7 +44,6 @@ * @class Migration | ||
constructor(path, options) { | ||
this.path = _path3.default.resolve(path); | ||
this.file = _path3.default.basename(this.path); | ||
this.path = _path2.default.resolve(path); | ||
this.file = _path2.default.basename(this.path); | ||
this.options = options; | ||
} | ||
/** | ||
@@ -62,2 +57,4 @@ * Tries to require migration module. CoffeeScript support requires | ||
*/ | ||
migration() { | ||
@@ -67,11 +64,8 @@ if (typeof this.options.migrations.customResolver === 'function') { | ||
} | ||
if (this.path.match(/\.coffee$/)) { | ||
// 2.x compiler registration | ||
_helper2.default.resolve('coffeescript/register') || | ||
// 1.7.x compiler registration | ||
_helper2.default.resolve('coffee-script/register') || | ||
// Prior to 1.7.x compiler registration | ||
_helper2.default.resolve('coffee-script') || | ||
_helper.default.resolve('coffeescript/register') || // 1.7.x compiler registration | ||
_helper.default.resolve('coffee-script/register') || // Prior to 1.7.x compiler registration | ||
_helper.default.resolve('coffee-script') || | ||
/* jshint expr: true */ | ||
@@ -86,3 +80,2 @@ function () { | ||
} | ||
/** | ||
@@ -93,6 +86,7 @@ * Executes method `up` of migration. | ||
*/ | ||
up() { | ||
return this._exec(this.options.upName, [].slice.apply(arguments)); | ||
} | ||
/** | ||
@@ -103,6 +97,7 @@ * Executes method `down` of migration. | ||
*/ | ||
down() { | ||
return this._exec(this.options.downName, [].slice.apply(arguments)); | ||
} | ||
/** | ||
@@ -113,6 +108,7 @@ * Check if migration file name is starting with needle. | ||
*/ | ||
testFileName(needle) { | ||
return this.file.indexOf(needle) === 0; | ||
} | ||
/** | ||
@@ -126,14 +122,21 @@ * Executes a given method of migration with given arguments. | ||
*/ | ||
_exec(method, args) { | ||
var _this = this; | ||
return (0, _asyncToGenerator3.default)(function* () { | ||
return _asyncToGenerator(function* () { | ||
const migration = yield _this.migration(); | ||
let fun = migration[method]; | ||
if (migration.default) { | ||
fun = migration.default[method] || migration[method]; | ||
} | ||
if (!fun) throw new Error('Could not find migration method: ' + method); | ||
const wrappedFun = _this.options.migrations.wrap(fun); | ||
const result = wrappedFun.apply(migration, args); | ||
if (!result || typeof result.then !== 'function') { | ||
@@ -146,2 +149,3 @@ throw new Error(`Migration ${_this.file} (or wrapper) didn't return a promise`); | ||
} | ||
}; |
@@ -1,11 +0,8 @@ | ||
'use strict'; | ||
"use strict"; | ||
var _JSONStorage = require('./JSONStorage'); | ||
var _JSONStorage = _interopRequireDefault(require("./JSONStorage")); | ||
var _JSONStorage2 = _interopRequireDefault(_JSONStorage); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
module.exports = _JSONStorage2.default; | ||
module.exports = _JSONStorage.default; | ||
console.warn('Deprecated: JSONStorage\'s filename has changed!', 'Use \'umzug/lib/storages/JSONStorage\' instead of \'umzug/lib/storages/json\'', 'For more information: https://github.com/sequelize/umzug/pull/139'); |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,23 +6,12 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.default = void 0; | ||
var _stringify = require('babel-runtime/core-js/json/stringify'); | ||
var _bluebird = _interopRequireDefault(require("bluebird")); | ||
var _stringify2 = _interopRequireDefault(_stringify); | ||
var _fs = _interopRequireDefault(require("fs")); | ||
var _bluebird = require('bluebird'); | ||
var _path2 = _interopRequireDefault(require("path")); | ||
var _bluebird2 = _interopRequireDefault(_bluebird); | ||
var _Storage = _interopRequireDefault(require("./Storage")); | ||
var _fs = require('fs'); | ||
var _fs2 = _interopRequireDefault(_fs); | ||
var _path2 = require('path'); | ||
var _path3 = _interopRequireDefault(_path2); | ||
var _Storage = require('./Storage'); | ||
var _Storage2 = _interopRequireDefault(_Storage); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -33,3 +22,3 @@ | ||
*/ | ||
class JSONStorage extends _Storage2.default { | ||
class JSONStorage extends _Storage.default { | ||
/** | ||
@@ -42,7 +31,8 @@ * Constructs JSON file storage. | ||
*/ | ||
constructor({ path = _path3.default.resolve(process.cwd(), 'umzug.json') } = {}) { | ||
constructor({ | ||
path = _path2.default.resolve(process.cwd(), 'umzug.json') | ||
} = {}) { | ||
super(); | ||
this.path = path; | ||
} | ||
/** | ||
@@ -54,13 +44,16 @@ * Logs migration to be considered as executed. | ||
*/ | ||
logMigration(migrationName) { | ||
const filePath = this.path; | ||
const readfile = _bluebird2.default.promisify(_fs2.default.readFile); | ||
const writefile = _bluebird2.default.promisify(_fs2.default.writeFile); | ||
const readfile = _bluebird.default.promisify(_fs.default.readFile); | ||
const writefile = _bluebird.default.promisify(_fs.default.writeFile); | ||
return readfile(filePath).catch(() => '[]').then(content => JSON.parse(content)).then(content => { | ||
content.push(migrationName); | ||
return writefile(filePath, (0, _stringify2.default)(content, null, ' ')); | ||
return writefile(filePath, JSON.stringify(content, null, ' ')); | ||
}); | ||
} | ||
/** | ||
@@ -72,13 +65,16 @@ * Unlogs migration to be considered as pending. | ||
*/ | ||
unlogMigration(migrationName) { | ||
const filePath = this.path; | ||
const readfile = _bluebird2.default.promisify(_fs2.default.readFile); | ||
const writefile = _bluebird2.default.promisify(_fs2.default.writeFile); | ||
const readfile = _bluebird.default.promisify(_fs.default.readFile); | ||
const writefile = _bluebird.default.promisify(_fs.default.writeFile); | ||
return readfile(filePath).catch(() => '[]').then(content => JSON.parse(content)).then(content => { | ||
content = content.filter(m => m !== migrationName); | ||
return writefile(filePath, (0, _stringify2.default)(content, null, ' ')); | ||
return writefile(filePath, JSON.stringify(content, null, ' ')); | ||
}); | ||
} | ||
/** | ||
@@ -89,9 +85,14 @@ * Gets list of executed migrations. | ||
*/ | ||
executed() { | ||
const filePath = this.path; | ||
const readfile = _bluebird2.default.promisify(_fs2.default.readFile); | ||
const readfile = _bluebird.default.promisify(_fs.default.readFile); | ||
return readfile(filePath).catch(() => '[]').then(content => JSON.parse(content)); | ||
} | ||
} | ||
exports.default = JSONStorage; |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.default = void 0; | ||
var _Storage = require('./Storage'); | ||
var _Storage = _interopRequireDefault(require("./Storage")); | ||
var _Storage2 = _interopRequireDefault(_Storage); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -17,3 +16,3 @@ | ||
*/ | ||
class MongoDBStorage extends _Storage2.default { | ||
class MongoDBStorage extends _Storage.default { | ||
/** | ||
@@ -28,3 +27,7 @@ * Constructs MongoDB collection storage. | ||
*/ | ||
constructor({ connection, collectionName, collection }) { | ||
constructor({ | ||
connection, | ||
collectionName, | ||
collection | ||
}) { | ||
super(); | ||
@@ -43,3 +46,2 @@ this.connection = connection; | ||
} | ||
/** | ||
@@ -51,6 +53,9 @@ * Logs migration to be considered as executed. | ||
*/ | ||
logMigration(migrationName) { | ||
return this.collection.insertOne({ migrationName }); | ||
return this.collection.insertOne({ | ||
migrationName | ||
}); | ||
} | ||
/** | ||
@@ -62,6 +67,9 @@ * Unlogs migration to be considered as pending. | ||
*/ | ||
unlogMigration(migrationName) { | ||
return this.collection.removeOne({ migrationName }); | ||
return this.collection.removeOne({ | ||
migrationName | ||
}); | ||
} | ||
/** | ||
@@ -72,6 +80,12 @@ * Gets list of executed migrations. | ||
*/ | ||
executed() { | ||
return this.collection.find({}).sort({ migrationName: 1 }).toArray().then(records => records.map(r => r.migrationName)); | ||
return this.collection.find({}).sort({ | ||
migrationName: 1 | ||
}).toArray().then(records => records.map(r => r.migrationName)); | ||
} | ||
} | ||
exports.default = MongoDBStorage; |
@@ -1,11 +0,8 @@ | ||
'use strict'; | ||
"use strict"; | ||
var _Storage = require('./Storage'); | ||
var _Storage = _interopRequireDefault(require("./Storage")); | ||
var _Storage2 = _interopRequireDefault(_Storage); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
module.exports = _Storage2.default; | ||
module.exports = _Storage.default; | ||
console.warn('Deprecated: Storage\'s (former none storage) filename has changed!', 'Use \'umzug/lib/storages/Storage\' instead of \'umzug/lib/storages/none\'', 'For more information: https://github.com/sequelize/umzug/pull/139'); |
@@ -1,11 +0,8 @@ | ||
'use strict'; | ||
"use strict"; | ||
var _SequelizeStorage = require('./SequelizeStorage'); | ||
var _SequelizeStorage = _interopRequireDefault(require("./SequelizeStorage")); | ||
var _SequelizeStorage2 = _interopRequireDefault(_SequelizeStorage); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
module.exports = _SequelizeStorage2.default; | ||
module.exports = _SequelizeStorage.default; | ||
console.warn('Deprecated: SequelizeStorage\'s filename has changed!', 'Use \'umzug/lib/storages/SequelizeStorage\' instead of \'umzug/lib/storages/sequelize\'', 'For more information: https://github.com/sequelize/umzug/pull/139'); |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.default = void 0; | ||
var _Storage = require('./Storage'); | ||
var _Storage = _interopRequireDefault(require("./Storage")); | ||
var _Storage2 = _interopRequireDefault(_Storage); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -17,3 +16,3 @@ | ||
*/ | ||
class SequelizeStorage extends _Storage2.default { | ||
class SequelizeStorage extends _Storage.default { | ||
/** | ||
@@ -63,2 +62,3 @@ * Constructs Sequelize based storage. | ||
super(); | ||
if (!model && !sequelize) { | ||
@@ -69,5 +69,3 @@ throw new Error('One of "sequelize" or "model" storage option is required'); | ||
this.sequelize = sequelize || model.sequelize; | ||
const Sequelize = this.sequelize.constructor; | ||
this.columnType = columnType || Sequelize.STRING; | ||
@@ -103,3 +101,2 @@ this.columnName = columnName; | ||
} | ||
/** | ||
@@ -111,5 +108,6 @@ * Logs migration to be considered as executed. | ||
*/ | ||
logMigration(migrationName) { | ||
const self = this; | ||
return this._model().sync().then(Model => { | ||
@@ -121,3 +119,2 @@ const migration = {}; | ||
} | ||
/** | ||
@@ -129,2 +126,4 @@ * Unlogs migration to be considered as pending. | ||
*/ | ||
unlogMigration(migrationName) { | ||
@@ -134,3 +133,2 @@ const self = this; | ||
const sequelizeVersion = sequelize.modelManager ? 2 : 1; | ||
return this._model().sync().then(Model => { | ||
@@ -142,3 +140,5 @@ let where = {}; | ||
// This is an ugly hack to find out which function signature we have to use. | ||
where = { where: where }; | ||
where = { | ||
where: where | ||
}; | ||
} | ||
@@ -149,3 +149,2 @@ | ||
} | ||
/** | ||
@@ -156,8 +155,10 @@ * Gets list of executed migrations. | ||
*/ | ||
executed() { | ||
const self = this; | ||
return this._model().sync().then(Model => Model.findAll({ order: [[self.columnName, 'ASC']] })).then(migrations => migrations.map(migration => migration[self.columnName])); | ||
return this._model().sync().then(Model => Model.findAll({ | ||
order: [[self.columnName, 'ASC']] | ||
})).then(migrations => migrations.map(migration => migration[self.columnName])); | ||
} | ||
/** | ||
@@ -169,6 +170,10 @@ * Gets Sequelize model used as a storage. | ||
*/ | ||
_model() { | ||
return this.model; | ||
} | ||
} | ||
exports.default = SequelizeStorage; |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.default = void 0; | ||
var _bluebird = require('bluebird'); | ||
var _bluebird = _interopRequireDefault(require("bluebird")); | ||
var _bluebird2 = _interopRequireDefault(_bluebird); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -25,5 +24,4 @@ | ||
logMigration(migrationName) { | ||
return _bluebird2.default.resolve(); | ||
return _bluebird.default.resolve(); | ||
} | ||
/** | ||
@@ -35,6 +33,7 @@ * Does nothing. | ||
*/ | ||
unlogMigration(migrationName) { | ||
return _bluebird2.default.resolve(); | ||
return _bluebird.default.resolve(); | ||
} | ||
/** | ||
@@ -45,6 +44,10 @@ * Does nothing. | ||
*/ | ||
executed() { | ||
return _bluebird2.default.resolve([]); | ||
return _bluebird.default.resolve([]); | ||
} | ||
} | ||
exports.default = Storage; |
{ | ||
"name": "umzug", | ||
"version": "2.2.0", | ||
"version": "2.3.0", | ||
"description": "Framework agnostic migration tool for Node.JS", | ||
@@ -13,13 +13,13 @@ "keywords": [ | ||
"dependencies": { | ||
"babel-runtime": "^6.23.0", | ||
"bluebird": "^3.5.3" | ||
"bluebird": "^3.7.2" | ||
}, | ||
"devDependencies": { | ||
"babel-cli": "^6.24.1", | ||
"babel-plugin-dynamic-import-node": "^2.2.0", | ||
"@babel/cli": "^7.8.4", | ||
"@babel/core": "^7.9.0", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.9.0", | ||
"@babel/plugin-transform-runtime": "^7.9.0", | ||
"@babel/preset-env": "^7.9.0", | ||
"@babel/register": "^7.9.0", | ||
"babel-plugin-dynamic-import-node": "^2.3.0", | ||
"babel-plugin-syntax-dynamic-import": "^6.18.0", | ||
"babel-plugin-transform-object-rest-spread": "^6.23.0", | ||
"babel-plugin-transform-runtime": "^6.23.0", | ||
"babel-preset-env": "^1.7.0", | ||
"babel-register": "^6.24.1", | ||
"chai": "^4.2.0", | ||
@@ -29,20 +29,20 @@ "coffee-script": "^1.8.0", | ||
"eslint-config-standard": "^12.0.0", | ||
"eslint-plugin-import": "^2.14.0", | ||
"eslint-plugin-mocha": "^5.2.0", | ||
"eslint-plugin-import": "^2.20.1", | ||
"eslint-plugin-mocha": "^6.3.0", | ||
"eslint-plugin-node": "^8.0.0", | ||
"eslint-plugin-promise": "^4.0.1", | ||
"eslint-plugin-standard": "^4.0.0", | ||
"lodash": "^4.17.11", | ||
"mocha": "^5.2.0", | ||
"sequelize": "^4.41.2", | ||
"sinon": "^7.1.1", | ||
"sinon-chai": "^3.2.0", | ||
"sqlite3": "^4.0.4", | ||
"typescript": "^3.1.6", | ||
"uuid": "^3.3.2" | ||
"eslint-plugin-promise": "^4.2.1", | ||
"eslint-plugin-standard": "^4.0.1", | ||
"lodash": "^4.17.15", | ||
"mocha": "^6.2.2", | ||
"sequelize": "^5.21.5", | ||
"sinon": "^7.5.0", | ||
"sinon-chai": "^3.5.0", | ||
"sqlite3": "^4.1.1", | ||
"typescript": "^3.8.3", | ||
"uuid": "^7.0.2" | ||
}, | ||
"scripts": { | ||
"build": "babel src --out-dir lib", | ||
"lint": "eslint src test", | ||
"test": "mocha -r babel-register --check-leaks test/index.js" | ||
"prepare": "babel src --out-dir lib", | ||
"test": "mocha -r @babel/register --check-leaks test/index.js" | ||
}, | ||
@@ -49,0 +49,0 @@ "repository": { |
544
README.md
@@ -1,233 +0,193 @@ | ||
# Umzug [![Build Status](https://travis-ci.org/sequelize/umzug.svg?branch=master)](https://travis-ci.org/sequelize/umzug) | ||
# Umzug [![Build Status](https://travis-ci.org/sequelize/umzug.svg?branch=master)](https://travis-ci.org/sequelize/umzug) [![npm version](https://badgen.net/npm/v/umzug)](https://www.npmjs.com/package/umzug) | ||
The *umzug* lib is a framework agnostic migration tool for Node.JS. The tool itself is not specifically related to databases but basically provides a clean API for running and rolling back tasks. | ||
## Persistence | ||
In order to keep track of already executed tasks, *umzug* logs successfully executed migrations. This is done in order to allow rollbacks of tasks. There are multiple storage presets available, from which you can choose. Adding a custom is super simple as well. | ||
* Programmatic API for migrations | ||
* Database agnostic | ||
* Supports logging of migration process | ||
* Supports multiple storages for migration data | ||
## Documentation | ||
## Storages | ||
### Minimal Example | ||
### JSONStorage | ||
Using the [JSONStorage](src/storages/JSONStorage.js) will create a JSON file which will contain an array with all the executed migrations. You can specify the path to the file. The default for that is `umzug.json` in the working directory of the process. | ||
The following example uses a Sqlite database through sequelize and persists the migration data in the database itself through the sequelize storage. | ||
#### Options | ||
`index.js`: | ||
```js | ||
{ | ||
// The path to the json storage. | ||
// Defaults to process.cwd() + '/umzug.json'; | ||
path: process.cwd() + '/db/sequelize-meta.json' | ||
} | ||
``` | ||
```javascript | ||
### SequelizeStorage | ||
Using the [SequelizeStorage](src/storages/SequelizeStorage.js) will create a table in your SQL database called `SequelizeMeta` containing an entry for each executed migration. You will have to pass a configured instance of Sequelize or an existing Sequelize model. Optionally you can specify the model name, table name, or column name. All major Sequelize versions are supported. | ||
const Sequelize = require('sequelize') | ||
const path = require('path') | ||
const Umzug = require('umzug') | ||
#### Options | ||
// creates a basic sqlite database | ||
const sequelize = new Sequelize({ | ||
dialect: 'sqlite', | ||
storage: './db.sqlite' | ||
}) | ||
```js | ||
{ | ||
// The configured instance of Sequelize. | ||
// Optional if `model` is passed. | ||
sequelize: instance, | ||
const umzug = new Umzug({ | ||
migrations: { | ||
// indicates the folder containing the migration .js files | ||
path: path.join(__dirname, './migrations'), | ||
// inject sequelize's QueryInterface in the migrations | ||
params: [ | ||
sequelize.getQueryInterface() | ||
] | ||
}, | ||
// indicates that the migration data should be store in the database | ||
// itself through sequelize. The default configuration creates a table | ||
// named `SequelizeMeta`. | ||
storage: 'sequelize', | ||
storageOptions: { | ||
sequelize: sequelize | ||
} | ||
}) | ||
// The to be used Sequelize model. | ||
// Must have column name matching `columnName` option | ||
// Optional if `sequelize` is passed. | ||
model: model, | ||
// The name of the to be used model. | ||
// Defaults to 'SequelizeMeta' | ||
modelName: 'Schema', | ||
// The name of table to create if `model` option is not supplied | ||
// Defaults to `modelName` | ||
tableName: 'Schema', | ||
// The name of table column holding migration name. | ||
// Defaults to 'name'. | ||
columnName: 'migration', | ||
// The type of the column holding migration name. | ||
// Defaults to `Sequelize.STRING` | ||
columnType: new Sequelize.STRING(100) | ||
} | ||
;(async () => { | ||
// checks migrations and run them if they are not already applied | ||
await umzug.up() | ||
console.log('All migrations performed successfully') | ||
})() | ||
``` | ||
### MongoDBStorage | ||
Using the [MongoDBStorage](src/storages/MongoDBStorage.js) will create a collection in your MongoDB database called `migrations` containing an entry for each executed migration. You will have either to pass a MongoDB Driver Collection as `collection` property. Alternatively you can pass a established MongoDB Driver connection and a collection name. | ||
`migrations/00_initial.js`: | ||
#### Options | ||
```javascript | ||
```js | ||
{ | ||
// a connection to target database established with MongoDB Driver | ||
connection: MongoDBDriverConnection, | ||
const Sequelize = require('sequelize') | ||
// name of migration collection in MongoDB | ||
collectionName: 'migrations', | ||
// All migrations must provide a `up` and `down` async functions | ||
// reference to a MongoDB Driver collection | ||
collection: MongoDBDriverCollection | ||
module.exports = { | ||
// `query` was passed in the `index.js` file | ||
up: async (query) => { | ||
await query.createTable('users', { | ||
id: { | ||
type: Sequelize.INTEGER, | ||
allowNull: false, | ||
primaryKey: true | ||
}, | ||
name: { | ||
type: Sequelize.STRING, | ||
allowNull: false | ||
}, | ||
createdAt: { | ||
type: Sequelize.DATE, | ||
allowNull: false | ||
}, | ||
updatedAt: { | ||
type: Sequelize.DATE, | ||
allowNull: false | ||
} | ||
}) | ||
}, | ||
down: async (query) => { | ||
await query.dropTable('users') | ||
} | ||
} | ||
``` | ||
#### Events | ||
Umzug is an EventEmitter. Each of the following events will be called with `name, migration` as arguments. Events are a convenient place | ||
to implement application-specific logic that must run around each migration: | ||
### Usage | ||
* *migrating* - A migration is about to be executed. | ||
* *migrated* - A migration has successfully been executed. | ||
* *reverting* - A migration is about to be reverted. | ||
* *reverted* - A migration has successfully been reverted. | ||
#### Installation | ||
The *umzug* lib is available on npm: | ||
### Storage | ||
If want to run migrations without storing them anywhere, you can use the [Storage](src/storages/Storage.js). | ||
### Custom | ||
In order to use custom storage, you have two options: | ||
#### Way 1: Pass instance to constructor | ||
You can pass your storage instance to Umzug constructor. | ||
```js | ||
class CustomStorage { | ||
constructor(...) {...} | ||
logMigration(...) {...} | ||
unlogMigration(...) {...} | ||
executed(...) {...} | ||
} | ||
let umzug = new Umzug({ storage: new CustomStorage(...) }) | ||
npm install umzug | ||
``` | ||
#### Way 2: Require external module from npmjs.com | ||
#### Umzug instance | ||
Create and publish a module which has to fulfill the following API. You can just pass the name of the module to the configuration and *umzug* will require it accordingly. The API that needs to be exposed looks like this: | ||
It is possible to configure *umzug* instance by passing an object to the constructor. The possible options are: | ||
```js | ||
var Bluebird = require('bluebird'); | ||
var redefine = require('redefine'); | ||
const Umzug = require('umzug') | ||
module.exports = redefine.Class({ | ||
constructor: function ({ option1: 'defaultValue1' } = {}) { | ||
this.option1 = option1; | ||
}, | ||
const umzug = new Umzug({ | ||
// The storage. | ||
// Possible values: 'none', 'json', 'mongodb', 'sequelize', an argument for `require()`, including absolute paths | ||
storage: 'json', | ||
logMigration: function (migrationName) { | ||
return new Bluebird(function (resolve, reject) { | ||
// This function logs a migration as executed. | ||
// It will get called once a migration was | ||
// executed successfully. | ||
}); | ||
}, | ||
// The options for the storage. | ||
// Check the available storages for further details. | ||
storageOptions: {}, | ||
unlogMigration: function (migrationName) { | ||
return new Bluebird(function (resolve, reject) { | ||
// This function removes a previously logged migration. | ||
// It will get called once a migration has been reverted. | ||
}); | ||
}, | ||
// The logging function. | ||
// A function that gets executed everytime migrations start and have ended. | ||
logging: false, | ||
executed: function () { | ||
return new Bluebird(function (resolve, reject) { | ||
// This function lists the names of the logged | ||
// migrations. It will be used to calculate | ||
// pending migrations. The result has to be an | ||
// array with the names of the migration files. | ||
}); | ||
} | ||
}); | ||
``` | ||
// The name of the positive method in migrations. | ||
upName: 'up', | ||
## Migrations | ||
Migrations are basically files that describe ways of executing and reverting tasks. In order to allow asynchronicity, tasks return a Promise object which provides a `then` method. | ||
// The name of the negative method in migrations. | ||
downName: 'down', | ||
### Format | ||
A migration file ideally contains an `up` and a `down` method, which represent a function which achieves the task and a function that reverts a task. The file could look like this: | ||
// (advanced) you can pass an array of migrations built with `migrationsList()` instead of the options below | ||
migrations: { | ||
// The params that gets passed to the migrations. | ||
// Might be an array or a synchronous function which returns an array. | ||
params: [], | ||
```js | ||
'use strict'; | ||
// The path to the migrations directory. | ||
path: 'migrations', | ||
var Bluebird = require('bluebird'); | ||
// The pattern that determines whether or not a file is a migration. | ||
pattern: /^\d+[\w-]+\.js$/, | ||
module.exports = { | ||
up: function () { | ||
return new Bluebird(function (resolve, reject) { | ||
// Describe how to achieve the task. | ||
// Call resolve/reject at some point. | ||
}); | ||
}, | ||
down: function () { | ||
return new Bluebird(function (resolve, reject) { | ||
// Describe how to revert the task. | ||
// Call resolve/reject at some point. | ||
}); | ||
// A function that receives and returns the to be executed function. | ||
// This can be used to modify the function. | ||
wrap: function (fun) { return fun; }, | ||
// A function that maps a file path to a migration object in the form | ||
// { up: Function, down: Function }. The default for this is to require(...) | ||
// the file as javascript, but you can use this to transpile TypeScript, | ||
// read raw sql etc. | ||
// See https://github.com/sequelize/umzug/tree/master/test/fixtures | ||
// for examples. | ||
customResolver: function (sqlPath) { | ||
return { up: () => sequelize.query(require('fs').readFileSync(sqlPath, 'utf8')) } | ||
} | ||
} | ||
}; | ||
}) | ||
``` | ||
## Examples | ||
#### Executing migrations | ||
- [sequelize-migration-hello](https://github.com/abelnation/sequelize-migration-hello) | ||
## Usage | ||
### Installation | ||
The *umzug* lib is available on npm: | ||
```js | ||
npm install umzug | ||
``` | ||
### API | ||
The basic usage of *umzug* is as simple as: | ||
```js | ||
var Umzug = require('umzug'); | ||
var umzug = new Umzug({}); | ||
umzug.someMethod().then(function (result) { | ||
// do something with the result | ||
}); | ||
``` | ||
#### Executing migrations | ||
The `execute` method is a general purpose function that runs for every specified migrations the respective function. | ||
```js | ||
umzug.execute({ | ||
const migrations = await umzug.execute({ | ||
migrations: ['some-id', 'some-other-id'], | ||
method: 'up' | ||
}).then(function (migrations) { | ||
// "migrations" will be an Array of all executed/reverted migrations. | ||
}); | ||
}) | ||
// returns an array of all executed/reverted migrations. | ||
``` | ||
#### Getting all pending migrations | ||
You can get a list of pending/not yet executed migrations like this: | ||
```js | ||
umzug.pending().then(function (migrations) { | ||
// "migrations" will be an Array with the names of | ||
// pending migrations. | ||
}); | ||
const migrations = await umzug.pending() | ||
// returns an array of all pending migrations. | ||
``` | ||
#### Getting all executed migrations | ||
You can get a list of already executed migrations like this: | ||
```js | ||
umzug.executed().then(function (migrations) { | ||
// "migrations" will be an Array of already executed migrations. | ||
}); | ||
const migrations = await umzug.executed() | ||
// returns an array of all already executed migrations | ||
``` | ||
#### Executing pending migrations | ||
The `up` method can be used to execute all pending migrations. | ||
```js | ||
umzug.up().then(function (migrations) { | ||
// "migrations" will be an Array with the names of the | ||
// executed migrations. | ||
}); | ||
const migrations = await umzug.up() | ||
// returns an array of all executed migrations | ||
``` | ||
@@ -238,3 +198,3 @@ | ||
```js | ||
umzug.up({ to: '20141101203500-task' }).then(function (migrations) {}); | ||
await umzug.up({ to: '20141101203500-task' }) | ||
``` | ||
@@ -245,3 +205,3 @@ | ||
```js | ||
umzug.up({ from: '20141101203500-task' }).then(function (migrations) {}); | ||
await umzug.up({ from: '20141101203500-task' }) | ||
``` | ||
@@ -254,3 +214,3 @@ | ||
```js | ||
umzug.up({ from: '20141101203500-task', to: '20151201103412-items' }).then(function (migrations) {}); | ||
await umzug.up({ from: '20141101203500-task', to: '20151201103412-items' }) | ||
``` | ||
@@ -261,3 +221,3 @@ | ||
```js | ||
umzug.up({ migrations: ['20141101203500-task', '20141101203501-task-2'] }); | ||
await umzug.up({ migrations: ['20141101203500-task', '20141101203501-task-2'] }) | ||
``` | ||
@@ -268,15 +228,13 @@ | ||
```js | ||
umzug.up('20141101203500-task'); // Runs just the passed migration | ||
umzug.up(['20141101203500-task', '20141101203501-task-2']); | ||
await umzug.up('20141101203500-task'); // Runs just the passed migration | ||
await umzug.up(['20141101203500-task', '20141101203501-task-2']); | ||
``` | ||
Running | ||
#### Reverting executed migration | ||
#### Reverting executed migration | ||
The `down` method can be used to revert the last executed migration. | ||
```js | ||
umzug.down().then(function (migration) { | ||
// "migration" will the name of the reverted migration. | ||
}); | ||
const migration = await umzug.down() | ||
// returns the reverted migration. | ||
``` | ||
@@ -287,5 +245,4 @@ | ||
```js | ||
umzug.down({ to: '20141031080000-task' }).then(function (migrations) { | ||
// "migrations" will be an Array with the names of all reverted migrations. | ||
}); | ||
const migrations = await umzug.down({ to: '20141031080000-task' }) | ||
// returns an array of all reverted migrations. | ||
``` | ||
@@ -296,3 +253,3 @@ | ||
```js | ||
umzug.down({ to: 0 }); | ||
await umzug.down({ to: 0 }) | ||
``` | ||
@@ -303,3 +260,3 @@ | ||
```js | ||
umzug.down({ migrations: ['20141101203500-task', '20141101203501-task-2'] }); | ||
await umzug.down({ migrations: ['20141101203500-task', '20141101203501-task-2'] }) | ||
``` | ||
@@ -310,55 +267,164 @@ | ||
```js | ||
umzug.down('20141101203500-task'); // Runs just the passed migration | ||
umzug.down(['20141101203500-task', '20141101203501-task-2']); | ||
await umzug.down('20141101203500-task') // Runs just the passed migration | ||
await umzug.down(['20141101203500-task', '20141101203501-task-2']) | ||
``` | ||
### Configuration | ||
### Migrations | ||
It is possible to configure *umzug* instance by passing an object to the constructor. The possible options are: | ||
There are two ways to specify migrations. | ||
#### Migration files | ||
A migration file ideally exposes an `up` and a `down` async functions. They will perform the task of upgrading or downgrading the database. | ||
```js | ||
module.exports = { | ||
up: async () => { | ||
... | ||
}, | ||
down: async () => { | ||
... | ||
}, | ||
}; | ||
``` | ||
Migration files should be located in the same directory, according to the info you gave to the `Umzug` constructor. | ||
#### Direct migrations list | ||
You can also specify directly a list of migrations to the `Umzug` constructor. We recommend the usage of the `Umzug.migrationsList()` function | ||
as bellow: | ||
```js | ||
const umzug = new Umzug({ | ||
migrations: Umzug.migrationsList([ | ||
{ | ||
// the name of the migration is mandatory | ||
name: '00-first-migration', | ||
up: ..., | ||
down: ... | ||
} | ||
], | ||
// a facultative list of parameters that will be sent to the `up` and `down` functions | ||
[sequelize.getQueryInterface()]) | ||
}) | ||
``` | ||
### Storages | ||
Storages define where the migration data is stored. | ||
#### JSON Storage | ||
Using the `json` storage will create a JSON file which will contain an array with all the executed migrations. You can specify the path to the file. The default for that is `umzug.json` in the working directory of the process. | ||
Options: | ||
```js | ||
{ | ||
// The storage. | ||
// Possible values: 'none', 'json', 'mongodb', 'sequelize', an argument for `require()`, including absolute paths | ||
storage: 'json', | ||
// The path to the json storage. | ||
// Defaults to process.cwd() + '/umzug.json'; | ||
path: process.cwd() + '/db/sequelize-meta.json' | ||
} | ||
``` | ||
// The options for the storage. | ||
// Check the available storages for further details. | ||
storageOptions: {}, | ||
#### Sequelize Storage | ||
// The logging function. | ||
// A function that gets executed everytime migrations start and have ended. | ||
logging: false, | ||
Using the `sequelize` storage will create a table in your SQL database called `SequelizeMeta` containing an entry for each executed migration. You will have to pass a configured instance of Sequelize or an existing Sequelize model. Optionally you can specify the model name, table name, or column name. All major Sequelize versions are supported. | ||
// The name of the positive method in migrations. | ||
upName: 'up', | ||
Options: | ||
// The name of the negative method in migrations. | ||
downName: 'down', | ||
```js | ||
{ | ||
// The configured instance of Sequelize. | ||
// Optional if `model` is passed. | ||
sequelize: instance, | ||
// (advanced) you can pass an array of Migration instances instead of the options below | ||
migrations: { | ||
// The params that gets passed to the migrations. | ||
// Might be an array or a synchronous function which returns an array. | ||
params: [], | ||
// The to be used Sequelize model. | ||
// Must have column name matching `columnName` option | ||
// Optional if `sequelize` is passed. | ||
model: model, | ||
// The path to the migrations directory. | ||
path: 'migrations', | ||
// The name of the to be used model. | ||
// Defaults to 'SequelizeMeta' | ||
modelName: 'Schema', | ||
// The pattern that determines whether or not a file is a migration. | ||
pattern: /^\d+[\w-]+\.js$/, | ||
// The name of table to create if `model` option is not supplied | ||
// Defaults to `modelName` | ||
tableName: 'Schema', | ||
// A function that receives and returns the to be executed function. | ||
// This can be used to modify the function. | ||
wrap: function (fun) { return fun; }, | ||
// A function that maps a file path to a migration object in the form | ||
// { up: Function, down: Function }. The default for this is to require(...) | ||
// the file as javascript, but you can use this to transpile TypeScript, | ||
// read raw sql etc. | ||
// See https://github.com/sequelize/umzug/tree/master/test/fixtures | ||
// for examples. | ||
customResolver: function (sqlPath) { | ||
return { up: () => sequelize.query(require('fs').readFileSync(sqlPath, 'utf8')) } | ||
} | ||
// The name of table column holding migration name. | ||
// Defaults to 'name'. | ||
columnName: 'migration', | ||
// The type of the column holding migration name. | ||
// Defaults to `Sequelize.STRING` | ||
columnType: new Sequelize.STRING(100) | ||
} | ||
``` | ||
#### MongoDB Storage | ||
Using the `mongodb` storage will create a collection in your MongoDB database called `migrations` containing an entry for each executed migration. You will have either to pass a MongoDB Driver Collection as `collection` property. Alternatively you can pass a established MongoDB Driver connection and a collection name. | ||
Options: | ||
```js | ||
{ | ||
// a connection to target database established with MongoDB Driver | ||
connection: MongoDBDriverConnection, | ||
// name of migration collection in MongoDB | ||
collectionName: 'migrations', | ||
// reference to a MongoDB Driver collection | ||
collection: MongoDBDriverCollection | ||
} | ||
``` | ||
#### Custom | ||
In order to use custom storage, you have two options: | ||
##### Method 1: Pass instance to constructor | ||
You can pass your storage instance to Umzug constructor. | ||
```js | ||
class CustomStorage { | ||
constructor(...) {...} | ||
logMigration(...) {...} | ||
unlogMigration(...) {...} | ||
executed(...) {...} | ||
} | ||
let umzug = new Umzug({ storage: new CustomStorage(...) }) | ||
``` | ||
##### Method 2: Require external module from npmjs.com | ||
Create and publish a module which has to fulfill the following API. You can just pass the name of the module to the configuration and *umzug* will require it accordingly. The API that needs to be exposed looks like this: | ||
```js | ||
module.exports = class MyStorage { | ||
constructor({ option1: 'defaultValue1' } = {}) { | ||
this.option1 = option1; | ||
}, | ||
async logMigration(migrationName) { | ||
// This function logs a migration as executed. | ||
// It will get called once a migration was | ||
// executed successfully. | ||
}, | ||
async unlogMigration(migrationName) { | ||
// This function removes a previously logged migration. | ||
// It will get called once a migration has been reverted. | ||
}, | ||
async executed() { | ||
// This function lists the names of the logged | ||
// migrations. It will be used to calculate | ||
// pending migrations. The result has to be an | ||
// array with the names of the migration files. | ||
} | ||
@@ -368,23 +434,17 @@ } | ||
## License | ||
The MIT License (MIT) | ||
### Events | ||
Copyright (c) 2014-2017 Sequelize contributors | ||
Umzug is an EventEmitter. Each of the following events will be called with `name, migration` as arguments. Events are a convenient place to implement application-specific logic that must run around each migration: | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
* *migrating* - A migration is about to be executed. | ||
* *migrated* - A migration has successfully been executed. | ||
* *reverting* - A migration is about to be reverted. | ||
* *reverted* - A migration has successfully been reverted. | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
## Examples | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. | ||
* [sequelize-migration-hello](https://github.com/abelnation/sequelize-migration-hello) | ||
## License | ||
See the [LICENSE file](./LICENSE) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
58096
1
1035
441
25
18
- Removedbabel-runtime@^6.23.0
- Removedbabel-runtime@6.26.0(transitive)
- Removedcore-js@2.6.12(transitive)
- Removedregenerator-runtime@0.11.1(transitive)
Updatedbluebird@^3.7.2