UNPKG

gen-jhipster

Version:

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

282 lines (281 loc) 12.6 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 * as _ from 'lodash-es'; import BaseApplicationGenerator from "../base-application/index.js"; import writeEntitiesTasks, { cleanupEntitiesTask } from "./entity-files.js"; import writeGrpcFilesTask from "./files.js"; export default class GrpcGenerator extends BaseApplicationGenerator { grpcConfig; enableGrpc; async beforeQueue() { if (!this.fromBlueprint) { await this.composeWithBlueprints(); } if (!this.delegateToBlueprint) { await this.dependsOnBootstrapApplication(); } } get initializing() { return this.asInitializingTaskGroup({ async loadConfig() { const config = this.jhipsterConfigWithDefaults; const grpcEnabled = Boolean(config.enableGrpc ?? config.grpcEnabled); this.grpcConfig = { grpcEnabled, grpcPort: config.grpcPort, grpcSecured: config.grpcSecured, grpcUseSsl: config.grpcUseSsl, grpcCertificatePath: config.grpcCertificatePath, grpcPrivateKeyPath: config.grpcPrivateKeyPath, }; // Must match jhipsterConfigWithDefaults (same as entity-files writing), not raw jhipsterConfig only. // Otherwise when enableGrpc is omitted from .yo-rc.json, defaults turn it on for writes but // preparingEachEntity skips and fieldProtobufType is never set → invalid proto ("optional id = 1"). this.enableGrpc = grpcEnabled; }, }); } get [BaseApplicationGenerator.INITIALIZING]() { return this.delegateTasksToBlueprint(() => this.initializing); } get prompting() { return this.asPromptingTaskGroup({ async showPrompts() { // gRPC prompts handled in spring-boot askForVhipsterOpts for correct prompt order }, }); } get [BaseApplicationGenerator.PROMPTING]() { return this.delegateTasksToBlueprint(() => this.prompting); } get preparing() { return this.asPreparingTaskGroup({ async preparing() { // gRPC-specific preparing if needed }, }); } get [BaseApplicationGenerator.PREPARING]() { return this.delegateTasksToBlueprint(() => this.preparing); } get preparingEachEntity() { return this.asPreparingEachEntityTaskGroup({ prepareEntity({ entity }) { if (this.enableGrpc && entity.fields) { for (const field of entity.fields) { const f = field; if (f.fieldTypeBlobContent === 'text') { f.fieldDomainType = 'String'; } else { f.fieldDomainType = f.fieldType; } f.fieldTypeUpperUnderscored = _.snakeCase(String(f.fieldType)).toUpperCase(); f.fieldProtobufType = getProtobufType(String(f.fieldDomainType)); f.isProtobufCustomType = isProtobufCustomType(String(f.fieldProtobufType)); } entity.isFilterableType = (fieldType) => !['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) { const rel = relationship; const otherEntityNameCapitalized = _.upperFirst(relationship.otherEntityName); const otherEntityNameUnderscored = _.snakeCase(relationship.otherEntityName).toLowerCase(); const otherEntityFieldUnderscored = relationship.otherEntityField ? _.snakeCase(relationship.otherEntityField).toLowerCase() : ''; rel.relationshipNameUnderscored = _.snakeCase(relationship.relationshipName).toLowerCase(); rel.otherEntityNameUnderscored = otherEntityNameUnderscored; rel.otherEntityFieldUnderscored = otherEntityFieldUnderscored; rel.otherEntityNameCapitalized = otherEntityNameCapitalized; if (otherEntityNameCapitalized === 'User') { rel.otherEntityProtobufType = 'entity.UserProto'; rel.otherEntityProtoMapper = `${application.packageName}.web.grpc.mapper.UserProtoMapper`; rel.otherEntityTest = `${application.packageName}.web.grpc.service.UserGrpcServiceIntTest`; rel.otherEntityProtobufFile = 'entity/user.proto'; } else { rel.otherEntityProtobufType = `entity.${otherEntityNameCapitalized}Proto`; rel.otherEntityProtoMapper = `${application.packageName}.web.grpc.mapper.${otherEntityNameCapitalized}ProtoMapper`; rel.otherEntityTest = `${application.packageName}.web.grpc.service.${otherEntityNameCapitalized}GrpcServiceIntTest`; rel.otherEntityProtobufFile = `entity/${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' || application.buildToolMaven) { 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.addMavenPlugin?.({ groupId: 'kr.motd.maven', artifactId: 'os-maven-plugin', version: '1.7.1', additionalContent: ` <executions> <execution> <phase>initialize</phase> <goals> <goal>detect</goal> </goals> </execution> </executions>`, }); } }, }); } 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': case 'LocalDateTime': case 'Date': 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'); }