Yeoman generator version 0.18.0 - Release announcement

Allo’ Allo’ today we’re happy to announce the release of yeoman-generator@0.18.0!

It’s been multiple months since our last minor version bump. This new release bring lots of new features and strive at improving the composability features (first introduced in 0.17).

New features!

Storing prompt answers

Using the {store: true} property on a prompt will store the user answers in a machine global storage. This mean next time the user run a generator, the default answer will be filled with the value previously stored.

Careful notice, providing a default value prevent user from returning empty answers.

Huge thanks to @stefanbuck for the PR https://github.com/yeoman/generator/pull/688

New File System

Since version 0.17, the Yeoman file system proved to be poorly designed to attack composability issues. That’s why with 0.18 we release a completely rethought file system abstraction. You can see the discussion and design process taking place in this issue.

Every legacy methods (this.write, this.copy, etc) have been back ported to use this new system. So updating to 0.18.0 should magically improve your generator.

New fs methods

The core system can be accessed on generator.fs. This object is an instance of mem-fs-editor and provide the same methods.

This system is way simpler than the current legacy method and doesn’t do any kind of magic. It won’t automatically compile templates (use this.fs.copyTpl() for this), it won’t pass this as template context, and it won’t automatically assume paths are relative to anything.

An example/usual usage would be:

this.fs.copyTpl(
  this.templatePath("mocha/base-test.js"),
  this.destinationPath("test/index.js"),
  { projectName: "my-awesome-module" }
);

As you can see, we also added two new paths helpers:

  1. this.templatePath() which is: path.join(this.sourceRoot(), ...rest)
  2. this.destinationPath() which is: path.join(this.destinationRoot(), ...rest)

Try it out and please give us feedback on how you like this new API. It is more verbose than our legacy methods, but it is clearer and less magical.

Note that the legacy system will remain available at least until version 1.0.0

What about the 0.17.0 this.src and this.dest file utils

These should be considered deprecated. The design decision they make isn’t a good fit with composability and will create issues on the long run.

File writing filters

Ever wished to apply custom filters on every file write? Beautifying files, normalizing whitespace, etc, is now possible.

Once per Yeoman process, we will write every modified files to disk. This process is passed through a vinyl object stream (just like gulp). Any author can register a transformStream to modify the file path or content.

For example:

var beautify = require("gulp-beautify");
this.registerTransformStream(beautify({ indentSize: 2 }));

Note that every file type will be passed through this stream. So make sure any transform stream passthrough unsupported files. Tools like gulp-if or gulp-filter will help filter invalid type and pass them through.

This new feature means you can basically use any gulp plugins to process generated files during the writing phase.

Improvements

  • Tests using helpers.run() won’t output to the console keeping the test output clean. Every log method is now a sinon.stub() making it easy to assert your generator outputted the correct content.
  • Testing run context now automatically run your tests in a unique tmpdir. No need to manually call helper.run().inDir() anymore.
  • assert.fileContent and assert.noFileContent accept a String as arguments (before we just accepted Regex)
  • The Conflicter have been refactored to be simple and easy to use.

Installation methods only running once

npm and bower installation helpers are now always running once per process. This was a change made in 0.17, but we extended the feature to cover every use/methods who could launch these process.

This was a breaking an edge case in 0.17. But for the sake of clarity, let’s be clear. The following construct will break:

this.installDependencies({
  callback: this.async() // This will block the process forever, and node will fail
});

Every install method will be registered on the install run queue. Using this.async() as a callback will create a deadlock.

Fixes

  • Installation methods (npm, bower helpers) now correctly pass the options to the spawn process.
  • When a conflict occurs on a directory, we don’t show the diff option anymore. (selecting diff on directory threw an error)
  • You can now correctly overwrite the stdio with generator.spawnCommand()
  • generator.composeWith() now correctly resolve the local option path.

Meta

  • We’ve extracted yeoman-environment on it’s own repository. This mean these two core Yeoman parts can now evolve at their own pace.
  • All our tests now uses tmpdir for testing making them more reliable.
  • Completely remove network connection from our test suite - it is now way faster.

Potentially breaking change

  • We stopped manually mocking Inquirer in tests. Mainly because Inquirer parses values in ways we didn’t imitate and this caused too much issue. Now we rely more on Inquirer and only mock the minimum. This also mean we don’t create the magic errors property during test. You can listen for generator errors instead.
  • We removed require('yeoman-generator').inquirer. Require your own version from now on.
  • We removed generator.shell and generator.request. Require your own version.

In conclusion

The work is still not completed. We still need to update some of our website documentation to include the new APIs methods. And we’ll need to update our core generators to this new version. These should come soon, in the meantime refer to this post about the new features.

So, enjoy this new release! Please upgrade and let us know how the API feels, and as usual feel free to report any bug you encounter!

Cheers


« View More Posts