Internally, JHipster uses Yeoman as the core. JHipster is the most popular generator of all time.
.blueprint
- development blueprint, used to generate and manage samples.devcontainer
- vscode's devcontainer definitions.github
- github configuration.vscode
- vscode's configurationbin
- jit executable and helpercli
- (exported) cli implementationgenerators/*
- (exported) generatorscommand.m[tj]s
- cli options, cli arguments definitionsgenerator.m[tj]s
- generator implementationindex.m[tj]s
- generator exports. Must re-export generator as default export and the commandinternal
- non-exported supporting libsresources
- supporting resourcesjdl
- generator's jdl specificationssupport
- (exported) exported supporting libstemplates
- templates folder
jdl
- (exported) jdl parser implementationrfcs
- (RFCs)[CONTRIBUTING.md#rfcs]test
- package teststest-integration
- CI related stuff. Samples, scripts.
- CLI entry point
- Basic environment validation
- Cli arguments parsing and Environment bootstrap
- Lookup for generators and blueprints
- Build CLI options and arguments definition
- Parse options and arguments
- Run Generator (start the Environment) passing options and arguments
- Run every task from the highest precedence priority until there is no more pending task
Initial generator information.
- say generator specific hello
- initial environment checks
- argument and options loading
get [Generator.INITIALIZING]() {
return this.asInitializingTaskGroup() {
sayHelloTask() {
this.log.info('Welcome to your generator');
},
envChecks() {
checkNode();
checkDocker();
},
async loadOptions() {
this.parseJHipsterArguments(command.arguments);
this.parseJHipsterOptions(command.options);
},
}
}
Prompt for configuration.
get [Generator.PROMPTING]() {
return this.asPromptingTaskGroup() {
async prompting() {
await this.prompt(this.prepareQuestions(command.configs));
},
}
}
Check and fix configurations:
get [Generator.CONFIGURING]() {
return this.asConfiguringTaskGroup() {
checkConfig() {
if (this.jhipsterConfigWithDefaults.reactive && this.jhipsterConfigWithDefaults.cacheProvider !== 'no') {
this.log.warn("Reactive applications doesn't support cache. Disabling");
this.jhipsterConfig.cacheProvider = 'no';
}
},
}
}
Compose with other generators:
get [Generator.COMPOSING]() {
return this.asComposingTaskGroup() {
async composing() {
if (this.jhipsterConfigWithDefaults.clientFramework === 'angular') {
await this.composeWithJHipster('angular');
}
},
}
}
Load configuration:
get [Generator.LOADING]() {
return this.asLoadingTaskGroup() {
loading({ application }) {
application.myCustomConfig = this.jhipsterConfig.myCustomConfig;
application.myBlueprintCustomConfig = this.blueprintConfig.myBlueprintCustomConfig;
},
}
}
Generate properties to improve understanding:
get [Generator.PREPARING]() {
return this.asPreparingTaskGroup() {
preparing({ application }) {
application.myCustomConfigFoo = this.jhipsterConfig.myCustomConfig === 'foo';
application.myCustomConfigBar = this.jhipsterConfig.myCustomConfig === 'bar';
application.myCustomConfigNo = !this.jhipsterConfig.myCustomConfig || this.jhipsterConfig.myCustomConfig === 'no';
},
}
}
Configure and check entity's configuration:
get [Generator.CONFIGURING_EACH_ENTITY]() {
return this.asConfiguringEachEntityTaskGroup() {
configuring({ application, entityConfig }) {
if (application.searchEngineNo && entityConfig.searchEngine && entityConfig.searchEngine !== 'no') {
this.log.warn("Search engine cannot be enabled at entity because it's disabled at application");
entityConfig.searchEngine = 'no';
}
},
}
}
Usually empty the entire entity configuration is loaded by default.
Generate properties to improve understanding at the entity level:
get [Generator.PREPARING_EACH_ENTITY]() {
return this.asPreparingEachEntityTaskGroup() {
preparing({ application, entity }) {
entity.dtoMapstruct = entity.dto === 'mapstruct';
},
}
}
Generate properties to improve understanding at the field level:
get [Generator.PREPARING_EACH_ENTITY_FIELD]() {
return this.asPreparingEachEntityFieldTaskGroup() {
preparing({ application, entity, field }) {
field.technologyFieldTypeIntegerMap = field.fieldType === 'Integer';
},
}
}
Generate properties to improve understanding at the relationship level:
get [Generator.PREPARING_EACH_ENTITY_RELATIONSHIP]() {
return this.asPreparingEachEntityRelationshipTaskGroup() {
preparing({ application, entity, relationship }) {
relationship.technologyRelationshipDbName = relationship.relationshipTypeOneToOne ? 'foo' : 'bar';
},
};
}
Generate properties to improve understanding that depends on others' properties:
get [Generator.DEFAULT]() {
return this.asDefaultTaskGroup() {
preparing({ application, entities }) {
application.hasEntityFieldInteger = entities.some(entity => entity.fields.some(field => field.fieldTypeInteger));
},
};
}
Write files to the in-memory file system.
There are a lot of APIs to write files, copy files, and delete files.
The writeFiles()
method is the most used in official generators.
get [Generator.WRITING]() {
return this.asWritingTaskGroup({
async writingTask({ application }) {
await this.writeFiles({
blocks: [
{
condition: ctx => ctx.shouldWrite,
templates: ['template.file'],
}
],
context: application,
});
},
});
}
Write entity files to the in-memory file system.
Writing entities is a separate priority to keep the workflow sane when using options like --skip-application
and --single-entity
.
get [Generator.WRITING_ENTITIES]() {
return this.asWritingTaskGroup({
async writingTask({ application, entities }) {
for (const entity of entities) {
await this.writeFiles({
blocks: [
{
condition: ctx => ctx.shouldWrite,
templates: ['entity.template.file'],
}
],
context: { ...application, ...entity },
});
}
},
});
}
Injects code in the generated source.
JHipster adds APIs for code injection:
get [Generator.POST_WRITING]() {
return this.asPostWritingTaskGroup({
postWritingTask({ source }) {
source.someProvidedInjectionApi({ code: 'some code' });
}
});
}
Every file can be edited manually.
get [Generator.POST_WRITING]() {
return this.asPostWritingTaskGroup({
postWritingTask({ source }) {
this.editFile('path/to/some/file', content => content.replaceAll('some content', 'another content'));
}
});
}
Usually empty.
Install task is queued by detecting package.json
changes.
Print generator result and info:
get [Generator.END]() {
return this.asEndTaskGroup() {
preparing({ application }) {
this.log.success('Tech application generated successfully');
this.log.log(`Start the application running 'npm run start:app'`);
},
};
}
Blueprint support allows customizing the generation process.
A Blueprint package can include any number of sub-generators, each can be a replacement blueprint, a side-by-side blueprint, or a stand alone blueprint.
- Normal blueprints will completely replace the blueprinted sub-generator with a replacement.
- Side by side blueprint doesn't change the generation process, it customizes it.
- Stand alone blueprint doesn't hook into a sub-generator.
Examples:
- Micronaut has a server replacement blueprint, a angular, client, cypress, docker and react side by side blueprints, and a micronaut-cache stand alone blueprint
More information can be found at:
Extending and customizing Creating a stand alone Blueprint Creating a blueprint
Priority | Blueprinted sub-gen | Blueprint sub-gen |
---|---|---|
beforeQueue | composes with blueprints/dependencies | composes with dependencies |
initializing | X | replacement initializing tasks |
prompting | X | replacement prompting tasks |
... | X | ... |
Priority | Blueprinted sub-gen | Blueprint sub-gen | Another blueprint sub-gen |
---|---|---|---|
beforeQueue | composes with blueprints/dependencies | composes with dependencies | composes with dependencies |
initializing | initializing tasks | additional initializing tasks | additional initializing tasks |
prompting | prompting tasks | additional prompting tasks | additional prompting tasks |
... | ... | ... | ... |
Priority | Blueprint sub-gen |
---|---|
beforeQueue | composes with dependencies |
initializing | initializing tasks |
prompting | prompting tasks |
... | ... |
Adds custom APIS to yeoman-generator
and customizes the behavior.
Adds Blueprint composing APIS.
Adds Entities related apis.