diff --git a/.editorconfig b/.editorconfig index d2cc08509..017b589e3 100644 --- a/.editorconfig +++ b/.editorconfig @@ -19,3 +19,7 @@ insert_final_newline = true [*.md] trim_trailing_whitespace = false indent_size = 4 + +[{Makefile,**.mk}] +# Use tabs for indentation (Makefiles require tabs) +indent_style = tab diff --git a/config/config.json b/config/config.json new file mode 100644 index 000000000..aa09c8ed0 --- /dev/null +++ b/config/config.json @@ -0,0 +1,36 @@ +{ + "development": { + "username": "root", + "password": "secret_pass", + "database": "database_development", + "host": "127.0.0.1", + "dialect": "mysql", + "pool": { + "maxConnections": 1, + "some": { + "other": { + "nested": { + "object": "here" + } + } + } + } + }, + "env": { + "use_env_variable": "postgresql://[user[:password]@][netlocation][:port][/dbname]" + }, + "test": { + "username": "root", + "password": null, + "database": "database_test", + "host": "127.0.0.1", + "dialect": "mysql" + }, + "production": { + "username": "root", + "password": null, + "database": "database_production", + "host": "127.0.0.1", + "dialect": "mysql" + } +} diff --git a/makefile b/makefile new file mode 100644 index 000000000..ab8c0fdd4 --- /dev/null +++ b/makefile @@ -0,0 +1,30 @@ +build: + npm run build + +info: + @echo "INFO" && \ + lib/sequelize db:info + +fail: + @echo "FAIL" && \ + NODE_ENV=nope lib/sequelize db:info + +raw: + @echo "RAW" && lib/sequelize db:info --raw + +show: + @echo "PWD" && lib/sequelize db:info --show-password + +env: + @echo "ENV" && NODE_ENV=env lib/sequelize db:info + +env-pass: + @echo "ENV" && NODE_ENV=env lib/sequelize db:info --show-password + +run: build show + @echo "----\n" + +loop: + while inotifywait -q -e modify src/**; \ + do clear; make run; done; + diff --git a/package.json b/package.json index 84c743e83..fd6dc7780 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,8 @@ "pretty": "prettier src test --write", "prepare": "husky install && npm run build", "test-raw": "mocha 'test/**/*.test.js'", - "test": "npm run lint && npm run build && npm run test-raw" + "test": "npm run lint && npm run build && npm run test-raw", + "test-one": "mocha 'test/db/db-info.test.js' --timeout 5000" }, "repository": { "type": "git", diff --git a/src/commands/database_info.js b/src/commands/database_info.js new file mode 100644 index 000000000..3f6cd070d --- /dev/null +++ b/src/commands/database_info.js @@ -0,0 +1,65 @@ +import process from 'process'; +import { _baseOptions } from '../core/yargs'; + +import helpers from '../helpers'; +import { pick } from 'lodash'; +import clc from 'cli-color'; + +exports.builder = (yargs) => { + _baseOptions(yargs) + .option('show-password', { + describe: 'Will show password as plain text', + type: 'boolean', + default: false, + }) + .option('raw', { + describe: 'Display the raw object', + type: 'boolean', + default: false, + }).argv; +}; + +exports.handler = async function (args) { + const command = args._[0]; + + // legacy, gulp used to do this + await helpers.config.init(); + + const options = pick(args, ['showPassword', 'raw']); + + switch (command) { + case 'db:info': + displayConfigObject(options); + break; + } + + process.exit(0); +}; + +function displayConfigObject(options) { + let config = null; + + try { + config = helpers.config.readConfig(); + } catch (e) { + helpers.view.error(e); + } + + if (!options.showPassword) { + config.password = '***'; + } + + helpers.view.log(); + helpers.view.log(clc.bold('Sequelize configuration:')); + + options.raw + ? helpers.view.log(JSON.stringify(config, null, 2)) + : display(config); +} + +function display(i, p = '') { + Object.entries(i).forEach(([k, v]) => { + if (typeof v == 'object' && v !== null) display(v, `${p}${k}.`); + else helpers.view.log(`${p}${k}:`, v); + }); +} diff --git a/src/sequelize.js b/src/sequelize.js index 7249135c6..db1766ce1 100644 --- a/src/sequelize.js +++ b/src/sequelize.js @@ -14,6 +14,7 @@ import migrationGenerate from './commands/migration_generate'; import modelGenerate from './commands/model_generate'; import seedGenerate from './commands/seed_generate'; import database from './commands/database'; +import databaseInfo from './commands/database_info'; import helpers from './helpers/index'; @@ -35,6 +36,7 @@ yargs .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('db:info', 'Displays the database configuration', databaseInfo) .command('db:create', 'Create database specified by configuration', database) .command('db:drop', 'Drop database specified by configuration', database) .command('init', 'Initializes project', init) diff --git a/test/db/db-info.test.js b/test/db/db-info.test.js new file mode 100644 index 000000000..618425edf --- /dev/null +++ b/test/db/db-info.test.js @@ -0,0 +1,74 @@ +const expect = require('expect.js'); +const Support = require(__dirname + '/../support'); +const helpers = require(__dirname + '/../support/helpers'); +const gulp = require('gulp'); +const _ = require('lodash'); + +['db:info'].forEach((flag) => { + describe(Support.getTestDialectTeaser(flag), function () { + this.timeout(5000); + + if (Support.dialectIsPostgres() || Support.dialectIsMySQL()) { + console.log("we're testing"); + const combineFlags = function (flags) { + let result = flag; + + _.forEach(flags || {}, (value, key) => { + result = result + ' --' + key; + }); + + return result; + }; + + const prepare = function (options, callback) { + options = _.assign( + { + flags: {}, + cli: { pipeStdout: true }, + }, + options || {} + ); + + console.log('fl', combineFlags(options.flags)); + + const configPath = 'config/config.json'; + const config = _.assign( + { password: 'secret_password' }, + helpers.getTestConfig(), + options.config + ); + const configContent = JSON.stringify(config); + + gulp + .src(Support.resolveSupportPath('tmp')) + .pipe(helpers.clearDirectory()) + .pipe(helpers.runCli('init')) + .pipe(helpers.runCli('db:create')) + .pipe( + // helpers.overwriteFile(helpers.getTestConfig(), 'config/config.json') + helpers.overwriteFile(configContent, configPath) + ) + .pipe(helpers.runCli(flag, { pipeStdout: true })) + // .pipe(helpers.runCli(combineFlags(options.flags), options.cli)) + .pipe(helpers.teardown(callback)); + }; + + describe('show-password', function () { + it('hides the password', function (done) { + prepare({}, (err, stdout) => { + expect(stdout).to.contain('password: ***'); + done(); + }); + }); + + it.only('reveals the password', function (done) { + prepare({ flags: { 'show-password': true } }, done); + // prepare({ flags: { showPassword: true } }, (err, stdout) => { + // expect(stdout).not.to.contain('password: ***'); + // done(); + // }); + }); + }); + } + }); +});