UNPKG

gen-jhipster

Version:

VHipster - Spring Boot + Angular/React/Vue in one handy generator

275 lines (274 loc) 11.7 kB
/** * Copyright 2013-2026 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 * * https://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. */ import chalk from 'chalk'; import { intersection } from 'lodash-es'; import { APPLICATION_TYPE_GATEWAY, APPLICATION_TYPE_MONOLITH } from "../../lib/core/application-types.js"; import { applicationOptions, authenticationTypes, cacheTypes, databaseTypes, testFrameworkTypes } from "../../lib/jhipster/index.js"; import { asPromptingTask } from "../base-application/support/task-type-inference.js"; import { R2DBC_DB_OPTIONS, SQL_DB_OPTIONS } from "../server/support/database.js"; const { OptionNames } = applicationOptions; 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; const config = this.jhipsterConfigWithDefaults; await this.prompt([ { type: 'confirm', name: 'enableGrpc', message: `Do you want to enable ${chalk.yellow('gRPC')} integration?`, default: config.enableGrpc ?? true, }, { when: (response) => response.enableGrpc === true, type: 'input', name: 'grpcPort', message: 'Which port would you like gRPC to listen on?', default: config.grpcPort ?? '9090', validate: (input) => (/^\d+$/.test(input) ? true : 'Please enter a valid port number'), }, { type: 'select', 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: 'select', 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: 'select', 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, }, ].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: 'select', 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 === APPLICATION_TYPE_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); }); /** APISIX, testing - asked before database/cache. gRPC and grpcPort are in askForServerSideOpts (same prompt as database). */ export const askForVhipsterOpts = asPromptingTask(async function askForVhipsterOpts({ control }) { if (control.existingProject && !this.options.askAnswered) return; const config = this.jhipsterConfigWithDefaults; const testFrameworks = config.testFrameworks ?? []; const answers = await this.prompt([ { type: 'confirm', name: 'syncRoutesWithApisix', message: 'Will you use APISIX for Gateway? If you use it, do you wanna sync routes to APISIX?', default: config.syncRoutesWithApisix ?? false, }, { 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], testFrameworks), }, ], this.config); this.jhipsterConfig.testFrameworks = [ ...new Set([...(this.jhipsterConfig.testFrameworks ?? []), ...(answers.serverTestFrameworks ?? [])]), ]; }); /** allowVauthzUserRelationship - asked after "other technologies" */ export const askForVhipsterOpts2 = asPromptingTask(async function askForVhipsterOpts2({ control }) { if (control.existingProject && !this.options.askAnswered) return; const config = this.jhipsterConfigWithDefaults; await this.prompt([ { when: () => config.vauthz === true, type: 'confirm', name: 'allowVauthzUserRelationship', message: 'Do you want to allow User relationship in Vauthz?', default: config.allowVauthzUserRelationship ?? true, }, ], this.config); }); export const askForOptionalItems = asPromptingTask(async function askForOptionalItems({ control }) { if (control.existingProject && !this.options.askAnswered) return; const { applicationType, reactive, databaseType } = 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 === APPLICATION_TYPE_MONOLITH || applicationType === APPLICATION_TYPE_GATEWAY) { choices.push({ name: 'WebSockets using Spring Websocket', value: 'websocket:spring-websocket', }); } } choices.push({ name: 'Apache Kafka as asynchronous messages broker', value: 'messageBroker:kafka', }, { name: 'Apache Pulsar as asynchronous messages broker', value: 'messageBroker:pulsar', }, { name: 'API first development using OpenAPI-generator', value: 'enableSwaggerCodegen:true', }, { name: 'VAuthz - Robust Authorization as a Services, support RBAC, ABAC, ReBAC', value: 'vauthz:true', }); if (choices.length > 0) { const selectedChoices = [WEBSOCKET, SEARCH_ENGINE, 'messageBroker', ENABLE_SWAGGER_CODEGEN, 'vauthz'] .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]))); } });