gen-jhipster
Version:
VHipster - Spring Boot + Angular/React/Vue in one handy generator
246 lines (245 loc) • 11.8 kB
JavaScript
/**
* 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 { clientFrameworkTypes, testFrameworkTypes } from "../../lib/jhipster/index.js";
import BaseApplicationGenerator from "../base-application/index.js";
import { createNeedleCallback } from "../base-core/support/index.js";
import { isReservedTypescriptKeyword } from "../javascript-simple-application/support/reserved-words.js";
import { addEnumerationFiles } from "./entity-files.js";
import { writeFiles as writeCommonFiles } from "./files-common.js";
import { askForClientTheme, askForClientThemeVariant } from "./prompts.js";
import { filterEntitiesAndPropertiesForClient } from "./support/filter-entities.js";
const { ANGULAR, NO: CLIENT_FRAMEWORK_NO } = clientFrameworkTypes;
const { CYPRESS } = testFrameworkTypes;
export class ClientApplicationGenerator extends BaseApplicationGenerator {
}
export default class ClientGenerator extends ClientApplicationGenerator {
constructor(args, options, features) {
super(args, options, { skipLoadCommand: true, ...features });
}
async beforeQueue() {
if (!this.fromBlueprint) {
await this.composeWithBlueprints();
}
if (!this.delegateToBlueprint) {
await this.dependsOnBootstrap('client');
await this.dependsOnJHipster('common');
}
}
get prompting() {
return this.asPromptingTaskGroup({
askForClientTheme,
askForClientThemeVariant,
});
}
get [ClientApplicationGenerator.PROMPTING]() {
return this.delegateTasksToBlueprint(() => this.prompting);
}
get configuring() {
return this.asConfiguringTaskGroup({
applyNoFramework() {
const { clientFramework } = this.jhipsterConfigWithDefaults;
if (clientFramework === CLIENT_FRAMEWORK_NO) {
this.jhipsterConfig.skipClient = true;
this.cancelCancellableTasks();
}
},
mergeTestConfig() {
if (this.jhipsterConfig.clientTestFrameworks) {
this.jhipsterConfig.testFrameworks = [
...new Set([...(this.jhipsterConfig.testFrameworks ?? []), ...this.jhipsterConfig.clientTestFrameworks]),
];
delete this.jhipsterConfig.clientTestFrameworks;
}
},
upgradeAngular() {
if (this.jhipsterConfig.clientFramework === 'angularX') {
this.jhipsterConfig.clientFramework = ANGULAR;
}
},
configureDevServerPort() {
if (this.jhipsterConfig.devServerPort !== undefined || this.jhipsterConfig.applicationIndex === undefined)
return;
const { applicationIndex, devServerPort } = this.jhipsterConfigWithDefaults;
this.jhipsterConfig.devServerPort = devServerPort + applicationIndex;
},
});
}
get [ClientApplicationGenerator.CONFIGURING]() {
return this.delegateTasksToBlueprint(() => this.configuring);
}
get composing() {
return this.asComposingTaskGroup({
async composing() {
const { clientFramework, testFrameworks } = this.jhipsterConfigWithDefaults;
if (['angular', 'react', 'vue'].includes(clientFramework)) {
await this.composeWithJHipster(clientFramework);
}
if (Array.isArray(testFrameworks) && testFrameworks.includes(CYPRESS)) {
await this.composeWithJHipster('cypress');
}
},
});
}
get [ClientApplicationGenerator.COMPOSING]() {
return this.delegateTasksToBlueprint(() => this.composing);
}
get preparing() {
return this.asPreparingTaskGroup({
loadPackageJson({ application }) {
// Load common client package.json into packageJson
this.loadNodeDependenciesFromPackageJson(application.nodeDependencies, this.fetchFromInstalledJHipster('client', 'resources', 'package.json'));
},
addExternalResource({ application, source }) {
if (!application.clientFrameworkBuiltIn) {
return;
}
source.addExternalResourceToRoot = ({ resource, comment }) => this.editFile(`${application.clientSrcDir}index.html`, createNeedleCallback({
needle: 'add-resources-to-root',
contentToAdd: [comment ? `<!-- ${comment} -->` : undefined, resource].filter(i => i).join('\n'),
}));
},
});
}
get [ClientApplicationGenerator.PREPARING]() {
return this.delegateTasksToBlueprint(() => this.preparing);
}
get preparingEachEntity() {
return this.asPreparingEachEntityTaskGroup({
preparing({ entityName }) {
if (isReservedTypescriptKeyword(entityName)) {
throw new Error(`The entity name "${entityName}" is a reserved TypeScript keyword. It may cause issues in your application.`);
}
},
});
}
get [ClientApplicationGenerator.PREPARING_EACH_ENTITY]() {
return this.delegateTasksToBlueprint(() => this.preparingEachEntity);
}
get preparingEachEntityField() {
return this.asPreparingEachEntityFieldTaskGroup({
preparing({ entity, field }) {
if (isReservedTypescriptKeyword(field.fieldName)) {
throw new Error(`The field name "${field.fieldName}" in entity "${entity.name}" is a reserved TypeScript keyword.`);
}
},
});
}
get [ClientApplicationGenerator.PREPARING_EACH_ENTITY_FIELD]() {
return this.delegateTasksToBlueprint(() => this.preparingEachEntityField);
}
get preparingEachEntityRelationship() {
return this.asPreparingEachEntityRelationshipTaskGroup({
preparing({ entity, relationship }) {
if (isReservedTypescriptKeyword(relationship.relationshipName)) {
throw new Error(`The relationship name "${relationship.relationshipName}" in entity "${entity.name}" is a reserved TypeScript keyword.`);
}
},
});
}
get [ClientApplicationGenerator.PREPARING_EACH_ENTITY_RELATIONSHIP]() {
return this.delegateTasksToBlueprint(() => this.preparingEachEntityRelationship);
}
get writing() {
return this.asWritingTaskGroup({
async cleanup({ application, control }) {
await control.cleanupFiles({
'8.7.4': [`${application.clientSrcDir}swagger-ui/dist/images/throbber.gif`],
});
},
webappFakeDataSeed({ application: { clientFramework } }) {
this.resetEntitiesFakeData(clientFramework);
},
writeCommonFiles,
});
}
get [ClientApplicationGenerator.WRITING]() {
return this.delegateTasksToBlueprint(() => this.writing);
}
get writingEntities() {
return this.asWritingEntitiesTaskGroup({
async writeEnumerationFiles({ application, entities }) {
if (!application.webappEnumerationsDir || !application.clientFrameworkBuiltIn) {
return;
}
for (const entity of (application.filterEntitiesAndPropertiesForClient ?? filterEntitiesAndPropertiesForClient)(entities)) {
await addEnumerationFiles.call(this, { application, entity });
}
},
});
}
get [ClientApplicationGenerator.WRITING_ENTITIES]() {
return this.delegateTasksToBlueprint(() => this.writingEntities);
}
get postWriting() {
return this.asPostWritingTaskGroup({
packageJsonScripts({ application }) {
if (!application.clientFrameworkBuiltIn) {
return;
}
const packageJsonStorage = this.createStorage(this.destinationPath(application.clientRootDir, 'package.json'));
const scriptsStorage = packageJsonStorage.createStorage('scripts');
const devDependencies = packageJsonStorage.createStorage('devDependencies');
devDependencies.set('wait-on', application.nodeDependencies['wait-on']);
devDependencies.set('concurrently', application.nodeDependencies.concurrently);
if (application.clientFrameworkReact) {
scriptsStorage.set('ci:frontend:test', 'npm run webapp:build:$npm_package_config_default_environment && npm run test');
}
else {
scriptsStorage.set('ci:frontend:build', 'npm run webapp:build:$npm_package_config_default_environment');
scriptsStorage.set('ci:frontend:test', 'npm run ci:frontend:build && npm test');
}
if (application.clientRootDir) {
// Add scripts to map to client package.json
this.packageJson.merge({
scripts: {
'webapp:build': `npm run -w ${application.clientRootDir} webapp:build`,
'ci:frontend:test': `npm run -w ${application.clientRootDir} ci:frontend:test`,
},
});
const clientWorkspace = application.clientRootDir.slice(0, -1);
const packageJson = this.packageJson.createProxy();
const workspaces = packageJson.workspaces;
if (!workspaces?.includes(clientWorkspace)) {
packageJson.workspaces = [...(workspaces ?? []), clientWorkspace];
}
}
},
microfrontend({ application, source }) {
if (!application.microfrontend || !application.clientFrameworkBuiltIn || !application.clientBundlerWebpack) {
return;
}
if (application.clientFrameworkAngular) {
const conditional = application.applicationTypeMicroservice ? "targetOptions.target === 'serve' ? {} : " : '';
source.addWebpackConfig({
config: `${conditional}require('./webpack.microfrontend')(config, options, targetOptions)`,
});
}
else if (application.clientFrameworkVue || application.clientFrameworkReact) {
source.addWebpackConfig({ config: "require('./webpack.microfrontend')({ serve: options.env.WEBPACK_SERVE })" });
}
else {
throw new Error(`Client framework ${application.clientFramework} doesn't support microfrontends`);
}
},
});
}
get [ClientApplicationGenerator.POST_WRITING]() {
return this.delegateTasksToBlueprint(() => this.postWriting);
}
}