| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- package swagger_api
- import (
- "context"
- "fmt"
- "git.ikuban.com/server/swagger-api/v2/generator"
- "github.com/go-kratos/kratos/v2/api/metadata"
- "github.com/xmkuban/utils/utils"
- "google.golang.org/protobuf/compiler/protogen"
- "google.golang.org/protobuf/types/descriptorpb"
- "google.golang.org/protobuf/types/pluginpb"
- )
- // Service is service
- type Service struct {
- ser *Server
- }
- // New service
- func New(skipError bool) *Service {
- return &Service{
- ser: NewServer(nil, skipError),
- }
- }
- // ListServices list services
- func (s *Service) ListServices(ctx context.Context, in *metadata.ListServicesRequest) (*metadata.ListServicesReply, error) {
- return s.ser.ListServices(ctx, &metadata.ListServicesRequest{})
- }
- // GetServiceOpenAPI get service open api
- func (s *Service) GetServiceOpenAPI(ctx context.Context, in *metadata.GetServiceDescRequest) (string, error) {
- protoSet, err := s.ser.GetServiceDesc(ctx, in)
- if err != nil {
- return "", err
- }
- files := protoSet.FileDescSet.File
- newFiles := make([]*descriptorpb.FileDescriptorProto, 0)
- newFileMap := make(map[string]byte)
- for _, v := range files {
- if _, ok := newFileMap[v.GetName()]; !ok {
- newFiles = append(newFiles, v)
- newFileMap[v.GetName()] = 1
- }
- }
- files = newFiles
- var target string
- if len(files) == 0 {
- return "", fmt.Errorf("proto file is empty")
- }
- if files[len(files)-1].Name == nil {
- return "", fmt.Errorf("proto file's name is null")
- }
- target = files[len(files)-1].GetName()
- req := new(pluginpb.CodeGeneratorRequest)
- req.FileToGenerate = []string{target}
- var para = ""
- req.Parameter = ¶
- req.ProtoFile = files
- opts := protogen.Options{}
- plugin, err := opts.New(req)
- if err != nil {
- return "", err
- }
- plugin.SupportedFeatures = uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL)
- var content []byte
- gen := generator.NewOpenAPIv3Generator(plugin, generator.Configuration{
- Version: utils.ToPointString("1.0"),
- Title: utils.ToPointString(""),
- Description: utils.ToPointString(""),
- Naming: utils.ToPointString("proto"),
- FQSchemaNaming: utils.ToPointBool(true),
- EnumType: utils.ToPointString("integer"),
- CircularDepth: utils.ToPointInt(2),
- DefaultResponse: utils.ToPointBool(false),
- OutputMode: utils.ToPointString("merged"),
- }, plugin.Files)
- content, err = gen.RunV2()
- if err != nil {
- return "", err
- }
- return string(content), nil
- }
- // GetAllServicesOpenAPI get all services merged into one openapi document
- // servicesList: specific services to include, pass nil or empty slice to include all services
- // title: the title for the merged API document
- // description: the description for the merged API document
- func (s *Service) GetAllServicesOpenAPI(ctx context.Context, servicesList []string, title, description string) (string, error) {
- // Determine which services to process
- var servicesToProcess []string
- if len(servicesList) > 0 {
- // Use the specified services list
- servicesToProcess = servicesList
- } else {
- // Get all services if no list specified
- allServices, err := s.ser.ListServices(ctx, &metadata.ListServicesRequest{})
- if err != nil {
- return "", err
- }
- servicesToProcess = allServices.Services
- }
- if len(servicesToProcess) == 0 {
- return "", fmt.Errorf("no services found")
- }
- // Collect all proto files from specified services
- allFiles := make([]*descriptorpb.FileDescriptorProto, 0)
- fileMap := make(map[string]byte)
- filesToGenerate := make([]string, 0)
- for _, serviceName := range servicesToProcess {
- protoSet, err := s.ser.GetServiceDesc(ctx, &metadata.GetServiceDescRequest{Name: serviceName})
- if err != nil {
- // Skip services that fail to load
- continue
- }
- for _, file := range protoSet.FileDescSet.File {
- if _, ok := fileMap[file.GetName()]; !ok {
- allFiles = append(allFiles, file)
- fileMap[file.GetName()] = 1
- // Add files that contain services to the generation list
- if len(file.Service) > 0 {
- filesToGenerate = append(filesToGenerate, file.GetName())
- }
- }
- }
- }
- if len(allFiles) == 0 {
- return "", fmt.Errorf("no proto files found")
- }
- if len(filesToGenerate) == 0 {
- return "", fmt.Errorf("no service files found")
- }
- // Create code generator request
- req := new(pluginpb.CodeGeneratorRequest)
- req.FileToGenerate = filesToGenerate
- var para = ""
- req.Parameter = ¶
- req.ProtoFile = allFiles
- opts := protogen.Options{}
- plugin, err := opts.New(req)
- if err != nil {
- return "", err
- }
- plugin.SupportedFeatures = uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL)
- // Generate merged OpenAPI document
- gen := generator.NewOpenAPIv3Generator(plugin, generator.Configuration{
- Version: utils.ToPointString("1.0"),
- Title: utils.ToPointString(title),
- Description: utils.ToPointString(description),
- Naming: utils.ToPointString("proto"),
- FQSchemaNaming: utils.ToPointBool(true),
- EnumType: utils.ToPointString("integer"),
- CircularDepth: utils.ToPointInt(2),
- DefaultResponse: utils.ToPointBool(false),
- OutputMode: utils.ToPointString("merged"),
- }, plugin.Files)
- content, err := gen.RunV2()
- if err != nil {
- return "", err
- }
- return string(content), nil
- }
|