generator-begcode
Version:
Spring Boot + Angular/React/Vue in one handy generator
471 lines (470 loc) • 17.9 kB
JavaScript
import chalk from 'chalk';
import { intersection } from 'lodash-es';
import { applicationOptions, applicationTypes, authenticationTypes, cacheTypes, databaseTypes, testFrameworkTypes, } from '../../lib/jhipster/index.js';
import { R2DBC_DB_OPTIONS, SQL_DB_OPTIONS } from '../server/support/database.js';
import { asPromptingTask } from '../base-application/support/index.js';
const { OptionNames } = applicationOptions;
const { GATEWAY, MONOLITH } = applicationTypes;
const { CAFFEINE, EHCACHE, HAZELCAST, INFINISPAN, MEMCACHED, REDIS } = cacheTypes;
const { OAUTH2 } = authenticationTypes;
const { CASSANDRA, H2_DISK, H2_MEMORY, MONGODB, NEO4J, SQL, COUCHBASE } = databaseTypes;
const { WEBSOCKET, SEARCH_ENGINE, ENABLE_SWAGGER_CODEGEN } = OptionNames;
const NO_DATABASE = databaseTypes.NO;
const NO_CACHE_PROVIDER = cacheTypes.NO;
const { GATLING, CUCUMBER } = testFrameworkTypes;
export const askForServerSideOpts = asPromptingTask(async function ({ control }) {
if (control.existingProject && !this.options.askAnswered)
return;
const { applicationType, authenticationType, reactive } = this.jhipsterConfigWithDefaults;
await this.prompt([
{
type: 'list',
name: 'databaseType',
message: `Which ${chalk.yellow('*type*')} of database would you like to use?`,
choices: () => {
const opts = [];
if (!reactive) {
opts.push({
value: SQL,
name: 'SQL (H2, PostgreSQL, MySQL, MariaDB, Oracle, MSSQL)',
});
}
else {
opts.push({
value: SQL,
name: 'SQL (H2, PostgreSQL, MySQL, MariaDB, MSSQL)',
});
}
opts.push({
value: MONGODB,
name: 'MongoDB',
});
if (authenticationType !== OAUTH2) {
opts.push({
value: CASSANDRA,
name: 'Cassandra',
});
}
opts.push({
value: 'couchbase',
name: '[BETA] Couchbase',
});
opts.push({
value: NEO4J,
name: '[BETA] Neo4j',
});
opts.push({
value: NO_DATABASE,
name: 'No database',
});
return opts;
},
default: this.jhipsterConfigWithDefaults.databaseType,
},
{
when: response => response.databaseType === SQL,
type: 'list',
name: 'prodDatabaseType',
message: `Which ${chalk.yellow('*production*')} database would you like to use?`,
choices: reactive ? R2DBC_DB_OPTIONS : SQL_DB_OPTIONS,
default: this.jhipsterConfigWithDefaults.prodDatabaseType,
},
{
when: response => response.databaseType === SQL,
type: 'list',
name: 'devDatabaseType',
message: `Which ${chalk.yellow('*development*')} database would you like to use?`,
choices: response => {
const currentDatabase = SQL_DB_OPTIONS.find(it => it.value === response.prodDatabaseType);
return [
{
...currentDatabase,
name: `${currentDatabase.name} (requires Docker or manually configured database)`,
},
].concat([
{ value: H2_DISK, name: `H2 with disk-based persistence` },
{ value: H2_MEMORY, name: `H2 with in-memory persistence` },
]);
},
default: this.jhipsterConfigWithDefaults.devDatabaseType,
},
{
when: !reactive,
type: 'list',
name: 'cacheProvider',
message: 'Which cache do you want to use? (Spring cache abstraction)',
choices: [
{
value: EHCACHE,
name: 'Ehcache (local cache, for a single node)',
},
{
value: CAFFEINE,
name: 'Caffeine (local cache, for a single node)',
},
{
value: HAZELCAST,
name: 'Hazelcast (distributed cache for multiple nodes)',
},
{
value: INFINISPAN,
name: 'Infinispan (hybrid cache, for multiple nodes)',
},
{
value: MEMCACHED,
name: 'Memcached (distributed cache) - Warning, when using an SQL database, this will disable the Hibernate 2nd level cache!',
},
{
value: REDIS,
name: 'Redis (distributed cache)',
},
{
value: NO_CACHE_PROVIDER,
name: 'No cache - Warning, when using an SQL database, this will disable the Hibernate 2nd level cache!',
},
],
default: this.jhipsterConfigWithDefaults.cacheProvider,
},
{
when: answers => ((answers.cacheProvider !== NO_CACHE_PROVIDER && answers.cacheProvider !== MEMCACHED) || applicationType === GATEWAY) &&
answers.databaseType === SQL &&
!reactive,
type: 'confirm',
name: 'enableHibernateCache',
message: 'Do you want to use Hibernate 2nd level cache?',
default: this.jhipsterConfigWithDefaults.enableHibernateCache,
},
], this.config);
});
export const askForOptionalItems = asPromptingTask(async function askForOptionalItems({ control }) {
if (control.existingProject && !this.options.askAnswered)
return;
const { applicationType, reactive, databaseType, serverSideOptions = [] } = this.jhipsterConfigWithDefaults;
const choices = [];
if ([SQL, MONGODB, NEO4J].includes(databaseType)) {
choices.push({
name: 'Elasticsearch as search engine',
value: 'searchEngine:elasticsearch',
});
}
if (databaseType === COUCHBASE) {
choices.push({
name: 'Couchbase FTS as search engine',
value: 'searchEngine:couchbase',
});
}
if (!reactive) {
if (applicationType === MONOLITH || applicationType === GATEWAY) {
choices.push({
name: 'WebSockets using Spring Websocket',
value: 'websocket:spring-websocket',
});
}
}
choices.push({
name: 'Apache Kafka as asynchronous messages broker',
value: 'messageBroker:kafka',
});
choices.push({
name: 'Apache Pulsar as asynchronous messages broker',
value: 'messageBroker:pulsar',
});
choices.push({
name: 'API first development using OpenAPI-generator',
value: 'enableSwaggerCodegen:true',
});
if (choices.length > 0) {
const selectedChoices = [WEBSOCKET, SEARCH_ENGINE, 'messageBroker', ENABLE_SWAGGER_CODEGEN]
.map(property => [property, this.jhipsterConfig[property]])
.filter(([, value]) => value !== undefined)
.map(([key, value]) => `${key}:${value}`)
.filter(Boolean);
choices.forEach(choice => {
choice.checked = selectedChoices.includes(choice.value);
});
const answers = await this.prompt({
type: 'checkbox',
name: 'serverSideOptions',
message: 'Which other technologies would you like to use?',
choices,
default: selectedChoices,
});
Object.assign(this.jhipsterConfig, Object.fromEntries(answers.serverSideOptions
.map(it => it.split(':'))
.map(([key, value]) => [key, ['true', 'false'].includes(value) ? value === 'true' : value])));
}
});
export const askForServerTestOpts = asPromptingTask(async function ({ control }) {
if (control.existingProject && this.options.askAnswered !== true)
return;
const testFrameworks = this.jhipsterConfigWithDefaults.testFrameworks ?? [];
const answers = await this.prompt([
{
type: 'checkbox',
name: 'serverTestFrameworks',
message: 'Besides JUnit, which testing frameworks would you like to use?',
choices: [
{ name: 'Gatling', value: GATLING, checked: testFrameworks.includes(GATLING) },
{ name: 'Cucumber', value: CUCUMBER, checked: testFrameworks.includes(CUCUMBER) },
],
default: intersection([GATLING, CUCUMBER], this.jhipsterConfigWithDefaults.testFrameworks),
},
]);
this.jhipsterConfig.testFrameworks = [...new Set([...(this.jhipsterConfig.testFrameworks ?? []), ...answers.serverTestFrameworks])];
});
export async function askForOrmTool({ control }) {
if (control.existingProject && !this.options.askAnswered)
return;
if (this.jhipsterConfig.databaseType !== 'sql' || this.jhipsterConfig.applicationType === 'gateway' || this.jhipsterConfig.reactive) {
this.jhipsterConfig.ormTool = 'hibernate';
return;
}
const choices = [
{
value: 'mybatis',
name: 'Mybatis-Plus',
},
{
value: 'hibernate',
name: 'Hibernate',
},
];
const answers = await this.prompt([
{
type: 'list',
name: 'ormTool',
message: `Which ${chalk.yellow('OrmTools')} would you like to use for your application?`,
choices,
default: 'mybatis',
},
]);
this.jhipsterConfig.ormTool = answers.ormTool;
}
export async function askForUserIdType({ control }) {
if (control.existingProject && !this.options.askAnswered)
return;
if (OAUTH2 === this.jhipsterConfig.authenticationType && CASSANDRA === this.jhipsterConfig.databaseType) {
this.jhipsterConfig.userIdType = 'string';
return;
}
const choices = [
{
value: 'long',
name: 'Long',
},
{
value: 'string',
name: 'String',
},
{
value: 'uuid',
name: 'UUID',
},
];
const answers = await this.prompt([
{
type: 'list',
name: 'userIdType',
message: `Which ${chalk.yellow('*type*')} of user id type would you like to use?`,
choices,
default: 'long',
},
]);
this.jhipsterConfig.userIdType = answers.userIdType;
}
export async function askJobScheduler({ control }) {
this.jhipsterConfig.jobScheduler = this.jhipsterConfig.jobScheduler = 'quartz';
}
export async function askUseLombok({ control }) {
if (control.existingProject && !this.options.askAnswered) {
return;
}
const answers = await this.prompt([
{
type: 'confirm',
name: 'useLombok',
message: `Would you like to use the ${chalk.yellow('Lombok')} for your application?`,
default: true,
},
]);
this.jhipsterConfig.useLombok = answers.useLombok;
}
export async function askForIdmServicePath({ control }) {
if ((control.existingProject && !this.options.askAnswered) ||
this.jhipsterConfig.applicationType !== 'microservice' ||
(this.jhipsterConfig.applicationType === 'microservice' && this.jhipsterConfig.builtInServices?.includes('idm'))) {
if (this.jhipsterConfig.applicationType === 'microservice' && this.jhipsterConfig.builtInServices?.includes('idm')) {
this.jhipsterConfig.skipUserManagement = false;
}
return;
}
const answers = await this.prompt([
{
type: 'input',
name: 'idmServicePath',
message: `Please input ${chalk.yellow('idm service')} project path ?`,
default: '../system/',
validate: (input) => (input.length === 0 ? 'Please enter your idm service path' : true),
},
]);
this.jhipsterConfig.skipUserManagement = true;
this.jhipsterConfig.idmServicePath = answers.idmServicePath;
}
export async function askForSoftDelete({ control }) {
if (control.existingProject && this.options.askAnswered !== true)
return;
await this.prompt({
type: 'confirm',
name: 'softDelete',
message: `Would you like to use the ${chalk.yellow('SOFT_DELETE')} for your application?`,
default: false,
}, this.config);
}
export async function askFrontOrBack({ control }) {
if (control.existingProject && this.options.askAnswered !== true)
return;
if (control.existingProject) {
this.jhipsterConfig.frontOrBack = this.config.get('frontOrBack') || ['front', 'back'];
return;
}
const config = this.jhipsterConfigWithDefaults;
const choices = ['back', 'front'];
choices.push(...(config.frontOrBack || []));
if (config.applicationType === 'commonmodule' || config.applicationType === 'microservice') {
choices.splice(choices.indexOf('front'), 1);
}
if (config.applicationType === 'monolith' && config.skipServer) {
choices.splice(choices.indexOf('back'), 1);
}
if (config.applicationType === 'monolith' && config.skipClient) {
choices.splice(choices.indexOf('front'), 1);
}
if (config.applicationType === 'gateway' && config.skipClient) {
choices.splice(choices.indexOf('front'), 1);
}
if (config.applicationType === 'gateway' && config.skipServer) {
choices.splice(choices.indexOf('back'), 1);
}
const choicesData = [
{
value: 'all',
name: 'All',
},
{
value: 'front',
name: 'Front End',
},
{
value: 'back',
name: 'Back End',
},
{
value: 'mobile',
name: 'Mobile End',
},
];
const answer = await this.prompt([
{
when: () => choices.length > 1,
type: 'checkbox',
name: 'frontOrBack',
message: `Which ${chalk.yellow('Front Or Back End')} would you like to use for your application?`,
choices: choicesData.filter(choice => choices.includes(choice.value)),
default: choices,
},
]);
if (choices.length > 1) {
this.jhipsterConfig.frontOrBack = answer.frontOrBack;
}
else {
this.jhipsterConfig.frontOrBack = choices;
}
if (!this.jhipsterConfig.frontOrBack.includes('front')) {
this.jhipsterConfig.skipClient = true;
this.jhipsterConfig.clientFramework = 'no';
}
if (!this.jhipsterConfig.frontOrBack.includes('mobile')) {
this.jhipsterConfig.skipMobile = true;
this.jhipsterConfig.mobileTheme = 'no';
}
if (!this.jhipsterConfig.frontOrBack.includes('back')) {
this.jhipsterConfig.skipServer = true;
}
}
export async function askUseMultiTenant({ control }) {
if (control.existingProject && this.options.askAnswered !== true)
return;
const config = this.jhipsterConfigWithDefaults;
if (config.applicationType === 'gateway') {
this.jhipsterConfig.useMultiTenant = false;
return;
}
const answers = await this.prompt([
{
type: 'confirm',
name: 'useMultiTenant',
message: `Would you like to use the ${chalk.yellow('Use Multi-Tenant')} for your application?`,
default: false,
},
]);
this.jhipsterConfig.useMultiTenant = answers.useMultiTenant;
}
export async function askBuiltInServices({ control }) {
if (control.existingProject && this.options.askAnswered !== true)
return;
const config = this.jhipsterConfigWithDefaults;
if (config.applicationType === 'monolith' || config.applicationType === 'gateway') {
return;
}
const choices = [];
const defaultChoice = [];
defaultChoice.push('idm');
choices.push({
name: 'User Center',
value: 'idm',
});
defaultChoice.push('oss', 'log');
choices.push({
name: 'Object Storage Service',
value: 'oss',
});
choices.push({
name: 'Log Service',
value: 'log',
});
choices.push({
name: 'Report',
value: 'report',
});
const answers = await this.prompt([
{
type: 'checkbox',
name: 'builtInServices',
message: 'Which other services would you like to use?',
choices,
default: defaultChoice,
},
]);
this.jhipsterConfig.builtInServices = answers.builtInServices;
}
export async function askForMobileTheme({ control }) {
if (control.existingProject && !this.options.askAnswered)
return;
const config = this.jhipsterConfigWithDefaults;
if (config.skipMobile && !config.frontOrBack.includes('mobile'))
return;
const mobileThemes = [...(config.mobileThemes || [])].map(theme => theme.value);
const mobileThemeChoices = [...(config.mobileThemes || [])];
config.mobileThemes?.splice(0);
const answer = await this.prompt([
{
type: 'checkbox',
name: 'mobileThemes',
when: () => !this.jhipsterConfig.skipMobile && mobileThemeChoices.length > 0,
message: 'Would you like to use a Mobile App framework?',
choices: () => mobileThemeChoices,
default: mobileThemes,
},
]);
this.jhipsterConfig.mobileThemes = answer.mobileThemes;
}