generator-luna
Version:
generate specific EHR application,it's built beyond the jhipster
473 lines (433 loc) • 21.5 kB
JavaScript
/**
* Copyright 2013-2019 the original author or authors from the JHipster project.
*
* This file is part of the JHipster project, see https://www.jhipster.tech/
* for more information.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const chalk = require('chalk');
const shelljs = require('shelljs');
const semver = require('semver');
const fs = require('fs');
const gitignore = require('parse-gitignore');
const BaseGenerator = require('../generator-base');
const constants = require('../generator-constants');
const statistics = require('../statistics');
/* Constants used throughout */
const GENERATOR_JHIPSTER = 'generator-jhipster';
const UPGRADE_BRANCH = 'jhipster_upgrade';
const GIT_VERSION_NOT_ALLOW_MERGE_UNRELATED_HISTORIES = '2.9.0';
const FIRST_CLI_SUPPORTED_VERSION = '4.5.1'; // The first version in which CLI support was added
const SERVER_MAIN_RES_DIR = constants.SERVER_MAIN_RES_DIR;
module.exports = class extends BaseGenerator {
constructor(args, opts) {
super(args, opts);
this.force = this.options.force;
// This adds support for a `--from-cli` flag
this.option('from-cli', {
desc: 'Indicates the command is run from JHipster CLI',
type: Boolean,
defaults: false
});
// This adds support for a `--target-version` flag
this.option('target-version', {
desc: 'Upgrade to a specific version instead of the latest',
type: String
});
// This adds support for a `--target-blueprint-version` flag
this.option('target-blueprint-version', {
desc: 'Upgrade to a specific blueprint version instead of the latest',
type: String
});
// This adds support for a `--skip-install` flag
this.option('skip-install', {
desc: 'Skips installing dependencies during the upgrade process',
type: Boolean,
defaults: false
});
// This adds support for a `--silent` flag
this.option('silent', {
desc: 'Hides output of the generation process',
type: Boolean,
defaults: false
});
this.targetJhipsterVersion = this.options['target-version'];
this.targetBlueprintVersion = this.options['target-blueprint-version'];
this.skipInstall = this.options['skip-install'];
this.silent = this.options.silent;
}
get initializing() {
return {
validateFromCli() {
this.checkInvocationFromCLI();
},
displayLogo() {
this.log(chalk.green('Welcome to the JHipster Upgrade Sub-Generator'));
this.log(chalk.green('This will upgrade your current application codebase to the latest JHipster version'));
},
loadConfig() {
this.config = this.getAllJhipsterConfig(this, true);
this.currentJhipsterVersion = this.config.get('jhipsterVersion');
this.blueprint = this.config.get('blueprint');
this.currentBlueprintVersion = this.config.get('blueprintVersion');
this.clientPackageManager = this.config.get('clientPackageManager');
this.clientFramework = this.config.get('clientFramework');
}
};
}
_gitCheckout(branch, callback) {
this.gitExec(['checkout', '-q', branch], { silent: this.silent }, (code, msg, err) => {
if (code !== 0) this.error(`Unable to checkout branch ${branch}:\n${err}`);
this.success(`Checked out branch "${branch}"`);
callback();
});
}
_cleanUp() {
const ignoredFiles = gitignore(fs.readFileSync('.gitignore'));
const filesToKeep = ['.yo-rc.json', '.jhipster', 'node_modules', '.git', '.idea', '.mvn', ...ignoredFiles];
shelljs.ls('-A').forEach(file => {
if (!filesToKeep.includes(file)) {
this.info(`Removing ${file}`);
shelljs.rm('-rf', file);
}
});
this.success('Cleaned up project directory');
}
_generate(jhipsterVersion, blueprintVersion, callback) {
const blueprintInfo = this.blueprint ? ` and ${this.blueprint} ${blueprintVersion}` : '';
this.log(`Regenerating application with JHipster ${jhipsterVersion}${blueprintInfo}...`);
let generatorCommand = 'yo jhipster';
if (semver.gte(jhipsterVersion, FIRST_CLI_SUPPORTED_VERSION)) {
const generatorDir =
this.clientPackageManager === 'yarn'
? shelljs.exec('yarn bin', { silent: this.silent }).stdout
: shelljs.exec('npm bin', { silent: this.silent }).stdout;
generatorCommand = `"${generatorDir.replace('\n', '')}/jhipster"`;
}
const regenerateCmd = `${generatorCommand} --with-entities --force --skip-install --skip-git --no-insight`;
this.info(regenerateCmd);
shelljs.exec(regenerateCmd, { silent: this.silent }, (code, msg, err) => {
if (code === 0) this.success(`Successfully regenerated application with JHipster ${jhipsterVersion}${blueprintInfo}`);
else this.error(`Something went wrong while generating project! ${err}`);
callback();
});
}
_gitCommitAll(commitMsg, callback) {
const commit = () => {
this.gitExec(
['commit', '-q', '-m', `"${commitMsg}"`, '-a', '--allow-empty', '--no-verify'],
{ silent: this.silent },
(code, msg, err) => {
if (code !== 0) this.error(`Unable to commit in git:\n${err}`);
this.success(`Committed with message "${commitMsg}"`);
callback();
}
);
};
this.gitExec(['add', '-A'], { maxBuffer: 1024 * 10000, silent: this.silent }, (code, msg, err) => {
if (code !== 0) this.error(`Unable to add resources in git:\n${err}`);
commit();
});
}
_regenerate(jhipsterVersion, blueprintVersion, callback) {
this._generate(jhipsterVersion, blueprintVersion, () => {
const keystore = `${SERVER_MAIN_RES_DIR}config/tls/keystore.p12`;
this.info(`Removing ${keystore}`);
shelljs.rm('-Rf', keystore);
const blueprintInfo = this.blueprint ? ` and ${this.blueprint} ${blueprintVersion}` : '';
this._gitCommitAll(`Generated with JHipster ${jhipsterVersion}${blueprintInfo}`, () => {
callback();
});
});
}
_retrieveLatestVersion(npmPackage, callback) {
this.log(`Looking for latest ${npmPackage} version...`);
const commandPrefix = this.clientPackageManager === 'yarn' ? 'yarn info' : 'npm show';
shelljs.exec(`${commandPrefix} ${npmPackage} version`, { silent: this.silent }, (code, msg, err) => {
if (err) {
this.warning(`Something went wrong fetching the latest ${npmPackage} version number...\n${err}`);
this.error('Exiting process');
}
const latestVersion = this.clientPackageManager === 'yarn' ? msg.split('\n')[1] : msg.replace('\n', '');
callback(latestVersion);
});
}
_installNpmPackageLocally(npmPackage, version, callback) {
this.log(`Installing ${npmPackage} ${version} locally`);
const commandPrefix = this.clientPackageManager === 'yarn' ? 'yarn add' : 'npm install';
const devDependencyParam = this.clientPackageManager === 'yarn' ? '--dev' : '--save-dev';
const noPackageLockParam = this.clientPackageManager === 'yarn' ? '--no-lockfile' : '--no-package-lock';
const generatorCommand = `${commandPrefix} ${npmPackage}@${version} ${devDependencyParam} ${noPackageLockParam} --ignore-scripts`;
this.info(generatorCommand);
shelljs.exec(generatorCommand, { silent: this.silent }, (code, msg, err) => {
if (code === 0) this.success(`Installed ${npmPackage}@${version}`);
else this.error(`Something went wrong while installing ${npmPackage}! ${msg} ${err}`);
callback();
});
}
get configuring() {
return {
assertJHipsterProject() {
const done = this.async();
if (!this.config.baseName) {
this.error('Current directory does not contain a JHipster project.');
}
done();
},
assertGitPresent() {
const done = this.async();
this.isGitInstalled(code => {
if (code !== 0) this.error('Exiting the process.');
done();
});
},
checkLatestBlueprintVersion() {
if (!this.blueprint) {
this.log('No blueprint detected, skipping check of last blueprint version');
return;
}
if (!this.currentBlueprintVersion) {
this.error('No blueprintVersion defined in .yo-rc.json, unable to upgrade');
}
if (this.targetBlueprintVersion) {
this.log(`Upgrading to the target blueprint version: ${this.targetBlueprintVersion}`);
this.latestBlueprintVersion = this.targetBlueprintVersion;
return;
}
const done = this.async();
this._retrieveLatestVersion(this.blueprint, latestVersion => {
this.latestBlueprintVersion = latestVersion;
if (semver.lt(this.currentBlueprintVersion, this.latestBlueprintVersion)) {
this.newBlueprintVersionFound = true;
this.success(`New ${this.blueprint} version found: ${this.latestBlueprintVersion}`);
} else if (this.force) {
this.newBlueprintVersionFound = true;
this.log(chalk.yellow('Forced re-generation'));
} else {
this.newBlueprintVersionFound = false;
this.warning(
`${chalk.green('No update available.')} Application has already been generated with latest blueprint version.`
);
}
done();
});
},
checkLatestJhipsterVersion() {
if (this.targetJhipsterVersion) {
this.log(`Upgrading to the target JHipster version: ${this.targetJhipsterVersion}`);
this.latestJhipsterVersion = this.targetJhipsterVersion;
return;
}
this.log(`Looking for latest ${GENERATOR_JHIPSTER} version...`);
const done = this.async();
this._retrieveLatestVersion(GENERATOR_JHIPSTER, latestVersion => {
this.latestJhipsterVersion = latestVersion;
if (semver.lt(this.currentJhipsterVersion, this.latestJhipsterVersion)) {
this.success(`New ${GENERATOR_JHIPSTER} version found: ${this.latestJhipsterVersion}`);
} else if (this.force) {
this.log(chalk.yellow('Forced re-generation'));
} else if (!this.newBlueprintVersionFound) {
this.error(`${chalk.green('No update available.')} Application has already been generated with latest version.`);
}
done();
});
},
assertGitRepository() {
const done = this.async();
const gitInit = () => {
this.gitExec('init', { silent: this.silent }, (code, msg, err) => {
if (code !== 0) this.error(`Unable to initialize a new Git repository:\n${msg} ${err}`);
this.success('Initialized a new Git repository');
this._gitCommitAll('Initial', () => {
done();
});
});
};
this.gitExec(['rev-parse', '-q', '--is-inside-work-tree'], { silent: this.silent }, (code, msg, err) => {
if (code !== 0) gitInit();
else {
this.success('Git repository detected');
done();
}
});
},
assertNoLocalChanges() {
const done = this.async();
this.gitExec(['status', '--porcelain'], { silent: this.silent }, (code, msg, err) => {
if (code !== 0) this.error(`Unable to check for local changes:\n${msg} ${err}`);
if (msg) {
this.warning(' local changes found.\n\tPlease commit/stash them before upgrading');
this.error('Exiting process');
}
done();
});
},
detectCurrentBranch() {
const done = this.async();
this.gitExec(['rev-parse', '-q', '--abbrev-ref', 'HEAD'], { silent: this.silent }, (code, msg, err) => {
if (code !== 0) this.error(`Unable to detect current Git branch:\n${msg} ${err}`);
this.sourceBranch = msg.replace('\n', '');
done();
});
},
prepareUpgradeBranch() {
const done = this.async();
const getGitVersion = callback => {
this.gitExec(['--version'], { silent: this.silent }, (code, msg) => {
callback(String(msg.match(/([0-9]+\.[0-9]+\.[0-9]+)/g)));
});
};
const recordCodeHasBeenGenerated = () => {
getGitVersion(gitVersion => {
let args;
if (semver.lt(gitVersion, GIT_VERSION_NOT_ALLOW_MERGE_UNRELATED_HISTORIES)) {
args = ['merge', '--strategy=ours', '-q', '--no-edit', UPGRADE_BRANCH];
} else {
args = ['merge', '--strategy=ours', '-q', '--no-edit', '--allow-unrelated-histories', UPGRADE_BRANCH];
}
this.gitExec(args, { silent: this.silent }, (code, msg, err) => {
if (code !== 0) {
this.error(
`Unable to record current code has been generated with version ${
this.currentJhipsterVersion
}:\n${msg} ${err}`
);
}
this.success(`Current code has been generated with version ${this.currentJhipsterVersion}`);
done();
});
});
};
const installJhipsterLocally = (version, callback) => {
this._installNpmPackageLocally(GENERATOR_JHIPSTER, version, callback);
};
const installBlueprintLocally = (version, callback) => {
if (!this.blueprint) {
this.log('Skipping local blueprint installation since no blueprint has been detected');
callback();
return;
}
this._installNpmPackageLocally(this.blueprint, version, callback);
};
const regenerate = () => {
this._cleanUp();
installJhipsterLocally(this.currentJhipsterVersion, () => {
installBlueprintLocally(this.currentBlueprintVersion, () => {
this._regenerate(this.currentJhipsterVersion, this.currentBlueprintVersion, () => {
this._gitCheckout(this.sourceBranch, () => {
// consider code up-to-date
recordCodeHasBeenGenerated();
});
});
});
});
};
const createUpgradeBranch = () => {
this.gitExec(['checkout', '--orphan', UPGRADE_BRANCH], { silent: this.silent }, (code, msg, err) => {
if (code !== 0) this.error(`Unable to create ${UPGRADE_BRANCH} branch:\n${msg} ${err}`);
this.success(`Created branch ${UPGRADE_BRANCH}`);
regenerate();
});
};
this.gitExec(['rev-parse', '-q', '--verify', UPGRADE_BRANCH], { silent: this.silent }, (code, msg, err) => {
if (code !== 0) createUpgradeBranch();
else done();
});
}
};
}
get default() {
return {
insight() {
statistics.sendSubGenEvent('generator', 'upgrade');
},
checkoutUpgradeBranch() {
const done = this.async();
this._gitCheckout(UPGRADE_BRANCH, done);
},
updateJhipster() {
const done = this.async();
this._installNpmPackageLocally(GENERATOR_JHIPSTER, this.latestJhipsterVersion, done);
},
updateBlueprint() {
if (!this.blueprint) {
this.log('Skipping blueprint update since no blueprint has been detected');
return;
}
const done = this.async();
this._installNpmPackageLocally(this.blueprint, this.latestBlueprintVersion, done);
},
generateWithLatestVersion() {
const done = this.async();
this._cleanUp();
this._regenerate(this.latestJhipsterVersion, this.latestBlueprintVersion, done);
},
checkoutSourceBranch() {
const done = this.async();
this._gitCheckout(this.sourceBranch, done);
},
mergeChangesBack() {
this.log(`Merging changes back to ${this.sourceBranch}...`);
const done = this.async();
this.gitExec(['merge', '-q', UPGRADE_BRANCH], { silent: this.silent }, (code, msg, err) => {
this.success('Merge done!');
done();
});
},
checkConflictsInPackageJson() {
const done = this.async();
this.gitExec(['diff', '--name-only', '--diff-filter=U', 'package.json'], { silent: this.silent }, (code, msg, err) => {
if (code !== 0) this.error(`Unable to check for conflicts in package.json:\n${msg} ${err}`);
if (msg) {
const installCommand = this.clientPackageManager === 'yarn' ? 'yarn' : 'npm install';
this.warning(`There are conflicts in package.json, please fix them and then run ${installCommand}`);
this.skipInstall = true;
}
done();
});
}
};
}
install() {
const done = this.async();
if (!this.skipInstall) {
this.log('Installing dependencies, please wait...');
this.info('Removing the node_modules directory');
shelljs.rm('-rf', 'node_modules');
const installCommand = this.clientPackageManager === 'yarn' ? 'yarn' : 'npm install';
this.info(installCommand);
shelljs.exec(installCommand, { silent: this.silent }, (code, msg, err) => {
if (code !== 0) {
this.error(`${installCommand} failed.`);
}
done();
});
} else {
const logMsg = `Start your Webpack development server with:\n${chalk.yellow.bold(`${this.clientPackageManager} start`)}\n`;
this.success(logMsg);
done();
}
}
end() {
const done = this.async();
this.gitExec(['diff', '--name-only', '--diff-filter=U'], { silent: this.silent }, (code, msg, err) => {
if (code !== 0) this.error(`Unable to check for conflicts:\n${msg} ${err}`);
this.success(chalk.bold('Upgraded successfully.'));
if (msg) {
this.warning(`Please fix conflicts listed below and commit!\n${msg}`);
}
done();
});
}
};