From d3db117776525a1e21f9418b88459f26c8509830 Mon Sep 17 00:00:00 2001 From: Sascha Depold Date: Sat, 14 Jun 2014 21:51:37 +0200 Subject: [PATCH 1/3] Remove migration helper and separate functions into more sensible places --- lib/helpers/init-helper.js | 66 +++++++++++++++++++++++++++++++++ lib/helpers/migration-helper.js | 39 ------------------- lib/helpers/path-helper.js | 14 +++++++ 3 files changed, 80 insertions(+), 39 deletions(-) create mode 100644 lib/helpers/init-helper.js delete mode 100644 lib/helpers/migration-helper.js create mode 100644 lib/helpers/path-helper.js diff --git a/lib/helpers/init-helper.js b/lib/helpers/init-helper.js new file mode 100644 index 00000000..74e7a03b --- /dev/null +++ b/lib/helpers/init-helper.js @@ -0,0 +1,66 @@ +var helpers = require(__dirname) + , args = require('yargs').argv + , path = require('path') + , fs = require('fs') + , clc = require('cli-color') + +module.exports = { + notifyAboutExistingFile: function(file) { + helpers.view.log('The file ' + clc.blueBright(file) + ' already exists. Run "sequelize init --force" to overwrite it.') + }, + + createFolder: function(folderName, folder, force) { + if (force) { + console.log('Deleting the ' + folderName + 'folder. (--force)') + + try { + fs.readdirSync(folder).forEach(function(filename) { + fs.unlinkSync(folder + '/' + filename) + }) + } catch(e) { + console.log(e) + } + + try { + fs.rmdirSync(folder) + console.log('Successfully deleted the ' + folderName + ' folder.') + } catch(e) { + console.log(e) + } + } + + try { + helpers.generic.mkdirp(folder) + console.log('Successfully created ' + folderName + ' folder at "' + folder + '".') + } catch(e) { + console.log(e) + } + }, + + createMigrationsFolder: function(force) { + this.createFolder('migrations', helpers.path.getMigrationsPath(), force) + }, + + createModelsFolder: function(force) { + this.createFolder('models', helpers.path.getModelsPath(), force) + }, + + createModelsIndexFile: function(force) { + var modelsPath = helpers.path.getModelsPath() + , indexPath = path.resolve(modelsPath, 'index.js') + + if (!fs.existsSync(modelsPath)) { + helpers.view.log('Models folder not available.') + } else if (fs.existsSync(indexPath) && !force) { + this.notifyAboutExistingFile(indexPath) + } else { + var relativeConfigPath = path.relative( + helpers.path.getModelsPath(), + helpers.config.getConfigFile() + ) + + helpers.asset.copy('models/index.js', indexPath) + helpers.asset.injectConfigFilePath(indexPath, "__dirname + '/" + relativeConfigPath + "'") + } + } +} diff --git a/lib/helpers/migration-helper.js b/lib/helpers/migration-helper.js deleted file mode 100644 index 9aff7c27..00000000 --- a/lib/helpers/migration-helper.js +++ /dev/null @@ -1,39 +0,0 @@ -var helpers = require(__dirname) - , args = require('yargs').argv - , path = require('path') - , fs = require('fs') - -module.exports = { - getMigrationsPath: function() { - return args.migrationsPath || path.resolve(process.cwd(), 'migrations') - }, - - createMigrationsFolder: function(force) { - var migrationsPath = this.getMigrationsPath() - - if (force) { - console.log('Deleting the migrations folder. (--force)') - - try { - fs.readdirSync(migrationsPath).forEach(function(filename) { - fs.unlinkSync(migrationsPath + '/' + filename) - }) - } catch(e) { - console.log(e) - } - try { - fs.rmdirSync(migrationsPath) - console.log('Successfully deleted the migrations folder.') - } catch(e) { - console.log(e) - } - } - - try { - helpers.generic.mkdirp(migrationsPath) - console.log('Successfully created migrations folder at "' + migrationsPath + '".') - } catch(e) { - console.log(e) - } - } -} diff --git a/lib/helpers/path-helper.js b/lib/helpers/path-helper.js new file mode 100644 index 00000000..a1f55ce6 --- /dev/null +++ b/lib/helpers/path-helper.js @@ -0,0 +1,14 @@ +var helpers = require(__dirname) + , args = require('yargs').argv + , path = require('path') + , fs = require('fs') + +module.exports = { + getMigrationsPath: function() { + return args.migrationsPath || path.resolve(process.cwd(), 'migrations') + }, + + getModelsPath: function() { + return args.modelsPath || path.resolve(process.cwd(), 'models') + } +} From f0c6f61d2b1430ac0ec9961b1665750e738600cc Mon Sep 17 00:00:00 2001 From: Sascha Depold Date: Sat, 14 Jun 2014 21:52:08 +0200 Subject: [PATCH 2/3] Let the executable print the teaser --- bin/sequelize | 17 ++++++++++------- lib/helpers/gulp-helper.js | 2 -- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/bin/sequelize b/bin/sequelize index e00e611d..3ffe3a1b 100755 --- a/bin/sequelize +++ b/bin/sequelize @@ -2,13 +2,14 @@ 'use strict'; -var spawn = require('child_process').spawn - , fs = require('fs') - , path = require('path') - , gulp = path.resolve(__dirname, '..', 'node_modules', '.bin', 'gulp') - , args = process.argv.slice(2) - , yargs = require('yargs') - , _ = require('lodash') +var spawn = require('child_process').spawn + , fs = require('fs') + , path = require('path') + , gulp = path.resolve(__dirname, '..', 'node_modules', '.bin', 'gulp') + , args = process.argv.slice(2) + , yargs = require('yargs') + , _ = require('lodash') + , helpers = require(path.resolve(__dirname, '..', 'lib', 'helpers')) if (!fs.existsSync(gulp)) { gulp = path.resolve(process.cwd(), 'node_modules', '.bin', 'gulp') @@ -54,6 +55,8 @@ if (_.contains(args, '--harmony')) { var call = spawn(process.argv[0], args) +helpers.view.teaser() + call.stdout.on('data', function(data) { var lines = data.toString().split("\n") , output = "" diff --git a/lib/helpers/gulp-helper.js b/lib/helpers/gulp-helper.js index 073f4ce3..539848e8 100644 --- a/lib/helpers/gulp-helper.js +++ b/lib/helpers/gulp-helper.js @@ -9,7 +9,6 @@ module.exports = { task.descriptions.short, task.dependencies || [], function() { - helpers.view.teaser() task.task() }, { aliases: task.aliases || [] @@ -24,7 +23,6 @@ module.exports = { "help:" + taskName, false, function() { - helpers.view.teaser() helpers.view.log(clc.bold("COMMANDS")) var commands = [ taskName ].concat(task.aliases || []) From b6b6744aba7d95b058dc4cdaa159f4765c86c3ba Mon Sep 17 00:00:00 2001 From: Sascha Depold Date: Sat, 14 Jun 2014 21:52:47 +0200 Subject: [PATCH 3/3] init now creates models and models/index.js --- lib/assets/models/index.js | 29 +++++++++++++ lib/helpers/asset-helper.js | 14 +++++++ lib/helpers/gulp-helper.js | 6 ++- lib/helpers/view-helper.js | 17 +++++++- lib/tasks/db.js | 2 +- lib/tasks/init.js | 77 ++++++++++++++++++++++++++++++---- lib/tasks/migration.js | 6 +-- package.json | 9 ++-- test/init.test.js | 83 +++++++++++++++++++++++++++++++++---- 9 files changed, 214 insertions(+), 29 deletions(-) create mode 100644 lib/assets/models/index.js create mode 100644 lib/helpers/asset-helper.js diff --git a/lib/assets/models/index.js b/lib/assets/models/index.js new file mode 100644 index 00000000..4f69745f --- /dev/null +++ b/lib/assets/models/index.js @@ -0,0 +1,29 @@ +var fs = require('fs') + , path = require('path') + , Sequelize = require('sequelize') + , lodash = require('lodash') + , env = process.env.NODE_ENV || 'development' + , config = require(__CONFIG_FILE__)[env] + , sequelize = new Sequelize(config.database, config.username, config.password, config) + , db = {} + +fs + .readdirSync(__dirname) + .filter(function(file) { + return (file.indexOf('.') !== 0) && (file !== 'index.js') + }) + .forEach(function(file) { + var model = sequelize.import(path.join(__dirname, file)) + db[model.name] = model + }) + +Object.keys(db).forEach(function(modelName) { + if ('associate' in db[modelName]) { + db[modelName].associate(db) + } +}) + +module.exports = lodash.extend({ + sequelize: sequelize, + Sequelize: Sequelize +}, db) diff --git a/lib/helpers/asset-helper.js b/lib/helpers/asset-helper.js new file mode 100644 index 00000000..450209b9 --- /dev/null +++ b/lib/helpers/asset-helper.js @@ -0,0 +1,14 @@ +var fs = require('fs-extra') + , path = require('path') + +module.exports = { + copy: function (from, to) { + fs.copySync(path.resolve(__dirname, '..', 'assets', from), to) + }, + + injectConfigFilePath: function(filePath, configPath) { + var fileContent = fs.readFileSync(filePath).toString() + fs.writeFileSync(filePath, fileContent.replace('__CONFIG_FILE__', configPath) + ) + } +} diff --git a/lib/helpers/gulp-helper.js b/lib/helpers/gulp-helper.js index 539848e8..790c07f5 100644 --- a/lib/helpers/gulp-helper.js +++ b/lib/helpers/gulp-helper.js @@ -67,9 +67,11 @@ module.exports = { getGlobalOptions: function() { return { "--env": "The environment to run the command in. " + clc.blueBright("Default: development"), - "--options-path": "The path to a JSON file with additional options. " + clc.blueBright("Default: none"), "--coffee": "Enables coffee script support. " + clc.blueBright("Default: false"), - "--config": "The path to the config file. " + clc.blueBright("Default: config/config.json") + "--config": "The path to the config file. " + clc.blueBright("Default: config/config.json"), + "--options-path": "The path to a JSON file with additional options. " + clc.blueBright("Default: none"), + "--migrations-path": "The path to the migrations folder. " + clc.blueBright("Default: migrations"), + "--models-path": "The path to the models folder." + clc.blueBright("Default: models") } }, diff --git a/lib/helpers/view-helper.js b/lib/helpers/view-helper.js index c5ef4d0b..c3c94cc5 100644 --- a/lib/helpers/view-helper.js +++ b/lib/helpers/view-helper.js @@ -1,5 +1,6 @@ var helpers = require(__dirname) , clc = require('cli-color') + , _ = require('lodash') module.exports = { teaser: function() { @@ -18,5 +19,19 @@ module.exports = { this.log() }, - log: console.log + log: console.log, + + pad: function(s, smth) { + var margin = smth + + if (_.isObject(margin)) { + margin = Object.keys(margin) + } + + if (Array.isArray(margin)) { + margin = Math.max.apply(null, margin.map(function(o) { return o.length })) + } + + return s + new Array(margin - s.length + 1).join(" ") + } } diff --git a/lib/tasks/db.js b/lib/tasks/db.js index 395bf1ab..8aaf2492 100644 --- a/lib/tasks/db.js +++ b/lib/tasks/db.js @@ -53,7 +53,7 @@ var getMigrator = function(callback) { if (helpers.config.configFileExists() || args.url) { var sequelize = getSequelizeInstance() - , migratorOptions = { path: helpers.migration.getMigrationsPath() } + , migratorOptions = { path: helpers.path.getMigrationsPath() } if (helpers.config.supportsCoffee()) { migratorOptions = _.merge(migratorOptions, { filesFilter: /\.js$|\.coffee$/ }) diff --git a/lib/tasks/init.js b/lib/tasks/init.js index 0a9341ff..991c2393 100644 --- a/lib/tasks/init.js +++ b/lib/tasks/init.js @@ -3,33 +3,92 @@ var path = require('path') , helpers = require(path.resolve(__dirname, '..', 'helpers')) , args = require('yargs').argv , clc = require('cli-color') + , _ = require('lodash') module.exports = { "init": { descriptions: { short: "Initializes the project.", - long: [ - "The command will initialize the current directory. The result", - "will be a 'config' as well as a 'migration' folder. Furthermore", - "'config/config.json' will be generated.", - ], + long: (function() { + var result = [ + "The command will initialize the current directory.", + "In detail this means, that you will find the following items afterwards:", + "", + ] + + var items = { + "config": "A folder that contains the config files.", + "config/config.json": "A file that contains the configuration for the ORM.", + "migrations": "A folder that containts the migration files.", + "models": "A folder that contains the model files.", + "models/index.js": "A file that can be required to load all the models." + } + + _.each(items, function(value, key) { + result.push([ + clc.blueBright(helpers.view.pad(key, items)), + value + ].join(" ")) + }) + + result = result.concat([ + "", + "Most of the files and folders can be changed to fit custom folder structures.", + "Check the options for further information." + ]) + + return result + })(), + options: { - "--force": "Will drop the existing config folder and re-create it. " + clc.blueBright("Default: false"), - "--migrations-path": "The path to the migrations folder. " + clc.blueBright("Default: migrations/") + "--force": "Will drop the existing config folder and re-create it. " + clc.blueBright("Default: false") } }, + dependencies: [ + 'init:config', + 'init:migrations', + 'init:models' + ], + + task: function() {} + }, + + "init:config": { + descriptions: { + short: "Initializes the configuration." + }, + task: function() { if (!helpers.config.configFileExists() || !!args.force) { helpers.config.writeDefaultConfig() console.log('Created "' + helpers.config.relativeConfigFile() + '"') } else { - console.log('The file "' + helpers.config.relativeConfigFile() + '" already exists. Run "sequelize init --force" to overwrite it.') + helpers.init.notifyAboutExistingFile(helpers.config.relativeConfigFile()) process.exit(1) } + } + }, - helpers.migration.createMigrationsFolder(!!args.force) + "init:models": { + descriptions: { + short: "Initializes the models." + }, + + task: function() { + helpers.init.createModelsFolder(!!args.force) + helpers.init.createModelsIndexFile(!!args.force) + } + }, + + "init:migrations": { + descriptions: { + short: "Initializes the migrations." + }, + + task: function() { + helpers.init.createMigrationsFolder(!!args.force) } } } diff --git a/lib/tasks/migration.js b/lib/tasks/migration.js index dc79ebd6..b522154c 100644 --- a/lib/tasks/migration.js +++ b/lib/tasks/migration.js @@ -55,7 +55,7 @@ module.exports = { task: function() { var config = null - helpers.migration.createMigrationsFolder() + helpers.init.createMigrationsFolder() try { config = helpers.config.readConfig() @@ -70,11 +70,11 @@ module.exports = { !!args.name ? args.name : 'unnamed-migration' ].join('-') + migrationExtension - fs.writeFileSync(helpers.migration.getMigrationsPath() + '/' + migrationName, getSkeleton()) + fs.writeFileSync(helpers.path.getMigrationsPath() + '/' + migrationName, getSkeleton()) console.log( 'New migration "' + migrationName + '" was added to "' + - path.relative(process.cwd(), helpers.migration.getMigrationsPath()) + '/".' + path.relative(process.cwd(), helpers.path.getMigrationsPath()) + '/".' ) } } diff --git a/package.json b/package.json index 6382ef45..aeefddf9 100644 --- a/package.json +++ b/package.json @@ -4,13 +4,14 @@ "description": "The sequelize CLI.", "main": "index.js", "dependencies": { + "cli-color": "~0.3.2", + "fs-extra": "^0.9.1", "gulp": "~3.6.2", "gulp-help": "~0.1.6", - "sequelize": "*", - "moment": "~2.6.0", - "yargs": "~1.2.1", "lodash": "~2.4.1", - "cli-color": "~0.3.2" + "moment": "~2.6.0", + "sequelize": "*", + "yargs": "~1.2.1" }, "devDependencies": { "coffee-script": "~1.7.1", diff --git a/test/init.test.js b/test/init.test.js index db993390..2fd8e4db 100644 --- a/test/init.test.js +++ b/test/init.test.js @@ -9,17 +9,37 @@ var Support = require(__dirname + '/support') describe(Support.getTestDialectTeaser(flag), function() { ;(function(folders) { folders.forEach(function(folder) { - it("creates a '" + folder + "' folder", function(done) { + it("creates '" + folder + "'", function(done) { + var sourcePath = Support.resolveSupportPath('tmp') + , file = folder + + if (folder.indexOf('/') > -1) { + var split = folder.split('/') + file = split.pop() + sourcePath = Support.resolveSupportPath('tmp', split.join("/")) + } + gulp .src(Support.resolveSupportPath('tmp')) .pipe(helpers.clearDirectory()) .pipe(helpers.runCli(flag)) - .pipe(helpers.listFiles()) - .pipe(helpers.ensureContent(folder)) - .pipe(helpers.teardown(done)) + .pipe(helpers.teardown(function() { + gulp + .src(sourcePath) + .pipe(helpers.listFiles()) + .pipe(helpers.ensureContent(file)) + .pipe(helpers.teardown(done)) + + })) }) }) - })(['config', 'migrations']) + })([ + 'config', + 'config/config.json', + 'migrations', + 'models', + 'models/index.js' + ]) it("creates a custom migrations folder", function(done) { gulp @@ -31,16 +51,61 @@ var Support = require(__dirname + '/support') .pipe(helpers.teardown(done)) }) - it("creates a config.json file", function(done) { + it('creates a custom config file', function(done) { gulp .src(Support.resolveSupportPath('tmp')) .pipe(helpers.clearDirectory()) - .pipe(helpers.runCli(flag)) - .pipe(helpers.listFiles('config')) - .pipe(helpers.ensureContent('config.json')) + .pipe(helpers.runCli(flag + " --config config/database.json")) + .pipe(helpers.teardown(function() { + gulp + .src(Support.resolveSupportPath('tmp', 'config')) + .pipe(helpers.listFiles()) + .pipe(helpers.ensureContent("database.json")) + .pipe(helpers.teardown(done)) + })) + }) + + it('creates a custom models folder', function(done) { + gulp + .src(Support.resolveSupportPath('tmp')) + .pipe(helpers.clearDirectory()) + .pipe(helpers.runCli(flag + " --models-path daos")) + .pipe(helpers.listFiles()) + .pipe(helpers.ensureContent("daos")) .pipe(helpers.teardown(done)) }) + describe('models/index.js', function() { + it('correctly injects the reference to the default config file', function(done) { + gulp + .src(Support.resolveSupportPath('tmp')) + .pipe(helpers.clearDirectory()) + .pipe(helpers.runCli(flag)) + .pipe(helpers.teardown(function() { + gulp + .src(Support.resolveSupportPath('tmp', 'models')) + .pipe(helpers.readFile('index.js')) + .pipe(helpers.ensureContent("__dirname + '/../config/config.json'")) + .pipe(helpers.teardown(done)) + })) + }) + + it('correctly injects the reference to the custom config file', function(done) { + gulp + .src(Support.resolveSupportPath('tmp')) + .pipe(helpers.clearDirectory()) + .pipe(helpers.runCli(flag + " --config my/configuration-file.json")) + .pipe(helpers.teardown(function() { + gulp + .src(Support.resolveSupportPath('tmp', 'models')) + .pipe(helpers.readFile('index.js')) + .pipe(helpers.ensureContent("__dirname + '/../my/configuration-file.json'")) + .pipe(helpers.teardown(done)) + })) + }) + }) + + it("does not overwrite an existing config.json file", function(done) { gulp .src(Support.resolveSupportPath('tmp'))