@codejen/pack-yeoman

yeoman.

Yeoman generators, JHipster included, run through jen's plan – the same diff, the same --dry-run, the same --force.

Never interactive, never online, and nothing is written until jen applies the plan.

Install

The pack runs the generators you have installed: every dependency named generator-<name> or @scope/generator-<name> becomes yeoman:<name>. jen adds no dependency for it – yeoman-generator, mem-fs and EJS come with the generator.

Globally

$ npm install -g @codejen/jen @codejen/pack-yeoman generator-code
$ jen yeoman:code --extensionType=command-ts --extensionDisplayName="My Extension"

Locally

$ npm install --save-dev @codejen/jen @codejen/pack-yeoman generator-code
$ npx jen yeoman:code --extensionType=command-ts --extensionDisplayName="My Extension"

Not at all

Ask for yeoman:code with nothing installed, and jen fetches @codejen/pack-yeoman and generator-code into a throwaway directory, runs the generator once and removes it again – like yo code, without the global install. jen only does this for a fixed list of generators: generator-code and generator-jhipster. A typo like yeoman:jhispter matches nothing on the list, so it can never install someone else's package. JEN_NO_FETCH=1 turns it off.

$ jen yeoman:code --extensionType=command-ts --extensionDisplayName="My Extension"
Fetching @codejen/pack-yeoman@latest …
yeoman:code (pack @codejen/pack-yeoman) – Yeoman generator-code – fetched when run
Fetching generator-code@latest …

  + my-extension/package.json
  + my-extension/src/extension.ts
  …

✓ 15 written

Any other generator can be fetched for one run with --from:

$ npx @codejen/jen --from generator-code yeoman:code --extensionType=command-ts --extensionDisplayName="My Extension"

Running generators

How it runs

The generator writes into memory, and what it wrote becomes jen's plan: new files, changed files, deleted files. jen applies it like any other – existing files are skipped unless you pass --force, --dry-run only shows it, and nothing outside the project is touched. Binary files, like images and keystores, are written as they are.

Some things are left out on purpose:

  • No questions. Every answer comes from a flag or the question's default – see below.
  • No network. While a generator runs, fetch and every outgoing connection fail, and so does the run – even if the generator catches the error itself. Generators that download their templates, like generator-office, can't run under jen.
  • No install step. Yeoman's install and end steps run npm install, git init or open an editor, on files that aren't written yet when the generator runs. They never run: install and initialize the project yourself afterwards.

Questions

A generator's questions are answered from a flag with the question's name – as it's written, or in kebab-case: --extensionType and --extension-type both answer extensionType. Without a flag, the answer is what pressing enter would give: the question's default, the first choice of a list, yes for a confirm. A question with none of these stops jen with Missing: --<name> before anything is written. Questions the generator would skip, it skips here too.

Most generators also take options for the things they ask; check the generator's own docs. Positionals after the generator name go to the generator as its arguments.

yeoman:<name>

Runs the package's default generator – the one yo <name> runs – with just enough of a Yeoman environment around it. Generators that compose other generators (composeWith) fail with a clear message; JHipster is the one that gets a real environment. A generator that writes to disk itself, past Yeoman's file system, isn't caught by the plan – the generators on jen's fetch list don't.

$ jen yeoman:code --extensionType=command-ts --extensionDisplayName="My Extension"
yeoman:code (pack @codejen/pack-yeoman) – Yeoman generator-code
…

  + my-extension/.vscode/extensions.json
  + my-extension/.vscode/launch.json
  + my-extension/package.json
  + my-extension/tsconfig.json
  + my-extension/src/extension.ts
  + my-extension/src/test/extension.test.ts
  …

✓ 15 written

JHipster

yeoman:jhipster

With generator-jhipster installed, yeoman:jhipster runs JHipster in its own Yeoman environment, with its sub-generators, priorities and Prettier formatting – the files are the ones the jhipster command would write, minus npm install and git init. --defaults takes every default instead of asking; any other JHipster option works as a flag, e.g. --base-name=blog.

$ jen yeoman:jhipster --defaults --base-name=demo
yeoman:jhipster (pack @codejen/pack-yeoman) – JHipster: an app, or a command like jdl
…

  + package.json
  + .yo-rc.json
  + sonar-project.properties
  …
  + src/main/java/com/mycompany/myapp/repository/package-info.java

✓ 482 written

Blueprints are turned off, since JHipster would install a missing one from npm. Files JHipster keeps outside the project, like ~/.yo-rc-global.json, are skipped.

JDL and commands

The first positional picks a JHipster command, the same as with jhipster: jen yeoman:jhipster jdl blog.jdl applies a JDL file. The file has to be inside the project – JHipster would otherwise look it up online. Describe entities in JDL: jhipster entity asks for every field one by one, so without JDL it stops at the first field. Regenerating changes files that exist, so it needs --force:

$ jen yeoman:jhipster jdl blog.jdl --force
yeoman:jhipster (pack @codejen/pack-yeoman) – JHipster: an app, or a command like jdl
…

  + .jhipster/Post.json
  ! .yo-rc.json  will be overwritten
  + src/test/java/com/mycompany/myapp/domain/PostTest.java
  + src/main/resources/config/liquibase/fake-data/blob/hipster.png
  + src/main/webapp/app/entities/post/post.model.ts
  …

✓ 40 written

Credits

  • Yeoman by the Yeoman team: the generators, and the environment the pack stands in for
  • JHipster by the JHipster team: the environment builder and the deferred commit the pack runs JHipster with

The pack is ISC licensed.