generator-begcode
Version:
Spring Boot + Angular/React/Vue in one handy generator
398 lines (397 loc) • 18.4 kB
JavaScript
import { rm } from 'node:fs/promises';
import chalk from 'chalk';
import { camelCase, snakeCase, upperFirst } from 'lodash-es';
import BaseGenerator from '../base-application/index.js';
import { PRIORITY_NAMES_LIST as BASE_PRIORITY_NAMES_LIST } from '../base/priorities.js';
import * as GENERATOR_LIST from '../generator-list.js';
import { packageJson } from '../../lib/index.js';
import { BLUEPRINT_API_VERSION, NODE_VERSION } from '../generator-constants.js';
import { files, generatorFiles } from './files.js';
import { ADDITIONAL_SUB_GENERATORS, ALL_GENERATORS, ALL_PRIORITIES, DYNAMIC, GENERATE_SNAPSHOTS, GENERATORS, LINK_JHIPSTER_DEPENDENCY, LOCAL_BLUEPRINT_OPTION, PRIORITIES, SUB_GENERATORS, WRITTEN, allGeneratorsConfig, defaultConfig, defaultSubGeneratorConfig, prompts, requiredConfig, subGeneratorPrompts, } from './constants.js';
const { GENERATOR_PROJECT_NAME, GENERATOR_INIT } = GENERATOR_LIST;
const defaultPublishedFiles = ['generators', '!**/__*', '!**/*.snap', '!**/*.spec.?(c|m)js'];
export default class extends BaseGenerator {
application;
recreatePackageLock;
skipWorkflows;
ignoreExistingGenerators;
gitDependency;
async _beforeQueue() {
if (!this.fromBlueprint) {
await this.composeWithBlueprints();
}
if (!this.delegateToBlueprint) {
await this.dependsOnJHipster(GENERATOR_PROJECT_NAME);
}
}
get initializing() {
return this.asInitializingTaskGroup({
async loadOptions() {
if (this[ALL_GENERATORS]) {
this.config.set(allGeneratorsConfig());
}
if (this.options.defaults) {
this.config.defaults(defaultConfig({ config: this.jhipsterConfig }));
}
},
});
}
get [BaseGenerator.INITIALIZING]() {
return this.delegateTasksToBlueprint(() => this.initializing);
}
get prompting() {
return this.asPromptingTaskGroup({
async prompting() {
await this.prompt(prompts(this), this.config);
},
async eachSubGenerator() {
const { localBlueprint } = this.jhipsterConfig;
const { [ALL_PRIORITIES]: allPriorities } = this.options;
const subGenerators = this.config.get(SUB_GENERATORS) || [];
for (const subGenerator of subGenerators) {
const subGeneratorStorage = this.getSubGeneratorStorage(subGenerator);
if (allPriorities) {
subGeneratorStorage.defaults({ [PRIORITIES]: BASE_PRIORITY_NAMES_LIST });
}
await this.prompt(subGeneratorPrompts({ subGenerator, localBlueprint, options: this.options }), subGeneratorStorage);
}
},
async eachAdditionalSubGenerator() {
const { localBlueprint } = this.jhipsterConfig;
const { [ALL_PRIORITIES]: allPriorities } = this.options;
const additionalSubGenerators = this.config.get(ADDITIONAL_SUB_GENERATORS) || '';
for (const subGenerator of additionalSubGenerators
.split(',')
.map(sub => sub.trim())
.filter(Boolean)) {
const subGeneratorStorage = this.getSubGeneratorStorage(subGenerator);
if (allPriorities) {
subGeneratorStorage.defaults({ [PRIORITIES]: BASE_PRIORITY_NAMES_LIST });
}
await this.prompt(subGeneratorPrompts({ subGenerator, localBlueprint, additionalSubGenerator: true }), subGeneratorStorage);
}
},
});
}
get [BaseGenerator.PROMPTING]() {
return this.delegateTasksToBlueprint(() => this.prompting);
}
get configuring() {
return this.asConfiguringTaskGroup({
requiredConfig() {
this.config.defaults(requiredConfig());
},
conditionalConfig() {
if (this.jhipsterConfig[LOCAL_BLUEPRINT_OPTION]) {
this.config.defaults({
[DYNAMIC]: true,
js: false,
});
}
},
});
}
get [BaseGenerator.CONFIGURING]() {
return this.delegateTasksToBlueprint(() => this.configuring);
}
get composing() {
return this.asComposingTaskGroup({
storeCurrentVersion() {
this.storeCurrentJHipsterVersion();
},
async compose() {
if (this.jhipsterConfig[LOCAL_BLUEPRINT_OPTION])
return;
const initGenerator = await this.composeWithJHipster(GENERATOR_INIT, { generatorOptions: { packageJsonType: 'module' } });
initGenerator.generateReadme = false;
},
});
}
get [BaseGenerator.COMPOSING]() {
return this.delegateTasksToBlueprint(() => this.composing);
}
get loading() {
return this.asLoadingTaskGroup({
async createContext() {
this.application = { ...defaultConfig(), ...this.config.getAll() };
await this.loadCurrentJHipsterCommandConfig(this.application);
},
async load() {
this.application.packagejs = packageJson;
},
});
}
get [BaseGenerator.LOADING]() {
return this.delegateTasksToBlueprint(() => this.loading);
}
get preparing() {
return this.asPreparingTaskGroup({
prepareCommands() {
this.application.commands = [];
this.application.nodeVersion = NODE_VERSION;
if (!this.application[GENERATORS])
return;
for (const generator of Object.keys(this.application[GENERATORS])) {
const subGeneratorConfig = this.getSubGeneratorStorage(generator).getAll();
if (subGeneratorConfig.command) {
this.application.commands.push(generator);
}
}
},
preparePath() {
this.application.blueprintsPath = this.application[LOCAL_BLUEPRINT_OPTION] ? '.blueprint/' : 'generators/';
},
prepare({ application }) {
const { cli, cliName, baseName } = this.application;
this.application.githubRepository = this.jhipsterConfig.githubRepository ?? `jhipster/generator-jhipster-${baseName}`;
application.blueprintMjsExtension = this.application.js ? 'js' : 'mjs';
if (cli) {
this.application.cliName = cliName ?? `jhipster-${baseName}`;
}
},
});
}
get [BaseGenerator.PREPARING]() {
return this.delegateTasksToBlueprint(() => this.preparing);
}
get writing() {
return this.asWritingTaskGroup({
async cleanup({ control }) {
await control.cleanupFiles({
'8.5.1': ['.eslintrc.json'],
'8.7.2': ['.eslintignore', 'vitest.test-setup.ts'],
'8.7.4': ['.blueprint/generate-sample/get-samples.mjs', '.blueprint/github-build-matrix/build-matrix.mjs'],
});
},
async writing({ application }) {
this.application.sampleWritten = this.jhipsterConfig.sampleWritten;
const { skipWorkflows, ignoreExistingGenerators } = this;
await this.writeFiles({
sections: files,
context: {
...application,
skipWorkflows,
ignoreExistingGenerators,
...this.application,
},
});
this.jhipsterConfig.sampleWritten = true;
},
async writingGenerators({ application }) {
if (!this.application[GENERATORS])
return;
const { skipWorkflows, ignoreExistingGenerators } = this;
for (const generator of Object.keys(this.application[GENERATORS])) {
const subGeneratorStorage = this.getSubGeneratorStorage(generator);
const subGeneratorConfig = subGeneratorStorage.getAll();
const priorities = (subGeneratorConfig[PRIORITIES] || []).map(priority => ({
name: priority,
asTaskGroup: `as${upperFirst(priority)}TaskGroup`,
constant: `${snakeCase(priority).toUpperCase()}`,
}));
const customGenerator = !Object.values(GENERATOR_LIST).includes(generator);
const jhipsterGenerator = customGenerator || subGeneratorConfig.sbs ? 'base-application' : generator;
const subTemplateData = {
...application,
skipWorkflows,
ignoreExistingGenerators,
application: this.application,
...defaultSubGeneratorConfig(),
...subGeneratorConfig,
generator,
customGenerator,
jhipsterGenerator,
subGenerator: generator,
generatorClass: upperFirst(camelCase(jhipsterGenerator)),
priorities,
};
await this.writeFiles({
sections: generatorFiles,
context: subTemplateData,
});
subGeneratorStorage.set(WRITTEN, true);
}
},
});
}
get [BaseGenerator.WRITING]() {
return this.delegateTasksToBlueprint(() => this.writing);
}
get postWriting() {
return this.asPostWritingTaskGroup({
upgrade({ application }) {
if (!this.application[GENERATORS])
return;
if (!this.isJhipsterVersionLessThan('8.7.2'))
return;
for (const generator of Object.keys(this.application[GENERATORS])) {
const commandFile = `${this.application.blueprintsPath}${generator}/command.${application.blueprintMjsExtension}`;
this.editFile(commandFile, { ignoreNonExisting: true }, content => content
.replace(`/**
* @type {import('generator-jhipster').JHipsterCommandDefinition}
*/`, `import { asCommand } from 'generator-jhipster';
`)
.replace('const command = ', 'export default asCommand(')
.replace(`
};`, '});')
.replace('export default command;', ''));
const generatorSpec = `${this.application.blueprintsPath}${generator}/generator.spec.${application.blueprintMjsExtension}`;
this.editFile(generatorSpec, { ignoreNonExisting: true }, content => content.replaceAll(/blueprint: '([\w-]*)'/g, "blueprint: ['$1']"));
}
},
packageJson() {
if (this.jhipsterConfig[LOCAL_BLUEPRINT_OPTION])
return;
const { packagejs } = this.application;
const mainDependencies = {
...packagejs.dependencies,
...packagejs.devDependencies,
};
this.loadNodeDependenciesFromPackageJson(mainDependencies, this.fetchFromInstalledJHipster('generate-blueprint/resources/package.json'));
this.packageJson.merge({
name: `generator-jhipster-${this.jhipsterConfig.baseName}`,
keywords: ['yeoman-generator', 'jhipster-blueprint', BLUEPRINT_API_VERSION],
files: defaultPublishedFiles,
scripts: {
ejslint: 'ejslint generators/**/*.ejs',
lint: 'eslint .',
'lint-fix': 'npm run ejslint && npm run lint -- --fix',
pretest: 'npm run prettier-check && npm run lint',
test: 'vitest run',
'update-snapshot': 'vitest run --update',
vitest: 'vitest',
},
devDependencies: {
'ejs-lint': `${mainDependencies['ejs-lint']}`,
eslint: `${mainDependencies.eslint}`,
globals: `${mainDependencies.globals}`,
vitest: mainDependencies.vitest,
prettier: `${mainDependencies.prettier}`,
'yeoman-test': '>=8.2.0',
},
engines: {
node: packagejs.engines.node,
},
});
},
addCliToPackageJson() {
if (!this.jhipsterConfig.cli || this.jhipsterConfig[LOCAL_BLUEPRINT_OPTION])
return;
const { cliName } = this.application;
this.packageJson.merge({
bin: {
[cliName]: 'cli/cli.cjs',
},
files: ['cli', ...defaultPublishedFiles],
});
},
addGeneratorJHipsterDependency() {
if (this.jhipsterConfig[LOCAL_BLUEPRINT_OPTION])
return;
const { packagejs } = this.application;
const exactDependency = {
'generator-jhipster': `${packagejs.version}`,
};
const caretDependency = {
'generator-jhipster': `^${packagejs.version}`,
};
if (this.jhipsterConfig.dynamic) {
this.packageJson.merge({
devDependencies: exactDependency,
peerDependencies: caretDependency,
engines: caretDependency,
});
}
else {
this.packageJson.merge({
dependencies: this.gitDependency ? { 'generator-jhipster': this.gitDependency } : exactDependency,
engines: this.jhipsterConfig.caret ? caretDependency : exactDependency,
});
}
},
});
}
get [BaseGenerator.POST_WRITING]() {
return this.delegateTasksToBlueprint(() => this.postWriting);
}
get postInstall() {
return this.asPostInstallTaskGroup({
async addSnapshot({ control }) {
const { [LOCAL_BLUEPRINT_OPTION]: localBlueprint } = this.jhipsterConfig;
const { skipInstall, skipGit, existed, [GENERATE_SNAPSHOTS]: generateSnapshots = !localBlueprint && !skipInstall && !skipGit && !existed, } = this.options;
if (!generateSnapshots)
return;
if (this.recreatePackageLock) {
await rm(this.destinationPath('package-lock.json'), { force: true });
await rm(this.destinationPath('node_modules'), { force: true, recursive: true });
await this.spawnCommand('npm', ['install'], { stdio: 'inherit' });
}
try {
if (this.options[LINK_JHIPSTER_DEPENDENCY]) {
this.log.verboseInfo('Linking generator-begcode');
await this.spawnCommand('npm', ['link', 'generator-begcode'], { stdio: 'inherit' });
}
this.log.verboseInfo(`
This is a new blueprint, executing '${chalk.yellow('npm run update-snapshot')}' to generate snapshots and commit to git.`);
await this.spawnCommand('npm', ['run', 'update-snapshot']);
}
catch (error) {
if (generateSnapshots !== undefined) {
throw error;
}
this.log.warn('Fail to generate snapshots');
}
if (control.jhipsterOldVersion) {
try {
await this.spawnCommand('npm', ['run', 'prettier-format']);
}
catch {
}
try {
await this.spawnCommand('npm', ['run', 'lint-fix']);
}
catch {
}
}
},
});
}
get [BaseGenerator.POST_INSTALL]() {
return this.delegateTasksToBlueprint(() => this.postInstall);
}
get end() {
return this.asEndTaskGroup({
end() {
if (this.jhipsterConfig[LOCAL_BLUEPRINT_OPTION])
return;
this.log.log(`${chalk.bold.green('##### USAGE #####')}
To begin to work:
- launch: ${chalk.yellow.bold('npm install')}
- link: ${chalk.yellow.bold('npm link')}
- link begcode: ${chalk.yellow.bold('npm link generator-begcode')}
- test your module in a JHipster project:
- create a new directory and go into it
- link the blueprint: ${chalk.yellow.bold(`npm link generator-begcode-${this.moduleName}`)}
- launch JHipster with flags: ${chalk.yellow.bold(`begcode --blueprints ${this.moduleName}`)}
- then, come back here, and begin to code!
`);
},
});
}
get [BaseGenerator.END]() {
return this.delegateTasksToBlueprint(() => this.end);
}
getSubGeneratorStorage(subGenerator) {
return this.config.createStorage(`${GENERATORS}.${subGenerator}`);
}
validateGitHubName(input) {
if (/^([a-zA-Z0-9]+)(-([a-zA-Z0-9])+)*$/.test(input) && input !== '')
return true;
return 'Your username is mandatory, cannot contain special characters or a blank space';
}
validateModuleName(input) {
return /^[a-zA-Z0-9-]+$/.test(input)
? true
: 'Your blueprint name is mandatory, cannot contain special characters or a blank space, using the default name instead';
}
}