diff --git a/bin/migrate-mongo.js b/bin/migrate-mongo.js index ed07360..d701ed4 100755 --- a/bin/migrate-mongo.js +++ b/bin/migrate-mongo.js @@ -6,6 +6,7 @@ const Table = require('cli-table'); const migrateMongo = require('../lib/migrate-mongo'); const database = require('../lib/env/database'); const pkgjson = require('../package.json'); +const config = require('../lib/env/configFile'); program.version(pkgjson.version); @@ -23,10 +24,11 @@ program .command('create [description]') .description('create a new database migration with the provided description') .option('-f --file ', 'use a custom config file') - .action((description) =>{ + .action((description, options) => { + global.options = options; migrateMongo.create(description, (err, filename) => { if (err) return handleError(err); - console.log('Created: migrations/' + filename); + console.log(`Created: ${config.read().migrationsDir}/${filename}`); }); }); diff --git a/lib/actions/create.js b/lib/actions/create.js index 048460b..887c1f1 100644 --- a/lib/actions/create.js +++ b/lib/actions/create.js @@ -15,7 +15,7 @@ module.exports = function (description, done) { description = description.split(' ').join('_'); const source = path.join(__dirname, '../../samples/migration.js'); const filename = moment.utc().format('YYYYMMDDHHmmss') + '-' + description + '.js'; - const destination = path.join(process.cwd(), 'migrations', filename); + const destination = path.join(migrationsDir.resolve(), filename); return fs.copy(source, destination, (err) => { if (err) return taskDone(err); return taskDone(null, filename); diff --git a/lib/env/migrationsDir.js b/lib/env/migrationsDir.js index 36e8ef9..91e3209 100644 --- a/lib/env/migrationsDir.js +++ b/lib/env/migrationsDir.js @@ -2,11 +2,33 @@ const fs = require('fs-extra'); const path = require('path'); +const _ = require('lodash'); +const configFile = require('./configFile'); + +const DEFAULT_MIGRATIONS_DIR_NAME = 'migrations'; + +function resolveMigrationsDirPath() { + let migrationsDir; + try { + migrationsDir = configFile.read().migrationsDir; + } catch(err) { + // config file could not be read, assume default 'migrations' dir + migrationsDir = DEFAULT_MIGRATIONS_DIR_NAME; + } + + if (path.isAbsolute(migrationsDir)) { + return migrationsDir; + } else { + return path.join(process.cwd(), migrationsDir); + } +} module.exports = { + resolve: resolveMigrationsDirPath, + shouldExist(done) { - const migrationsDir = path.join(process.cwd(), 'migrations'); + const migrationsDir = resolveMigrationsDirPath(); return fs.stat(migrationsDir, (err) => { if (err) return done(new Error('migrations directory does not exist: ' + migrationsDir)); return done(); @@ -14,7 +36,7 @@ module.exports = { }, shouldNotExist(done) { - const migrationsDir = path.join(process.cwd(), 'migrations'); + const migrationsDir = resolveMigrationsDirPath(); return fs.stat(migrationsDir, (err) => { if (err && err.code === 'ENOENT') return done(); return done(new Error('migrations directory already exists: ' + migrationsDir)); @@ -22,7 +44,7 @@ module.exports = { }, getFileNames(done) { - const migrationsDir = path.join(process.cwd(), 'migrations'); + const migrationsDir = resolveMigrationsDirPath(); fs.readdir(migrationsDir, (err, files) => { if (err) return done(err); return done(null, files.filter((file) => path.extname(file) === '.js')); @@ -30,6 +52,6 @@ module.exports = { }, loadMigration(fileName) { - return require(path.join(process.cwd(), 'migrations', fileName)); + return require(path.join(resolveMigrationsDirPath(), fileName)); } -}; \ No newline at end of file +}; diff --git a/samples/config.js b/samples/config.js index b750e91..37830bc 100644 --- a/samples/config.js +++ b/samples/config.js @@ -1,21 +1,26 @@ 'use strict'; -// This is where you can configure migrate-mongo -module.exports = { +// In this file you can configure migrate-mongo - // The mongodb collection where the applied changes are stored: - changelogCollectionName: 'changelog', +module.exports = { mongodb: { - // TODO edit this connection url to your MongoDB database: + // TODO You MUST edit this connection url to your MongoDB database: url: 'mongodb://localhost:27017/YOURDATABASENAME', - // uncomment and edit to specify Mongo client connect options + // uncomment and edit to specify Mongo client connect options (eg. increase the timeouts) // see https://mongodb.github.io/node-mongodb-native/2.2/api/MongoClient.html // // options: { // connectTimeoutMS: 3600000, // 1 hour // socketTimeoutMS: 3600000, // 1 hour // } - } + }, + + // The migrations dir, can be an relative or absolute path. Only edit this when really necessary. + migrationsDir: 'migrations', + + // The mongodb collection where the applied changes are stored. Only edit this when really necessary. + changelogCollectionName: 'changelog', + }; \ No newline at end of file diff --git a/test/env/migrationsDir.test.js b/test/env/migrationsDir.test.js index 5405a2c..1bc6856 100644 --- a/test/env/migrationsDir.test.js +++ b/test/env/migrationsDir.test.js @@ -9,11 +9,38 @@ const path = require('path'); describe('migrationsDir', function () { let migrationsDir; - let fs; + let fs, configFile; beforeEach(function () { fs = mockFs(); - migrationsDir = proxyquire('../../lib/env/migrationsDir', {'fs-extra': fs}); + configFile = mockConfigFile(); + migrationsDir = proxyquire('../../lib/env/migrationsDir', { + 'fs-extra': fs, + './configFile': configFile, + }); + }); + + describe('resolve()', function () { + + it('should use the configured relative migrations dir when a config file is available', function () { + configFile.read.returns({ + migrationsDir: 'custom-migrations-dir' + }); + expect(migrationsDir.resolve()).to.equal(path.join(process.cwd(), 'custom-migrations-dir')); + }); + + it('should use the configured absolute migrations dir when a config file is available', function () { + configFile.read.returns({ + migrationsDir: '/absolute/path/to/my/custom-migrations-dir' + }); + expect(migrationsDir.resolve()).to.equal('/absolute/path/to/my/custom-migrations-dir'); + }); + + it('should use the default migrations directory when unable to read the config file', function () { + configFile.read.throws(new Error('Cannot read config file')); + expect(migrationsDir.resolve()).to.equal(path.join(process.cwd(), 'migrations')); + }); + }); describe('shouldExist()', function () { @@ -101,4 +128,12 @@ describe('migrationsDir', function () { }; } + function mockConfigFile() { + return { + read: sinon.stub().returns({ + migrationsDir: 'migrations', + }), + }; + } + }); \ No newline at end of file