generator-begcode
Version:
Spring Boot + Angular/React/Vue in one handy generator
255 lines (254 loc) • 11.7 kB
JavaScript
import { setTimeout } from 'timers/promises';
import { readdir, rm } from 'fs/promises';
import chalk from 'chalk';
import gitignore from 'parse-gitignore';
import semver from 'semver';
import { ResetMode } from 'simple-git';
import BaseGenerator from '../base/index.js';
import { packageJson } from '../../lib/index.js';
import EnvironmentBuilder from '../../cli/environment-builder.mjs';
import { SERVER_MAIN_RES_DIR } from '../generator-constants.js';
import { GIT_VERSION_NOT_ALLOW_MERGE_UNRELATED_HISTORIES, UPGRADE_BRANCH } from './support/index.js';
const GENERATOR_JHIPSTER = 'generator-begcode';
const GENERATOR_APP = 'app';
const DEFAULT_CLI_OPTIONS = '--force --skip-install --skip-git --ignore-errors --no-insight --skip-checks';
const DEFAULT_NON_INTERATIVE_OPTIONS = {
skipInstall: true,
skipGit: true,
skipChecks: true,
force: true,
ignoreErrors: true,
skipPriorities: ['prompting'],
};
const DEFAULT_MERGE_OPTIONS = ['--strategy', 'ours'];
export default class UpgradeGenerator extends BaseGenerator {
requiredPackage = GENERATOR_JHIPSTER;
createEnvBuilder;
actualApplicationBranch;
silent;
applyConfig;
spawnStdio = 'inherit';
executable;
verbose;
async beforeQueue() {
if (!this.fromBlueprint) {
await this.composeWithBlueprints();
}
}
get initializing() {
return this.asInitializingTaskGroup({
displayLogo() {
this.log.log(chalk.green('Welcome to the JHipster Upgrade Sub-Generator'));
this.log.log(chalk.green(`This will upgrade your current application codebase to JHipster version ${packageJson.version}`));
this.log.log(chalk.green('For advanced options, please use the jhipster-migrate blueprint (https://github.com/jhipster/generator-jhipster-migrate/)'));
this.log.log('');
},
initializeOptions() {
if (this.silent) {
this.spawnStdio = 'ignore';
}
this.executable = this.executable ?? this.options.programName ?? 'jhipster';
this.createEnvBuilder = this.options.createEnvBuilder ?? EnvironmentBuilder.createDefaultBuilder;
},
assertJHipsterProject() {
if (!this.config.existed) {
throw new Error("Could not find a valid BegCode application configuration, check if the '.yo-rc.json' file exists and if the 'generator-begcode' key exists inside it.");
}
if (!this.config.get('baseName')) {
throw new Error('Current directory does not contain a JHipster project.');
}
},
async checkoutDependency() {
if (this.applyConfig)
return;
const jhipsterVersion = this.getPackageJsonVersion();
if (!jhipsterVersion) {
throw new Error('No generator-jhipster dependency found in your package.json');
}
if (this.isV7(jhipsterVersion)) {
if (jhipsterVersion !== '7.9.4') {
throw new Error('Upgrade the project to JHipster 7.9.4 before upgrading to the latest version.');
}
if ((this.jhipsterConfig.blueprints ?? []).length > 0) {
const errorMessage = 'Upgrade does not support upgrading a v7 project with blueprints. Please use the jhipster-migrate blueprint.';
if (!this.skipChecks) {
throw new Error(errorMessage);
}
else {
this.log.warn(errorMessage);
}
}
}
},
async assertGitPresent() {
if (!(await this.checkGitVersion(GIT_VERSION_NOT_ALLOW_MERGE_UNRELATED_HISTORIES))) {
this.log.warn('git is not found on your computer.\n', ` Install git: ${chalk.yellow('https://git-scm.com/')}`);
throw new Error('Exiting the process.');
}
},
async assertGitRepository() {
const git = this.createGit();
if (!(await git.checkIsRepo())) {
this.log.warn('Current directory is not a git repository. Initializing git.');
await git.init().add('.').commit('initial commit', ['--allow-empty', '--no-verify']);
}
},
async assertNoLocalChanges() {
const result = await this.createGit().status();
if (!result.isClean()) {
throw new Error(` local changes found.\n\tPlease commit/stash them before upgrading\n\t${result.files
.map(file => `${file.index} ${file.path}`)
.join('\n\t')}`);
}
},
async detectCurrentBranch() {
this.actualApplicationBranch = await this.createGit().revparse(['--abbrev-ref', 'HEAD']);
if (this.actualApplicationBranch === UPGRADE_BRANCH) {
throw new Error('You are on the upgrade branch, please switch to another branch before upgrading.');
}
},
});
}
get [BaseGenerator.INITIALIZING]() {
return this.delegateTasksToBlueprint(() => this.initializing);
}
get default() {
return this.asDefaultTaskGroup({
async prepareUpgradeBranch() {
const git = this.createGit();
try {
await git.revparse(['--verify', UPGRADE_BRANCH]);
await git.checkout(UPGRADE_BRANCH);
}
catch {
await git.checkout(['--orphan', UPGRADE_BRANCH]);
}
await this.cleanUp();
if (this.applyConfig) {
await this.runNonInteractive(false);
}
else {
await this.spawnCommand('npm install', { stdio: this.spawnStdio });
const customCliOptions = [];
if (this.getPackageJsonVersion() === '7.9.4') {
customCliOptions.push('--with-entities');
}
this.log.info(`Regenerating sources using ${this.executable} executable`);
await this.spawn('npx', ['--no', this.executable, ...customCliOptions, ...DEFAULT_CLI_OPTIONS.split(' ')], {
stdio: this.spawnStdio,
});
}
await this.rmRf(`${SERVER_MAIN_RES_DIR}config/tls/keystore.p12`);
await git.add('.').commit(`generated ${UPGRADE_BRANCH} using JHipster ${this.getPackageJsonVersion()}`, ['--no-verify']);
this.log.info('reference application created');
await setTimeout(1000);
},
async prepareSourceBranch() {
const git = this.createGit();
await git
.checkout(this.actualApplicationBranch, ['-f'])
.merge([
UPGRADE_BRANCH,
...DEFAULT_MERGE_OPTIONS,
'-m',
`reference merge of ${UPGRADE_BRANCH} branch into ${this.actualApplicationBranch}`,
'--allow-unrelated-histories',
]);
this.log.info('reference application merged into source branch');
await setTimeout(1000);
},
async updateUpgradeBranch() {
const git = this.createGit();
await git.checkout(UPGRADE_BRANCH);
await this.cleanUp();
await this.runNonInteractive();
await this.rmRf(`${SERVER_MAIN_RES_DIR}config/tls/keystore.p12`);
await git.add('.').commit(`generated ${UPGRADE_BRANCH} using JHipster ${packageJson.version}`, ['--no-verify']);
this.log.info('upgrade commit created');
await setTimeout(1000);
},
async upgradeSourceBranch() {
const git = this.createGit();
await git
.checkout(this.actualApplicationBranch, ['-f'])
.merge([UPGRADE_BRANCH, '-m', `upgrade merge of ${UPGRADE_BRANCH} branch into ${this.actualApplicationBranch}`])
.reset(ResetMode.HARD);
this.log.info('upgrade application merged into source branch');
if (!this.applyConfig) {
await this.rmRf('node_modules');
await this.rmRf('package-lock.json');
this.log.info('node_modules and package-lock.json removed to allow a clean install');
}
},
});
}
get [BaseGenerator.DEFAULT]() {
return this.delegateTasksToBlueprint(() => this.default);
}
get end() {
return this.asEndTaskGroup({
async end() {
const diff = await this.createGit().diff(['--name-only', '--diff-filter', 'U']);
this.log.ok(chalk.bold('upgraded successfully.'));
if (diff) {
this.log.warn(`please fix conflicts listed below and commit!\n${diff}`);
}
},
});
}
get [BaseGenerator.END]() {
return this.delegateTasksToBlueprint(() => this.end);
}
async rmRf(file) {
const absolutePath = this.destinationPath(file);
if (this.verbose) {
this.log.verboseInfo(`Removing ${absolutePath}`);
}
try {
await rm(absolutePath, { recursive: true });
}
catch {
}
}
async cleanUp() {
const gitignoreContent = this.readDestination('.gitignore', { defaults: '' });
const ignoredFiles = gitignoreContent ? (gitignore(gitignoreContent).patterns ?? []) : [];
const filesToKeep = ['.yo-rc.json', '.jhipster', 'package.json', 'package-lock.json', 'node_modules', '.git', ...ignoredFiles];
for (const file of await readdir(this.destinationPath())) {
if (!filesToKeep.includes(file)) {
await this.rmRf(file);
}
}
this.log.info('cleaned up project directory');
}
getPackageJsonVersion() {
return this.readDestinationJSON('package.json').devDependencies?.['generator-jhipster'];
}
isV7(version) {
return version.includes('.') && parseInt(version.split('.', 2), 10) < 8;
}
async runNonInteractive(inherit = true) {
const adapter = this.env.adapter.newAdapter?.();
const sharedFs = inherit ? this.env.sharedFs : undefined;
const inheritedOptions = inherit ? this.options : {};
const envOptions = { sharedFs, adapter };
const generatorOptions = { ...inheritedOptions, ...DEFAULT_NON_INTERATIVE_OPTIONS };
delete generatorOptions.sharedData;
const envBuilder = await this.createEnvBuilder(envOptions);
const env = envBuilder.getEnvironment();
await env.run([`begcode:${GENERATOR_APP}`], generatorOptions);
}
async checkGitVersion(minVersion) {
try {
const rawVersion = await this.createGit().raw('--version');
const gitVersion = String(rawVersion.match(/([0-9]+\.[0-9]+\.[0-9]+)/g));
if (minVersion) {
return semver.gte(gitVersion, minVersion);
}
return true;
}
catch {
return false;
}
}
}