decaffeinate / bulk-decaffeinate

Run decaffeinate and related operations on a whole codebase, or just part of one.
MIT License
74 stars 13 forks source link

bulk-decaffeinate

Build Status npm version MIT License

A tool, backed by decaffeinate, to help you convert some or all of a CoffeeScript codebase to JavaScript.

The tool can check a codebase for decaffeinate-readiness, and once the code (or a part of it) is ready, bulk-decaffeinate can actually run the conversion and some follow-up cleanups. Here's an example of checking the Hubot repo:

> npm install -g bulk-decaffeinate decaffeinate eslint
...
> git clone https://github.com/philc/vimium.git
...
> cd vimium
> bulk-decaffeinate check
Doing a dry run of decaffeinate on 50 files...
50/50
All checks succeeded! decaffeinate can convert all 50 files.
Run "bulk-decaffeinate convert" to convert the files to JavaScript.
> bulk-decaffeinate convert
Verifying that decaffeinate can successfully convert these files...
50/50
Backing up files to .original.coffee...
50/50
Renaming files from .coffee to .js...
50/50
Generating the first commit: "decaffeinate: Rename bg_utils.coffee and 49 other files from .coffee to .js"...
Moving files back...
50/50
Running decaffeinate on all files...
50/50
Deleting old files...
50/50
Setting proper extension for all files...
50/50
Generating the second commit: decaffeinate: Convert bg_utils.coffee and 49 other files to JS...
Running eslint --fix on all files...
50/50
[Skips eslint for all files because there is no config.]
Generating the third commit: decaffeinate: Run post-processing cleanups on bg_utils.coffee and 49 other files...
Successfully ran decaffeinate on 50 files.
You should now fix lint issues in any affected files.
All CoffeeScript files were backed up as .original.coffee files that you can use for comparison.
You can run "bulk-decaffeinate clean" to remove those files.
To allow git to properly track file history, you should NOT squash the generated commits together.

Assumptions

While the underlying decaffeinate tool tries to be general-purpose, bulk-decaffeinate intentionally makes some assumptions about your use case:

Feel free to file an issue or submit a PR if these assumptions don't match your current project. Most steps shouldn't be hard to disable using a config setting.

What it does

bulk-decaffeinate supports a number of commands:

Here's what convert does in more detail:

  1. It does a dry run of decaffeinate on all files to make sure there won't be any failures.
  2. It backs up all .coffee files to .original.coffee files, which makes it easily to manually do a before-and-after comparison later.
  3. It generates a commit renaming the files from .coffee to .js (but not changing the contents). Putting this step in its own commit allows git to track the file history across renames (so, if possible, you should land the changes as a merge commit rather than squashing the commits together).
  4. It runs decaffeinate on all files and gets rid of the .coffee files, then generates a commit.
  5. If the jscodeshiftScripts config value is specified, it runs jscodeshift with those scripts in the order specified.
  6. If the mochaEnvFilePattern config value is specified, it prepends /* eslint-env mocha */ to the top of every test file.
  7. If the fixImportsConfig config value is specified, it runs a transform that does whole-codebase analysis to fix any import problems that might have been introduced by decaffeinate.
  8. It runs eslint --fix on all files, which applies some style fixes according to your lint rules. For any remaining lint failures, it puts a comment at the top of the file disabling those specific lint rules and leaves a TODO comment to fix any remaining style issues.
  9. If the codePrefix config value is specified, it prepends that string to every affected file.
  10. All post-decaffeinate changes are committed as a third commit.

In all generated commits, "decaffeinate" is used as the author name (but not the email address). This makes it clear to people using git blame that the file was generated using decaffeinate, and not necessarily authored by the person who happened to run the decaffeinate script.

If you want to see the full details, the source code should hopefully be fairly readable.

Configuration

You can specify custom configuration in a config file, usually called bulk-decaffeinate.config.js, in the current working directory. It should export a JS object with your config. Any file starting with bulk-decaffeinate and ending with .config.js will be counted, and multiple config files may exist at once. If there are multiple config files, they are merged, with alphabetically-later config file names taking precedence over alphabetically-earlier files.

Alternatively, you may specify the config file location using the --config option, e.g. bulk-decaffeinate --config ../bulk-decaffeinate.config.js to use a config file one level up in the directory structure.

Many config options can also be specified directly as CLI arguments, with CLI arguments taking precedence over any config file setting.

Here's an example config file:

module.exports = {
  jscodeshiftScripts: [
    './scripts/dev/codemods/arrow-function.js',
    './scripts/dev/codemods/rd-to-create-element.js',
    './scripts/dev/codemods/create-element-to-jsx.js',
  ],
  mochaEnvFilePattern: '^.*-test.js$',
  fixImportsConfig: {
    searchPath: './coffee',
    absoluteImportPaths: ['./coffee'],
  },
};

Specifying files to process

The following config keys can be specified:

If multiple of searchDirectory, pathFile, or filesToProcess are specified, the union of the files is taken. If none is specified, bulk-decaffeinate will recursively discover all CoffeeScript files in the working directory.

Each of these has a command line arg version, which takes precedence over config file values; see the result of --help for more information.

Common configuration options

Other configuration

Configuring paths to external tools

Rather than having bulk-decaffeinate automatically discover the relevant binaries, you can specify them explicitly. If a path is not specified explicitly, bulk-decaffeinate will first search node_modules, then your PATH, then offer to install the tool globally, so generally it's unnecessary to specify these paths in the config file.

These keys can be specified: