jscodeshift.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #!/usr/bin/env node
  2. /**
  3. * Copyright (c) Facebook, Inc. and its affiliates.
  4. *
  5. * This source code is licensed under the MIT license found in the
  6. * LICENSE file in the root directory of this source tree.
  7. */
  8. 'use strict';
  9. const Runner = require('../src/Runner.js');
  10. const fs = require('fs');
  11. const path = require('path');
  12. const pkg = require('../package.json');
  13. const parser = require('../src/argsParser')
  14. .options({
  15. transform: {
  16. display_index: 15,
  17. abbr: 't',
  18. default: './transform.js',
  19. help: 'path to the transform file. Can be either a local path or url',
  20. metavar: 'FILE',
  21. required: true
  22. },
  23. cpus: {
  24. display_index: 1,
  25. abbr: 'c',
  26. help: 'start at most N child processes to process source files',
  27. defaultHelp: 'max(all - 1, 1)',
  28. metavar: 'N',
  29. process: Number,
  30. },
  31. verbose: {
  32. display_index: 16,
  33. abbr: 'v',
  34. choices: [0, 1, 2],
  35. default: 0,
  36. help: 'show more information about the transform process',
  37. metavar: 'N',
  38. process: Number,
  39. },
  40. dry: {
  41. display_index: 2,
  42. abbr: 'd',
  43. flag: true,
  44. default: false,
  45. help: 'dry run (no changes are made to files)'
  46. },
  47. print: {
  48. display_index: 11,
  49. abbr: 'p',
  50. flag: true,
  51. default: false,
  52. help: 'print transformed files to stdout, useful for development'
  53. },
  54. babel: {
  55. display_index: 0,
  56. flag: true,
  57. default: true,
  58. help: 'apply babeljs to the transform file'
  59. },
  60. extensions: {
  61. display_index: 3,
  62. default: 'js',
  63. help: 'transform files with these file extensions (comma separated list)',
  64. metavar: 'EXT',
  65. },
  66. ignorePattern: {
  67. display_index: 7,
  68. full: 'ignore-pattern',
  69. list: true,
  70. help: 'ignore files that match a provided glob expression',
  71. metavar: 'GLOB',
  72. },
  73. ignoreConfig: {
  74. display_index: 6,
  75. full: 'ignore-config',
  76. list: true,
  77. help: 'ignore files if they match patterns sourced from a configuration file (e.g. a .gitignore)',
  78. metavar: 'FILE'
  79. },
  80. gitignore: {
  81. display_index: 8,
  82. flag: true,
  83. default: false,
  84. help: 'adds entries the current directory\'s .gitignore file',
  85. },
  86. runInBand: {
  87. display_index: 12,
  88. flag: true,
  89. default: false,
  90. full: 'run-in-band',
  91. help: 'run serially in the current process'
  92. },
  93. silent: {
  94. display_index: 13,
  95. abbr: 's',
  96. flag: true,
  97. default: false,
  98. help: 'do not write to stdout or stderr'
  99. },
  100. parser: {
  101. display_index: 9,
  102. choices: ['babel', 'babylon', 'flow', 'ts', 'tsx'],
  103. default: 'babel',
  104. help: 'the parser to use for parsing the source files'
  105. },
  106. parserConfig: {
  107. display_index: 10,
  108. full: 'parser-config',
  109. help: 'path to a JSON file containing a custom parser configuration for flow or babylon',
  110. metavar: 'FILE',
  111. process: file => JSON.parse(fs.readFileSync(file)),
  112. },
  113. failOnError: {
  114. display_index: 4,
  115. flag: true,
  116. help: 'Return a non-zero code when there are errors',
  117. full: 'fail-on-error',
  118. default: false,
  119. },
  120. version: {
  121. display_index: 17,
  122. help: 'print version and exit',
  123. callback: function() {
  124. const requirePackage = require('../utils/requirePackage');
  125. return [
  126. `jscodeshift: ${pkg.version}`,
  127. ` - babel: ${require('babel-core').version}`,
  128. ` - babylon: ${requirePackage('@babel/parser').version}`,
  129. ` - flow: ${requirePackage('flow-parser').version}`,
  130. ` - recast: ${requirePackage('recast').version}\n`,
  131. ].join('\n');
  132. },
  133. },
  134. stdin: {
  135. display_index: 14,
  136. help: 'read file/directory list from stdin',
  137. flag: true,
  138. default: false,
  139. },
  140. });
  141. let options, positionalArguments;
  142. try {
  143. ({options, positionalArguments} = parser.parse());
  144. if (positionalArguments.length === 0 && !options.stdin) {
  145. process.stderr.write(
  146. 'Error: You have to provide at least one file/directory to transform.' +
  147. '\n\n---\n\n' +
  148. parser.getHelpText()
  149. );
  150. process.exit(1);
  151. }
  152. } catch(e) {
  153. const exitCode = e.exitCode === undefined ? 1 : e.exitCode;
  154. (exitCode ? process.stderr : process.stdout).write(e.message);
  155. process.exit(exitCode);
  156. }
  157. function run(paths, options) {
  158. Runner.run(
  159. /^https?/.test(options.transform) ? options.transform : path.resolve(options.transform),
  160. paths,
  161. options
  162. );
  163. }
  164. if (options.stdin) {
  165. let buffer = '';
  166. process.stdin.on('data', data => buffer += data);
  167. process.stdin.on('end', () => run(buffer.split('\n'), options));
  168. } else {
  169. run(positionalArguments, options);
  170. }