diff --git a/.babelrc b/.babelrc new file mode 100644 index 00000000..eb394a07 --- /dev/null +++ b/.babelrc @@ -0,0 +1,24 @@ +{ + "presets": [ + ["env", { + "targets": { + "node": "4.0" + }, + "exclude": [ + "transform-async-to-generator", + "transform-regenerator" + ], + "useBuiltIns": true + }] + ], + "plugins": [ + "transform-object-rest-spread", + ["transform-async-to-module-method", { + "module": "bluebird", + "method": "coroutine" + }] + ], + "ignore": [ + "src/assets" + ] +} diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000..6a1e0321 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,49 @@ +{ + "rules": { + "no-console": "off", + "no-extra-parens": "warn", + "valid-jsdoc": "off", + "new-cap": ["warn", {"properties": false}], + "comma-spacing": ["error", {"before": false, "after": true}], + "no-extra-boolean-cast": "warn", + "strict": ["warn", "global"], + "no-var": "error", + "prefer-const": "error", + "semi": ["error", "always"], + "space-before-function-paren": ["warn", "always"], + "keyword-spacing": ["warn"], + "prefer-arrow-callback": "error", + "arrow-parens": ["error", "as-needed"], + "comma-style": ["warn", "last"], + "no-bitwise": "off", + "no-cond-assign": ["error", "except-parens"], + "curly": "off", + "eqeqeq": "error", + "no-extend-native": "error", + "wrap-iife": ["error", "any"], + "indent": ["error", 2, {"SwitchCase": 1}], + "no-use-before-define": "off", + "no-caller": "error", + "no-undef": "error", + "no-unused-vars": "error", + "no-irregular-whitespace": "error", + "max-depth": ["error", 8], + "quotes": ["error", "single", {"avoidEscape": true}], + "linebreak-style": "error", + "no-loop-func": "warn", + "object-shorthand": "error", + "one-var-declaration-per-line": "warn", + "comma-dangle": "warn", + "no-shadow": "warn", + "camelcase": "warn" + }, + "parserOptions": { + "ecmaVersion": 2017, + "sourceType": "module" + }, + "env": { + "node": true, + "mocha": true, + "es6": true + } +} diff --git a/.gitignore b/.gitignore index e7a45c28..ada6b1c3 100644 --- a/.gitignore +++ b/.gitignore @@ -7,24 +7,24 @@ pids *.pid *.seed +# Editor files +.vscode + # Directory for instrumented libs generated by jscoverage/JSCover lib-cov # Coverage directory used by tools like istanbul coverage -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Vagrant intermediate storage -var/vagrant/.vagrant - # Compiled binary addons (http://nodejs.org/api/addons.html) build/Release -# Dependency directory -# Deployed apps should consider commenting this line out: -# see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git +# Extra folders node_modules +lib +test/support/tmp/* +!test/support/tmp/.gitkeep -test/support/tmp +# Extra files +package-lock.json +npm-debug.log diff --git a/.jscsrc b/.jscsrc deleted file mode 100644 index 3e0e14f2..00000000 --- a/.jscsrc +++ /dev/null @@ -1,57 +0,0 @@ -{ - "disallowEmptyBlocks": true, - "disallowKeywordsOnNewLine": ["else"], - "disallowKeywords": ["with"], - "disallowMixedSpacesAndTabs": true, - "disallowMultipleLineBreaks": true, - "disallowMultipleLineStrings": true, - "disallowMultipleVarDecl": "exceptUndefined", - "disallowNewlineBeforeBlockStatements": true, - "disallowPaddingNewlinesInBlocks": true, - "disallowSpaceAfterObjectKeys": true, - "disallowSpaceAfterPrefixUnaryOperators": true, - "disallowSpaceBeforePostfixUnaryOperators": true, - "disallowSpacesInCallExpression": true, - "disallowTrailingComma": true, - "disallowTrailingWhitespace": true, - "disallowYodaConditions": true, - "maximumLineLength": 100, - "requireBlocksOnNewline": true, - "requireCapitalizedConstructors": true, - "requireCurlyBraces": ["if", "else", "for", "while", "do", "try", "catch"], - "requireLineFeedAtFileEnd": true, - "requirePaddingNewlinesBeforeKeywords": [ - "do","for","if","switch","try","while","with" - ], - "requireParenthesesAroundIIFE": true, - "requireSpaceAfterBinaryOperators": true, - "requireSpaceAfterKeywords": true, - "requireSpaceAfterLineComment": true, - "requireSpaceBeforeBinaryOperators": true, - "requireSpaceBeforeBlockStatements": true, - "requireSpaceBeforeKeywords": [ - "else", "while", "catch" - ], - "requireSpaceBetweenArguments": true, - "requireSpaceBeforeObjectValues": true, - "requireSpacesInConditionalExpression": { - "afterTest": true, - "beforeConsequent": true, - "afterConsequent": true, - "beforeAlternate": true - }, - "requireSpacesInFunctionDeclaration": { - "beforeOpeningRoundBrace": true, - "beforeOpeningCurlyBrace": true - }, - "requireSpacesInFunctionExpression": { - "beforeOpeningRoundBrace": true, - "beforeOpeningCurlyBrace": true - }, - "validateIndentation": 2, - "validateLineBreaks": "LF", - "validateParameterSeparator": ", ", - "validateQuoteMarks": "'", - "requireSemicolons": true, - "requirePaddingNewLineAfterVariableDeclaration": true -} diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index 650fdb3a..00000000 --- a/.jshintrc +++ /dev/null @@ -1,19 +0,0 @@ -{ - "node": true, - "quotmark": "single", - "curly": true, - "eqeqeq": true, - "forin": true, - "indent": 2, - "immed": true, - "latedef": "nofunc", - "newcap": true, - "noempty": true, - "nonbsp": true, - "unused": true, - "strict": true, - "maxdepth": 3, - "maxlen": 100, - "nomen": true, - "trailing": true -} diff --git a/.mention-bot b/.mention-bot deleted file mode 100644 index cf152b3f..00000000 --- a/.mention-bot +++ /dev/null @@ -1,4 +0,0 @@ -{ - "userBlacklist": ["sdepold"], - "userBlacklistForPR": ["greenkeeperio-bot"] -} diff --git a/.npmignore b/.npmignore new file mode 100644 index 00000000..a3b78c77 --- /dev/null +++ b/.npmignore @@ -0,0 +1,20 @@ +# Logs +logs +*.log + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +node_modules + +package-lock.json +.vscode +npm-debug.log diff --git a/.travis.yml b/.travis.yml index f9eac802..3e054cd1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,27 +1,35 @@ -before_script: - - "mysql -e 'create database sequelize_test;'" - - "psql -c 'create database sequelize_test;' -U postgres" - - npm install js2coffee@$(echo $JS2COFFEE) - - npm install sequelize@$(echo $SEQUELIZE) - -script: - - travis_retry node_modules/.bin/gulp - -env: - - JS2COFFEE=2.0.0 DIALECT=mysql SEQUELIZE=3.30.4 - - JS2COFFEE=2.0.0 DIALECT=postgres SEQUELIZE=4.1.0 - -language: node_js - -node_js: - - "4.0" - - "6.0" - sudo: false +dist: trusty -addons: - postgresql: "9.4" +language: node_js cache: directories: - node_modules + +jobs: + include: + - stage: tests + node_js: 4 + env: DIALECT=mysql SEQUELIZE=3.30.4 + - stage: tests + node_js: 4 + env: DIALECT=postgres SEQUELIZE=3.30.4 + - stage: tests + node_js: 4 + env: DIALECT=sqlite SEQUELIZE=3.30.4 + - stage: tests + node_js: 6 + env: DIALECT=postgres SEQUELIZE=latest + - stage: tests + node_js: 6 + env: DIALECT=sqlite SEQUELIZE=latest + +before_script: + - "mysql -e 'create database sequelize_test;'" + - "psql -c 'create database sequelize_test;' -U postgres" + - npm install sequelize@$(echo $SEQUELIZE) + - npm run build + +script: + - npm run test diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fde583d..3e477c38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,32 @@ All notable changes to this project will be documented in this file. ## Upcoming + +## v3.0.0 - 1st, Sep 2017 + +### Removed +- `db:migrate:old_schema` +- `--coffee` support +- `help:*` commands + +### Fixed +- Drop Gulp [#344](https://github.com/sequelize/cli/issues/344) +- NSP Vulnerability [#466](https://github.com/sequelize/cli/issues/466) +- Non functional with Node 7 [#383](https://github.com/sequelize/cli/issues/383) +- Unable to find Gulp [#138](https://github.com/sequelize/cli/issues/138) +- Reintegrate Gulp [#5](https://github.com/sequelize/cli/issues/5) +- Unable to seed multiple files [#523](https://github.com/sequelize/cli/issues/523) +- No Gulpfile found [#480](https://github.com/sequelize/cli/issues/480) +- Exit Code(1) when migration undo fail [#394](https://github.com/sequelize/cli/issues/394) +- ES2015 [#389](https://github.com/sequelize/cli/issues/389) +- `--coffee` flag dont work with `.rc` file [#244](https://github.com/sequelize/cli/issues/244) +- CLI dont halt on error [#106](https://github.com/sequelize/cli/issues/106) + +### Improvements +- No Gulp, better startup time +- Proper exit codes +- Remove dependency on `moment` , `findup-sync`, `gulp` and `gulp-help` + ## v2.8.0 - 2017-08-04 ### Added - Timestamps db:migrate:schema:timestamps:add [#460](https://github.com/sequelize/cli/pull/460) diff --git a/README.md b/README.md index b99fa544..502d531d 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# sequelize/cli [![Build Status](https://travis-ci.org/sequelize/cli.svg?branch=master)](https://travis-ci.org/sequelize/cli) [![Code Climate](https://codeclimate.com/github/sequelize/cli.png)](https://codeclimate.com/github/sequelize/cli) [![Greenkeeper badge](https://badges.greenkeeper.io/sequelize/cli.svg)](https://greenkeeper.io/) +# sequelize/cli [![Build Status](https://travis-ci.org/sequelize/cli.svg?branch=master)](https://travis-ci.org/sequelize/cli) [![Greenkeeper badge](https://badges.greenkeeper.io/sequelize/cli.svg)](https://greenkeeper.io/) The Sequelize Command Line Interface (CLI) ## Sequelize Support -In current v2 release CLI generate migration/models which follow Sequelize v3 format, CLI will work with Sequelize v4 in most cases but migration/model skeleton is still generated to support v3. +In current v3 release CLI generate migration/models which follow Sequelize v3 format, CLI will work with Sequelize v4 in most cases but migration/model skeleton is still generated to support v3. Full support for Sequelize v4 will be coming soon with [Sequelize CLI v4](https://github.com/sequelize/cli/issues/441) @@ -24,56 +24,34 @@ $ npm install --save sequelize-cli ## Global Install Usage ```bash -$ sequelize [--HARMONY-FLAGS] +$ sequelize ``` - ``` -Sequelize [Node: 7.8.0, CLI: 2.7.0, ORM: 3.27.0] +Sequelize CLI [Node: 6.11.2, CLI: 3.0.0, ORM: 4.8.0] -Usage - sequelize [task][options...] -Available tasks - db:migrate Run pending migrations. - db:migrate:old_schema Update legacy migration table +Commands: + db:migrate Run pending migrations db:migrate:schema:timestamps:add Update migration table to have timestamps db:migrate:status List the status of all migrations - db:migrate:undo Reverts a migration. - db:migrate:undo:all Revert all migrations ran. - db:seed Run specified seeder. - db:seed:all Run every seeder. - db:seed:undo Deletes data from the database. - db:seed:undo:all Deletes data from the database. - help Display this help text. Aliases: h - init Initializes the project. [init:config, init:migrations, init:seeders, init:models] - init:config Initializes the configuration. - init:migrations Initializes the migrations. - init:models Initializes the models. - init:seeders Initializes the seeders. - migration:create Generates a new migration file. Aliases: migration:generate - model:create Generates a model and its migration. Aliases: model:generate - seed:create Generates a new seed file. Aliases: seed:generate - version Prints the version number. Aliases: v -Available manuals - help:db:migrate The documentation for "sequelize db:migrate". - help:db:migrate:old_schema The documentation for "sequelize db:migrate:old_schema". - help:db:migrate:schema:timestamps:add The documentation for "sequelize db:migrate:schema:timestamps:add". - help:db:migrate:status The documentation for "sequelize db:migrate:status". - help:db:migrate:undo The documentation for "sequelize db:migrate:undo". - help:db:migrate:undo:all The documentation for "sequelize db:migrate:undo:all". - help:db:seed The documentation for "sequelize db:seed". - help:db:seed:all The documentation for "sequelize db:seed:all". - help:db:seed:undo The documentation for "sequelize db:seed:undo". - help:db:seed:undo:all The documentation for "sequelize db:seed:undo:all". - help:init The documentation for "sequelize init". - help:init:config The documentation for "sequelize init:config". - help:init:migrations The documentation for "sequelize init:migrations". - help:init:models The documentation for "sequelize init:models". - help:init:seeders The documentation for "sequelize init:seeders". - help:migration:create The documentation for "sequelize migration:create". - help:model:create The documentation for "sequelize model:create". - help:seed:create The documentation for "sequelize seed:create". - help:version The documentation for "sequelize version". + db:migrate:undo Reverts a migration + db:migrate:undo:all Revert all migrations ran + db:seed Run specified seeder + db:seed:undo Deletes data from the database + db:seed:all Run every seeder + db:seed:undo:all Deletes data from the database + init Initializes project + init:config Initializes configuration + init:migrations Initializes migrations + init:models Initializes models + init:seeders Initializes seeders + migration:generate Generates a new migration file [aliases: migration:create] + model:generate Generates a model and its migration [aliases: model:create] + seed:generate Generates a new seed file [aliases: seed:create] + +Options: + --version Show version number [boolean] + --help Show help [boolean] ``` ## Local Install Usage @@ -104,11 +82,6 @@ module.exports = { This will configure the CLI to always treat `config/database.json` as config file and `db/migrate` as the directory for migrations. -### CoffeeScript support - -The CLI is compatible with CoffeeScript. You can tell the CLI to enable that support via the `--coffee` -flag. Please note that you'll need to install `js2coffee` and `coffee-script` for full support. - ### Configuration file By default the CLI will try to use the file `config/config.js` and `config/config.json`. You can modify that path either via the `--config` flag or via the option mentioned earlier. Here is how a configuration file might look like (this is the one that `sequelize init` generates): @@ -279,16 +252,7 @@ module.exports = { ### Schema migration -Since v1.0.0 the CLI supports a new schema for saving the executed migrations. It will tell you about that -when you run a migration while having the old schema. You can opt-in for auto migrating the schema by adding a special property to your config file: - -```json -{ - "development": { - "autoMigrateOldSchema": true - } -} -``` +Sequelize CLI continue to use schema from `v2` and fully compatible with `v2`. If you are still using old schema from pre `v2`, use `v2` to upgrade to current schema with `db:migrate:old_schema` #### Timestamps @@ -322,10 +286,6 @@ Please note that you can either return a Promise or call the third argument of t Additional note: If you need to access the sequelize instance, you can easily do that via `queryInterface.sequelize`. For example `queryInterface.sequelize.query('CREATE TABLE mytable();')`. -## Help - -Read the manuals via `sequelize help:` for further information. - -## FAQ +## Documentation and FAQ -You can find FAQ section [here](https://github.com/sequelize/cli/blob/master/FAQ.md) +More documentation around migrations [here](http://docs.sequelizejs.com/manual/tutorial/migrations.html). You can find FAQ section [here](https://github.com/sequelize/cli/blob/master/FAQ.md) diff --git a/bin/sequelize b/bin/sequelize deleted file mode 100755 index ea75e675..00000000 --- a/bin/sequelize +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env node - -'use strict'; - -var spawn = require('child_process').spawn; -var path = require('path'); -var args = process.argv.slice(2); -var yargs = require('yargs'); -var argv = yargs.argv; -var _ = require('lodash'); -var helpers = require(path.resolve(__dirname, '..', 'lib', 'helpers')); - -if ((args[0] === '-v') || (args[0] === '-V')) { - args = ['version']; -} - -// Let's load additional options from a file and add it to the gulp call -(function (optionsPath) { - var rcFile = path.resolve(process.cwd(), '.sequelizerc'); - - if (!optionsPath && helpers.path.existsSync(rcFile)) { - optionsPath = rcFile; - } - - if (optionsPath) { - optionsPath = path.resolve(process.cwd(), optionsPath); - - var options = require(optionsPath); - var optionsKeys = Object.keys(options); - - optionsKeys = optionsKeys.filter(function (optionKey) { - return !argv[optionKey]; - }); - - optionsKeys.forEach(function (optionKey) { - var value = options[optionKey]; - - if (optionKey.indexOf('--') !== 0) { - optionKey = '--' + optionKey; - } - - args = args.concat([optionKey, value]); - }); - } -})(yargs.argv.optionsPath); - -args = args.concat([ - '--gulpfile', path.resolve(__dirname, '..', 'lib', 'gulpfile.js'), - '--cwd', process.cwd() -]); - -args.unshift(findGulpCliPath()); - -// Add harmony support -[ '--harmony-scoping', '--harmony-modules', '--harmony-proxies', - '--harmony-generators', '--harmony-numeric-literals', '--harmony-strings', - '--harmony-arrays', '--harmony-arrow-functions', '--harmony' -].forEach(function (harmonyFlag) { - if (_.includes(args, harmonyFlag)) { - args = _.without(args, harmonyFlag); - args.unshift(harmonyFlag); - } -}); - -var call = spawn(process.argv[0], args); - -helpers.view.teaser(); - -call.stdout.on('data', function (data) { - var output = helpers.log.parse(data); - - if (!!output) { - console.log(output); - } -}); - -call.stderr.on('data', function (data) { - process.stderr.write(data); -}); - -call.on('exit', function (code) { - process.exit(code); -}); - -function findGulpCliPath () { - var gulp = path.resolve(__dirname, '..', 'node_modules', 'gulp', 'bin', 'gulp.js'); - - if (!helpers.path.existsSync(gulp)) { - gulp = path.resolve(process.cwd(), 'node_modules', 'gulp', 'bin', 'gulp.js'); - } - - if (!helpers.path.existsSync(gulp)) { - gulp = require.resolve('gulp').replace('index.js', 'bin/gulp.js'); - } - - if (!helpers.path.existsSync(gulp)) { - throw new Error('Unable to find the `gulp` binary'); - } - - return gulp; -} diff --git a/gulpfile.js b/gulpfile.js deleted file mode 100644 index 5ebc4452..00000000 --- a/gulpfile.js +++ /dev/null @@ -1,53 +0,0 @@ -'use strict'; - -var args = require('yargs').argv; -var gulp = require('gulp'); -var jscs = require('gulp-jscs'); -var jshint = require('gulp-jshint'); -var mocha = require('gulp-mocha'); -var path = require('path'); -var runSequence = require('run-sequence'); - -gulp.task('default', function (done) { - runSequence('lint', 'test', done); -}); - -gulp.task('test', function (done) { - runSequence('test-unit', 'test-integration', done); -}); - -gulp.task('lint', function (done) { - runSequence('lint-code', done); -}); - -gulp.task('lint-code', function () { - return gulp - .src([ - './gulpfile.js', - './index.js', - './bin/**/*', - './lib/**/*.js', - '!./lib/assets/**/*.js', - './test/**/*.js', - '!./test/support/tmp/**/*.js' - ]) - .pipe(jscs()) - .pipe(jshint()) - .pipe(jshint.reporter('default')) - .pipe(jshint.reporter('fail')); -}); - -gulp.task('test-unit', function () { - // TODO -}); - -gulp.task('test-integration', function () { - gulp - .src(path.resolve(__dirname, 'test', '**', '*.test.js'), { read: false }) - .pipe(mocha({ - reporter: 'spec', - ignoreLeaks: true, - timeout: 30000, - grep: args.grep - })); -}); diff --git a/lib/gulpfile.js b/lib/gulpfile.js deleted file mode 100644 index b795933c..00000000 --- a/lib/gulpfile.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -var gulp = require('gulp'); -var path = require('path'); -var fs = require('fs'); -var helpers = require(path.resolve(__dirname, 'helpers')); - -require('gulp-help')(gulp, { - aliases: ['h'], - afterPrintCallback: helpers.gulp.printManuals -}); - -fs - .readdirSync(path.resolve(__dirname, 'tasks')) - .filter(function (file) { - return (file.indexOf('.') !== 0); - }) - .map(function (file) { - return require(path.resolve(__dirname, 'tasks', file)); - }) - .forEach(function (tasks) { - Object.keys(tasks).forEach(function (taskName) { - helpers.gulp.addTask(gulp, taskName, tasks[taskName]); - helpers.gulp.addHelp(gulp, taskName, tasks[taskName]); - }); - }); diff --git a/lib/helpers/asset-helper.js b/lib/helpers/asset-helper.js deleted file mode 100644 index 46314020..00000000 --- a/lib/helpers/asset-helper.js +++ /dev/null @@ -1,28 +0,0 @@ -'use strict'; - -var fs = require('fs-extra'); -var path = require('path'); - -module.exports = { - copy: function (from, to) { - fs.copySync(path.resolve(__dirname, '..', 'assets', from), to); - }, - - read: function (assetPath) { - return fs.readFileSync(path.resolve(__dirname, '..', 'assets', assetPath)).toString(); - }, - - write: function (targetPath, content) { - fs.writeFileSync(targetPath, content); - }, - - inject: function (filePath, token, content) { - var fileContent = fs.readFileSync(filePath).toString(); - - fs.writeFileSync(filePath, fileContent.replace(token, content)); - }, - - injectConfigFilePath: function (filePath, configPath) { - this.inject(filePath, '__CONFIG_FILE__', configPath); - } -}; diff --git a/lib/helpers/generic-helper.js b/lib/helpers/generic-helper.js deleted file mode 100644 index 38e54345..00000000 --- a/lib/helpers/generic-helper.js +++ /dev/null @@ -1,58 +0,0 @@ -'use strict'; - -var fs = require('fs'); -var args = require('yargs').argv; -var path = require('path'); -var resolve = require('resolve').sync; - -module.exports = { - mkdirp: function (path, root) { - var dirs = path.split('/'); - var dir = dirs.shift(); - - root = (root || '') + dir + '/'; - - try { - fs.mkdirSync(root); - } catch (e) { - // dir wasn't made, something went wrong - if (!fs.statSync(root).isDirectory()) { - throw new Error(e); - } - } - - return !dirs.length || this.mkdirp(dirs.join('/'), root); - }, - - getEnvironment: function () { - return args.env || process.env.NODE_ENV || 'development'; - }, - - getSequelize: function (file) { - var sequelizePath; - var resolvePath = file ? path.join('sequelize', file) : 'sequelize'; - var resolveOptions = { basedir: process.cwd() }; - - try { - sequelizePath = require.resolve(resolvePath, resolveOptions); - } catch (e) { - } - - try { - sequelizePath = sequelizePath || resolve(resolvePath, resolveOptions); - } catch (e) { - console.error('Unable to resolve sequelize package in ' + process.cwd()); - process.exit(1); - } - - return require(sequelizePath); - }, - - execQuery: function (sequelize, sql, options) { - if (sequelize.query.length === 2) { - return sequelize.query(sql, options); - } else { - return sequelize.query(sql, null, options); - } - } -}; diff --git a/lib/helpers/gulp-helper.js b/lib/helpers/gulp-helper.js deleted file mode 100644 index 70fe3f60..00000000 --- a/lib/helpers/gulp-helper.js +++ /dev/null @@ -1,129 +0,0 @@ -'use strict'; - -var helpers = require(__dirname); -var _ = require('lodash'); -var clc = require('cli-color'); - -var config = helpers.config.init(); - -module.exports = { - addTask: function (gulp, taskName, task) { - gulp.task( - taskName, - task.descriptions.short, - task.dependencies || [], - function () { - return config.then(function () { - return task.task(); - }); - }, { - aliases: task.aliases || [] - } - ); - }, - - addHelp: function (gulp, taskName, task) { - var self = this; - - gulp.task( - 'help:' + taskName, - false, - function () { - return config.then(function () { - Object.keys(task.descriptions).forEach(function (description) { - if (typeof task.descriptions[description] === 'function') { - task.descriptions[description] = task.descriptions[description](); - } - }); - helpers.view.log(clc.bold('COMMANDS')); - - var commands = [ taskName ].concat(task.aliases || []); - var commandMargin = Math.max.apply(null, commands.map(function (c) { - return c.length; - })); - - commands.forEach(function (command) { - var s = [ - 'sequelize', command + (new Array(commandMargin - command.length + 1).join(' ')), - '--', task.descriptions.short - ].join(' '); - - helpers.view.log(' ' + s); - }); - helpers.view.log(); - - helpers.view.log(clc.bold('DESCRIPTION')); - - (task.descriptions.long || [task.descriptions.short]).forEach(function (line) { - helpers.view.log(' ' + line); - }); - - (function (options) { - if (options) { - var margin = Math.max.apply(null, Object.keys(options).map(function (o) { - return o.length; - })); - - helpers.view.log(); - helpers.view.log(clc.bold('OPTIONS')); - - Object.keys(options).forEach(function (option) { - var args = [' ', option]; - - args.push(new Array(margin - option.length + 1).join(' ')); - args.push(options[option]); - - helpers.view.log.apply(helpers.view, args); - }); - } - })(_.assign(self.getGlobalOptions(), task.descriptions.options)); - - helpers.view.log(); - }); - } - ); - }, - - getGlobalOptions: function () { - return { - '--env': 'The environment to run the command in. ' + - clc.blueBright('Default: development'), - '--coffee': 'Enables coffee script support. ' + - clc.blueBright('Default: false'), - '--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'), - '--seeders-path': 'The path to the seeders folder. ' + - clc.blueBright('Default: seeders'), - '--models-path': 'The path to the models folder.' + - clc.blueBright('Default: models'), - '--url': 'The database connection string to use. Alternative to using --config files. ' + - clc.blueBright('Default: none') - }; - }, - - printManuals: function (tasks) { - var manuals = Object.keys(tasks).filter(function (name) { - return name.indexOf('help:') === 0; - }).sort(); - var margin = manuals.reduce(function (m, taskName) { - return (m > taskName.length) ? m : taskName.length; - }, 0); - - console.log('Available manuals'); - - manuals.forEach(function (name) { - var args = [' ', name]; - - args.push(new Array(margin - name.length + 1).join(' ')); - args.push('The documentation for "sequelize ' + name.replace('help:', '') + '".'); - - console.log.apply(console, args); - }); - - console.log(); - } -}; diff --git a/lib/helpers/index.js b/lib/helpers/index.js deleted file mode 100644 index 80622459..00000000 --- a/lib/helpers/index.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; - -var path = require('path'); -var fs = require('fs'); - -module.exports = {}; - -fs - .readdirSync(__dirname) - .filter(function (file) { - return (file.indexOf('.') !== 0) && (file.indexOf('index.js') === -1); - }) - .forEach(function (file) { - module.exports[file.replace('-helper.js', '')] = require(path.resolve(__dirname, file)); - }); diff --git a/lib/helpers/init-helper.js b/lib/helpers/init-helper.js deleted file mode 100644 index 9215100f..00000000 --- a/lib/helpers/init-helper.js +++ /dev/null @@ -1,83 +0,0 @@ -'use strict'; - -var helpers = require(__dirname); -var path = require('path'); -var fs = require('fs'); -var 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(path.resolve(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.getPath('migration'), force); - }, - - createSeedersFolder: function (force) { - this.createFolder('seeders', helpers.path.getPath('seeder'), force); - }, - - createModelsFolder: function (force) { - this.createFolder('models', helpers.path.getModelsPath(), force); - }, - - createModelsIndexFile: function (force) { - var modelsPath = helpers.path.getModelsPath(); - var indexPath = path.resolve( - modelsPath, - helpers.path.addFileExtension('index') - ); - - if (!helpers.path.existsSync(modelsPath)) { - helpers.view.log('Models folder not available.'); - } else if (helpers.path.existsSync(indexPath) && !force) { - this.notifyAboutExistingFile(indexPath); - } else { - var relativeConfigPath = path.relative( - helpers.path.getModelsPath(), - helpers.config.getConfigFile() - ); - - helpers.asset.write( - indexPath, - helpers.template.render('models/index.js', { - configFile: '__dirname + \'/' + relativeConfigPath + '\'' - }, { - beautify: false - }) - ); - } - } -}; diff --git a/lib/helpers/log-helper.js b/lib/helpers/log-helper.js deleted file mode 100644 index 02454aae..00000000 --- a/lib/helpers/log-helper.js +++ /dev/null @@ -1,44 +0,0 @@ -'use strict'; - -var _ = require('lodash'); - -module.exports = { - parse: function (buffer) { - var lines = buffer.toString().split('\n'); - var result = lines.map(mapLine); - - return _.compact(result).join('\n'); - } -}; - -function mapLine (line) { - return filters().reduce(function (filteredLine, filter) { - if (!!filteredLine) { - return filter(filteredLine); - } - }, line); -} - -function filters () { - return [ - function filterTimestamps (l) { - if (!l.match(/\[\d{2}:\d{2}:\d{2}\]/)) { - return l; - } - }, - - function filterGulpfile (l) { - if (!l.match(/^Using\sgulpfile/) && !l.match(/^Starting|Finished\s/)) { - return l; - } - }, - - function parseProgramName (l) { - if (!l.match(/gulp \[TASK\]/)) { - return l; - } else { - return l.replace('gulp [TASK]', 'sequelize [task]'); - } - } - ]; -} diff --git a/lib/helpers/template-helper.js b/lib/helpers/template-helper.js deleted file mode 100644 index 0139ac6f..00000000 --- a/lib/helpers/template-helper.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; - -var _ = require('lodash'); -var beautify = require('js-beautify'); -var helpers = require(__dirname); - -module.exports = { - getCoffeeConverter: function () { - return helpers.path.resolve('js2coffee') || (function () { - console.log('Unable to find \'js2coffee\'. Please add it to your project.'); - process.exit(1); - })(); - }, - - render: function (path, locals, options) { - options = _.assign({ - beautify: true, - indent_size: 2, - preserve_newlines: false - }, options || {}); - - var template = helpers.asset.read(path); - var content = _.template(template)(locals || {}); - - if (options.beautify) { - content = beautify(content, options); - } - - if (helpers.config.supportsCoffee()) { - content = this.getCoffeeConverter().build(content); - content = content.code || content; - } - - return content; - } -}; diff --git a/lib/helpers/version-helper.js b/lib/helpers/version-helper.js deleted file mode 100644 index 38a63399..00000000 --- a/lib/helpers/version-helper.js +++ /dev/null @@ -1,58 +0,0 @@ -'use strict'; - -var path = require('path'); -var packageJson = require(path.resolve(__dirname, '..', '..', 'package.json')); -var helpers = require(__dirname); -var findup = require('findup-sync'); - -module.exports = { - getCliVersion: function () { - return packageJson.version; - }, - - getOrmVersion: function () { - return helpers.generic.getSequelize('package.json').version; - }, - - getDialect: function () { - try { - return helpers.config.readConfig(); - } catch (e) { - return null; - } - }, - - getDialectVersion: function () { - var adapterName = this.getDialectName(); - - try { - if (adapterName) { - return require( - findup('package.json') - ).dependencies[adapterName]; - } - } catch (e) { - } - - return null; - }, - - getDialectName: function () { - var config = this.getDialect(); - - if (config) { - return { - 'sqlite': 'sqlite3', - 'postgres': 'pg', - 'mariadb': 'mariasql', - 'mysql': 'mysql' - }[config.dialect]; - } else { - return null; - } - }, - - getNodeVersion: function () { - return process.version.replace('v', ''); - } -}; diff --git a/lib/helpers/view-helper.js b/lib/helpers/view-helper.js deleted file mode 100644 index 9332c7d3..00000000 --- a/lib/helpers/view-helper.js +++ /dev/null @@ -1,46 +0,0 @@ -'use strict'; - -var helpers = require(__dirname); -var clc = require('cli-color'); -var _ = require('lodash'); - -module.exports = { - teaser: function () { - var versions = [ - 'Node: ' + helpers.version.getNodeVersion(), - 'CLI: ' + helpers.version.getCliVersion(), - 'ORM: ' + helpers.version.getOrmVersion() - ]; - - if (helpers.version.getDialectName() && helpers.version.getDialectVersion()) { - versions.push( - helpers.version.getDialectName() + - ': ' + - helpers.version.getDialectVersion() - ); - } - - this.log(); - this.log(clc.underline('Sequelize [' + versions.join(', ') + ']')); - this.log(); - }, - - log: console.log, - error: console.error, - - 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 deleted file mode 100644 index 761934f6..00000000 --- a/lib/tasks/db.js +++ /dev/null @@ -1,569 +0,0 @@ -'use strict'; - -var Bluebird = require('bluebird'); -var fs = require('fs'); -var path = require('path'); -var helpers = require(path.resolve(__dirname, '..', 'helpers')); -var args = require('yargs').string('seed').argv; -var _ = require('lodash'); -var Sequelize = helpers.generic.getSequelize(); -var Umzug = require('umzug'); -var clc = require('cli-color'); - -module.exports = { - 'db:migrate': { - descriptions: { - 'short': 'Run pending migrations.', - 'long': [ - 'The command runs every not yet executed migration.' - ] - }, - - task: function () { - return getMigrator('migration').then(function (migrator) { - return ensureCurrentMetaSchema(migrator).then(function () { - return migrator.pending(); - }).then(function (migrations) { - if (migrations.length === 0) { - console.log('No migrations were executed, database schema was already up to date.'); - process.exit(0); - } - }).then(function () { - return migrator.up(); - }).then(function () { - process.exit(0); - }).catch(function (err) { - console.error(err); - process.exit(1); - }); - }); - } - }, - - 'db:seed': { - descriptions: { - 'short': 'Run specified seeder.', - 'long': [ - 'The command runs every existing seed file.' - ], - options: { - '--seed': 'List of seed files to run.' - } - }, - - preChecks: [ - ensureSeeds - ], - - task: function () { - this.preChecks.forEach(function (preCheck) { - preCheck(); - }); - - return getMigrator('seeder').then(function (migrator) { - return migrator.up(args.seed) - .then(function () { - process.exit(0); - }) - .catch(function (err) { - console.error('Seed file failed with error:', err.message, err.stack); - process.exit(1); - }); - }); - } - }, - - 'db:seed:all': { - descriptions: { - 'short': 'Run every seeder.', - 'long': [ - 'The command runs every existing seed file in alphabetical order.' - ] - }, - - task: function () { - return getMigrator('seeder').then(function (migrator) { - return migrator.pending() - .then(function (seeders) { - if (seeders.length === 0) { - console.log('No seeders found.'); - process.exit(0); - } - - return migrator.up({migrations: _.chain(seeders).map('file').value()}); - }).then(function () { - process.exit(0); - }) - .catch(function (err) { - console.error('Seed file failed with error:', err.message, err.stack); - process.exit(1); - }); - }); - } - }, - - 'db:seed:undo:all': { - descriptions: { - 'short': 'Deletes data from the database.', - 'long': [ - 'The command tries unseeding every existing seed.' - ] - }, - - task: function () { - return getMigrator('seeder').then(function (migrator) { - return ( - helpers.umzug.getStorage('seeder') === 'none' ? migrator.pending() : migrator.executed() - ) - .then(function (seeders) { - if (seeders.length === 0) { - console.log('No seeders found.'); - process.exit(0); - } - - return migrator.down({migrations: _.chain(seeders).map('file').reverse().value()}); - }).then(function () { - process.exit(0); - }) - .catch(function (err) { - console.error('Seed file failed with error:', err.message, err.stack); - process.exit(1); - }); - }); - } - }, - - 'db:seed:undo': { - descriptions: { - 'short': 'Deletes data from the database.', - 'long': [ - 'The command unseeds every existing seed.' - ], - options: { - '--seed': 'List of seed files to unseed.' - } - }, - - preChecks: [ - ensureSeeds - ], - - task: function () { - this.preChecks.forEach(function (preCheck) { - preCheck(); - }); - - return getMigrator('seeder').then(function (migrator) { - return migrator.down({migrations: args.seed}) - .then(function () { - process.exit(0); - }) - .catch(function (err) { - console.error('Seed file failed with error:', err.message, err.stack); - process.exit(1); - }); - }); - } - }, - - 'db:migrate:status': { - descriptions: { - 'short': 'List the status of all migrations' - }, - - task: function () { - return getMigrator('migration').then(function (migrator) { - return ensureCurrentMetaSchema(migrator).then(function () { - return migrator.executed(); - }).then(function (migrations) { - _.forEach(migrations, function (migration) { - console.log('up ', migration.file); - }); - }).then(function () { - return migrator.pending(); - }).then(function (migrations) { - _.forEach(migrations, function (migration) { - console.log('down', migration.file); - }); - }).then(function () { - process.exit(0); - }).catch(function (err) { - console.error(err); - process.exit(1); - }); - }); - } - }, - - 'db:migrate:undo': { - descriptions: { - 'short': 'Reverts a migration.', - options: { - '--name': 'Name of the migration to undo.' - } - }, - - task: function () { - return getMigrator('migration').then(function (migrator) { - return ensureCurrentMetaSchema(migrator).then(function () { - return migrator.executed(); - }).then(function (migrations) { - if (migrations.length === 0) { - console.log('No executed migrations found.'); - process.exit(0); - } - }).then(function () { - if (args.name) { - return migrator.down(args.name); - } else { - return migrator.down(); - } - }).then(function () { - process.exit(0); - }).catch(function (err) { - console.error(err); - process.exit(1); - }); - }); - } - }, - - 'db:migrate:undo:all': { - descriptions: { - 'short': 'Revert all migrations ran.', - options: { - '--to': 'Revert to the provided migration. Default is 0.' - } - }, - - task: function () { - return getMigrator('migration').then(function (migrator) { - return ensureCurrentMetaSchema(migrator).then(function () { - return migrator.executed(); - }).then(function (migrations) { - if (migrations.length === 0) { - console.log('No executed migrations found.'); - process.exit(0); - } - }).then(function () { - var to = args.to || 0; - return migrator.down({to: to}); - }).then(function () { - process.exit(0); - }).catch(function (err) { - console.error(err); - process.exit(1); - }); - }); - } - }, - - 'db:migrate:old_schema': { - descriptions: { - 'short': 'Update legacy migration table', - 'long': [ - 'This command updates the legacy structure of the SequelizeMeta table to', - 'the newer version which is shipped with the migrator engine "umzug" and', - 'which is the required structure of the CLI since version 1.0.0.', - '', - 'In details this means, that the previous structure (id:int, from:string,', - 'to:string) gets migrated to the new structure (name:string). As the old', - 'structure does not actually contain all single migration names but only', - 'certain ranges, the script will take a look at the migrations folder and', - 'generate the single migration names accordingly.', - '', - 'Please note that the script will create a backup of your old table schema', - 'table by renaming the original table to SequelizeMetaBackup.' - ] - }, - - task: function () { - return getMigrator('migration') - .then(function (migrator) { - return tryToMigrateFromOldSchema(migrator) - .then(function (items) { - if (items) { - console.log('Successfully migrated ' + items.length + ' migrations.'); - } - - process.exit(0); - }, function (err) { - console.error(err); - process.exit(1); - }); - }); - } - }, - - 'db:migrate:schema:timestamps:add': { - descriptions: { - 'short': 'Update migration table to have timestamps', - 'long': [ - 'This command updates the structure of the SequelizeMeta table to include', - '"createdAt" and "updatedAt" columns. This is an optional definition and', - 'not required to keep on working with sequelize-cli.', - '', - 'Please note that the script will create a backup of your old table schema', - 'table by renaming the original table to "Backup".' - ] - }, - - task: function () { - return getMigrator('migration') - .then(function (migrator) { - return addTimestampsToSchema(migrator) - .then(function (items) { - if (items) { - console.log('Successfully added timestamps to MetaTable.'); - } else { - console.log('MetaTable already has timestamps.'); - } - - process.exit(0); - }, function (err) { - console.error(err); - process.exit(1); - }); - }); - } - } -}; - -function ensureCurrentMetaSchema (migrator) { - var queryInterface = migrator.options.storageOptions.sequelize.getQueryInterface(); - var tableName = migrator.options.storageOptions.tableName; - var columnName = migrator.options.storageOptions.columnName; - var config = helpers.config.readConfig(); - - return ensureMetaTable(queryInterface, tableName) - .then(function (table) { - var columns = Object.keys(table); - - if ((columns.length === 1) && (columns[0] === columnName)) { - return; - } else if (columns.length === 3 && columns.indexOf('createdAt') >= 0) { - return; - } else { - if (!config.autoMigrateOldSchema) { - console.error( - 'Database schema was not migrated. Please run ' + - '"sequelize db:migrate:old_schema" first.' - ); - process.exit(1); - } - - return tryToMigrateFromOldSchema(migrator); - } - }, - function () { - return; - }); -} - -function logMigrator (s) { - if (s.indexOf('Executing') !== 0) { - helpers.view.log(s); - } -} - -function ensureMetaTable (queryInterface, tableName) { - return queryInterface.showAllTables() - .then(function (tableNames) { - if (tableNames.indexOf(tableName) === -1) { - throw new Error('No MetaTable table found.'); - } - }) - .then(function () { - return queryInterface.describeTable(tableName); - }); -} - -function getSequelizeInstance () { - var config = null; - - try { - config = helpers.config.readConfig(); - } catch (e) { - console.log(e.message); - process.exit(1); - } - - config = _.defaults(config, { logging: logMigrator }); - - try { - return new Sequelize(config); - } catch (e) { - console.warn(e); - throw e; - } -} - -function getMigrator (type) { - if (helpers.config.configFileExists() || args.url) { - var sequelize = getSequelizeInstance(); - var migrator = new Umzug({ - storage: helpers.umzug.getStorage(type), - storageOptions: helpers.umzug.getStorageOptions(type, { sequelize: sequelize }), - logging: console.log, - migrations: { - params: [ sequelize.getQueryInterface(), Sequelize ], - path: helpers.path.getPath(type), - pattern: helpers.config.supportsCoffee() ? /\.js$|\.coffee$/ : /\.js$/, - wrap: function (fun) { - if (fun.length === 3) { - return Bluebird.promisify(fun); - } else { - return fun; - } - } - } - }); - - return sequelize - .authenticate() - .then(function () { - return migrator; - }) - .catch(function (err) { - console.error('Unable to connect to database: ' + err); - process.exit(1); - }); - } else { - console.log( - 'Cannot find "' + helpers.config.getConfigFile() + - '". Have you run "sequelize init"?' - ); - process.exit(1); - } -} - -/** - * tryToMigrateFromOldSchema - migrates from old schema - * - * @return {Promise} - */ -function tryToMigrateFromOldSchema (migrator) { - var sequelize = migrator.options.storageOptions.sequelize; - var queryInterface = sequelize.getQueryInterface(); - - return ensureMetaTable(queryInterface, 'SequelizeMeta') - .then(function (table) { - if (JSON.stringify(Object.keys(table).sort()) === JSON.stringify(['id', 'from', 'to'])) { - return; - } - return queryInterface.renameTable('SequelizeMeta', 'SequelizeMetaBackup') - .then(function () { - var sql = queryInterface.QueryGenerator.selectQuery('SequelizeMetaBackup'); - - return helpers.generic.execQuery(sequelize, sql, { type: 'SELECT', raw: true }); - }) - .then(function (result) { - var timestamps = result.map(function (item) { - return item.to; - }); - var files = fs.readdirSync(helpers.path.getPath('migration')); - - return files.filter(function (file) { - var match = file.match(/(\d+)-?/); - - if (match) { - var timestamp = match[0].replace('-', ''); - - return timestamps.indexOf(timestamp) > -1; - } - }); - }) - .then(function (files) { - var SequelizeMeta = sequelize.define('SequelizeMeta', { - name: { - type: Sequelize.STRING, - allowNull: false, - unique: true, - primaryKey: true, - autoIncrement: false - } - }, { - tableName: 'SequelizeMeta', - timestamps: false - }); - - return SequelizeMeta.sync().then(function () { - return SequelizeMeta.bulkCreate( - files.map(function (file) { - return { name: file }; - }) - ); - }); - }); - }); -} - -/** - * Add timestamps - * - * @return {Promise} - */ -function addTimestampsToSchema (migrator) { - var sequelize = migrator.options.storageOptions.sequelize; - var queryInterface = sequelize.getQueryInterface(); - var tableName = migrator.options.storageOptions.tableName; - - return ensureMetaTable(queryInterface, tableName) - .then(function (table) { - if (table.createdAt) { - return; - } - - return ensureCurrentMetaSchema(migrator) - .then(function () { - return queryInterface.renameTable(tableName, tableName + 'Backup'); - }) - .then(function () { - var sql = queryInterface.QueryGenerator.selectQuery(tableName + 'Backup'); - - return helpers.generic.execQuery(sequelize, sql, { type: 'SELECT', raw: true }); - }) - .then(function (result) { - var SequelizeMeta = sequelize.define(tableName, { - name: { - type: Sequelize.STRING, - allowNull: false, - unique: true, - primaryKey: true, - autoIncrement: false - } - }, { - tableName: tableName, - timestamps: true - }); - - return SequelizeMeta.sync() - .then(function () { - return SequelizeMeta.bulkCreate(result); - }); - }); - }); -} - -/** - * ensureSeeds - checks that the `--seed` option exists - */ - -function ensureSeeds () { - if ( !args.seed ) { - helpers.view.error( - 'Unspecified flag ' + - clc.blueBright('"seed"') + - '. Check the manual for further details.' - ); - process.exit(1); - } - - if ( !_.isArray(args.seed) ) { - args.seed = [args.seed]; - } - - args.seed.forEach(function (file, ind) { - args.seed[ind] = path.basename(file); - }); -} diff --git a/lib/tasks/init.js b/lib/tasks/init.js deleted file mode 100644 index 616203d9..00000000 --- a/lib/tasks/init.js +++ /dev/null @@ -1,107 +0,0 @@ -'use strict'; - -var path = require('path'); -var helpers = require(path.resolve(__dirname, '..', 'helpers')); -var args = require('yargs').argv; -var clc = require('cli-color'); -var _ = require('lodash'); - -module.exports = { - 'init': { - descriptions: { - 'short': 'Initializes the project.', - '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 contains the migration files.', - 'seeders': 'A folder that contains the seed files.', - 'models': 'A folder that contains the model files.', - 'models/index.js': 'A file that can be required to load all the models.' - }; - - _.forEach(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') - } - }, - - dependencies: [ - 'init:config', - 'init:migrations', - 'init:seeders', - '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 { - helpers.init.notifyAboutExistingFile(helpers.config.relativeConfigFile()); - process.exit(1); - } - } - }, - - '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); - } - }, - - 'init:seeders': { - descriptions: { - 'short': 'Initializes the seeders.' - }, - - task: function () { - helpers.init.createSeedersFolder(!!args.force); - } - } -}; diff --git a/lib/tasks/migration.js b/lib/tasks/migration.js deleted file mode 100644 index f7505f7e..00000000 --- a/lib/tasks/migration.js +++ /dev/null @@ -1,48 +0,0 @@ -'use strict'; - -var path = require('path'); -var helpers = require(path.resolve(__dirname, '..', 'helpers')); -var args = require('yargs').argv; -var fs = require('fs'); -var clc = require('cli-color'); - -module.exports = { - 'migration:create': { - descriptions: { - 'short': 'Generates a new migration file.', - options: { - '--name': 'Defines the name of the migration. ' + - clc.blueBright('Default: unnamed-migration'), - '--underscored': 'Use snake case for the timestamp\'s attribute names' - } - }, - - aliases: [ 'migration:generate' ], - - task: function () { - var config = null; - - helpers.init.createMigrationsFolder(); - - try { - config = helpers.config.readConfig(); - } catch (e) { - console.log(e.message); - process.exit(1); - } - - fs.writeFileSync( - helpers.path.getMigrationPath(args.name), - helpers.template.render('migrations/skeleton.js', {}, { - beautify: false - }) - ); - - helpers.view.log( - 'New migration was created at', - clc.blueBright(helpers.path.getMigrationPath(args.name)), - '.' - ); - } - } -}; diff --git a/lib/tasks/model.js b/lib/tasks/model.js deleted file mode 100644 index 3a2d06ab..00000000 --- a/lib/tasks/model.js +++ /dev/null @@ -1,136 +0,0 @@ -'use strict'; - -var path = require('path'); -var helpers = require(path.resolve(__dirname, '..', 'helpers')); -var args = require('yargs').argv; -var clc = require('cli-color'); - -module.exports = { - 'model:create': { - aliases: [ 'model:generate' ], - - descriptions: { - 'short': 'Generates a model and its migration.', - - 'long': function () { - var migrationFileName = helpers.path.getFileName( - 'migration', - helpers.migration.generateMigrationName({ name: 'User' }), - { ignoreConfig: true } - ); - - var result = [ - 'This task generates a model file and its respective migration.', - 'It is necessary to specify the name of the new model as well as', - 'the model\'s attributes.', - '', - 'The attributes can be specified as in the following (and semantically equal) examples:', - '', - 'sequelize model:create --name User --attributes ' + - 'first_name:string,last_name:string,bio:text', - 'sequelize model:create --name User --attributes ' + - '\'first_name:string last_name:string bio:text\'', - 'sequelize model:create --name User --attributes ' + - '\'first_name:string, last_name:string, bio:text\'', - '', - 'This command will generate a new migration and model definition:', - '', - '// the model file', - '// located under models/user.js' - ]; - - result = result.concat( - helpers.model.generateFileContent({ - name: 'User', - attributes: 'first_name:string,last_name:string,bio:text' - }).split('\n') - ); - - result = result.concat([ - '', - '// the migration file', - '// located under migrations/' + migrationFileName - ]); - - result = result.concat( - helpers.migration.generateTableCreationFileContent({ - name: 'User', - attributes: 'first_name:string,last_name:string,bio:text', - underscored: args.underscored - }).split('\n') - ); - - return result; - }, - - options: { - '--name': 'The name of the new model.', - '--attributes': 'A list of attributes.', - '--underscored': 'Set timestamps to snake_case' - } - }, - - preChecks: [ - function ensureAttributesFlag () { - if (!args.attributes) { - helpers.view.error( - 'Unspecified flag ' + - clc.blueBright('"attributes"') + - '. Check the manual for further details.' - ); - process.exit(1); - } - }, - - function ensureNameFlag () { - if (!args.name) { - helpers.view.error( - 'Unspecified flag ' + clc.blueBright('"name"') + - '. Check the manual for further details.' - ); - process.exit(1); - } - }, - - function ensureModelsFolder () { - if (!helpers.path.existsSync(helpers.path.getModelsPath())) { - helpers.view.error( - 'Unable to find models path (' + - helpers.path.getModelsPath() + - '). Did you run ' + clc.blueBright('sequelize init') + '?' - ); - process.exit(1); - } - }, - - function ensureMigrationsFolder () { - if (!helpers.path.existsSync(helpers.path.getPath('migration'))) { - helpers.view.error( - 'Unable to find migrations path (' + - helpers.path.getPath('migration') + - '). Did you run ' + clc.blueBright('sequelize init') + '?' - ); - process.exit(1); - } - }, - - function checkModelFileExistence () { - var modelPath = helpers.path.getModelPath(args.name); - - if (!args.force && helpers.model.modelFileExists(modelPath)) { - helpers.model.notifyAboutExistingFile(modelPath); - process.exit(1); - } - } - ], - - task: function () { - this.preChecks.forEach(function (preCheck) { - preCheck(); - }); - - helpers.model.generateFile(args); - helpers.migration.generateTableCreationFile(args); - } - } -}; diff --git a/lib/tasks/seed.js b/lib/tasks/seed.js deleted file mode 100644 index 13a1b9d6..00000000 --- a/lib/tasks/seed.js +++ /dev/null @@ -1,47 +0,0 @@ -'use strict'; - -var path = require('path'); -var helpers = require(path.resolve(__dirname, '..', 'helpers')); -var args = require('yargs').argv; -var fs = require('fs'); -var clc = require('cli-color'); - -module.exports = { - 'seed:create': { - descriptions: { - 'short': 'Generates a new seed file.', - options: { - '--name': 'Defines the name of the seed. ' + - clc.blueBright('Default: unnamed-seed') - } - }, - - aliases: [ 'seed:generate' ], - - task: function () { - var config = null; - - helpers.init.createSeedersFolder(); - - try { - config = helpers.config.readConfig(); - } catch (e) { - console.log(e.message); - process.exit(1); - } - - fs.writeFileSync( - helpers.path.getSeederPath(args.name), - helpers.template.render('seeders/skeleton.js', {}, { - beautify: false - }) - ); - - helpers.view.log( - 'New seed was created at', - clc.blueBright(helpers.path.getSeederPath(args.name)), - '.' - ); - } - } -}; diff --git a/lib/tasks/version.js b/lib/tasks/version.js deleted file mode 100644 index 9db482c3..00000000 --- a/lib/tasks/version.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; - -module.exports = { - 'version': { - descriptions: { - 'short': 'Prints the version number.', - 'long': [ 'Prints the version number.' ] - }, - - aliases: [ 'v' ], - - task: function () { - } - } -}; diff --git a/package.json b/package.json index 820a127d..25249284 100644 --- a/package.json +++ b/package.json @@ -2,43 +2,52 @@ "name": "sequelize-cli", "version": "2.8.0", "description": "The Sequelize CLI", - "main": "index.js", + "bin": { + "sequelize": "./lib/sequelize" + }, "dependencies": { "bluebird": "^3.5.0", - "cli-color": "~1.2.0", - "findup-sync": "^1.0.0", + "cli-color": "^1.2.0", "fs-extra": "^4.0.1", - "gulp": "^3.9.1", - "gulp-help": "~1.6.1", - "js-beautify": "^1.6.11", + "js-beautify": "^1.6.14", "lodash": "^4.17.4", - "moment": "^2.17.1", - "resolve": "^1.3.3", - "umzug": "^1.12.0", + "resolve": "^1.4.0", + "umzug": "^2.0.1", "yargs": "^8.0.1" }, "devDependencies": { - "coffee-script": "^1.12.5", - "expect.js": "~0.3.1", - "gulp-jscs": "^4.0.0", - "gulp-jshint": "^2.0.4", - "gulp-jshint-instafail": "^1.0.0", - "gulp-mocha": "^4.3.1", - "js2coffee": "^2.2.0", - "jshint": "^2.9.4", - "jshint-stylish": "^2.2.0", - "mocha": "^3.3.0", + "babel-cli": "^6.24.1", + "babel-plugin-transform-async-to-module-method": "^6.24.1", + "babel-plugin-transform-object-rest-spread": "^6.23.0", + "babel-preset-env": "^1.6.0", + "babel-register": "^6.24.1", + "eslint": "^4.6.0", + "expect.js": "^0.3.1", + "gulp": "^3.9.1", + "mocha": "^3.5.0", "mysql": "^2.13.0", "nodeify": "^1.0.1", "pg": "^6.1.3", "pg-hstore": "^2.3.2", - "run-sequence": "^2.1.0", "sequelize": "^4.0.0", "sqlite3": "^3.1.8", "through2": "^2.0.3" }, + "options": { + "mocha": "--require scripts/mocha-bootload.js --check-leaks --timeout 30000 --colors --reporter spec" + }, + "eslintIgnore": [ + "test/support", + "src/assets" + ], "scripts": { - "test": "gulp" + "build": "npm run build-clean && babel src -d lib && npm run build-bin && npm run build-assets", + "build-bin": "mv ./lib/sequelize.js ./lib/sequelize && chmod +x ./lib/sequelize", + "build-assets": "cp -R ./src/assets ./lib/", + "build-clean": "rm -rf ./lib/", + "lint": "eslint test src sequelize.js", + "test-raw": "mocha $npm_package_options_mocha 'test/**/*.test.js'", + "test": "npm run lint && npm run build && npm run test-raw" }, "repository": { "type": "git", @@ -48,13 +57,23 @@ "sequelize", "cli" ], - "author": "Sascha Depold", + "author": "Sascha Depold ", + "contributors": [ + { + "name": "Sushant Dhiman", + "email": "sushantdhiman@outlook.com" + }, + { + "name": "Paulo R Lopes", + "email": "prplopes@gmail.com" + } + ], "license": "MIT", "bugs": { "url": "https://github.com/sequelize/cli/issues" }, "homepage": "https://github.com/sequelize/cli", - "bin": { - "sequelize": "bin/sequelize" + "engines": { + "node": ">=4.0.0" } } diff --git a/scripts/mocha-bootload.js b/scripts/mocha-bootload.js new file mode 100644 index 00000000..bf12cab1 --- /dev/null +++ b/scripts/mocha-bootload.js @@ -0,0 +1 @@ +require('babel-register'); \ No newline at end of file diff --git a/lib/assets/migrations/create-table.js b/src/assets/migrations/create-table.js similarity index 100% rename from lib/assets/migrations/create-table.js rename to src/assets/migrations/create-table.js diff --git a/lib/assets/migrations/skeleton.js b/src/assets/migrations/skeleton.js similarity index 100% rename from lib/assets/migrations/skeleton.js rename to src/assets/migrations/skeleton.js diff --git a/lib/assets/models/index.js b/src/assets/models/index.js similarity index 100% rename from lib/assets/models/index.js rename to src/assets/models/index.js diff --git a/lib/assets/models/model.js b/src/assets/models/model.js similarity index 100% rename from lib/assets/models/model.js rename to src/assets/models/model.js diff --git a/lib/assets/seeders/skeleton.js b/src/assets/seeders/skeleton.js similarity index 100% rename from lib/assets/seeders/skeleton.js rename to src/assets/seeders/skeleton.js diff --git a/src/commands/init.js b/src/commands/init.js new file mode 100644 index 00000000..f6ea7fb2 --- /dev/null +++ b/src/commands/init.js @@ -0,0 +1,65 @@ +import { _baseOptions } from '../core/yargs'; +import helpers from '../helpers'; + +exports.builder = yargs => _baseOptions(yargs) + .option('force', { + describe: 'Will drop the existing config folder and re-create it', + type: 'boolean', + default: false + }) + .help() + .argv; + +exports.handler = async function (argv) { + const command = argv._[0]; + + switch (command) { + case 'init': + await initConfig(argv); + await initModels(argv); + await initMigrations(argv); + await initSeeders(argv); + break; + + case 'init:config': + await initConfig(argv); + break; + + case 'init:models': + await initModels(argv); + break; + + case 'init:migrations': + await initMigrations(argv); + break; + + case 'init:seeders': + await initSeeders(argv); + break; + } + + process.exit(0); +}; + +function initConfig (args) { + if (!helpers.config.configFileExists() || !!args.force) { + helpers.config.writeDefaultConfig(); + console.log('Created "' + helpers.config.relativeConfigFile() + '"'); + } else { + helpers.init.notifyAboutExistingFile(helpers.config.relativeConfigFile()); + process.exit(1); + } +} + +function initModels (args) { + helpers.init.createModelsFolder(!!args.force); + helpers.init.createModelsIndexFile(!!args.force); +} + +function initMigrations (args) { + helpers.init.createMigrationsFolder(!!args.force); +} + +function initSeeders (args) { + helpers.init.createSeedersFolder(!!args.force); +} \ No newline at end of file diff --git a/src/commands/migrate.js b/src/commands/migrate.js new file mode 100644 index 00000000..78764269 --- /dev/null +++ b/src/commands/migrate.js @@ -0,0 +1,82 @@ +import { _baseOptions } from '../core/yargs'; +import { getMigrator, ensureCurrentMetaSchema, addTimestampsToSchema } from '../core/migrator'; + +import helpers from '../helpers'; +import _ from 'lodash'; + +exports.builder = yargs => _baseOptions(yargs).help().argv; +exports.handler = async function (args) { + const command = args._[0]; + + // legacy, gulp used to do this + await helpers.config.init(); + + switch (command) { + case 'db:migrate': + await migrate(args); + break; + case 'db:migrate:schema:timestamps:add': + await migrateSchemaTimestampAdd(args); + break; + case 'db:migrate:status': + await migrationStatus(args); + break; + } + + process.exit(0); +}; + +function migrate(args) { + return getMigrator('migration', args).then(migrator => { + return ensureCurrentMetaSchema(migrator) + .then(() => migrator.pending()) + .then(migrations => { + if (migrations.length === 0) { + console.log('No migrations were executed, database schema was already up to date.'); + process.exit(0); + } + }) + .then(() => migrator.up()) + .catch(err => { + console.error(err); + process.exit(1); + }); + }); +} + +function migrationStatus(args) { + return getMigrator('migration', args).then(migrator => { + return ensureCurrentMetaSchema(migrator) + .then(() => migrator.executed()) + .then(migrations => { + _.forEach(migrations, migration => { + console.log('up', migration.file); + }); + }).then(() => migrator.pending()) + .then(migrations => { + _.forEach(migrations, migration => { + console.log('down', migration.file); + }); + }).catch(err => { + console.error(err); + process.exit(1); + }); + }); +} + +function migrateSchemaTimestampAdd(args) { + return getMigrator('migration', args).then(migrator => { + return addTimestampsToSchema(migrator) + .then(items => { + if (items) { + console.log('Successfully added timestamps to MetaTable.'); + } else { + console.log('MetaTable already has timestamps.'); + } + }) + .catch(err => { + console.error(err); + process.exit(1); + }); + }); +} diff --git a/src/commands/migrate_undo.js b/src/commands/migrate_undo.js new file mode 100644 index 00000000..00c86c9d --- /dev/null +++ b/src/commands/migrate_undo.js @@ -0,0 +1,46 @@ +import { _baseOptions } from '../core/yargs'; +import { getMigrator, ensureCurrentMetaSchema } from '../core/migrator'; + +import helpers from '../helpers'; + +exports.builder = + yargs => + _baseOptions(yargs) + .option('name', { + describe: 'Name of the migration to undo', + type: 'string' + }) + .help() + .argv; + +exports.handler = async function (args) { + // legacy, gulp used to do this + await helpers.config.init(); + + await migrateUndo(args); + + process.exit(0); +}; + +function migrateUndo (args) { + return getMigrator('migration', args).then(migrator => { + return ensureCurrentMetaSchema(migrator).then(() => migrator.executed()) + .then(migrations => { + if (migrations.length === 0) { + console.log('No executed migrations found.'); + process.exit(0); + } + }) + .then(() => { + if (args.name) { + return migrator.down(args.name); + } else { + return migrator.down(); + } + }) + .catch(err => { + console.error(err); + process.exit(1); + }); + }); +} \ No newline at end of file diff --git a/src/commands/migrate_undo_all.js b/src/commands/migrate_undo_all.js new file mode 100644 index 00000000..37198f03 --- /dev/null +++ b/src/commands/migrate_undo_all.js @@ -0,0 +1,41 @@ +import { _baseOptions } from '../core/yargs'; +import { getMigrator, ensureCurrentMetaSchema } from '../core/migrator'; + +import helpers from '../helpers'; + +exports.builder = + yargs => + _baseOptions(yargs) + .option('to', { + describe: 'Revert to the provided migration', + default: 0, + type: 'string' + }) + .help() + .argv; + +exports.handler = async function (args) { + // legacy, gulp used to do this + await helpers.config.init(); + + await migrationUndoAll(args); + + process.exit(0); +}; + +function migrationUndoAll (args) { + return getMigrator('migration', args).then(migrator => { + return ensureCurrentMetaSchema(migrator).then(() => migrator.executed()) + .then(migrations => { + if (migrations.length === 0) { + console.log('No executed migrations found.'); + process.exit(0); + } + }) + .then(() => migrator.down({ to: args.to || 0 })) + .catch(err => { + console.error(err); + process.exit(1); + }); + }); +} \ No newline at end of file diff --git a/src/commands/migration_generate.js b/src/commands/migration_generate.js new file mode 100644 index 00000000..1b651712 --- /dev/null +++ b/src/commands/migration_generate.js @@ -0,0 +1,37 @@ +import { _baseOptions, _underscoreOption } from '../core/yargs'; + +import helpers from '../helpers'; +import fs from 'fs'; +import clc from 'cli-color'; + +exports.builder = + yargs => + _underscoreOption( + _baseOptions(yargs) + .option('name', { + describe: 'Defines the name of the migration', + type: 'string', + demandOption: true + }) + ) + .help() + .argv; + +exports.handler = function (args) { + helpers.init.createMigrationsFolder(); + + fs.writeFileSync( + helpers.path.getMigrationPath(args.name), + helpers.template.render('migrations/skeleton.js', {}, { + beautify: false + }) + ); + + helpers.view.log( + 'New migration was created at', + clc.blueBright(helpers.path.getMigrationPath(args.name)), + '.' + ); + + process.exit(0); +}; \ No newline at end of file diff --git a/src/commands/model_generate.js b/src/commands/model_generate.js new file mode 100644 index 00000000..109f1eda --- /dev/null +++ b/src/commands/model_generate.js @@ -0,0 +1,74 @@ +import { _baseOptions, _underscoreOption } from '../core/yargs'; + +import helpers from '../helpers'; +import clc from 'cli-color'; + +exports.builder = + yargs => + _underscoreOption( + _baseOptions(yargs) + .option('name', { + describe: 'Defines the name of the new model', + type: 'string', + demandOption: true + }) + .option('attributes', { + describe: 'A list of attributes', + type: 'string', + demandOption: true + }) + ) + .help() + .argv; + +exports.handler = function (args) { + ensureModelsFolder(); + ensureMigrationsFolder(); + checkModelFileExistence(args); + + helpers.model.generateFile(args); + helpers.migration.generateTableCreationFile(args); + helpers.view.log( + 'New model was created at', + clc.blueBright(helpers.path.getModelPath(args.name)), + '.' + ); + helpers.view.log( + 'New migration was created at', + clc.blueBright(helpers.path.getMigrationPath(args.name)), + '.' + ); + + process.exit(0); +}; + +function ensureModelsFolder () { + if (!helpers.path.existsSync(helpers.path.getModelsPath())) { + helpers.view.error( + 'Unable to find models path (' + + helpers.path.getModelsPath() + + '). Did you run ' + clc.blueBright('sequelize init') + '?' + ); + process.exit(1); + } +} + +function ensureMigrationsFolder () { + if (!helpers.path.existsSync(helpers.path.getPath('migration'))) { + helpers.view.error( + 'Unable to find migrations path (' + + helpers.path.getPath('migration') + + '). Did you run ' + clc.blueBright('sequelize init') + '?' + ); + process.exit(1); + } +} + +function checkModelFileExistence (args) { + const modelPath = helpers.path.getModelPath(args.name); + + if (!args.force && helpers.model.modelFileExists(modelPath)) { + helpers.model.notifyAboutExistingFile(modelPath); + process.exit(1); + } +} \ No newline at end of file diff --git a/src/commands/seed.js b/src/commands/seed.js new file mode 100644 index 00000000..1c9c8ba4 --- /dev/null +++ b/src/commands/seed.js @@ -0,0 +1,63 @@ +import { _baseOptions } from '../core/yargs'; +import { getMigrator } from '../core/migrator'; + +import helpers from '../helpers'; +import _ from 'lodash'; + +exports.builder = yargs => _baseOptions(yargs).help().argv; +exports.handler = async function (args) { + const command = args._[0]; + + // legacy, gulp used to do this + await helpers.config.init(); + + switch (command) { + case 'db:seed:all': + await seedAll(args); + break; + + case 'db:seed:undo:all': + await seedUndoAll(args); + break; + } + + process.exit(0); +}; + +function seedAll (args) { + return getMigrator('seeder', args).then(migrator => { + return migrator.pending() + .then(seeders => { + if (seeders.length === 0) { + console.log('No seeders found.'); + return; + } + + return migrator.up({ migrations: _.chain(seeders).map('file').value() }); + }) + .catch(err => { + console.error('Seed file failed with error:', err.message, err.stack); + process.exit(1); + }); + }); +} + +function seedUndoAll (args) { + return getMigrator('seeder', args).then(migrator => { + return ( + helpers.umzug.getStorage('seeder') === 'none' ? migrator.pending() : migrator.executed() + ) + .then(seeders => { + if (seeders.length === 0) { + console.log('No seeders found.'); + return; + } + + return migrator.down({ migrations: _.chain(seeders).map('file').reverse().value() }); + }) + .catch(err => { + console.error('Seed file failed with error:', err.message, err.stack); + process.exit(1); + }); + }); +} diff --git a/src/commands/seed_generate.js b/src/commands/seed_generate.js new file mode 100644 index 00000000..8a1881fa --- /dev/null +++ b/src/commands/seed_generate.js @@ -0,0 +1,35 @@ +import { _baseOptions } from '../core/yargs'; + +import helpers from '../helpers'; +import fs from 'fs'; +import clc from 'cli-color'; + +exports.builder = + yargs => + _baseOptions(yargs) + .option('name', { + describe: 'Defines the name of the seed', + type: 'string', + demandOption: true + }) + .help() + .argv; + +exports.handler = function (args) { + helpers.init.createSeedersFolder(); + + fs.writeFileSync( + helpers.path.getSeederPath(args.name), + helpers.template.render('seeders/skeleton.js', {}, { + beautify: false + }) + ); + + helpers.view.log( + 'New seed was created at', + clc.blueBright(helpers.path.getSeederPath(args.name)), + '.' + ); + + process.exit(0); +}; diff --git a/src/commands/seed_one.js b/src/commands/seed_one.js new file mode 100644 index 00000000..90142dc1 --- /dev/null +++ b/src/commands/seed_one.js @@ -0,0 +1,54 @@ +import { _baseOptions } from '../core/yargs'; +import { getMigrator } from '../core/migrator'; + +import helpers from '../helpers'; +import path from 'path'; + +exports.builder = + yargs => + _baseOptions(yargs) + .option('seed', { + describe: 'List of seed files', + type: 'array' + }) + .help() + .argv; + +exports.handler = async function (args) { + const command = args._[0]; + + // legacy, gulp used to do this + await helpers.config.init(); + + // filter out cmd names + // for case like --seeders-path seeders --seed seedPerson.js db:seed + const seeds= (args.seed || []) + .filter(name => name !== 'db:seed' && name !== 'db:seed:undo') + .map(file => path.basename(file)); + + + switch (command) { + case 'db:seed': + await getMigrator('seeder', args).then(migrator => { + return migrator.up(seeds) + .catch(err => { + console.error('Seed file failed with error:', err.message, err.stack); + process.exit(1); + }); + }); + break; + + case 'db:seed:undo': + await getMigrator('seeder', args).then(migrator => { + return migrator.down({ migrations: seeds }) + .catch(err => { + console.error('Seed file failed with error:', err.message, err.stack); + process.exit(1); + }); + }); + break; + } + + process.exit(0); +}; + diff --git a/src/core/migrator.js b/src/core/migrator.js new file mode 100644 index 00000000..7d1e095f --- /dev/null +++ b/src/core/migrator.js @@ -0,0 +1,143 @@ +import helpers from '../helpers/index'; +import Umzug from 'umzug'; +import Bluebird from 'bluebird'; +import _ from 'lodash'; + +const Sequelize = helpers.generic.getSequelize(); + +function logMigrator (s) { + if (s.indexOf('Executing') !== 0) { + helpers.view.log(s); + } +} + +function getSequelizeInstance () { + let config = null; + + try { + config = helpers.config.readConfig(); + } catch (e) { + console.log(e.message); + process.exit(1); + } + + config = _.defaults(config, { logging: logMigrator }); + + try { + return new Sequelize(config); + } catch (e) { + console.warn(e); + throw e; + } +} + +export function getMigrator (type, args) { + return Bluebird.try(() => { + if (!(helpers.config.configFileExists() || args.url)) { + console.log( + 'Cannot find "' + helpers.config.getConfigFile() + + '". Have you run "sequelize init"?' + ); + process.exit(1); + } + + const sequelize = getSequelizeInstance(); + const migrator = new Umzug({ + storage: helpers.umzug.getStorage(type), + storageOptions: helpers.umzug.getStorageOptions(type, { sequelize }), + logging: console.log, + migrations: { + params: [sequelize.getQueryInterface(), Sequelize], + path: helpers.path.getPath(type), + pattern: /\.js$/, + wrap: fun => { + if (fun.length === 3) { + return Bluebird.promisify(fun); + } else { + return fun; + } + } + } + }); + + return sequelize + .authenticate() + .then(() => migrator) + .catch(err => { + console.error('Unable to connect to database: ' + err); + process.exit(1); + }); + }); +} + +export function ensureCurrentMetaSchema (migrator) { + const queryInterface = migrator.options.storageOptions.sequelize.getQueryInterface(); + const tableName = migrator.options.storageOptions.tableName; + const columnName = migrator.options.storageOptions.columnName; + + return ensureMetaTable(queryInterface, tableName) + .then(table => { + const columns = Object.keys(table); + + if (columns.length === 1 && columns[0] === columnName) { + return; + } else if (columns.length === 3 && columns.indexOf('createdAt') >= 0) { + return; + } + }) + .catch(() => {}); +} + +function ensureMetaTable (queryInterface, tableName) { + return queryInterface.showAllTables() + .then(tableNames => { + if (tableNames.indexOf(tableName) === -1) { + throw new Error('No MetaTable table found.'); + } + return queryInterface.describeTable(tableName); + }); +} + +/** + * Add timestamps + * + * @return {Promise} + */ +export function addTimestampsToSchema (migrator) { + const sequelize = migrator.options.storageOptions.sequelize; + const queryInterface = sequelize.getQueryInterface(); + const tableName = migrator.options.storageOptions.tableName; + + return ensureMetaTable(queryInterface, tableName) + .then(table => { + if (table.createdAt) { + return; + } + + return ensureCurrentMetaSchema(migrator) + .then(() => queryInterface.renameTable(tableName, tableName + 'Backup')) + .then(() => { + const sql = queryInterface.QueryGenerator.selectQuery(tableName + 'Backup'); + return helpers.generic.execQuery(sequelize, sql, { type: 'SELECT', raw: true }); + }) + .then(result => { + const SequelizeMeta = sequelize.define(tableName, { + name: { + type: Sequelize.STRING, + allowNull: false, + unique: true, + primaryKey: true, + autoIncrement: false + } + }, { + tableName, + timestamps: true + }); + + return SequelizeMeta.sync() + .then(() => { + return SequelizeMeta.bulkCreate(result); + }); + }); + }); +} \ No newline at end of file diff --git a/src/core/yargs.js b/src/core/yargs.js new file mode 100644 index 00000000..e919e545 --- /dev/null +++ b/src/core/yargs.js @@ -0,0 +1,44 @@ +export function _baseOptions (yargs) { + return yargs + .option('env', { + describe: 'The environment to run the command in', + default: 'development', + type: 'string' + }) + .option('config', { + describe: 'The path to the config file', + type: 'string' + }) + .option('options-path', { + describe: 'The path to a JSON file with additional options', + type: 'string' + }) + .option('migrations-path', { + describe: 'The path to the migrations folder', + default: 'migrations', + type: 'string' + }) + .option('seeders-path', { + describe: 'The path to the seeders folder', + default: 'seeders', + type: 'string' + }) + .option('models-path', { + describe: 'The path to the models folder', + default: 'models', + type: 'string' + }) + .option('url', { + describe: 'The database connection string to use. Alternative to using --config files', + type: 'string' + }); +} + +export function _underscoreOption (yargs) { + return yargs + .option('underscored', { + describe: "Use snake case for the timestamp's attribute names", + default: false, + type: 'boolean' + }); +} diff --git a/src/helpers/asset-helper.js b/src/helpers/asset-helper.js new file mode 100644 index 00000000..a6482b31 --- /dev/null +++ b/src/helpers/asset-helper.js @@ -0,0 +1,32 @@ +import fs from 'fs-extra'; +import path from 'path'; + +const assets = { + copy: (from, to) => { + fs.copySync(path.resolve(__dirname, '..', 'assets', from), to); + }, + + read: assetPath => { + return fs.readFileSync(path.resolve(__dirname, '..', 'assets', assetPath)).toString(); + }, + + write: (targetPath, content) => { + fs.writeFileSync(targetPath, content); + }, + + inject: (filePath, token, content) => { + const fileContent = fs.readFileSync(filePath).toString(); + fs.writeFileSync(filePath, fileContent.replace(token, content)); + }, + + injectConfigFilePath: (filePath, configPath) => { + this.inject(filePath, '__CONFIG_FILE__', configPath); + }, + + mkdirp: pathToCreate => { + fs.mkdirpSync(pathToCreate); + } +}; + +module.exports = assets; +module.exports.default = assets; \ No newline at end of file diff --git a/lib/helpers/config-helper.js b/src/helpers/config-helper.js similarity index 72% rename from lib/helpers/config-helper.js rename to src/helpers/config-helper.js index 5d27ad57..5592f58a 100644 --- a/lib/helpers/config-helper.js +++ b/src/helpers/config-helper.js @@ -1,21 +1,20 @@ -'use strict'; +import Bluebird from 'bluebird'; +import path from 'path'; +import fs from 'fs'; +import url from 'url'; +import _ from 'lodash'; +import helpers from './index'; -var args = require('yargs').argv; -var Bluebird = require('bluebird'); -var path = require('path'); -var fs = require('fs'); -var helpers = require(__dirname); -var url = require('url'); -var _ = require('lodash'); +const args = require('yargs').argv; -var api = { +const api = { config: undefined, rawConfig: undefined, error: undefined, - init: function () { + init () { return Bluebird.resolve() - .then(function () { - var config; + .then(() => { + let config; if (args.url) { config = api.parseDbUrl(args.url); @@ -28,7 +27,7 @@ var api = { } return config; }) - .then(function (config) { + .then(config => { if (typeof config === 'object' || config === undefined) { return config; } else if (config.length === 1) { @@ -37,34 +36,34 @@ var api = { return config(); } }) - .then(function (config) { + .then(config => { api.rawConfig = config; }) - .then(function () { + .then(() => { // Always return the full config api return api; }); }, - getConfigFile: function () { + getConfigFile () { if (args.config) { return path.resolve(process.cwd(), args.config); } - var defaultPath = path.resolve(process.cwd(), 'config', 'config.json'); - var alternativePath = defaultPath.replace('.json', '.js'); + const defaultPath = path.resolve(process.cwd(), 'config', 'config.json'); + const alternativePath = defaultPath.replace('.json', '.js'); return helpers.path.existsSync(alternativePath) ? alternativePath : defaultPath; }, - relativeConfigFile: function () { + relativeConfigFile () { return path.relative(process.cwd(), api.getConfigFile()); }, - configFileExists: function () { + configFileExists () { return helpers.path.existsSync(api.getConfigFile()); }, - getDefaultConfig: function () { + getDefaultConfig () { return JSON.stringify({ development: { username: 'root', @@ -90,8 +89,8 @@ var api = { }, undefined, 2) + '\n'; }, - writeDefaultConfig: function () { - var configPath = path.dirname(api.getConfigFile()); + writeDefaultConfig () { + const configPath = path.dirname(api.getConfigFile()); if (!helpers.path.existsSync(configPath)) { fs.mkdirSync(configPath); @@ -100,9 +99,9 @@ var api = { fs.writeFileSync(api.getConfigFile(), api.getDefaultConfig()); }, - readConfig: function () { + readConfig () { if (!api.config) { - var env = helpers.generic.getEnvironment(); + const env = helpers.generic.getEnvironment(); if (api.rawConfig === undefined) { throw new Error( @@ -151,36 +150,15 @@ var api = { return api.config; }, - filteredUrl: function (url, config) { - var regExp = new RegExp(':?' + (config.password || '') + '@'); - - return url.replace(regExp, ':*****@'); - }, - - supportsCoffee: function (options) { - var config = null; - - options = _.assign({ - ignoreConfig: true - }, options || {}); - - try { - config = api.readConfig(); - } catch (e) { - if (options.ignoreConfig) { - config = {}; - } else { - throw e; - } - } - - return args.coffee || config.coffee; + filteredUrl (uri, config) { + const regExp = new RegExp(':?' + (config.password || '') + '@'); + return uri.replace(regExp, ':*****@'); }, - urlStringToConfigHash: function (urlString) { + urlStringToConfigHash (urlString) { try { - var urlParts = url.parse(urlString); - var result = { + const urlParts = url.parse(urlString); + let result = { database: urlParts.pathname.replace(/^\//, ''), host: urlParts.hostname, port: urlParts.port, @@ -201,8 +179,8 @@ var api = { } }, - parseDbUrl: function (urlString) { - var config = api.urlStringToConfigHash(urlString); + parseDbUrl (urlString) { + let config = api.urlStringToConfigHash(urlString); config = _.assign(config, { dialect: config.protocol diff --git a/src/helpers/generic-helper.js b/src/helpers/generic-helper.js new file mode 100644 index 00000000..0e418b2c --- /dev/null +++ b/src/helpers/generic-helper.js @@ -0,0 +1,42 @@ +import path from 'path'; + +const resolve = require('resolve').sync; +const args = require('yargs').argv; + +const generic = { + getEnvironment: () => { + return args.env || process.env.NODE_ENV || 'development'; + }, + + getSequelize: file => { + const resolvePath = file ? path.join('sequelize', file) : 'sequelize'; + const resolveOptions = { basedir: process.cwd() }; + + let sequelizePath; + + try { + sequelizePath = require.resolve(resolvePath, resolveOptions); + } catch (e) { + } + + try { + sequelizePath = sequelizePath || resolve(resolvePath, resolveOptions); + } catch (e) { + console.error('Unable to resolve sequelize package in ' + process.cwd()); + process.exit(1); + } + + return require(sequelizePath); + }, + + execQuery: (sequelize, sql, options) => { + if (sequelize.query.length === 2) { + return sequelize.query(sql, options); + } else { + return sequelize.query(sql, null, options); + } + } +}; + +module.exports = generic; +module.exports.default = generic; diff --git a/src/helpers/index.js b/src/helpers/index.js new file mode 100644 index 00000000..a58b5f28 --- /dev/null +++ b/src/helpers/index.js @@ -0,0 +1,13 @@ +import path from 'path'; +import fs from 'fs'; + +module.exports = {}; + +fs + .readdirSync(__dirname) + .filter(file => file.indexOf('.') !== 0 && file.indexOf('index.js') === -1) + .forEach(file => { + module.exports[file.replace('-helper.js', '')] = require(path.resolve(__dirname, file)); + }); + +module.exports.default = module.exports; diff --git a/src/helpers/init-helper.js b/src/helpers/init-helper.js new file mode 100644 index 00000000..91b0084c --- /dev/null +++ b/src/helpers/init-helper.js @@ -0,0 +1,84 @@ +import helpers from './index'; +import path from 'path'; +import fs from 'fs'; +import clc from 'cli-color'; + +function createFolder (folderName, folder, force) { + if (force) { + console.log('Deleting the ' + folderName + ' folder. (--force)'); + + try { + fs.readdirSync(folder).forEach(filename => { + fs.unlinkSync(path.resolve(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.asset.mkdirp(folder); + console.log('Successfully created ' + folderName + ' folder at "' + folder + '".'); + } catch (e) { + console.log(e); + } +}; + +const init = { + notifyAboutExistingFile: file => { + helpers.view.log( + 'The file ' + clc.blueBright(file) + ' already exists. Run ' + + '"sequelize init --force" to overwrite it.' + ); + }, + + createMigrationsFolder: force => { + createFolder('migrations', helpers.path.getPath('migration'), force); + }, + + createSeedersFolder: force => { + createFolder('seeders', helpers.path.getPath('seeder'), force); + }, + + createModelsFolder: force => { + createFolder('models', helpers.path.getModelsPath(), force); + }, + + createModelsIndexFile: force => { + const modelsPath = helpers.path.getModelsPath(); + const indexPath = path.resolve( + modelsPath, + helpers.path.addFileExtension('index') + ); + + if (!helpers.path.existsSync(modelsPath)) { + helpers.view.log('Models folder not available.'); + } else if (helpers.path.existsSync(indexPath) && !force) { + this.notifyAboutExistingFile(indexPath); + } else { + const relativeConfigPath = path.relative( + helpers.path.getModelsPath(), + helpers.config.getConfigFile() + ); + + helpers.asset.write( + indexPath, + helpers.template.render('models/index.js', { + configFile: '__dirname + \'/' + relativeConfigPath + '\'' + }, { + beautify: false + }) + ); + } + } +}; + +module.exports = init; +module.exports.default = init; diff --git a/lib/helpers/migration-helper.js b/src/helpers/migration-helper.js similarity index 56% rename from lib/helpers/migration-helper.js rename to src/helpers/migration-helper.js index e0139558..1d7e2191 100644 --- a/lib/helpers/migration-helper.js +++ b/src/helpers/migration-helper.js @@ -1,15 +1,14 @@ -'use strict'; +import _ from 'lodash'; +import helpers from './index'; -var _ = require('lodash'); -var helpers = require(__dirname); -var Sequelize = helpers.generic.getSequelize(); +const Sequelize = helpers.generic.getSequelize(); module.exports = { - getTableName: function (modelName) { + getTableName (modelName) { return Sequelize.Utils.pluralize(modelName); }, - generateTableCreationFileContent: function (args) { + generateTableCreationFileContent (args) { return helpers.template.render('migrations/create-table.js', { tableName: this.getTableName(args.name), attributes: helpers.model.transformAttributes(args.attributes), @@ -18,13 +17,13 @@ module.exports = { }); }, - generateMigrationName: function (args) { + generateMigrationName (args) { return _.trimStart(_.kebabCase('create-' + args.name), '-'); }, - generateTableCreationFile: function (args) { - var migrationName = this.generateMigrationName(args); - var migrationPath = helpers.path.getMigrationPath(migrationName); + generateTableCreationFile (args) { + const migrationName = this.generateMigrationName(args); + const migrationPath = helpers.path.getMigrationPath(migrationName); helpers.asset.write(migrationPath, this.generateTableCreationFileContent(args)); } diff --git a/lib/helpers/model-helper.js b/src/helpers/model-helper.js similarity index 61% rename from lib/helpers/model-helper.js rename to src/helpers/model-helper.js index 334db72c..287aff4c 100644 --- a/lib/helpers/model-helper.js +++ b/src/helpers/model-helper.js @@ -1,17 +1,15 @@ -'use strict'; - -var clc = require('cli-color'); -var helpers = require(__dirname); +import clc from 'cli-color'; +import helpers from './index'; module.exports = { - notifyAboutExistingFile: function (file) { + notifyAboutExistingFile (file) { helpers.view.error( 'The file ' + clc.blueBright(file) + ' already exists. ' + 'Run "sequelize model:create --force" to overwrite it.' ); }, - transformAttributes: function (flag) { + transformAttributes (flag) { /* possible flag formats: - first_name:string,last_name:string,bio:text @@ -19,11 +17,11 @@ module.exports = { - 'first_name:string, last_name:string, bio:text' */ - var set = flag.replace(/,/g, ' ').split(/\s+/); - var result = {}; + const set = flag.replace(/,/g, ' ').split(/\s+/); + const result = {}; - set.forEach(function (pair) { - var split = pair.split(':'); + set.forEach(pair => { + const split = pair.split(':'); result[split[0]] = split[1]; }); @@ -31,7 +29,7 @@ module.exports = { return result; }, - generateFileContent: function (args) { + generateFileContent (args) { return helpers.template.render('models/model.js', { name: args.name, attributes: this.transformAttributes(args.attributes), @@ -39,13 +37,13 @@ module.exports = { }); }, - generateFile: function (args) { - var modelPath = helpers.path.getModelPath(args.name); + generateFile (args) { + const modelPath = helpers.path.getModelPath(args.name); helpers.asset.write(modelPath, this.generateFileContent(args)); }, - modelFileExists: function (filePath) { + modelFileExists (filePath) { return helpers.path.existsSync(filePath); } }; diff --git a/lib/helpers/path-helper.js b/src/helpers/path-helper.js similarity index 51% rename from lib/helpers/path-helper.js rename to src/helpers/path-helper.js index 6a2597bb..efd9a975 100644 --- a/lib/helpers/path-helper.js +++ b/src/helpers/path-helper.js @@ -1,17 +1,30 @@ -'use strict'; +import path from 'path'; +import fs from 'fs'; -var helpers = require(__dirname); -var args = require('yargs').argv; -var fs = require('fs'); -var path = require('path'); -var moment = require('moment'); -var resolve = require('resolve').sync; +const resolve = require('resolve').sync; +const args = require('yargs').argv; + +function format (i) { + return parseInt(i, 10) < 10 ? '0' + i : i; +}; + +function getCurrentYYYYMMDDHHmms () { + const date = new Date(); + return [ + date.getUTCFullYear(), + format(date.getUTCMonth() + 1), + format(date.getUTCDate()), + format(date.getUTCHours()), + format(date.getUTCMinutes()), + format(date.getUTCSeconds()) + ].join(''); +} module.exports = { - getPath: function (type) { + getPath (type) { type = type + 's'; - var result = args[type + 'Path'] || path.resolve(process.cwd(), type); + let result = args[type + 'Path'] || path.resolve(process.cwd(), type); if (path.normalize(result) !== path.resolve(result)) { // the path is relative @@ -21,45 +34,45 @@ module.exports = { return result; }, - getFileName: function (type, name, options) { + getFileName (type, name, options) { return this.addFileExtension( [ - moment().utc().format('YYYYMMDDHHmmss'), - !!name ? name : 'unnamed-' + type + getCurrentYYYYMMDDHHmms(), + name ? name : 'unnamed-' + type ].join('-'), options ); }, - getFileExtension: function (options) { - return helpers.config.supportsCoffee(options) ? 'coffee' : 'js'; + getFileExtension () { + return 'js'; }, - addFileExtension: function (basename, options) { + addFileExtension (basename, options) { return [basename, this.getFileExtension(options)].join('.'); }, - getMigrationPath: function (migrationName) { + getMigrationPath (migrationName) { return path.resolve(this.getPath('migration'), this.getFileName('migration', migrationName)); }, - getSeederPath: function (seederName) { + getSeederPath (seederName) { return path.resolve(this.getPath('seeder'), this.getFileName('seeder', seederName)); }, - getModelsPath: function () { + getModelsPath () { return args.modelsPath || path.resolve(process.cwd(), 'models'); }, - getModelPath: function (modelName) { + getModelPath (modelName) { return path.resolve( this.getModelsPath(), this.addFileExtension(modelName.toLowerCase()) ); }, - resolve: function (packageName) { - var result; + resolve (packageName) { + let result; try { result = resolve(packageName, { basedir: process.cwd() }); @@ -67,22 +80,22 @@ module.exports = { } catch (e) { try { result = require(packageName); - } catch (e) {} + } catch (err) {} } return result; }, - existsSync: function (path) { + existsSync (pathToCheck) { if (fs.accessSync) { try { - fs.accessSync(path, fs.R_OK); + fs.accessSync(pathToCheck, fs.R_OK); return true; } catch (e) { return false; } } else { - return fs.existsSync(path); + return fs.existsSync(pathToCheck); } } }; diff --git a/src/helpers/template-helper.js b/src/helpers/template-helper.js new file mode 100644 index 00000000..c299990b --- /dev/null +++ b/src/helpers/template-helper.js @@ -0,0 +1,22 @@ +import _ from 'lodash'; +import beautify from 'js-beautify'; +import helpers from './index'; + +module.exports = { + render (path, locals, options) { + options = _.assign({ + beautify: true, + indent_size: 2, + preserve_newlines: false + }, options || {}); + + const template = helpers.asset.read(path); + let content = _.template(template)(locals || {}); + + if (options.beautify) { + content = beautify(content, options); + } + + return content; + } +}; diff --git a/lib/helpers/umzug-helper.js b/src/helpers/umzug-helper.js similarity index 61% rename from lib/helpers/umzug-helper.js rename to src/helpers/umzug-helper.js index a66f3fe8..93c2589b 100644 --- a/lib/helpers/umzug-helper.js +++ b/src/helpers/umzug-helper.js @@ -1,43 +1,41 @@ -'use strict'; +import path from 'path'; +import _ from 'lodash'; +import helpers from './index'; -var path = require('path'); -var _ = require('lodash'); -var helpers = require(__dirname); - -var storage = { +const storage = { migration: 'sequelize', seeder: 'none' }; -var storageTableName = { +const storageTableName = { migration: 'SequelizeMeta', seeder: 'SequelizeData' }; -var storageJsonName = { +const storageJsonName = { migration: 'sequelize-meta.json', seeder: 'sequelize-data.json' }; module.exports = { - getStorageOption: function (property, fallback) { + getStorageOption (property, fallback) { return helpers.config.readConfig()[property] || fallback; }, - getStorage: function (type) { + getStorage (type) { return this.getStorageOption(type + 'Storage', storage[type]); }, - getStoragePath: function (type) { - var fallbackPath = path.join(process.cwd(), storageJsonName[type]); + getStoragePath (type) { + const fallbackPath = path.join(process.cwd(), storageJsonName[type]); return this.getStorageOption(type + 'StoragePath', fallbackPath); }, - getTableName: function (type) { + getTableName (type) { return this.getStorageOption(type + 'StorageTableName', storageTableName[type]); }, - getStorageOptions: function (type, extraOptions) { - var options = {}; + getStorageOptions (type, extraOptions) { + const options = {}; if (this.getStorage(type) === 'json') { options.path = this.getStoragePath(type); diff --git a/src/helpers/version-helper.js b/src/helpers/version-helper.js new file mode 100644 index 00000000..90158964 --- /dev/null +++ b/src/helpers/version-helper.js @@ -0,0 +1,41 @@ +import path from 'path'; +import helpers from './index'; + +const packageJson = require(path.resolve(__dirname, '..', '..', 'package.json')); + +module.exports = { + getCliVersion () { + return packageJson.version; + }, + + getOrmVersion () { + return helpers.generic.getSequelize('package.json').version; + }, + + getDialect () { + try { + return helpers.config.readConfig(); + } catch (e) { + return null; + } + }, + + getDialectName () { + const config = this.getDialect(); + + if (config) { + return { + 'sqlite': 'sqlite3', + 'postgres': 'pg', + 'mariadb': 'mariasql', + 'mysql': 'mysql' + }[config.dialect]; + } else { + return null; + } + }, + + getNodeVersion () { + return process.version.replace('v', ''); + } +}; diff --git a/src/helpers/view-helper.js b/src/helpers/view-helper.js new file mode 100644 index 00000000..e1e9702d --- /dev/null +++ b/src/helpers/view-helper.js @@ -0,0 +1,36 @@ +import clc from 'cli-color'; +import _ from 'lodash'; +import helpers from './index'; + +module.exports = { + teaser () { + const versions = [ + 'Node: ' + helpers.version.getNodeVersion(), + 'CLI: ' + helpers.version.getCliVersion(), + 'ORM: ' + helpers.version.getOrmVersion() + ]; + + this.log(); + this.log(clc.underline('Sequelize CLI [' + versions.join(', ') + ']')); + this.log(); + }, + + log: console.log, + error: console.error, + + pad (s, smth) { + let margin = smth; + + if (_.isObject(margin)) { + margin = Object.keys(margin); + } + + if (Array.isArray(margin)) { + margin = Math.max.apply(null, margin.map(o => { + return o.length; + })); + } + + return s + new Array(margin - s.length + 1).join(' '); + } +}; diff --git a/src/sequelize.js b/src/sequelize.js new file mode 100644 index 00000000..adcbaabc --- /dev/null +++ b/src/sequelize.js @@ -0,0 +1,73 @@ +#!/usr/bin/env node + +import yargs from 'yargs'; +import fs from 'fs'; +import path from 'path'; +import cliPackage from '../package'; +import Promise from 'bluebird'; +import { isEmpty } from 'lodash'; + +Promise.coroutine.addYieldHandler(yieldedValue => { + if (Array.isArray(yieldedValue)) { + return Promise.all(yieldedValue); + } +}); + +Promise.coroutine.addYieldHandler(yieldedValue => { + if (isEmpty(yieldedValue)) { + return Promise.resolve(yieldedValue); + } +}); + +import init from './commands/init'; +import migrate from './commands/migrate'; +import migrateUndo from './commands/migrate_undo'; +import migrateUndoAll from './commands/migrate_undo_all'; +import seed from './commands/seed'; +import seedOne from './commands/seed_one'; +import migrationGenerate from './commands/migration_generate'; +import modelGenerate from './commands/model_generate'; +import seedGenerate from './commands/seed_generate'; + +import helpers from './helpers/index'; + +helpers.view.teaser(); + +const cli = yargs + .command('db:migrate', 'Run pending migrations', migrate) + .command('db:migrate:schema:timestamps:add', 'Update migration table to have timestamps', migrate) + .command('db:migrate:status', 'List the status of all migrations', migrate) + .command('db:migrate:undo', 'Reverts a migration', migrateUndo) + .command('db:migrate:undo:all', 'Revert all migrations ran', migrateUndoAll) + .command('db:seed', 'Run specified seeder', seedOne) + .command('db:seed:undo', 'Deletes data from the database', seedOne) + .command('db:seed:all', 'Run every seeder', seed) + .command('db:seed:undo:all', 'Deletes data from the database', seed) + .command('init', 'Initializes project', init) + .command('init:config', 'Initializes configuration', init) + .command('init:migrations', 'Initializes migrations', init) + .command('init:models', 'Initializes models', init) + .command('init:seeders', 'Initializes seeders', init) + .command(['migration:generate', 'migration:create'], 'Generates a new migration file', migrationGenerate) + .command(['model:generate', 'model:create'], 'Generates a model and its migration', modelGenerate) + .command(['seed:generate', 'seed:create'], 'Generates a new seed file', seedGenerate) + .config(loadRCFile(yargs.argv.optionsPath)) + .version(() => cliPackage.version) + .wrap(yargs.terminalWidth()) + .strict() + .help(); + +const args = cli.argv; + +// if no command then show help +if (!args._[0]) { + cli.showHelp(); +} + +function loadRCFile(optionsPath) { + const rcFile = optionsPath || path.resolve(process.cwd(), '.sequelizerc'); + const rcFileResolved = path.resolve(rcFile); + return fs.existsSync(rcFileResolved) + ? JSON.parse(JSON.stringify(require(rcFileResolved))) + : {}; +}; diff --git a/test/.jshintrc b/test/.jshintrc deleted file mode 100644 index 5fda380c..00000000 --- a/test/.jshintrc +++ /dev/null @@ -1,14 +0,0 @@ -{ - "extends": "../.jshintrc", - "globals": { - "describe": false, - "it": false, - "refute": false, - "before": false, - "beforeEach":false, - "beforeAll": false, - "after": false, - "afterEach": false, - "afterAll": false - } -} diff --git a/test/db/migrate-json.test.js b/test/db/migrate-json.test.js index f225213a..f2b0d672 100644 --- a/test/db/migrate-json.test.js +++ b/test/db/migrate-json.test.js @@ -1,34 +1,31 @@ -'use strict'; - -var expect = require('expect.js'); -var Support = require(__dirname + '/../support'); -var helpers = require(__dirname + '/../support/helpers'); -var gulp = require('gulp'); -var fs = require('fs'); -var _ = require('lodash'); - -([ +const expect = require('expect.js'); +const Support = require(__dirname + '/../support'); +const helpers = require(__dirname + '/../support/helpers'); +const gulp = require('gulp'); +const fs = require('fs'); +const _ = require('lodash'); + +[ 'db:migrate', 'db:migrate --migrations-path migrations', '--migrations-path migrations db:migrate', 'db:migrate --migrations-path ./migrations', 'db:migrate --migrations-path ./migrations/', - 'db:migrate --coffee', 'db:migrate --config ../../support/tmp/config/config.json', 'db:migrate --config ' + Support.resolveSupportPath('tmp', 'config', 'config.json'), 'db:migrate --config ../../support/tmp/config/config.js' -]).forEach(function (flag) { - var prepare = function (callback, options) { +].forEach(flag => { + const prepare = function (callback, options) { options = _.assign({ config: {} }, options || {}); - var configPath = 'config/'; - var migrationFile = options.migrationFile || 'createPerson'; - var config = _.assign({ + let configPath = 'config/'; + let migrationFile = options.migrationFile || 'createPerson'; + const config = _.assign({ migrationStorage: 'json' }, helpers.getTestConfig(), options.config); - var configContent = JSON.stringify(config); + let configContent = JSON.stringify(config); - migrationFile = migrationFile + '.' + ((flag.indexOf('coffee') === -1) ? 'js' : 'coffee'); + migrationFile = migrationFile + '.js'; if (flag.match(/config\.js$/)) { configPath = configPath + 'config.js'; @@ -48,36 +45,36 @@ var _ = require('lodash'); .pipe(helpers.teardown(callback)); }; - describe(Support.getTestDialectTeaser(flag) + ' (JSON)', function () { - describe('the migration storage file', function () { - it('should be written to the default location', function (done) { - var storageFile = Support.resolveSupportPath('tmp', 'sequelize-meta.json'); + describe(Support.getTestDialectTeaser(flag) + ' (JSON)', () => { + describe('the migration storage file', () => { + it('should be written to the default location', done => { + const storageFile = Support.resolveSupportPath('tmp', 'sequelize-meta.json'); - prepare(function () { + prepare(() => { expect(fs.statSync(storageFile).isFile()).to.be(true); expect(fs.readFileSync(storageFile).toString()) - .to.match(/^\[\n "\d{14}-createPerson\.(js|coffee)"\n\]$/); + .to.match(/^\[\n "\d{14}-createPerson\.(js)"\n\]$/); done(); }); }); - it('should be written to the specified location', function (done) { - var storageFile = Support.resolveSupportPath('tmp', 'custom-meta.json'); + it('should be written to the specified location', done => { + const storageFile = Support.resolveSupportPath('tmp', 'custom-meta.json'); - prepare(function () { + prepare(() => { expect(fs.statSync(storageFile).isFile()).to.be(true); expect(fs.readFileSync(storageFile).toString()) - .to.match(/^\[\n "\d{14}-createPerson\.(js|coffee)"\n\]$/); + .to.match(/^\[\n "\d{14}-createPerson\.(js)"\n\]$/); done(); }, { config: { migrationStoragePath: storageFile } }); }); }); it('creates the respective table', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.readTables(self.sequelize, function (tables) { + prepare(() => { + helpers.readTables(self.sequelize, tables => { expect(tables).to.have.length(1); expect(tables).to.contain('Person'); done(); @@ -85,28 +82,28 @@ var _ = require('lodash'); }); }); - describe('the logging option', function () { - it('does not print sql queries by default', function (done) { - prepare(function (_, stdout) { + describe('the logging option', () => { + it('does not print sql queries by default', done => { + prepare((__, stdout) => { expect(stdout).to.not.contain('Executing'); done(); }); }); - it('interprets a custom option', function (done) { - prepare(function (_, stdout) { + it('interprets a custom option', done => { + prepare((__, stdout) => { expect(stdout).to.contain('Executing'); done(); }, { config: { logging: true } }); }); }); - describe('promise based migrations', function () { + describe('promise based migrations', () => { it('correctly creates two tables', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.readTables(self.sequelize, function (tables) { + prepare(() => { + helpers.readTables(self.sequelize, tables => { expect(tables.sort()).to.eql([ 'Person', 'Task' diff --git a/test/db/migrate.test.js b/test/db/migrate.test.js index cdce20e2..0368b940 100644 --- a/test/db/migrate.test.js +++ b/test/db/migrate.test.js @@ -1,35 +1,33 @@ -'use strict'; -var expect = require('expect.js'); -var Support = require(__dirname + '/../support'); -var helpers = require(__dirname + '/../support/helpers'); -var gulp = require('gulp'); -var _ = require('lodash'); -([ +const expect = require('expect.js'); +const Support = require(__dirname + '/../support'); +const helpers = require(__dirname + '/../support/helpers'); +const gulp = require('gulp'); +const _ = require('lodash'); + +[ 'db:migrate', 'db:migrate --migrations-path migrations', '--migrations-path migrations db:migrate', 'db:migrate --migrations-path ./migrations', 'db:migrate --migrations-path ./migrations/', - 'db:migrate --coffee', 'db:migrate --config ../../support/tmp/config/config.json', 'db:migrate --config ' + Support.resolveSupportPath('tmp', 'config', 'config.json'), 'db:migrate --config ../../support/tmp/config/config.js', 'db:migrate --config ../../support/tmp/config/config-promise.js' -]).forEach(function (flag) { - var prepare = function (callback, options) { +].forEach(flag => { + const prepare = function (callback, options) { options = _.assign({ config: {} }, options || {}); options.cli = options.cli || {}; _.defaults(options.cli, { pipeStdout: true }); - var configPath = 'config/'; - var migrationFile = options.migrationFile || 'createPerson'; - var config = _.assign({}, helpers.getTestConfig(), options.config); - var configContent = JSON.stringify(config); - - migrationFile = migrationFile + '.' + ((flag.indexOf('coffee') === -1) ? 'js' : 'coffee'); + let configPath = 'config/'; + let migrationFile = options.migrationFile || 'createPerson'; + const config = _.assign({}, helpers.getTestConfig(), options.config); + let configContent = JSON.stringify(config); + migrationFile = migrationFile + '.js'; if (flag.match(/config\.js$/)) { configPath = configPath + 'config.js'; configContent = 'module.exports = ' + configContent; @@ -42,7 +40,7 @@ var _ = require('lodash'); configPath = configPath + 'config.json'; } - var result = ''; + let result = ''; return gulp .src(Support.resolveSupportPath('tmp')) @@ -52,23 +50,23 @@ var _ = require('lodash'); .pipe(helpers.copyMigration(migrationFile)) .pipe(helpers.overwriteFile(configContent, configPath)) .pipe(helpers.runCli(flag, options.cli)) - .on('error', function (e) { + .on('error', e => { callback(e); }) - .on('data', function (data) { + .on('data', data => { result += data.toString(); }) - .on('end', function () { + .on('end', () => { callback(null, result); }); }; - describe(Support.getTestDialectTeaser(flag), function () { + describe(Support.getTestDialectTeaser(flag), () => { it('creates a SequelizeMeta table', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.readTables(self.sequelize, function (tables) { + prepare(() => { + helpers.readTables(self.sequelize, tables => { expect(tables).to.have.length(2); expect(tables).to.contain('SequelizeMeta'); done(); @@ -77,10 +75,10 @@ var _ = require('lodash'); }); it('creates the respective table', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.readTables(self.sequelize, function (tables) { + prepare(() => { + helpers.readTables(self.sequelize, tables => { expect(tables).to.have.length(2); expect(tables).to.contain('Person'); done(); @@ -88,35 +86,35 @@ var _ = require('lodash'); }); }); - it('fails with a not 0 exit code', function (done) { + it('fails with a not 0 exit code', done => { prepare(done, { migrationFile: 'invalid/*createPerson', cli: { exitCode: 1 } }); }); - describe('the logging option', function () { - it('does not print sql queries by default', function (done) { - prepare(function (_, stdout) { + describe('the logging option', () => { + it('does not print sql queries by default', done => { + prepare((__, stdout) => { expect(stdout).to.not.contain('Executing'); done(); }); }); - it('interpretes a custom option', function (done) { - prepare(function (_, stdout) { + it('interpretes a custom option', done => { + prepare((__, stdout) => { expect(stdout).to.contain('Executing'); done(); }, { config: { logging: true } }); }); }); - describe('promise based migrations', function () { + describe('promise based migrations', () => { it('correctly creates two tables', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.readTables(self.sequelize, function (tables) { + prepare(() => { + helpers.readTables(self.sequelize, tables => { expect(tables.sort()).to.eql([ 'Person', 'SequelizeMeta', @@ -131,12 +129,12 @@ var _ = require('lodash'); }); }); - describe('custom meta table name', function () { + describe('custom meta table name', () => { it('correctly uses the defined table name', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.readTables(self.sequelize, function (tables) { + prepare(() => { + helpers.readTables(self.sequelize, tables => { expect(tables.sort()).to.eql(['Person', 'Task', 'sequelize_meta']); done(); }); @@ -149,12 +147,12 @@ var _ = require('lodash'); }); }); -describe(Support.getTestDialectTeaser('db:migrate'), function () { - describe('with config.js', function () { - var prepare = function (callback) { - var config = helpers.getTestConfig(); - var configContent = 'module.exports = ' + JSON.stringify(config); - var result = ''; +describe(Support.getTestDialectTeaser('db:migrate'), () => { + describe('with config.js', () => { + const prepare = function (callback) { + const config = helpers.getTestConfig(); + const configContent = 'module.exports = ' + JSON.stringify(config); + let result = ''; return gulp .src(Support.resolveSupportPath('tmp')) @@ -164,22 +162,22 @@ describe(Support.getTestDialectTeaser('db:migrate'), function () { .pipe(helpers.copyMigration('createPerson.js')) .pipe(helpers.overwriteFile(configContent, 'config/config.js')) .pipe(helpers.runCli('db:migrate')) - .on('error', function (e) { + .on('error', e => { callback(e); }) - .on('data', function (data) { + .on('data', data => { result += data.toString(); }) - .on('end', function () { + .on('end', () => { callback(null, result); }); }; it('creates a SequelizeMeta table', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.readTables(self.sequelize, function (tables) { + prepare(() => { + helpers.readTables(self.sequelize, tables => { expect(tables).to.have.length(2); expect(tables).to.contain('SequelizeMeta'); done(); @@ -188,10 +186,10 @@ describe(Support.getTestDialectTeaser('db:migrate'), function () { }); it('creates the respective table', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.readTables(self.sequelize, function (tables) { + prepare(() => { + helpers.readTables(self.sequelize, tables => { expect(tables).to.have.length(2); expect(tables).to.contain('Person'); done(); @@ -201,37 +199,37 @@ describe(Support.getTestDialectTeaser('db:migrate'), function () { }); }); -describe(Support.getTestDialectTeaser('db:migrate'), function () { - describe('with config.json and url option', function () { - var prepare = function (callback) { - var config = { url: helpers.getTestUrl() }; - var configContent = 'module.exports = ' + JSON.stringify(config); - var result = ''; +describe(Support.getTestDialectTeaser('db:migrate'), () => { + describe('with config.json and url option', () => { + const prepare = function (callback) { + const config = { url: helpers.getTestUrl() }; + const configContent = 'module.exports = ' + JSON.stringify(config); + let result = ''; return gulp - .src(Support.resolveSupportPath('tmp')) - .pipe(helpers.clearDirectory()) - .pipe(helpers.runCli('init')) - .pipe(helpers.removeFile('config/config.json')) - .pipe(helpers.copyMigration('createPerson.js')) - .pipe(helpers.overwriteFile(configContent, 'config/config.js')) - .pipe(helpers.runCli('db:migrate')) - .on('error', function (e) { - callback(e); - }) - .on('data', function (data) { - result += data.toString(); - }) - .on('end', function () { - callback(null, result); - }); + .src(Support.resolveSupportPath('tmp')) + .pipe(helpers.clearDirectory()) + .pipe(helpers.runCli('init')) + .pipe(helpers.removeFile('config/config.json')) + .pipe(helpers.copyMigration('createPerson.js')) + .pipe(helpers.overwriteFile(configContent, 'config/config.js')) + .pipe(helpers.runCli('db:migrate')) + .on('error', e => { + callback(e); + }) + .on('data', data => { + result += data.toString(); + }) + .on('end', () => { + callback(null, result); + }); }; it('creates a SequelizeMeta table', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.readTables(self.sequelize, function (tables) { + prepare(() => { + helpers.readTables(self.sequelize, tables => { expect(tables).to.have.length(2); expect(tables).to.contain('SequelizeMeta'); done(); @@ -240,10 +238,10 @@ describe(Support.getTestDialectTeaser('db:migrate'), function () { }); it('creates the respective table', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.readTables(self.sequelize, function (tables) { + prepare(() => { + helpers.readTables(self.sequelize, tables => { expect(tables).to.have.length(2); expect(tables).to.contain('Person'); done(); diff --git a/test/db/migrate/old_schema.test.js b/test/db/migrate/old_schema.test.js deleted file mode 100644 index d704dae2..00000000 --- a/test/db/migrate/old_schema.test.js +++ /dev/null @@ -1,204 +0,0 @@ -'use strict'; - -var expect = require('expect.js'); -var Support = require(__dirname + '/../../support'); -var helpers = require(__dirname + '/../../support/helpers'); -var gulp = require('gulp'); -var Bluebird = require('bluebird'); -var execQuery = require('../../../lib/helpers').generic.execQuery; - -([ - 'db:migrate:old_schema' - ]).forEach(function (flag) { - var prepare = function (config, callback) { - config = helpers.getTestConfig(config); - - gulp - .src(Support.resolveSupportPath('tmp')) - .pipe(helpers.clearDirectory()) - .pipe(helpers.runCli('init')) - .pipe(helpers.copyMigration('createPerson.js')) - .pipe(helpers.copyMigration('emptyMigration.js')) - .pipe(helpers.copyMigration('renamePersonToUser.js')) - .pipe(helpers.overwriteFile(JSON.stringify(config), 'config/config.json')) - .pipe(helpers.teardown(callback)); - }; - - var prepareLegacyScenario = function (config, callback) { - var self = this; - - prepare(config, function () { - var SequelizeMeta = self.sequelize.define('SequelizeMeta', - { from: Support.Sequelize.STRING, to: Support.Sequelize.STRING }, - { timestamps: false } - ); - - SequelizeMeta.sync({ force: true }).then(function () { - return SequelizeMeta.bulkCreate([ - { from: '20111117063700', to: '20111117063700' }, - { from: '20111117063700', to: '20111205064000' } - ]); - }).then(callback); - }); - }; - - describe(Support.getTestDialectTeaser(flag + ' meta schema'), function () { - beforeEach(function (done) { - return prepareLegacyScenario.call(this, null, function () { - done(); - }); - }); - - it('is enforced', function (done) { - gulp - .src(Support.resolveSupportPath('tmp')) - .pipe(helpers.runCli('db:migrate', { pipeStderr: true })) - .pipe(helpers.teardown(function (err, stderr) { - expect(stderr).to.contain('Please run "sequelize db:migrate:old_schema" first.'); - done(); - })); - }); - }); - - describe(Support.getTestDialectTeaser(flag + ' auto migrate old schema'), function () { - beforeEach(function (done) { - return prepareLegacyScenario.call(this, { - autoMigrateOldSchema: true - }, function () { - done(); - return null; - }); - }); - - it('shouldn\'t enforce if we provide autoMigrateOldSchema option', function () { - return Bluebird.cast() - .bind(this) - .then(function () { - return this.sequelize.getQueryInterface().describeTable('SequelizeMeta'); - }) - .then(function (fields) { - expect(Object.keys(fields)).to.eql(['id', 'from', 'to']); - return null; - }) - .then(function () { - return new Bluebird(function (fulfill, reject) { - gulp - .src(Support.resolveSupportPath('tmp')) - .pipe(helpers.runCli('db:migrate', { pipeStderr: true })) - .pipe(helpers.teardown(function (err, stderr) { - if (err || stderr) { - return reject(err || stderr); - } - - fulfill(); - })); - }); - }) - .then(function () { - return this.sequelize.getQueryInterface().describeTable('SequelizeMeta'); - }) - .then(function (fields) { - expect(Object.keys(fields)).to.eql(['name']); - }); - }); - }); - - describe(Support.getTestDialectTeaser(flag), function () { - beforeEach(function (done) { - prepareLegacyScenario.call(this, null, function () { - return gulp - .src(Support.resolveSupportPath('tmp')) - .pipe(helpers.runCli(flag)) - .pipe(helpers.teardown(done)); - }); - }); - - it('renames the original table', function (done) { - var self = this; - - helpers.readTables(self.sequelize, function (tables) { - expect(tables).to.have.length(2); - expect(tables[0]).to.equal('SequelizeMeta'); - expect(tables[1]).to.equal('SequelizeMetaBackup'); - done(); - }); - }); - - it('keeps the data in the original table', function (done) { - execQuery( - this.sequelize, - this.sequelize.getQueryInterface().QueryGenerator.selectQuery('SequelizeMetaBackup'), - { raw: true } - ).then(function (items) { - expect(items.length).to.equal(2); - done(); - }); - }); - - it('keeps the structure of the original table', function (done) { - var self = this; - - helpers.readTables(self.sequelize, function () { - return self - .sequelize - .getQueryInterface() - .describeTable('SequelizeMetaBackup') - .then(function (fields) { - expect(Object.keys(fields).sort()).to.eql(['from', 'id', 'to']); - done(); - return null; - }); - }); - }); - - it('creates a new SequelizeMeta table with the new structure', function (done) { - this.sequelize.getQueryInterface().describeTable('SequelizeMeta').then(function (fields) { - expect(Object.keys(fields)).to.eql(['name']); - done(); - }); - }); - - it('creates two entries in the new table', function (done) { - execQuery( - this.sequelize, - this.sequelize.getQueryInterface().QueryGenerator.selectQuery('SequelizeMeta'), - { raw: true, type: 'SELECT' } - ).then(function (items) { - expect(items).to.eql([ - { name: '20111117063700-createPerson.js' }, - { name: '20111205064000-renamePersonToUser.js' } - ]); - done(); - }); - }); - - it('is possible to undo one of the already executed migrations', function (done) { - var self = this; - - // We are creating the User table here because the migrator will rename it to Person - // afterwards. - this.sequelize.define( - 'User', - { name: Support.Sequelize.STRING }, - { tableName: 'User' } - ).sync({ force: true }) - .then(function () { - gulp - .src(Support.resolveSupportPath('tmp')) - .pipe(helpers.runCli('db:migrate:undo')) - .pipe(helpers.teardown(function () { - execQuery( - self.sequelize, - self.sequelize.getQueryInterface().QueryGenerator.selectQuery('SequelizeMeta'), - { raw: true, type: 'SELECT' } - ).then(function (items) { - expect(items).to.eql([ - { name: '20111117063700-createPerson.js' } - ]); - done(); - }); - })); - }); - }); - }); - }); diff --git a/test/db/migrate/schema/add_timestamps.test.js b/test/db/migrate/schema/add_timestamps.test.js index 220581a9..3b81326b 100644 --- a/test/db/migrate/schema/add_timestamps.test.js +++ b/test/db/migrate/schema/add_timestamps.test.js @@ -1,31 +1,30 @@ -'use strict'; -var expect = require('expect.js'); -var Support = require(__dirname + '/../../../support'); -var helpers = require(__dirname + '/../../../support/helpers'); -var gulp = require('gulp'); -var execQuery = require('../../../../lib/helpers').generic.execQuery; -([ +const expect = require('expect.js'); +const Support = require(__dirname + '/../../../support'); +const helpers = require(__dirname + '/../../../support/helpers'); +const gulp = require('gulp'); + +[ 'db:migrate:schema:timestamps:add' -]).forEach(function (flag) { - var prepare = function (config, callback) { +].forEach(flag => { + const prepare = function (config, callback) { config = helpers.getTestConfig(config); gulp - .src(Support.resolveSupportPath('tmp')) - .pipe(helpers.clearDirectory()) - .pipe(helpers.runCli('init')) - .pipe(helpers.copyMigration('createPerson.js')) - .pipe(helpers.copyMigration('renamePersonToUser.js')) - .pipe(helpers.overwriteFile(JSON.stringify(config), 'config/config.json')) - .pipe(helpers.runCli('db:migrate')) - .pipe(helpers.teardown(callback)); + .src(Support.resolveSupportPath('tmp')) + .pipe(helpers.clearDirectory()) + .pipe(helpers.runCli('init')) + .pipe(helpers.copyMigration('createPerson.js')) + .pipe(helpers.copyMigration('renamePersonToUser.js')) + .pipe(helpers.overwriteFile(JSON.stringify(config), 'config/config.json')) + .pipe(helpers.runCli('db:migrate')) + .pipe(helpers.teardown(callback)); }; - describe(Support.getTestDialectTeaser(flag), function () { + describe(Support.getTestDialectTeaser(flag), () => { beforeEach(function (done) { - prepare.call(this, null, function () { + prepare.call(this, null, () => { return gulp .src(Support.resolveSupportPath('tmp')) .pipe(helpers.runCli(flag)) @@ -34,9 +33,9 @@ var execQuery = require('../../../../lib/helpers').generic.execQuery; }); it('renames the original table', function (done) { - var self = this; + const self = this; - helpers.readTables(self.sequelize, function (tables) { + helpers.readTables(self.sequelize, tables => { expect(tables).to.have.length(3); expect(tables.indexOf('SequelizeMeta')).to.be.above(-1); expect(tables.indexOf('SequelizeMetaBackup')).to.be.above(-1); @@ -45,25 +44,25 @@ var execQuery = require('../../../../lib/helpers').generic.execQuery; }); it('keeps the data in the original table', function (done) { - execQuery( + helpers.execQuery( this.sequelize, this.sequelize.getQueryInterface().QueryGenerator.selectQuery('SequelizeMetaBackup'), { raw: true } - ).then(function (items) { + ).then(items => { expect(items.length).to.equal(2); done(); }); }); it('keeps the structure of the original table', function (done) { - var self = this; + const self = this; - helpers.readTables(self.sequelize, function () { + helpers.readTables(self.sequelize, () => { return self .sequelize .getQueryInterface() .describeTable('SequelizeMetaBackup') - .then(function (fields) { + .then(fields => { expect(Object.keys(fields).sort()).to.eql(['name']); done(); return null; @@ -72,18 +71,18 @@ var execQuery = require('../../../../lib/helpers').generic.execQuery; }); it('creates a new SequelizeMeta table with the new structure', function (done) { - this.sequelize.getQueryInterface().describeTable('SequelizeMeta').then(function (fields) { + this.sequelize.getQueryInterface().describeTable('SequelizeMeta').then(fields => { expect(Object.keys(fields).sort()).to.eql(['createdAt', 'name', 'updatedAt']); done(); }); }); it('copies the entries into the new table', function (done) { - execQuery( + helpers.execQuery( this.sequelize, this.sequelize.getQueryInterface().QueryGenerator.selectQuery('SequelizeMeta'), { raw: true, type: 'SELECT' } - ).then(function (items) { + ).then(items => { expect(items[0].name).to.eql('20111117063700-createPerson.js'); expect(items[1].name).to.eql('20111205064000-renamePersonToUser.js'); done(); @@ -91,21 +90,21 @@ var execQuery = require('../../../../lib/helpers').generic.execQuery; }); it('is possible to undo one of the already executed migrations', function (done) { - var self = this; + const self = this; gulp - .src(Support.resolveSupportPath('tmp')) - .pipe(helpers.runCli('db:migrate:undo')) - .pipe(helpers.teardown(function () { - execQuery( - self.sequelize, - self.sequelize.getQueryInterface().QueryGenerator.selectQuery('SequelizeMeta'), - { raw: true, type: 'SELECT' } - ).then(function (items) { - expect(items[0].name).to.eql('20111117063700-createPerson.js'); - done(); - }); - })); + .src(Support.resolveSupportPath('tmp')) + .pipe(helpers.runCli('db:migrate:undo')) + .pipe(helpers.teardown(() => { + helpers.execQuery( + self.sequelize, + self.sequelize.getQueryInterface().QueryGenerator.selectQuery('SequelizeMeta'), + { raw: true, type: 'SELECT' } + ).then(items => { + expect(items[0].name).to.eql('20111117063700-createPerson.js'); + done(); + }); + })); }); }); }); diff --git a/test/db/migrate/status.test.js b/test/db/migrate/status.test.js index 5cc1d697..02cd4b63 100644 --- a/test/db/migrate/status.test.js +++ b/test/db/migrate/status.test.js @@ -1,14 +1,14 @@ - 'use strict'; -var Support = require(__dirname + '/../../support'); -var helpers = require(__dirname + '/../../support/helpers'); -var gulp = require('gulp'); -([ +const Support = require(__dirname + '/../../support'); +const helpers = require(__dirname + '/../../support/helpers'); +const gulp = require('gulp'); + +[ 'db:migrate:status' -]).forEach(function (flag) { - describe(Support.getTestDialectTeaser(flag), function () { - it('is correctly reports a down and an up migration', function (done) { +].forEach(flag => { + describe(Support.getTestDialectTeaser(flag), () => { + it('is correctly reports a down and an up migration', done => { gulp .src(Support.resolveSupportPath('tmp')) .pipe(helpers.clearDirectory()) @@ -18,7 +18,7 @@ var gulp = require('gulp'); .pipe(helpers.runCli('db:migrate', { pipeStdout: false })) .pipe(helpers.copyMigration('renamePersonToUser.js')) .pipe(helpers.runCli(flag, { pipeStdout: true })) - .pipe(helpers.ensureContent('up 20111117063700-createPerson.js')) + .pipe(helpers.ensureContent('up 20111117063700-createPerson.js')) .pipe(helpers.ensureContent('down 20111205064000-renamePersonToUser.js')) .pipe(helpers.teardown(done)); }); diff --git a/test/db/migrate/undo.test.js b/test/db/migrate/undo.test.js index 8c7011f0..23837fc3 100644 --- a/test/db/migrate/undo.test.js +++ b/test/db/migrate/undo.test.js @@ -1,15 +1,13 @@ - 'use strict'; +const expect = require('expect.js'); +const Support = require(__dirname + '/../../support'); +const helpers = require(__dirname + '/../../support/helpers'); +const gulp = require('gulp'); +const fs = require('fs'); -var expect = require('expect.js'); -var Support = require(__dirname + '/../../support'); -var helpers = require(__dirname + '/../../support/helpers'); -var gulp = require('gulp'); -var fs = require('fs'); - -([ +[ 'db:migrate:undo' -]).forEach(function (flag) { - var prepare = function (callback, _flag) { +].forEach(flag => { + const prepare = function (callback, _flag) { _flag = _flag || flag; gulp @@ -22,12 +20,12 @@ var fs = require('fs'); .pipe(helpers.teardown(callback)); }; - describe(Support.getTestDialectTeaser(flag), function () { + describe(Support.getTestDialectTeaser(flag), () => { it('creates a SequelizeMeta table', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.readTables(self.sequelize, function (tables) { + prepare(() => { + helpers.readTables(self.sequelize, tables => { expect(tables).to.have.length(1); expect(tables[0]).to.equal('SequelizeMeta'); done(); @@ -35,27 +33,27 @@ var fs = require('fs'); }); }); - it('stops execution if no migrations have been done yet', function (done) { - prepare(function (err, output) { + it('stops execution if no migrations have been done yet', done => { + prepare((err, output) => { expect(err).to.equal(null); expect(output).to.contain('No executed migrations found.'); done(); - }.bind(this)); + }); }); it('is correctly undoing a migration if they have been done already', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.readTables(self.sequelize, function (tables) { + prepare(() => { + helpers.readTables(self.sequelize, tables => { expect(tables).to.have.length(2); expect(tables[0]).to.equal('Person'); gulp .src(Support.resolveSupportPath('tmp')) .pipe(helpers.runCli(flag, { pipeStdout: true })) - .pipe(helpers.teardown(function () { - helpers.readTables(self.sequelize, function (tables) { + .pipe(helpers.teardown(() => { + helpers.readTables(self.sequelize, tables => { expect(tables).to.have.length(1); expect(tables[0]).to.equal('SequelizeMeta'); done(); @@ -66,14 +64,14 @@ var fs = require('fs'); }); it('correctly undoes a named migration', function (done) { - var self = this; + const self = this; - prepare(function () { - var migrationsPath = Support.resolveSupportPath('tmp', 'migrations'); - var migrations = fs.readdirSync(migrationsPath); - var createPersonMigration = migrations[0]; + prepare(() => { + const migrationsPath = Support.resolveSupportPath('tmp', 'migrations'); + const migrations = fs.readdirSync(migrationsPath); + const createPersonMigration = migrations[0]; - helpers.readTables(self.sequelize, function (tables) { + helpers.readTables(self.sequelize, tables => { expect(tables).to.have.length(2); expect(tables[0]).to.equal('Person'); @@ -82,11 +80,11 @@ var fs = require('fs'); .pipe(helpers.copyMigration('emptyMigration.js')) .pipe(helpers.runCli('db:migrate')) .pipe(helpers.runCli(flag + ' --name ' + createPersonMigration, { pipeStdout: true })) - .pipe(helpers.teardown(function () { - helpers.readTables(self.sequelize, function (tables) { + .pipe(helpers.teardown(() => { + helpers.readTables(self.sequelize, tables => { expect(tables).to.have.length(1); expect(tables[0]).to.equal('SequelizeMeta'); - helpers.countTable(self.sequelize, 'SequelizeMeta', function (count) { + helpers.countTable(self.sequelize, 'SequelizeMeta', count => { expect(count).to.eql([{ count: 1 }]); done(); }); diff --git a/test/db/migrate/undo/all.test.js b/test/db/migrate/undo/all.test.js index 1302fa48..4bd09290 100644 --- a/test/db/migrate/undo/all.test.js +++ b/test/db/migrate/undo/all.test.js @@ -1,14 +1,14 @@ - 'use strict'; -var expect = require('expect.js'); -var Support = require(__dirname + '/../../../support'); -var helpers = require(__dirname + '/../../../support/helpers'); -var gulp = require('gulp'); -([ +const expect = require('expect.js'); +const Support = require(__dirname + '/../../../support'); +const helpers = require(__dirname + '/../../../support/helpers'); +const gulp = require('gulp'); + +[ 'db:migrate:undo:all' -]).forEach(function (flag) { - var prepare = function (callback, _flag) { +].forEach(flag => { + const prepare = function (callback, _flag) { _flag = _flag || flag; gulp @@ -22,12 +22,12 @@ var gulp = require('gulp'); .pipe(helpers.teardown(callback)); }; - describe(Support.getTestDialectTeaser(flag), function () { + describe(Support.getTestDialectTeaser(flag), () => { it('creates a SequelizeMeta table', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.readTables(self.sequelize, function (tables) { + prepare(() => { + helpers.readTables(self.sequelize, tables => { expect(tables).to.have.length(1); expect(tables[0]).to.equal('SequelizeMeta'); done(); @@ -35,19 +35,19 @@ var gulp = require('gulp'); }); }); - it('stops execution if no migrations have been done yet', function (done) { - prepare(function (err, output) { + it('stops execution if no migrations have been done yet', done => { + prepare((err, output) => { expect(err).to.equal(null); expect(output).to.contain('No executed migrations found.'); done(); - }.bind(this)); + }); }); it('is correctly undoing all migrations if they have been done already', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.readTables(self.sequelize, function (tables) { + prepare(() => { + helpers.readTables(self.sequelize, tables => { expect(tables).to.have.length(2); expect(tables).to.contain('User'); expect(tables).to.contain('SequelizeMeta'); @@ -55,8 +55,8 @@ var gulp = require('gulp'); gulp .src(Support.resolveSupportPath('tmp')) .pipe(helpers.runCli(flag, { pipeStdout: true })) - .pipe(helpers.teardown(function () { - helpers.readTables(self.sequelize, function (tables) { + .pipe(helpers.teardown(() => { + helpers.readTables(self.sequelize, tables => { expect(tables).to.have.length(1); expect(tables[0]).to.equal('SequelizeMeta'); done(); diff --git a/test/db/migrate/undo/all_to.test.js b/test/db/migrate/undo/all_to.test.js index cde5f80b..9eef905a 100644 --- a/test/db/migrate/undo/all_to.test.js +++ b/test/db/migrate/undo/all_to.test.js @@ -1,14 +1,12 @@ - 'use strict'; +const expect = require('expect.js'); +const Support = require(__dirname + '/../../../support'); +const helpers = require(__dirname + '/../../../support/helpers'); +const gulp = require('gulp'); -var expect = require('expect.js'); -var Support = require(__dirname + '/../../../support'); -var helpers = require(__dirname + '/../../../support/helpers'); -var gulp = require('gulp'); - -([ +[ 'db:migrate:undo:all --to 20130909175939-createTestTableForTrigger.js' -]).forEach(function (flag) { - var prepare = function (callback, _flag) { +].forEach(flag => { + const prepare = function (callback, _flag) { _flag = _flag || flag; gulp @@ -24,12 +22,12 @@ var gulp = require('gulp'); .pipe(helpers.teardown(callback)); }; - describe(Support.getTestDialectTeaser(flag), function () { + describe(Support.getTestDialectTeaser(flag), () => { it('creates a SequelizeMeta table', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.readTables(self.sequelize, function (tables) { + prepare(() => { + helpers.readTables(self.sequelize, tables => { expect(tables).to.have.length(1); expect(tables[0]).to.equal('SequelizeMeta'); done(); @@ -37,38 +35,38 @@ var gulp = require('gulp'); }); }); - it('stops execution if no migrations have been done yet', function (done) { - prepare(function (err, output) { + it('stops execution if no migrations have been done yet', done => { + prepare((err, output) => { expect(err).to.equal(null); expect(output).to.contain('No executed migrations found.'); done(); - }.bind(this)); + }); }); it('is properly undoing migration with --to option and all migrations after', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.readTables(self.sequelize, function (tables) { + prepare(() => { + helpers.readTables(self.sequelize, tables => { expect(tables).to.have.length(4); expect(tables).to.contain('User'); expect(tables).to.contain('SequelizeMeta'); expect(tables).to.contain('Post'); expect(tables).to.contain('trigger_test'); - helpers.countTable(self.sequelize, 'SequelizeMeta', function(result) { + helpers.countTable(self.sequelize, 'SequelizeMeta', result => { expect(result[0].count).to.eql(4); gulp .src(Support.resolveSupportPath('tmp')) .pipe(helpers.runCli(flag, { pipeStdout: true })) - .pipe(helpers.teardown(function () { - helpers.readTables(self.sequelize, function (tables) { + .pipe(helpers.teardown(() => { + helpers.readTables(self.sequelize, tables => { expect(tables).to.have.length(2); expect(tables).to.contain('SequelizeMeta'); expect(tables).to.contain('User'); - helpers.countTable(self.sequelize, 'SequelizeMeta', function(result) { + helpers.countTable(self.sequelize, 'SequelizeMeta', result => { expect(result[0].count).to.eql(2); done(); }); diff --git a/test/db/seed-json.test.js b/test/db/seed-json.test.js index 9f63ba69..f7a8df11 100644 --- a/test/db/seed-json.test.js +++ b/test/db/seed-json.test.js @@ -1,34 +1,33 @@ -'use strict'; -var expect = require('expect.js'); -var Support = require(__dirname + '/../support'); -var helpers = require(__dirname + '/../support/helpers'); -var gulp = require('gulp'); -var fs = require('fs'); -var _ = require('lodash'); -([ +const expect = require('expect.js'); +const Support = require(__dirname + '/../support'); +const helpers = require(__dirname + '/../support/helpers'); +const gulp = require('gulp'); +const fs = require('fs'); +const _ = require('lodash'); + +[ 'db:seed --seed seedPerson.js', 'db:seed --seed seedPerson.js --seeders-path seeders', '--seeders-path seeders --seed seedPerson.js db:seed', 'db:seed --seed seedPerson.js --seeders-path ./seeders', 'db:seed --seed seedPerson.js --seeders-path ./seeders/', - 'db:seed --seed seedPerson.coffee --coffee', 'db:seed --seed seedPerson.js --config ../../support/tmp/config/config.json', 'db:seed --seed seedPerson.js --config ' + Support.resolveSupportPath('tmp', 'config', 'config.json'), 'db:seed --seed seedPerson.js --config ../../support/tmp/config/config.js' -]).forEach(function (flag) { - var prepare = function (callback, options) { +].forEach(flag => { + const prepare = function (callback, options) { options = _.assign({ config: {} }, options || {}); - var configPath = 'config/'; - var seederFile = options.seederFile || 'seedPerson'; - var config = _.assign({}, helpers.getTestConfig(), options.config); - var configContent = JSON.stringify(config); - var migrationFile = 'createPerson.' + ((flag.indexOf('coffee') === -1) ? 'js' : 'coffee'); + let configPath = 'config/'; + let seederFile = options.seederFile || 'seedPerson'; + const config = _.assign({}, helpers.getTestConfig(), options.config); + let configContent = JSON.stringify(config); + const migrationFile = 'createPerson.js'; - seederFile = seederFile + '.' + ((flag.indexOf('coffee') === -1) ? 'js' : 'coffee'); + seederFile = seederFile + '.js'; if (flag.match(/config\.js$/)) { configPath = configPath + 'config.js'; @@ -46,18 +45,18 @@ var _ = require('lodash'); .pipe(helpers.copySeeder(seederFile)) .pipe(helpers.overwriteFile(configContent, configPath)) .pipe(helpers.runCli('db:migrate' + - ((flag.indexOf('coffee') === -1 && flag.indexOf('config') === -1) ? - '' : flag.replace('db:seed', '')))) + (flag.indexOf('config') === -1 ? '' : flag.replace('db:seed --seed seedPerson.js', '')) + )) .pipe(helpers.runCli(flag, { pipeStdout: true })) .pipe(helpers.teardown(callback)); }; - describe(Support.getTestDialectTeaser(flag) + ' (JSON)', function () { + describe(Support.getTestDialectTeaser(flag) + ' (JSON)', () => { it('populates the respective table', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.countTable(self.sequelize, 'Person', function (result) { + prepare(() => { + helpers.countTable(self.sequelize, 'Person', result => { expect(result).to.have.length(1); expect(result[0].count).to.eql(1); done(); @@ -65,29 +64,29 @@ var _ = require('lodash'); }); }); - describe('the seeder storage file', function () { - it('should be written to the specified location', function (done) { - var storageFile = Support.resolveSupportPath('tmp', 'custom-data.json'); + describe('the seeder storage file', () => { + it('should be written to the specified location', done => { + const storageFile = Support.resolveSupportPath('tmp', 'custom-data.json'); - prepare(function () { + prepare(() => { expect(fs.statSync(storageFile).isFile()).to.be(true); expect(fs.readFileSync(storageFile).toString()) - .to.match(/^\[\n "seedPerson\.(js|coffee)"\n\]$/); + .to.match(/^\[\n "seedPerson\.(js)"\n\]$/); done(); }, { config: { seederStoragePath: storageFile, seederStorage: 'json' } }); }); }); - describe('the logging option', function () { - it('does not print sql queries by default', function (done) { - prepare(function (_, stdout) { + describe('the logging option', () => { + it('does not print sql queries by default', done => { + prepare((__, stdout) => { expect(stdout).to.not.contain('Executing'); done(); }); }); - it('interprets a custom option', function (done) { - prepare(function (_, stdout) { + it('interprets a custom option', done => { + prepare((__, stdout) => { expect(stdout).to.contain('Executing'); done(); }, { config: { logging: true } }); diff --git a/test/db/seed.test.js b/test/db/seed.test.js index 33c26d1e..2aa67f19 100644 --- a/test/db/seed.test.js +++ b/test/db/seed.test.js @@ -1,34 +1,33 @@ -'use strict'; -var expect = require('expect.js'); -var Support = require(__dirname + '/../support'); -var helpers = require(__dirname + '/../support/helpers'); -var gulp = require('gulp'); -var _ = require('lodash'); -([ +const expect = require('expect.js'); +const Support = require(__dirname + '/../support'); +const helpers = require(__dirname + '/../support/helpers'); +const gulp = require('gulp'); +const _ = require('lodash'); + +[ 'db:seed --seed seedPerson.js', 'db:seed --seeders-path seeders --seed seedPerson.js', '--seeders-path seeders db:seed --seed seedPerson.js', 'db:seed --seeders-path ./seeders --seed seedPerson.js', 'db:seed --seeders-path ./seeders/ --seed seedPerson.js', - 'db:seed --coffee --seed seedPerson.coffee', - 'db:seed --config ../../support/tmp/config/config.json --seed seedPerson.js', + 'db:seed --seed seedPerson.js --config ../../support/tmp/config/config.json', 'db:seed --seed seedPerson.js --config ' + Support.resolveSupportPath('tmp', 'config', 'config.json'), 'db:seed --seed seedPerson.js --config ../../support/tmp/config/config.js', 'db:seed --seed seedPerson.js --config ../../support/tmp/config/config-promise.js' -]).forEach(function (flag) { - var prepare = function (callback, options) { +].forEach(flag => { + const prepare = function (callback, options) { options = _.assign({ config: {} }, options || {}); - var configPath = 'config/'; - var seederFile = 'seedPerson'; - var config = _.assign({}, helpers.getTestConfig(), options.config); - var configContent = JSON.stringify(config); - var migrationFile = 'createPerson.' + ((flag.indexOf('coffee') === -1) ? 'js' : 'coffee'); + let configPath = 'config/'; + let seederFile = 'seedPerson'; + const config = _.assign({}, helpers.getTestConfig(), options.config); + let configContent = JSON.stringify(config); + const migrationFile = 'createPerson.js'; - seederFile = seederFile + '.' + ((flag.indexOf('coffee') === -1) ? 'js' : 'coffee'); + seederFile = seederFile + '.js'; if (flag.match(/config\.js$/)) { configPath = configPath + 'config.js'; @@ -51,18 +50,18 @@ var _ = require('lodash'); .pipe(helpers.copySeeder(seederFile)) .pipe(helpers.overwriteFile(configContent, configPath)) .pipe(helpers.runCli('db:migrate' + - ((flag.indexOf('coffee') === -1 && flag.indexOf('config') === -1) ? '' - : flag.replace('db:seed', '')))) + (flag.indexOf('config') === -1 ? '' : flag.replace('db:seed --seed seedPerson.js', '')) + )) .pipe(helpers.runCli(flag, { pipeStdout: true })) .pipe(helpers.teardown(callback)); }; - describe(Support.getTestDialectTeaser(flag), function () { + describe(Support.getTestDialectTeaser(flag), () => { it('creates a SequelizeData table', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.readTables(self.sequelize, function (tables) { + prepare(() => { + helpers.readTables(self.sequelize, tables => { expect(tables).to.have.length(3); expect(tables).to.contain('SequelizeData'); done(); @@ -71,10 +70,10 @@ var _ = require('lodash'); }); it('populates the respective table', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.countTable(self.sequelize, 'Person', function (result) { + prepare(() => { + helpers.countTable(self.sequelize, 'Person', result => { expect(result).to.have.length(1); expect(result[0].count).to.eql(1); done(); @@ -82,28 +81,28 @@ var _ = require('lodash'); }); }); - describe('the logging option', function () { - it('does not print sql queries by default', function (done) { - prepare(function (_, stdout) { + describe('the logging option', () => { + it('does not print sql queries by default', done => { + prepare((__, stdout) => { expect(stdout).to.not.contain('Executing'); done(); }); }); - it('interpretes a custom option', function (done) { - prepare(function (_, stdout) { + it('interpretes a custom option', done => { + prepare((__, stdout) => { expect(stdout).to.contain('Executing'); done(); }, { config: { logging: true } }); }); }); - describe('custom meta table name', function () { + describe('custom meta table name', () => { it('correctly uses the defined table name', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.readTables(self.sequelize, function (tables) { + prepare(() => { + helpers.readTables(self.sequelize, tables => { expect(tables.sort()).to.eql(['Person', 'SequelizeMeta', 'sequelize_data']); done(); }); diff --git a/test/db/seed/all.test.js b/test/db/seed/all.test.js index 6852d924..421a728d 100644 --- a/test/db/seed/all.test.js +++ b/test/db/seed/all.test.js @@ -1,32 +1,29 @@ -'use strict'; +const expect = require('expect.js'); +const Support = require(__dirname + '/../../support'); +const helpers = require(__dirname + '/../../support/helpers'); +const gulp = require('gulp'); +const _ = require('lodash'); -var expect = require('expect.js'); -var Support = require(__dirname + '/../../support'); -var helpers = require(__dirname + '/../../support/helpers'); -var gulp = require('gulp'); -var _ = require('lodash'); - -([ +[ 'db:seed:all', 'db:seed:all --seeders-path seeders', '--seeders-path seeders db:seed:all', 'db:seed:all --seeders-path ./seeders', 'db:seed:all --seeders-path ./seeders/', - 'db:seed:all --coffee', 'db:seed:all --config ../../support/tmp/config/config.json', 'db:seed:all --config ' + Support.resolveSupportPath('tmp', 'config', 'config.json'), 'db:seed:all --config ../../support/tmp/config/config.js' -]).forEach(function (flag) { - var prepare = function (callback, options) { +].forEach(flag => { + const prepare = function (callback, options) { options = _.assign({ config: {} }, options || {}); - var configPath = 'config/'; - var seederFile = options.seederFile || 'seedPerson'; - var config = _.assign({}, helpers.getTestConfig(), options.config); - var configContent = JSON.stringify(config); - var migrationFile = 'createPerson.' + ((flag.indexOf('coffee') === -1) ? 'js' : 'coffee'); + let configPath = 'config/'; + let seederFile = options.seederFile || 'seedPerson'; + const config = _.assign({}, helpers.getTestConfig(), options.config); + let configContent = JSON.stringify(config); + const migrationFile = 'createPerson.js'; - seederFile = seederFile + '.' + ((flag.indexOf('coffee') === -1) ? 'js' : 'coffee'); + seederFile = seederFile + '.js'; if (flag.match(/config\.js$/)) { configPath = configPath + 'config.js'; @@ -44,18 +41,18 @@ var _ = require('lodash'); .pipe(helpers.copySeeder(seederFile)) .pipe(helpers.overwriteFile(configContent, configPath)) .pipe(helpers.runCli('db:migrate' + - ((flag.indexOf('coffee') === -1 && flag.indexOf('config') === -1) ? '' - : flag.replace('db:seed:all', '')))) + (flag.indexOf('config') === -1 ? '' : flag.replace('db:seed:all', '')) + )) .pipe(helpers.runCli(flag, { pipeStdout: true })) .pipe(helpers.teardown(callback)); }; - describe(Support.getTestDialectTeaser(flag), function () { + describe(Support.getTestDialectTeaser(flag), () => { it('creates a SequelizeData table', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.readTables(self.sequelize, function (tables) { + prepare(() => { + helpers.readTables(self.sequelize, tables => { expect(tables).to.have.length(3); expect(tables).to.contain('SequelizeData'); done(); @@ -64,10 +61,10 @@ var _ = require('lodash'); }); it('populates the respective table', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.countTable(self.sequelize, 'Person', function (result) { + prepare(() => { + helpers.countTable(self.sequelize, 'Person', result => { expect(result).to.have.length(1); expect(result[0].count).to.eql(1); done(); @@ -75,28 +72,28 @@ var _ = require('lodash'); }); }); - describe('the logging option', function () { - it('does not print sql queries by default', function (done) { - prepare(function (_, stdout) { + describe('the logging option', () => { + it('does not print sql queries by default', done => { + prepare((__, stdout) => { expect(stdout).to.not.contain('Executing'); done(); }); }); - it('interpretes a custom option', function (done) { - prepare(function (_, stdout) { + it('interpretes a custom option', done => { + prepare((__, stdout) => { expect(stdout).to.contain('Executing'); done(); }, { config: { logging: true } }); }); }); - describe('custom meta table name', function () { + describe('custom meta table name', () => { it('correctly uses the defined table name', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.readTables(self.sequelize, function (tables) { + prepare(() => { + helpers.readTables(self.sequelize, tables => { expect(tables.sort()).to.eql(['Person', 'SequelizeMeta', 'sequelize_data']); done(); }); diff --git a/test/db/seed/undo.test.js b/test/db/seed/undo.test.js index ac379048..ba20109c 100644 --- a/test/db/seed/undo.test.js +++ b/test/db/seed/undo.test.js @@ -1,17 +1,15 @@ - 'use strict'; +const expect = require('expect.js'); +const Support = require(__dirname + '/../../support'); +const helpers = require(__dirname + '/../../support/helpers'); +const gulp = require('gulp'); -var expect = require('expect.js'); -var Support = require(__dirname + '/../../support'); -var helpers = require(__dirname + '/../../support/helpers'); -var gulp = require('gulp'); - -([ +[ 'db:seed:undo --seed seedPerson.js' -]).forEach(function (flag) { - var prepare = function (callback, options) { - var _flag = options.flag || flag; +].forEach(flag => { + const prepare = function (callback, options) { + const _flag = options.flag || flag; - var pipeline = gulp + const pipeline = gulp .src(Support.resolveSupportPath('tmp')) .pipe(helpers.clearDirectory()) .pipe(helpers.runCli('init')) @@ -28,27 +26,27 @@ var gulp = require('gulp'); .pipe(helpers.teardown(callback)); }; - describe(Support.getTestDialectTeaser(flag), function () { - it('stops execution if no seeder file is found', function (done) { - prepare(function (err, output) { + describe(Support.getTestDialectTeaser(flag), () => { + it('stops execution if no seeder file is found', done => { + prepare((err, output) => { expect(output).to.contain('Unable to find migration'); done(); - }.bind(this), {copySeeds: false}); + }, {copySeeds: false}); }); it('is correctly undoing a seeder if they have been done already', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.readTables(self.sequelize, function (tables) { + prepare(() => { + helpers.readTables(self.sequelize, tables => { expect(tables).to.have.length(2); expect(tables[0]).to.equal('Person'); gulp .src(Support.resolveSupportPath('tmp')) .pipe(helpers.runCli(flag, { pipeStdout: true })) - .pipe(helpers.teardown(function () { - helpers.countTable(self.sequelize, 'Person', function (res) { + .pipe(helpers.teardown(() => { + helpers.countTable(self.sequelize, 'Person', res => { expect(res).to.have.length(1); expect(res[0].count).to.eql(0); done(); diff --git a/test/db/seed/undo/all.test.js b/test/db/seed/undo/all.test.js index a5e7df60..1677f09d 100644 --- a/test/db/seed/undo/all.test.js +++ b/test/db/seed/undo/all.test.js @@ -1,19 +1,17 @@ - 'use strict'; +const expect = require('expect.js'); +const Support = require(__dirname + '/../../../support'); +const helpers = require(__dirname + '/../../../support/helpers'); +const gulp = require('gulp'); +const _ = require('lodash'); -var expect = require('expect.js'); -var Support = require(__dirname + '/../../../support'); -var helpers = require(__dirname + '/../../../support/helpers'); -var gulp = require('gulp'); -var _ = require('lodash'); - -([ +[ 'db:seed:undo:all' -]).forEach(function (flag) { - var prepare = function (callback, options) { - var _flag = options.flag || flag; - var config = _.assign({}, helpers.getTestConfig(), options.config || {}); +].forEach(flag => { + const prepare = function (callback, options) { + const _flag = options.flag || flag; + const config = _.assign({}, helpers.getTestConfig(), options.config || {}); - var pipeline = gulp + const pipeline = gulp .src(Support.resolveSupportPath('tmp')) .pipe(helpers.clearDirectory()) .pipe(helpers.runCli('init')) @@ -21,7 +19,7 @@ var _ = require('lodash'); if ( options.copySeeds ) { pipeline.pipe(helpers.copySeeder('seedPerson.js')) - .pipe(helpers.copySeeder('seedPerson2.js')); + .pipe(helpers.copySeeder('seedPerson2.js')); } pipeline.pipe(helpers.overwriteFile(JSON.stringify(config), @@ -31,28 +29,28 @@ var _ = require('lodash'); .pipe(helpers.teardown(callback)); }; - describe(Support.getTestDialectTeaser(flag), function () { - it('stops execution if no seeders have been found', function (done) { - prepare(function (err, output) { + describe(Support.getTestDialectTeaser(flag), () => { + it('stops execution if no seeders have been found', done => { + prepare((err, output) => { expect(err).to.equal(null); expect(output).to.contain('No seeders found.'); done(); - }.bind(this), {copySeeds: false}); + }, {copySeeds: false}); }); it('is correctly undoing all seeders if they have been done already', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.countTable(self.sequelize, 'Person', function (res) { + prepare(() => { + helpers.countTable(self.sequelize, 'Person', res => { expect(res).to.have.length(1); expect(res[0].count).to.eql(2); gulp .src(Support.resolveSupportPath('tmp')) .pipe(helpers.runCli(flag, { pipeStdout: true })) - .pipe(helpers.teardown(function () { - helpers.countTable(self.sequelize, 'Person', function (res) { + .pipe(helpers.teardown(() => { + helpers.countTable(self.sequelize, 'Person', res => { expect(res).to.have.length(1); expect(res[0].count).to.eql(0); done(); @@ -63,18 +61,18 @@ var _ = require('lodash'); }); it('is correctly undoing all seeders when storage is none', function (done) { - var self = this; + const self = this; - prepare(function () { - helpers.countTable(self.sequelize, 'Person', function (res) { + prepare(() => { + helpers.countTable(self.sequelize, 'Person', res => { expect(res).to.have.length(1); expect(res[0].count).to.eql(2); gulp .src(Support.resolveSupportPath('tmp')) .pipe(helpers.runCli(flag, { pipeStdout: true })) - .pipe(helpers.teardown(function () { - helpers.countTable(self.sequelize, 'Person', function (res) { + .pipe(helpers.teardown(() => { + helpers.countTable(self.sequelize, 'Person', res => { expect(res).to.have.length(1); expect(res[0].count).to.eql(0); done(); diff --git a/test/environment-variable.test.js b/test/environment-variable.test.js index 0ecbcd4f..8b36cad6 100644 --- a/test/environment-variable.test.js +++ b/test/environment-variable.test.js @@ -1,11 +1,9 @@ -'use strict'; +const expect = require('expect.js'); +const Support = require(__dirname + '/support'); +const helpers = require(__dirname + '/support/helpers'); +const gulp = require('gulp'); -var expect = require('expect.js'); -var Support = require(__dirname + '/support'); -var helpers = require(__dirname + '/support/helpers'); -var gulp = require('gulp'); - -var prepare = function (callback) { +const prepare = function (callback) { gulp .src(Support.resolveSupportPath('tmp')) .pipe(helpers.clearDirectory()) @@ -21,11 +19,11 @@ var prepare = function (callback) { .pipe(helpers.teardown(callback)); }; -describe(Support.getTestDialectTeaser('use_env_variable'), function () { +describe(Support.getTestDialectTeaser('use_env_variable'), () => { beforeEach(prepare); it('correctly runs the migration', function (done) { - helpers.readTables(this.sequelize, function (tables) { + helpers.readTables(this.sequelize, tables => { expect(tables).to.have.length(2); expect(tables).to.contain('SequelizeMeta'); done(); diff --git a/test/help.test.js b/test/help.test.js index 3cf9d601..eb9bc973 100644 --- a/test/help.test.js +++ b/test/help.test.js @@ -1,20 +1,16 @@ -'use strict'; +const Support = require(__dirname + '/support'); +const helpers = require(__dirname + '/support/helpers'); +const gulp = require('gulp'); -var Support = require(__dirname + '/support'); -var helpers = require(__dirname + '/support/helpers'); -var gulp = require('gulp'); - -([ - 'help', - 'h', - '' -]).forEach(function (flag) { - describe(Support.getTestDialectTeaser(flag), function () { - it('prints the help', function (done) { +[ + '--help' +].forEach(flag => { + describe(Support.getTestDialectTeaser(flag), () => { + it('prints the help', done => { gulp .src(process.cwd()) .pipe(helpers.runCli(flag, { pipeStdout: true })) - .pipe(helpers.ensureContent('Usage\n sequelize [task]')) + .pipe(helpers.ensureContent('Commands:\n')) .pipe(helpers.teardown(done)); }); }); diff --git a/test/init.test.js b/test/init.test.js index 8df3f884..d0dc04c5 100644 --- a/test/init.test.js +++ b/test/init.test.js @@ -1,21 +1,19 @@ -'use strict'; +const Support = require(__dirname + '/support'); +const helpers = require(__dirname + '/support/helpers'); +const gulp = require('gulp'); -var Support = require(__dirname + '/support'); -var helpers = require(__dirname + '/support/helpers'); -var gulp = require('gulp'); - -([ +[ 'init' -]).forEach(function (flag) { - describe(Support.getTestDialectTeaser(flag), function () { +].forEach(flag => { + describe(Support.getTestDialectTeaser(flag), () => { (function (folders) { - folders.forEach(function (folder) { - it('creates "' + folder + '"', function (done) { - var sourcePath = Support.resolveSupportPath('tmp'); - var file = folder; + folders.forEach(folder => { + it('creates "' + folder + '"', done => { + let sourcePath = Support.resolveSupportPath('tmp'); + let file = folder; if (folder.indexOf('/') > -1) { - var split = folder.split('/'); + const split = folder.split('/'); file = split.pop(); sourcePath = Support.resolveSupportPath('tmp', split.join('/')); @@ -25,7 +23,7 @@ var gulp = require('gulp'); .src(Support.resolveSupportPath('tmp')) .pipe(helpers.clearDirectory()) .pipe(helpers.runCli(flag)) - .pipe(helpers.teardown(function () { + .pipe(helpers.teardown(() => { gulp .src(sourcePath) .pipe(helpers.listFiles()) @@ -42,7 +40,7 @@ var gulp = require('gulp'); 'models/index.js' ]); - it('creates a custom migrations folder', function (done) { + it('creates a custom migrations folder', done => { gulp .src(Support.resolveSupportPath('tmp')) .pipe(helpers.clearDirectory()) @@ -52,12 +50,12 @@ var gulp = require('gulp'); .pipe(helpers.teardown(done)); }); - it('creates a custom config file', function (done) { + it('creates a custom config file', done => { gulp .src(Support.resolveSupportPath('tmp')) .pipe(helpers.clearDirectory()) .pipe(helpers.runCli(flag + ' --config config/database.json')) - .pipe(helpers.teardown(function () { + .pipe(helpers.teardown(() => { gulp .src(Support.resolveSupportPath('tmp', 'config')) .pipe(helpers.listFiles()) @@ -66,7 +64,7 @@ var gulp = require('gulp'); })); }); - it('creates a custom models folder', function (done) { + it('creates a custom models folder', done => { gulp .src(Support.resolveSupportPath('tmp')) .pipe(helpers.clearDirectory()) @@ -76,13 +74,13 @@ var gulp = require('gulp'); .pipe(helpers.teardown(done)); }); - describe('models/index.js', function () { - it('correctly injects the reference to the default config file', function (done) { + describe('models/index.js', () => { + it('correctly injects the reference to the default config file', done => { gulp .src(Support.resolveSupportPath('tmp')) .pipe(helpers.clearDirectory()) .pipe(helpers.runCli(flag)) - .pipe(helpers.teardown(function () { + .pipe(helpers.teardown(() => { gulp .src(Support.resolveSupportPath('tmp', 'models')) .pipe(helpers.readFile('index.js')) @@ -91,12 +89,12 @@ var gulp = require('gulp'); })); }); - it('correctly injects the reference to the custom config file', function (done) { + it('correctly injects the reference to the custom config file', done => { gulp .src(Support.resolveSupportPath('tmp')) .pipe(helpers.clearDirectory()) .pipe(helpers.runCli(flag + ' --config my/configuration-file.json')) - .pipe(helpers.teardown(function () { + .pipe(helpers.teardown(() => { gulp .src(Support.resolveSupportPath('tmp', 'models')) .pipe(helpers.readFile('index.js')) @@ -106,7 +104,7 @@ var gulp = require('gulp'); }); }); - it('does not overwrite an existing config.json file', function (done) { + it('does not overwrite an existing config.json file', done => { gulp .src(Support.resolveSupportPath('tmp')) .pipe(helpers.clearDirectory()) diff --git a/test/migration/create.test.js b/test/migration/create.test.js index 94c122c6..eaec0df8 100644 --- a/test/migration/create.test.js +++ b/test/migration/create.test.js @@ -1,21 +1,14 @@ -'use strict'; +const expect = require('expect.js'); +const Support = require(__dirname + '/../support'); +const helpers = require(__dirname + '/../support/helpers'); +const gulp = require('gulp'); -var expect = require('expect.js'); -var Support = require(__dirname + '/../support'); -var helpers = require(__dirname + '/../support/helpers'); -var gulp = require('gulp'); -var _ = require('lodash'); - -([ - 'migration:create', - 'migration:generate', - 'migration:create --coffee', - 'migration:generate --coffee' -]).forEach(function (flag) { - describe(Support.getTestDialectTeaser(flag), function () { - var migrationFile = 'foo.' + (_.includes(flag, '--coffee') ? 'coffee' : 'js'); - - var prepare = function (callback) { +[ + 'migration:create' +].forEach(flag => { + describe(Support.getTestDialectTeaser(flag), () => { + const migrationFile = 'foo.js'; + const prepare = function (callback) { gulp .src(Support.resolveSupportPath('tmp')) .pipe(helpers.clearDirectory()) @@ -24,20 +17,20 @@ var _ = require('lodash'); .pipe(helpers.teardown(callback)); }; - it('creates a new file with the current timestamp', function (done) { - prepare(function () { - var date = new Date(); - var format = function (i) { - return (parseInt(i, 10) < 10 ? '0' + i : i); + it('creates a new file with the current timestamp', done => { + prepare(() => { + const date = new Date(); + const format = function (i) { + return parseInt(i, 10) < 10 ? '0' + i : i; }; - var sDate = [ - date.getFullYear(), - format(date.getMonth() + 1), - format(date.getDate()), - format(date.getHours()), - format(date.getMinutes()) + const sDate = [ + date.getUTCFullYear(), + format(date.getUTCMonth() + 1), + format(date.getUTCDate()), + format(date.getUTCHours()), + format(date.getUTCMinutes()) ].join(''); - var expectation = new RegExp(sDate + '..-' + migrationFile); + const expectation = new RegExp(sDate + '..-' + migrationFile); gulp .src(Support.resolveSupportPath('tmp', 'migrations')) @@ -47,19 +40,14 @@ var _ = require('lodash'); }); }); - it('adds a skeleton with an up and a down method', function (done) { - prepare(function () { + it('adds a skeleton with an up and a down method', done => { + prepare(() => { gulp .src(Support.resolveSupportPath('tmp', 'migrations')) .pipe(helpers.readFile('*-' + migrationFile)) - .pipe(helpers.expect(function (stdout) { - if (_.includes(flag, 'coffee')) { - expect(stdout).to.contain('up: (queryInterface, Sequelize) ->'); - expect(stdout).to.contain('down: (queryInterface, Sequelize) ->'); - } else { - expect(stdout).to.contain('up: function (queryInterface, Sequelize) {'); - expect(stdout).to.contain('down: function (queryInterface, Sequelize) {'); - } + .pipe(helpers.expect(stdout => { + expect(stdout).to.contain('up: function (queryInterface, Sequelize) {'); + expect(stdout).to.contain('down: function (queryInterface, Sequelize) {'); })) .pipe(helpers.teardown(done)); }); diff --git a/test/model/create.test.js b/test/model/create.test.js index 5f640b5f..b2c87c0c 100644 --- a/test/model/create.test.js +++ b/test/model/create.test.js @@ -1,27 +1,26 @@ -'use strict'; - -var expect = require('expect.js'); -var Support = require(__dirname + '/../support'); -var helpers = require(__dirname + '/../support/helpers'); -var gulp = require('gulp'); -var _ = require('lodash'); - -([ - 'model:create', - 'model:generate' -]).forEach(function (flag) { - describe(Support.getTestDialectTeaser(flag), function () { - var combineFlags = function (flags) { - var result = flag; - - _.forEach(flags || {}, function (value, key) { + + +const expect = require('expect.js'); +const Support = require(__dirname + '/../support'); +const helpers = require(__dirname + '/../support/helpers'); +const gulp = require('gulp'); +const _ = require('lodash'); + +[ + 'model:create' +].forEach(flag => { + describe(Support.getTestDialectTeaser(flag), () => { + const combineFlags = function (flags) { + let result = flag; + + _.forEach(flags || {}, (value, key) => { result = result + ' --' + key + ' ' + value; }); return result; }; - var prepare = function (options, callback) { + const prepare = function (options, callback) { options = _.assign({ flags: {}, cli: { pipeStdout: true } @@ -35,64 +34,64 @@ var _ = require('lodash'); .pipe(helpers.teardown(callback)); }; - describe('name', function () { - describe('when missing', function () { - it('exits with an error code', function (done) { + describe('name', () => { + describe('when missing', () => { + it('exits with an error code', done => { prepare({ flags: { attributes: 'first_name:string' }, cli: { exitCode: 1 } }, done); }); - it('notifies the user about a missing name flag', function (done) { + it('notifies the user about a missing name flag', done => { prepare({ flags: { attributes: 'first_name:string' }, cli: { pipeStderr: true } - }, function (err, stdout) { - expect(stdout).to.match(/Unspecified flag.*name/); + }, (err, stdout) => { + expect(stdout).to.match(/Missing required argument: name/); done(); }); }); }); }); - describe('attributes', function () { - describe('when missing', function () { - it('exits with an error code', function (done) { + describe('attributes', () => { + describe('when missing', () => { + it('exits with an error code', done => { prepare({ flags: { name: 'User' }, cli: { exitCode: 1 } }, done); }); - it('notifies the user about a missing attributes flag', function (done) { + it('notifies the user about a missing attributes flag', done => { prepare({ flags: { name: 'User' }, cli: { pipeStderr: true } - }, function (err, stdout) { - expect(stdout).to.match(/Unspecified flag.*attributes/); + }, (err, stdout) => { + expect(stdout).to.match(/Missing required argument: attributes/); done(); }); }); }); - ;([ + ;[ 'first_name:string,last_name:string,bio:text', '\'first_name:string last_name:string bio:text\'', '\'first_name:string, last_name:string, bio:text\'' - ]).forEach(function (attributes) { - describe('--attributes ' + attributes, function () { - it('exits with exit code 0', function (done) { + ].forEach(attributes => { + describe('--attributes ' + attributes, () => { + it('exits with exit code 0', done => { prepare({ - flags: { name: 'User', attributes: attributes }, + flags: { name: 'User', attributes }, cli: { exitCode: 0 } }, done); }); - it('creates the model file', function (done) { + it('creates the model file', done => { prepare({ - flags: { name: 'User', attributes: attributes } - }, function () { + flags: { name: 'User', attributes } + }, () => { gulp .src(Support.resolveSupportPath('tmp', 'models')) .pipe(helpers.listFiles()) @@ -101,10 +100,10 @@ var _ = require('lodash'); }); }); - it('generates the model attributes correctly', function (done) { + it('generates the model attributes correctly', done => { prepare({ - flags: { name: 'User', attributes: attributes } - }, function () { + flags: { name: 'User', attributes } + }, () => { gulp .src(Support.resolveSupportPath('tmp', 'models')) .pipe(helpers.readFile('user.js')) @@ -116,10 +115,10 @@ var _ = require('lodash'); }); }); - it('creates the migration file', function (done) { + it('creates the migration file', done => { prepare({ - flags: { name: 'User', attributes: attributes } - }, function () { + flags: { name: 'User', attributes } + }, () => { gulp .src(Support.resolveSupportPath('tmp', 'migrations')) .pipe(helpers.listFiles()) @@ -128,15 +127,15 @@ var _ = require('lodash'); }); }); - ([ + [ { underscored: true, createdAt: 'created_at', updatedAt: 'updated_at'}, { underscored: false, createdAt: 'createdAt', updatedAt: 'updatedAt'} - ]).forEach(function (attrUnd) { - describe((attrUnd.underscored ? '' : 'without ') + '--underscored', function () { - it('generates the migration content correctly', function (done) { - var flags = { + ].forEach(attrUnd => { + describe((attrUnd.underscored ? '' : 'without ') + '--underscored', () => { + it('generates the migration content correctly', done => { + const flags = { name: 'User', - attributes: attributes + attributes }; if ( attrUnd.underscored ) { @@ -144,8 +143,8 @@ var _ = require('lodash'); } prepare({ - flags: flags - }, function () { + flags + }, () => { gulp .src(Support.resolveSupportPath('tmp', 'migrations')) .pipe(helpers.readFile('*-create-user.js')) @@ -186,13 +185,13 @@ var _ = require('lodash'); }); }); - it('generates the model content correctly', function (done) { - var flags = { + it('generates the model content correctly', done => { + const flags = { name: 'User', - attributes: attributes + attributes }; - var targetContent = attrUnd.underscored ? + const targetContent = attrUnd.underscored ? 'underscored: true' : '{\n classMethods'; @@ -201,8 +200,8 @@ var _ = require('lodash'); } prepare({ - flags: flags - }, function () { + flags + }, () => { gulp .src(Support.resolveSupportPath('tmp', 'models')) .pipe(helpers.readFile('user.js')) @@ -213,9 +212,9 @@ var _ = require('lodash'); }); }); - describe('when called twice', function () { + describe('when called twice', () => { beforeEach(function (done) { - this.flags = { name: 'User', attributes: attributes }; + this.flags = { name: 'User', attributes }; prepare({ flags: this.flags }, done); }); @@ -230,7 +229,7 @@ var _ = require('lodash'); gulp .src(Support.resolveSupportPath('tmp')) .pipe(helpers.runCli(combineFlags(this.flags), { pipeStderr: true })) - .pipe(helpers.teardown(function (err, stderr) { + .pipe(helpers.teardown((err, stderr) => { expect(stderr).to.contain('already exists'); done(); })); diff --git a/test/options.test.js b/test/options.test.js index a14f672f..e2696204 100644 --- a/test/options.test.js +++ b/test/options.test.js @@ -1,50 +1,49 @@ -'use strict'; +const Support = require(__dirname + '/support'); +const helpers = require(__dirname + '/support/helpers'); +const gulp = require('gulp'); +const optionsPath = Support.resolveSupportPath('config', 'options.js'); -var Support = require(__dirname + '/support'); -var helpers = require(__dirname + '/support/helpers'); -var gulp = require('gulp'); -var optionsPath = Support.resolveSupportPath('config', 'options.js'); +describe(Support.getTestDialectTeaser('options'), () => { + describe('--options-path', () => { + [ + optionsPath, + require('path').relative(Support.resolveSupportPath('tmp'), optionsPath) + ].forEach(path => { + it('using options file instead of cli switches (' + path + ')', done => { + gulp + .src(Support.resolveSupportPath('tmp')) + .pipe(helpers.clearDirectory()) + .pipe(helpers.runCli('init --options-path ' + path)) + .pipe(helpers.listFiles()) + .pipe(helpers.ensureContent('models')) + .pipe(helpers.teardown(done)); + }); + }); + }); -describe(Support.getTestDialectTeaser('--options-path'), function () { - [ - optionsPath, - require('path').relative(Support.resolveSupportPath('tmp'), optionsPath) - ].forEach(function (path) { - it('using options file instead of cli switches (' + path + ')', function (done) { - console.log(path); + describe('.sequelizerc', () => { + it('uses the .sequelizerc file', done => { gulp .src(Support.resolveSupportPath('tmp')) .pipe(helpers.clearDirectory()) - .pipe(helpers.runCli('init --options-path ' + path)) + .pipe(helpers.copyFile(optionsPath, '.sequelizerc')) + .pipe(helpers.runCli('init')) .pipe(helpers.listFiles()) - .pipe(helpers.ensureContent('db')) + .pipe(helpers.ensureContent('models')) .pipe(helpers.teardown(done)); }); - }); -}); -describe(Support.getTestDialectTeaser('.sequelizerc'), function () { - it('uses the .sequelizerc file', function (done) { - gulp - .src(Support.resolveSupportPath('tmp')) - .pipe(helpers.clearDirectory()) - .pipe(helpers.copyFile(optionsPath, '.sequelizerc')) - .pipe(helpers.runCli('init')) - .pipe(helpers.listFiles()) - .pipe(helpers.ensureContent('db')) - .pipe(helpers.teardown(done)); - }); - - it('prefers the CLI arguments over the sequelizerc file', function (done) { - var configPath = Support.resolveSupportPath('tmp', 'config', 'config.js'); + it('prefers the CLI arguments over the sequelizerc file', done => { + const configPath = Support.resolveSupportPath('tmp', 'config', 'config.js'); - gulp - .src(Support.resolveSupportPath('tmp')) - .pipe(helpers.clearDirectory()) - .pipe(helpers.copyFile(optionsPath, '.sequelizerc')) - .pipe(helpers.runCli('init --config=' + configPath)) - .pipe(helpers.listFiles()) - .pipe(helpers.ensureContent('db')) - .pipe(helpers.teardown(done)); + gulp + .src(Support.resolveSupportPath('tmp')) + .pipe(helpers.clearDirectory()) + .pipe(helpers.copyFile(optionsPath, '.sequelizerc')) + .pipe(helpers.runCli('init --config=' + configPath)) + .pipe(helpers.listFiles()) + .pipe(helpers.ensureContent('models')) + .pipe(helpers.teardown(done)); + }); }); -}); +}); \ No newline at end of file diff --git a/test/seed/create.test.js b/test/seed/create.test.js index 8269bafa..c168d8e0 100644 --- a/test/seed/create.test.js +++ b/test/seed/create.test.js @@ -1,21 +1,15 @@ -'use strict'; +const expect = require('expect.js'); +const Support = require(__dirname + '/../support'); +const helpers = require(__dirname + '/../support/helpers'); +const gulp = require('gulp'); -var expect = require('expect.js'); -var Support = require(__dirname + '/../support'); -var helpers = require(__dirname + '/../support/helpers'); -var gulp = require('gulp'); -var _ = require('lodash'); +[ + 'seed:create' +].forEach(flag => { + describe(Support.getTestDialectTeaser(flag), () => { + const seedFile = 'foo.js'; -([ - 'seed:create', - 'seed:generate', - 'seed:create --coffee', - 'seed:generate --coffee' -]).forEach(function (flag) { - describe(Support.getTestDialectTeaser(flag), function () { - var seedFile = 'foo.' + (_.includes(flag, '--coffee') ? 'coffee' : 'js'); - - var prepare = function (callback) { + const prepare = function (callback) { gulp .src(Support.resolveSupportPath('tmp')) .pipe(helpers.clearDirectory()) @@ -24,20 +18,21 @@ var _ = require('lodash'); .pipe(helpers.teardown(callback)); }; - it('creates a new file with the current timestamp', function (done) { - prepare(function () { - var date = new Date(); - var format = function (i) { - return (parseInt(i, 10) < 10 ? '0' + i : i); + it('creates a new file with the current timestamp', done => { + prepare(() => { + const date = new Date(); + const format = function (i) { + return parseInt(i, 10) < 10 ? '0' + i : i; }; - var sDate = [ - date.getFullYear(), - format(date.getMonth() + 1), - format(date.getDate()), - format(date.getHours()), - format(date.getMinutes()) + const sDate = [ + date.getUTCFullYear(), + format(date.getUTCMonth() + 1), + format(date.getUTCDate()), + format(date.getUTCHours()), + format(date.getUTCMinutes()) ].join(''); - var expectation = new RegExp(sDate + '..-' + seedFile); + + const expectation = new RegExp(sDate + '..-' + seedFile); gulp .src(Support.resolveSupportPath('tmp', 'seeders')) @@ -47,19 +42,14 @@ var _ = require('lodash'); }); }); - it('adds a skeleton with an up and a down method', function (done) { - prepare(function () { + it('adds a skeleton with an up and a down method', done => { + prepare(() => { gulp .src(Support.resolveSupportPath('tmp', 'seeders')) .pipe(helpers.readFile('*-' + seedFile)) - .pipe(helpers.expect(function (stdout) { - if (_.includes(flag, 'coffee')) { - expect(stdout).to.contain('up: (queryInterface, Sequelize) ->'); - expect(stdout).to.contain('down: (queryInterface, Sequelize) ->'); - } else { - expect(stdout).to.contain('up: function (queryInterface, Sequelize) {'); - expect(stdout).to.contain('down: function (queryInterface, Sequelize) {'); - } + .pipe(helpers.expect(stdout => { + expect(stdout).to.contain('up: function (queryInterface, Sequelize) {'); + expect(stdout).to.contain('down: function (queryInterface, Sequelize) {'); })) .pipe(helpers.teardown(done)); }); diff --git a/test/support/assets/migrations/20111117063700-createPerson.coffee b/test/support/assets/migrations/20111117063700-createPerson.coffee deleted file mode 100644 index c9d9ebca..00000000 --- a/test/support/assets/migrations/20111117063700-createPerson.coffee +++ /dev/null @@ -1,13 +0,0 @@ -nodeify = require 'nodeify' - -module.exports = - up: (migration, DataTypes, done) -> - nodeify migration.createTable('Person', - name: DataTypes.STRING - isBetaMember: - type: DataTypes.BOOLEAN - defaultValue: false - allowNull: false - ), done - down: (migration, DataTypes, done) -> - nodeify migration.dropTable('Person'), done diff --git a/test/support/assets/migrations/invalid/20141208213500-createPerson.coffee b/test/support/assets/migrations/invalid/20141208213500-createPerson.coffee deleted file mode 100644 index ec07cf1a..00000000 --- a/test/support/assets/migrations/invalid/20141208213500-createPerson.coffee +++ /dev/null @@ -1,10 +0,0 @@ -'use strict'; - -Bluebird = require('bluebird') -Sequelize = require('sequelize') - -module.exports = - up: (db) -> - Bluebird - .delay(1000) - .then(() -> db.sequelize.query 'INVALID QUERY' diff --git a/test/support/assets/migrations/new/20141208213500-createPerson.coffee b/test/support/assets/migrations/new/20141208213500-createPerson.coffee deleted file mode 100644 index a5734848..00000000 --- a/test/support/assets/migrations/new/20141208213500-createPerson.coffee +++ /dev/null @@ -1,11 +0,0 @@ -'use strict'; - -Bluebird = require('bluebird') -Sequelize = require('sequelize') - -module.exports = - up: (db) -> - Bluebird - .delay(1000) - .then(() -> db.createTable 'Person', name: Sequelize.STRING) - .then(() -> db.createTable 'Task', title: Sequelize.STRING) diff --git a/test/support/assets/seeders/20111117063700-seedPerson.coffee b/test/support/assets/seeders/20111117063700-seedPerson.coffee deleted file mode 100644 index b07ec685..00000000 --- a/test/support/assets/seeders/20111117063700-seedPerson.coffee +++ /dev/null @@ -1,12 +0,0 @@ -nodeify = require 'nodeify' - -module.exports = - up: (migration, DataTypes, done) -> - nodeify migration.bulkInsert('Person', [ - name: 'John Doe' - isBetaMember: false ], - name: {} - isBetaMember: {}), done - down: (migration, DataTypes, done) -> - nodeify migration - .bulkDelete 'Person', null, {}, done diff --git a/test/support/assets/seeders/new/20141208213500-seedPerson.coffee b/test/support/assets/seeders/new/20141208213500-seedPerson.coffee deleted file mode 100644 index 02819f3c..00000000 --- a/test/support/assets/seeders/new/20141208213500-seedPerson.coffee +++ /dev/null @@ -1,11 +0,0 @@ -'use strict'; - -Bluebird = require('bluebird') -Sequelize = require('sequelize') - -module.exports = - up: (db) -> - Bluebird - .delay(1000) - .then(() -> db.bulkInsert 'Person', [ name: 'John Doe' ], name: {} ) - .then(() -> db.bulkInsert 'Task', [ title: 'Find own identity' ], title: {} ) diff --git a/test/support/assets/seeders/new/20141208213500-seedPerson.coffee~ b/test/support/assets/seeders/new/20141208213500-seedPerson.coffee~ deleted file mode 100644 index 2e51390f..00000000 --- a/test/support/assets/seeders/new/20141208213500-seedPerson.coffee~ +++ /dev/null @@ -1,11 +0,0 @@ -'use strict'; - -Bluebird = require('bluebird') -Sequelize = require('sequelize') - -module.exports = - up: (db) -> - Bluebird - .delay(1000) - .then(() -> db.bulkInsert 'Person', name: 'John Doe', name: {} ) - .then(() -> db.bulkInsert 'Task', title: 'Find own identity', title: {} ) diff --git a/test/support/helpers.js b/test/support/helpers.js index dc458fb1..93a270cb 100644 --- a/test/support/helpers.js +++ b/test/support/helpers.js @@ -190,6 +190,13 @@ module.exports = { .then(function (result) { return callback((result.length === 2) ? result[0] : result ); }); + }, + execQuery: function(sequelize, sql, options) { + if (sequelize.query.length === 2) { + return sequelize.query(sql, options); + } else { + return sequelize.query(sql, null, options); + } } }; diff --git a/test/support/index.js b/test/support/index.js index 969bdaae..7789a945 100644 --- a/test/support/index.js +++ b/test/support/index.js @@ -2,13 +2,18 @@ var fs = require('fs'); var path = require('path'); -var helpers = require(__dirname + '/../../lib/helpers'); -var Sequelize = helpers.generic.getSequelize(); +var Sequelize = require('sequelize'); var _ = Sequelize.Utils._; var DataTypes = Sequelize; var Config = require(__dirname + '/config/config'); var expect = require('expect.js'); -var execQuery = require('../../lib/helpers').generic.execQuery; +var execQuery = function (sequelize, sql, options) { + if (sequelize.query.length === 2) { + return sequelize.query(sql, options); + } else { + return sequelize.query(sql, null, options); + } +} var Support = { Sequelize: Sequelize, @@ -50,7 +55,7 @@ var Support = { createSequelizeInstance: function (options) { options = options || {}; - options.dialect = options.dialect || 'mysql'; + options.dialect = options.dialect || 'sqlite'; var config = Config[options.dialect]; var sequelizeOptions = _.defaults(options, { @@ -125,7 +130,7 @@ var Support = { }, getTestDialect: function () { - var envDialect = process.env.DIALECT || 'mysql'; + var envDialect = process.env.DIALECT || 'sqlite'; if (envDialect === 'postgres-native') { envDialect = 'postgres'; @@ -159,7 +164,7 @@ var Support = { dialect = 'postgres-native'; } - return '[' + dialect.toUpperCase() + '] bin/sequelize ' + moduleName; + return '[' + dialect.toUpperCase() + '] lib/sequelize ' + moduleName; }, getTestUrl: function (config) { @@ -183,7 +188,7 @@ var Support = { }, getCliPath: function (cwd) { - return path.resolve(cwd, path.resolve(process.cwd(), 'bin', 'sequelize')); + return path.resolve(cwd, path.resolve(process.cwd(), 'lib', 'sequelize')); }, getCliCommand: function (cwd, flags) { diff --git a/test/url.test.js b/test/url.test.js index 619a5f7e..961e2863 100644 --- a/test/url.test.js +++ b/test/url.test.js @@ -1,14 +1,12 @@ -'use strict'; +const expect = require('expect.js'); +const Support = require(__dirname + '/support'); +const helpers = require(__dirname + '/support/helpers'); +const gulp = require('gulp'); -var expect = require('expect.js'); -var Support = require(__dirname + '/support'); -var helpers = require(__dirname + '/support/helpers'); -var gulp = require('gulp'); - -([ +[ '--url' -]).forEach(function (flag) { - var prepare = function (callback) { +].forEach(flag => { + const prepare = function (callback) { gulp .src(Support.resolveSupportPath('tmp')) .pipe(helpers.clearDirectory()) @@ -19,16 +17,16 @@ var gulp = require('gulp'); .pipe(helpers.teardown(callback)); }; - describe(Support.getTestDialectTeaser(flag), function () { + describe(Support.getTestDialectTeaser(flag), () => { beforeEach(function (done) { - prepare(function (err, stdout) { + prepare((err, stdout) => { this.stdout = stdout; done(); - }.bind(this)); + }); }); it('creates a SequelizeMeta table', function (done) { - helpers.readTables(this.sequelize, function (tables) { + helpers.readTables(this.sequelize, tables => { expect(tables).to.have.length(2); expect(tables).to.contain('SequelizeMeta'); done(); @@ -36,7 +34,7 @@ var gulp = require('gulp'); }); it('creates the respective table via url', function (done) { - helpers.readTables(this.sequelize, function (tables) { + helpers.readTables(this.sequelize, tables => { expect(tables).to.have.length(2); expect(tables).to.contain('Person'); done(); @@ -48,7 +46,7 @@ var gulp = require('gulp'); }); it('filters the password', function () { - var config = helpers.getTestConfig(); + const config = helpers.getTestConfig(); if (Support.getTestDialect() === 'sqlite') { return; diff --git a/test/version.test.js b/test/version.test.js index 0f42ed55..71ea078a 100644 --- a/test/version.test.js +++ b/test/version.test.js @@ -1,21 +1,14 @@ -/* jshint -W030 */ +const expect = require('expect.js'); +const Support = require(__dirname + '/support'); +const version = (require(__dirname + '/../package.json')).version; +const helpers = require(__dirname + '/support/helpers'); +const gulp = require('gulp'); -'use strict'; - -var expect = require('expect.js'); -var Support = require(__dirname + '/support'); -var version = (require(__dirname + '/../package.json')).version; -var helpers = require(__dirname + '/support/helpers'); -var gulp = require('gulp'); - -([ - 'version', - 'v', - '-v', - '-V' -]).forEach(function (flag) { - describe(Support.getTestDialectTeaser(flag), function () { - it('prints the version', function (done) { +[ + '--version' +].forEach(flag => { + describe(Support.getTestDialectTeaser(flag), () => { + it('prints the version', done => { expect(version).to.not.be.empty; gulp diff --git a/var/vagrant/README.md b/var/vagrant/README.md deleted file mode 100644 index 81743968..00000000 --- a/var/vagrant/README.md +++ /dev/null @@ -1,14 +0,0 @@ -## Vagrant - -[Vagrant](https://www.vagrantup.com/) machine could be used in order to speedup setting up the infrastructure for the test runs. - -## Installation and usage -```bash -vagrant up - -# in case you need to login to the vagrant machine -vagtant ssh -``` - -After the machine is up, you do have default mysql server on ```127.0.0.1:3306``` - diff --git a/var/vagrant/Vagrantfile b/var/vagrant/Vagrantfile deleted file mode 100644 index 185b624d..00000000 --- a/var/vagrant/Vagrantfile +++ /dev/null @@ -1,27 +0,0 @@ -# -*- mode: ruby -*- -# vi: set ft=ruby : - -Vagrant.configure(2) do |config| - # Every Vagrant development environment requires a box. You can search for - # boxes at https://atlas.hashicorp.com/search. - config.vm.box = "ubuntu/trusty64" - - # Create a private network, which allows host-only access to the machine - # using a specific IP. - config.vm.network "private_network", ip: "192.168.33.10" - - config.vm.provider "virtualbox" do |vb| - config.vm.network "forwarded_port", guest: 3306, host: 3306 - - vb.memory = 1024 - vb.cpus = 2 - end - - # Share an additional folder to the guest VM. The first argument is - # the path on the host to the actual folder. The second argument is - # the path on the guest to mount the folder. And the optional third - # argument is a set of non-required options. - config.vm.synced_folder "./", "/home/vagrant/sequelize-cli" - - config.vm.provision "shell", path: "./provision.sh", privileged: false -end diff --git a/var/vagrant/provision.sh b/var/vagrant/provision.sh deleted file mode 100644 index 30681ef5..00000000 --- a/var/vagrant/provision.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -echo "0. User and pwd" -echo "user: "$(id) -echo "pwd: "$(pwd) - -#first steps -echo "1. Updating and upgrading" -sudo apt-get update -sudo apt-get upgrade -y -printf '\n%s\n%s\n%s\n%s\n' 'export LC_CTYPE=en_US.UTF-8' 'export LC_ALL=en_US.UTF-8' 'export LANG=en_US.UTF-8' 'export LANGUAGE=en_US.UTF-8' >> ~/.profile -. ~/.profile -sudo locale-gen "en_US.UTF-8" -sudo touch /var/lib/cloud/instance/locale-check.skip - -echo "2. Install mysql" -sudo debconf-set-selections <<< "mysql-server mysql-server/root_password password PASS" -sudo debconf-set-selections <<< "mysql-server mysql-server/root_password_again password PASS" -sudo apt-get -y install mysql-server -mysql -uroot -pPASS -e "SET PASSWORD = PASSWORD('');" -sudo sed -i 's/bind-address/#bind-address/g' /etc/mysql/my.cnf -sudo service mysql restart -mysql --user="root" --password="" --execute="GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '';" -mysql --user="root" --password="" --execute="CREATE DATABASE sequelize_test;"