Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for config files #4

Open
wincent opened this issue Apr 3, 2015 · 8 comments
Open

Add support for config files #4

wincent opened this issue Apr 3, 2015 · 8 comments

Comments

@wincent
Copy link
Contributor

wincent commented Apr 3, 2015

Proposal

Teach the binary to accept a --config option

This option would allow you to specify a config file on disk from which additional options would be read. The file would contain additional options to be included with the invocation; for example:

--cpus 2 -v

Options explicitly provided on the command-line would override options read from the config file. For example, given the config above, --cpus would be set to 4 for an invocation like this:

jscodeshift --config my-config --cpus 4 target.js

In the absence of a --config option, look for config in default locations

Default locations could be:

  • .jscodeshiftrc in current directory
  • $HOME/.jscodeshiftrc
  • /etc/jscodeshiftrc (or something like that)

This would, for example, enable you to provide a consistent set of Recast printOptions that you would use, by convention, in all of your transform scripts (ie. in the call to toSource()).

Considerations

Do we want the config file to be just a dumb string that we split and pass into nomnom as though the args were passed on the commandline? Or do we prefer a more structured format (like JSON) which would allow us to pass richer configuration objects rather than just scalar values (strings, numbers, bools)? I'm inclined to think the latter, so that we could configure things like printOptions for Recast with:

{
  'cpus': 2,
  'v': true,
  'printOptions': {'quote': 'single'}
}
@wincent
Copy link
Contributor Author

wincent commented Apr 3, 2015

Throwing this up here for discussion. Happy to put together a pull request if we think this is a good idea.

@cpojer
Copy link
Contributor

cpojer commented Apr 3, 2015

It should definitely be JSON.

I think this makes sense. I'm a little bit worried that people would put a lot of script-specific options into those config files and that they'd potentially collide. I guess that is not a big deal though. Go for it!

@wincent
Copy link
Contributor Author

wincent commented Apr 6, 2015

I pushed a WIP commit for this here: https://github.com/wincent/jscodeshift/commit/7a8317a4dd66d201b5c97e89893b944e1a1408cb

  • currently doesn't try any validation of config file contents (other than them being parseable by JSON.parse)
  • want to add more tests for the ConfigReader and OptionParser modules, but...
  • ...Jest is acting very strangely with the mocks, and I can't get them to work properly (not mocking things I ask it to mock, mocking others I ask it not to mock etc...)

@cpojer
Copy link
Contributor

cpojer commented Jul 24, 2015

@wincent do you have time to rebase your diff against the current version of jscodeshift past #24? I'd really love for us to add this feature. I'd like it to travel up the hierarchy until it finds a .jscodeshiftrc file. At FB, we could add one to our JS codebases with default print settings so a developer doesn't have to worry about picking the right options.

@wincent
Copy link
Contributor Author

wincent commented Jul 24, 2015

Yeah, I have some time, although the exact amount and distribution of it is unpredictable right now.

Traversing up sounds fine.

@DrewML
Copy link
Contributor

DrewML commented Jun 23, 2016

Doesn't look like there has been progress on this in awhile (and I would like to see this feature for my own use), so I started working on a new branch. I did run into a bit of an issue, though.

I would assume that the preference is for command line arguments to override config in .jscodeshiftrc, right? This is problematic when trying to do this in combination with nomnom, because of the fact that nomnom handles setting the defaults. When merging .jscodeshiftrc values with the parsed CLI values, those defaults are always going to take precedence.

I considered pulling the defaults out of nomnom and handling that logic/config elsewhere, but that has the caveat that --help will no longer show defaults.

I looked at the previous WIP that Greg proposed for ideas, but (unless I'm looking at it wrong), it doesn't look like this logic will work, because options (coming from nomnom's parse) will always have the property name being passed to hasOwnProperty.

On second thought, I guess what I was doing doesn't have too much value. I was trying to make it possible to override CLI options in addition to recast print settings, but I can't think of a scenario where you'd ever want to set most of those CLI options as static config. Maybe for now, we just provide the ability to provide print settings in the config file, and structure the config in such a way that we can add more options in the future? Example config being:

{
   "recastPrintOpts": {}
}

@cpojer Any thoughts?

euphocat pushed a commit to euphocat/jscodeshift that referenced this issue Oct 22, 2017
@silvenon
Copy link
Contributor

silvenon commented Feb 6, 2020

I think this suggestion should be revisited (there are nice solutions today like cosmiconfig for dealing with format). I currently have to use a custom npm script which passes options to jscodeshift the way I want, I think a config file would be a cleaner solution. Also, libraries like react-codemod could read your configuration instead of asking you (and I still couldn't configure it to work, but that's another story).

@sibelius
Copy link
Contributor

that's I'm doing inside my transformer file

import path from 'path';

const cwd = process.cwd();

const getConfig = (options: Options) => {
  if (!options.config) {
    return defaultConfig;
  }

  try {
    const configPath = path.join(cwd, options.config);
    const config = require(configPath); // eslint-disable-line

    return config;
  } catch (e) {
    // eslint-disable-next-line
    console.log('Config not found');
    return defaultConfig;
  }
};

function transform(file: FileInfo, api: API, options: Options) {
    const config = getConfig(options);
}

how to use it

jscodeshift -t transform.ts --config path/to/config.js

config.js

module.exports = {
  options: 'optionA',
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants