cli.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. #!/usr/bin/env node
  2. /* eslint no-console:0, no-var:0 */
  3. var Liftoff = require('liftoff');
  4. var Promise = require('bluebird');
  5. var interpret = require('interpret');
  6. var path = require('path');
  7. var chalk = require('chalk');
  8. var tildify = require('tildify');
  9. var commander = require('commander');
  10. var argv = require('minimist')(process.argv.slice(2));
  11. var fs = Promise.promisifyAll(require('fs'));
  12. var cliPkg = require('../package');
  13. function exit(text) {
  14. if (text instanceof Error) {
  15. chalk.red(console.error(text.stack));
  16. } else {
  17. chalk.red(console.error(text));
  18. }
  19. process.exit(1);
  20. }
  21. function success(text) {
  22. console.log(text);
  23. process.exit(0);
  24. }
  25. function checkLocalModule(env) {
  26. if (!env.modulePath) {
  27. console.log(chalk.red('No local knex install found in:'), chalk.magenta(tildify(env.cwd)));
  28. exit('Try running: npm install knex.');
  29. }
  30. }
  31. function initKnex(env) {
  32. checkLocalModule(env);
  33. if (!env.configPath) {
  34. exit('No knexfile found in this directory. Specify a path with --knexfile');
  35. }
  36. if (process.cwd() !== env.cwd) {
  37. process.chdir(env.cwd);
  38. console.log('Working directory changed to', chalk.magenta(tildify(env.cwd)));
  39. }
  40. var environment = commander.env || process.env.NODE_ENV;
  41. var defaultEnv = 'development';
  42. var config = require(env.configPath);
  43. if (!environment && typeof config[defaultEnv] === 'object') {
  44. environment = defaultEnv;
  45. }
  46. if (environment) {
  47. console.log('Using environment:', chalk.magenta(environment));
  48. config = config[environment] || config;
  49. }
  50. if (!config) {
  51. console.log(chalk.red('Warning: unable to read knexfile config'));
  52. process.exit(1);
  53. }
  54. if (argv.debug !== undefined)
  55. config.debug = argv.debug;
  56. var knex = require(env.modulePath);
  57. return knex(config);
  58. }
  59. function invoke(env) {
  60. var filetypes = ['js', 'coffee', 'ts', 'eg', 'ls'];
  61. var pending = null;
  62. commander
  63. .version(
  64. chalk.blue('Knex CLI version: ', chalk.green(cliPkg.version)) + '\n' +
  65. chalk.blue('Local Knex version: ', chalk.green(env.modulePackage.version)) + '\n'
  66. )
  67. .option('--debug', 'Run with debugging.')
  68. .option('--knexfile [path]', 'Specify the knexfile path.')
  69. .option('--cwd [path]', 'Specify the working directory.')
  70. .option('--env [name]', 'environment, default: process.env.NODE_ENV || development');
  71. commander
  72. .command('init')
  73. .description(' Create a fresh knexfile.')
  74. .option(`-x [${filetypes.join('|')}]`, 'Specify the knexfile extension (default js)')
  75. .action(function() {
  76. var type = (argv.x || 'js').toLowerCase();
  77. if (filetypes.indexOf(type) === -1) {
  78. exit(`Invalid filetype specified: ${type}`);
  79. }
  80. if (env.configPath) {
  81. exit(`Error: ${env.configPath} already exists`);
  82. }
  83. checkLocalModule(env);
  84. var stubPath = `./knexfile.${type}`;
  85. pending = fs.readFileAsync(
  86. path.dirname(env.modulePath) +
  87. '/lib/migrate/stub/knexfile-' +
  88. type + '.stub'
  89. ).then(function(code) { return fs.writeFileAsync(stubPath, code) }).then(function() {
  90. success(chalk.green(`Created ${stubPath}`));
  91. }).catch(exit);
  92. });
  93. commander
  94. .command('migrate:make <name>')
  95. .description(' Create a named migration file.')
  96. .option(`-x [${filetypes.join('|')}]`, 'Specify the stub extension (default js)')
  97. .action(function(name) {
  98. var instance = initKnex(env);
  99. var ext = (argv.x || env.configPath.split('.').pop()).toLowerCase();
  100. pending = instance.migrate.make(name, {extension: ext}).then(function(name) {
  101. success(chalk.green(`Created Migration: ${name}`));
  102. }).catch(exit);
  103. });
  104. commander
  105. .command('migrate:latest')
  106. .description(' Run all migrations that have not yet been run.')
  107. .action(function() {
  108. pending = initKnex(env).migrate.latest().spread(function(batchNo, log) {
  109. if (log.length === 0) {
  110. success(chalk.cyan('Already up to date'));
  111. }
  112. success(
  113. chalk.green(`Batch ${batchNo} run: ${log.length} migrations \n`) +
  114. chalk.cyan(log.join('\n'))
  115. );
  116. }).catch(exit);
  117. });
  118. commander
  119. .command('migrate:rollback')
  120. .description(' Rollback the last set of migrations performed.')
  121. .action(function() {
  122. pending = initKnex(env).migrate.rollback().spread(function(batchNo, log) {
  123. if (log.length === 0) {
  124. success(chalk.cyan('Already at the base migration'));
  125. }
  126. success(
  127. chalk.green(`Batch ${batchNo} rolled back: ${log.length} migrations \n`) +
  128. chalk.cyan(log.join('\n'))
  129. );
  130. }).catch(exit);
  131. });
  132. commander
  133. .command('migrate:currentVersion')
  134. .description(' View the current version for the migration.')
  135. .action(function () {
  136. pending = initKnex(env).migrate.currentVersion().then(function(version) {
  137. success(chalk.green('Current Version: ') + chalk.blue(version));
  138. }).catch(exit);
  139. });
  140. commander
  141. .command('seed:make <name>')
  142. .description(' Create a named seed file.')
  143. .option(`-x [${filetypes.join('|')}]`, 'Specify the stub extension (default js)')
  144. .action(function(name) {
  145. var instance = initKnex(env);
  146. var ext = (argv.x || env.configPath.split('.').pop()).toLowerCase();
  147. pending = instance.seed.make(name, {extension: ext}).then(function(name) {
  148. success(chalk.green(`Created seed file: ${name}`));
  149. }).catch(exit);
  150. });
  151. commander
  152. .command('seed:run')
  153. .description(' Run seed files.')
  154. .action(function() {
  155. pending = initKnex(env).seed.run().spread(function(log) {
  156. if (log.length === 0) {
  157. success(chalk.cyan('No seed files exist'));
  158. }
  159. success(chalk.green(`Ran ${log.length} seed files \n${chalk.cyan(log.join('\n'))}`));
  160. }).catch(exit);
  161. });
  162. commander.parse(process.argv);
  163. Promise.resolve(pending).then(function() {
  164. commander.help();
  165. });
  166. }
  167. var cli = new Liftoff({
  168. name: 'knex',
  169. extensions: interpret.jsVariants,
  170. v8flags: require('v8flags')
  171. });
  172. cli.on('require', function(name) {
  173. console.log('Requiring external module', chalk.magenta(name));
  174. });
  175. cli.on('requireFail', function(name) {
  176. console.log(chalk.red('Failed to load external module'), chalk.magenta(name));
  177. });
  178. cli.launch({
  179. cwd: argv.cwd,
  180. configPath: argv.knexfile,
  181. require: argv.require,
  182. completion: argv.completion
  183. }, invoke);