gen-jhipster
Version:
Spring Boot + Angular/React/Vue in one handy generator
346 lines (345 loc) • 15.8 kB
JavaScript
/**
* Copyright 2013-2024 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 _ from 'lodash';
import BaseApplicationGenerator from '../base-application/index.js';
import writeGrpcFilesTask from './files.js';
import writeEntitiesTasks, { cleanupEntitiesTask } from './entity-files.js';
export default class GrpcGenerator extends BaseApplicationGenerator {
async beforeQueue() {
if (!this.fromBlueprint) {
await this.composeWithBlueprints();
}
if (!this.delegateToBlueprint) {
await this.dependsOnBootstrapApplication();
}
}
get initializing() {
return this.asInitializingTaskGroup({
async loadConfig() {
// Load gRPC config
const config = this.jhipsterConfigWithDefaults;
this.grpcConfig = {
grpcEnabled: config.grpcEnabled,
grpcPort: config.grpcPort,
grpcSecured: config.grpcSecured,
grpcUseSsl: config.grpcUseSsl,
grpcCertificatePath: config.grpcCertificatePath,
grpcPrivateKeyPath: config.grpcPrivateKeyPath,
};
this.enableGrpc = this.jhipsterConfig.enableGrpc;
},
});
}
get [BaseApplicationGenerator.INITIALIZING]() {
return this.delegateTasksToBlueprint(() => this.initializing);
}
get prompting() {
return this.asPromptingTaskGroup({
async showPrompts() {
if (!this.enableGrpc) {
await this.prompt([
{
type: 'confirm',
name: 'enableGrpc',
message: 'Do you want to enable gRPC integration?',
default: this.jhipsterConfigWithDefaults.enableGrpc,
},
{
when: response => response.enableGrpc,
type: 'input',
name: 'grpcPort',
message: 'Which port would you like gRPC to listen on?',
default: this.jhipsterConfigWithDefaults.grpcPort,
validate: (input) => {
if (/^\d+$/.test(input)) {
const port = parseInt(input, 10);
if (port > 0 && port < 65536)
return true;
}
return 'Please enter a valid port number between 1 and 65535';
},
},
], this.config);
// interface GrpcAnswers {
// grpcEnabled: boolean;
// grpcPort?: string;
// grpcSecured?: boolean;
// grpcUseSsl?: boolean;
// }
//
// const answers: GrpcAnswers = await this.prompt([
// {
// type: 'confirm',
// name: 'enableGrpc',
// message: 'Do you want to enable gRPC integration? (true)',
// default: true,
// },
// ]);
//
// if (answers.grpcEnabled) {
// const portAnswer = await this.prompt([
// {
// type: 'input',
// name: 'grpcPort',
// message: 'Which port would you like gRPC to listen on?',
// default: (this.grpcConfig.grpcPort ?? 9090).toString(),
// validate: (input: string) => {
// if (/^\d+$/.test(input)) {
// const port = parseInt(input, 10);
// if (port > 0 && port < 65536) return true;
// }
// return 'Please enter a valid port number between 1 and 65535';
// },
// },
// ]);
// const securityAnswers = await this.prompt([
// {
// type: 'confirm',
// name: 'grpcSecured',
// message: 'Do you want to secure your gRPC services with JWT authentication?',
// default: this.grpcConfig.grpcSecured ?? true,
// },
// {
// type: 'confirm',
// name: 'grpcUseSsl',
// message: 'Do you want to enable SSL/TLS for gRPC connections?',
// default: this.grpcConfig.grpcUseSsl ?? false,
// },
// ]);
// Object.assign(answers, portAnswer);
// }
//
// const newConfig = {
// ...this.grpcConfig,
// grpcEnabled: answers.grpcEnabled,
// grpcPort: answers.grpcPort,
// };
//
// if (answers.grpcPort) {
// newConfig.grpcPort = parseInt(answers.grpcPort, 10);
// }
//
// this.grpcConfig = newConfig;
}
},
});
}
get [BaseApplicationGenerator.PROMPTING]() {
return this.delegateTasksToBlueprint(() => this.prompting);
}
get preparing() {
return this.asPreparingTaskGroup({
async preparing({ application }) {
const anyApp = application;
},
});
}
get [BaseApplicationGenerator.PREPARING]() {
return this.delegateTasksToBlueprint(() => this.preparing);
}
get preparingEachEntity() {
return this.asPreparingEachEntityTaskGroup({
prepareEntity({ application, entity }) {
if (this.enableGrpc) {
entity.fields.forEach(field => {
if (field.fieldTypeBlobContent === 'text') {
field.fieldDomainType = 'String';
}
else {
field.fieldDomainType = field.fieldType;
}
field.fieldTypeUpperUnderscored = _.snakeCase(field.fieldType).toUpperCase();
field.fieldProtobufType = getProtobufType(field.fieldDomainType);
field.isProtobufCustomType = isProtobufCustomType(field.fieldProtobufType);
});
this.isFilterableType = function (fieldType) {
return !['byte[]', 'ByteBuffer'].includes(fieldType);
};
}
},
});
}
get [BaseApplicationGenerator.PREPARING_EACH_ENTITY]() {
return this.delegateTasksToBlueprint(() => this.preparingEachEntity);
}
get preparingEachEntityRelationship() {
return this.asPreparingEachEntityRelationshipTaskGroup({
prepareRelationship({ application, relationship }) {
if (this.enableGrpc) {
relationship.relationshipNameUnderscored = _.snakeCase(relationship.relationshipName).toLowerCase();
relationship.otherEntityNameUnderscored = _.snakeCase(relationship.otherEntityName).toLowerCase();
relationship.otherEntityFieldUnderscored = _.snakeCase(relationship.otherEntityField).toLowerCase();
if (relationship.otherEntityNameCapitalized === 'User') {
relationship.otherEntityProtobufType = `${application.packageName}.UserProto`;
relationship.otherEntityProtoMapper = `${application.packageName}.grpc.UserProtoMapper`;
relationship.otherEntityTest = `${application.packageName}.grpc.UserGrpcServiceIntTest`;
relationship.otherEntityProtobufFile = `${application.packageFolder}user.proto`;
}
else {
relationship.otherEntityProtobufType = `${application.packageName}.entity.${relationship.otherEntityNameCapitalized}Proto`;
relationship.otherEntityProtoMapper = `${application.packageName}.grpc.entity.${relationship.otherEntityNameUnderscored}.${relationship.otherEntityNameCapitalized}ProtoMapper`;
relationship.otherEntityTest = `${application.packageName}.grpc.entity.${relationship.otherEntityNameUnderscored}.${relationship.otherEntityNameCapitalized}GrpcServiceIntTest`;
relationship.otherEntityProtobufFile = `${application.packageFolder}/entity/${relationship.otherEntityNameUnderscored}.proto`;
}
}
},
});
}
get [BaseApplicationGenerator.PREPARING_EACH_ENTITY_RELATIONSHIP]() {
return this.delegateTasksToBlueprint(() => this.preparingEachEntityRelationship);
}
get writing() {
return {
writeGrpcFilesTask,
};
}
get [BaseApplicationGenerator.WRITING]() {
return this.delegateTasksToBlueprint(() => this.writing);
}
get writingEntities() {
return {
cleanupEntitiesTask,
writeEntitiesTasks,
};
}
get [BaseApplicationGenerator.WRITING_ENTITIES]() {
return this.delegateTasksToBlueprint(() => this.writingEntities);
}
get postWriting() {
return this.asPostWritingTaskGroup({
addDependencies({ source, application }) {
source.addJavaDependencies?.([
{ groupId: 'net.devh', artifactId: 'grpc-spring-boot-starter', version: '3.1.0.RELEASE' },
{ groupId: 'javax.annotation', artifactId: 'javax.annotation-api', version: '1.3.2' },
{ groupId: 'build.buf', artifactId: 'protovalidate', version: '0.5.0' },
]);
if (application.reactive) {
source.addJavaDependencies?.([
{ groupId: 'com.salesforce.servicelibs', artifactId: 'reactor-grpc-stub', version: '1.2.4' }
]);
}
},
addPlugins({ source, application }) {
if (this.jhipsterConfig.buildTool === 'maven') {
if (application.reactive) {
source.addMavenPlugin?.({
groupId: 'org.xolstice.maven.plugins',
artifactId: 'protobuf-maven-plugin',
version: '0.6.1',
additionalContent: `
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.23.4:exe:\${os.detected.classifier}
</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.58.0:exe:\${os.detected.classifier}
</pluginArtifact>
<useArgumentFile>true</useArgumentFile>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
<configuration>
<protocPlugins>
<protocPlugin>
<id>reactor-grpc</id>
<groupId>com.salesforce.servicelibs</groupId>
<artifactId>reactor-grpc</artifactId>
<version>1.2.4</version>
<mainClass>com.salesforce.reactorgrpc.ReactorGrpcGenerator</mainClass>
</protocPlugin>
</protocPlugins>
</configuration>
</execution>
</executions>`,
});
}
else {
source.addMavenPlugin?.({
groupId: 'org.xolstice.maven.plugins',
artifactId: 'protobuf-maven-plugin',
version: '0.6.1',
additionalContent: `
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.23.4:exe:\${os.detected.classifier}
</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.58.0:exe:\${os.detected.classifier}
</pluginArtifact>
<useArgumentFile>true</useArgumentFile>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</configuration>
</execution>
</executions>`,
});
}
source.addMavenExtension?.({
groupId: 'kr.motd.maven',
artifactId: 'os-maven-plugin',
version: '1.7.0',
});
}
},
});
}
get [BaseApplicationGenerator.POST_WRITING]() {
return this.delegateTasksToBlueprint(() => this.postWriting);
}
}
function getProtobufType(type) {
switch (type) {
case 'String':
case 'Float':
case 'Double':
return type.toLowerCase();
case 'Integer':
return 'int32';
case 'Long':
return 'int64';
case 'Boolean':
return 'bool';
case 'Instant':
case 'OffsetDateTime':
case 'ZonedDateTime':
return 'google.protobuf.Timestamp';
case 'LocalDate':
return 'util.Date';
case 'BigDecimal':
return 'util.Decimal';
case 'byte[]':
case 'ByteBuffer':
return 'bytes';
case 'UUID':
return 'string';
default:
// It's an enum
return `${type}Proto`;
}
}
function isProtobufCustomType(type) {
return type.startsWith('google') || type.startsWith('util');
}