mercredi 27 avril 2016

Yeoman : Passing data from generator to sub generator

I won't present Yeoman here. If you like to use scaffolding tool and use JavaScript, you already have heard about this great tool.

Maybe you've even tried to write your own generator. If you did, sooner or later you'll want to structure your code using sub generators and pass data from your (main) generator to your sub generators.

This simple task took me more time than needed, mainly because I was unable to find the right documentation.
The official documentation on the topic suggest using composeWith() with the options parameter to pass data to the called generator, but doesn't show how to get the data in the called generator.

So in hope the following could help others, you'll find below an example of how to do it.

In the generator you call the sub-generators this way :
//in generator-arhuman/generators/app/index.js 
this.composeWith('arhuman:express', { options: { my_opt: 'anystring' } }, { local: require.resolve('../express') });

Note the second parameter, the options object described in the documentation.
Now in the called sub-generator you get the data in the constructor by defining an option:

//in generator-arhuman/generators/app/express/index.js
module.exports = yeoman.generators.Base.extend({ 
  constructor: function () { 
      yeoman.generators.Base.apply(this, arguments); 
      
      // This option will get the value passed by the caller generator
      this.option('my_opt', { 
            type: String, 
            required: true, 
            desc: 'My option' 
          }); 
    }, 
  
  // Writing Logic here 
  writing: { 
    // Copy the configuration files 
    config: function() { 
      this.fs.copyTpl( 
        this.templatePath('_package.json'), 
        this.destinationPath('package.json'), { 
          name: this.options.my_opt
        } 
      ); 
     // ...
      ); 
    }, 

  install: function () {
    this.installDependencies();
  }
});

By giving it the same name as the key in the options object used in the composeWith() call you will get the value from the caller generator and use it later through this.options.my_opt