Skip to content

Commit 92afaa3

Browse files
feat: add merged spec document
1 parent 629f88b commit 92afaa3

File tree

6 files changed

+386
-97
lines changed

6 files changed

+386
-97
lines changed
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
package genopenapiv3
22

3-
const OpenAPIVersion = "3.0.2"
3+
const (
4+
OpenAPIVersion = "3.0.2"
5+
6+
statusProtoFQMN = ".google.rpc.Status"
7+
)

protoc-gen-openapiv3/internal/genopenapiv3/convertors.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,81 @@ package genopenapiv3
22

33
import (
44
"github.com/getkin/kin-openapi/openapi3"
5+
"github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor"
56
"github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv3/options"
7+
"google.golang.org/protobuf/proto"
68
)
79

10+
func convertFileOptions(target *descriptor.File) *openapi3.T {
11+
if openAPIAno := proto.GetExtension(target.GetOptions(), options.E_Openapiv3Document).(*options.OpenAPI); openAPIAno != nil {
12+
return &openapi3.T{
13+
OpenAPI: OpenAPIVersion,
14+
Info: convertInfo(openAPIAno.GetInfo()),
15+
Security: *convertSecurityRequiremnt(openAPIAno.GetSecurity()),
16+
Servers: convertServers(openAPIAno.GetServers()),
17+
}
18+
}
19+
20+
return &openapi3.T{OpenAPI: OpenAPIVersion}
21+
}
22+
23+
func convertServers(servers []*options.Server) openapi3.Servers {
24+
oAPIservers := make(openapi3.Servers, len(servers))
25+
26+
for i, srv := range servers {
27+
vars := map[string]*openapi3.ServerVariable{}
28+
29+
for k, v := range srv.GetVariables() {
30+
vars[k] = &openapi3.ServerVariable{
31+
Enum: v.GetEnum(),
32+
Default: v.GetDefault(),
33+
Description: v.GetDescription(),
34+
}
35+
}
36+
37+
oAPIservers[i] = &openapi3.Server{
38+
URL: srv.GetUrl(),
39+
Description: srv.GetDescription(),
40+
Variables: vars,
41+
}
42+
}
43+
44+
return oAPIservers
45+
}
46+
47+
func convertInfo(openAPIInfo *options.Info) *openapi3.Info {
48+
return &openapi3.Info{
49+
Title: openAPIInfo.GetTitle(),
50+
Description: openAPIInfo.GetDescription(),
51+
Version: openAPIInfo.GetVersion(),
52+
TermsOfService: openAPIInfo.GetTermsOfService(),
53+
Contact: convertContact(openAPIInfo.GetContact()),
54+
License: convertLicense(openAPIInfo.GetLicense()),
55+
}
56+
}
57+
58+
func convertContact(contactOption *options.Contact) *openapi3.Contact {
59+
if contactOption == nil {
60+
return nil
61+
}
62+
63+
return &openapi3.Contact{
64+
Name: contactOption.GetName(),
65+
URL: contactOption.GetUrl(),
66+
Email: contactOption.GetEmail(),
67+
}
68+
}
69+
70+
func convertLicense(licenseOption *options.License) *openapi3.License {
71+
if licenseOption == nil {
72+
return nil
73+
}
74+
75+
return &openapi3.License{
76+
Name: licenseOption.GetName(),
77+
URL: licenseOption.GetUrl(),
78+
}
79+
}
880
func convertSecurityRequiremnt(requirements []*options.SecurityRequirement) *openapi3.SecurityRequirements {
981
oAPIReqs := openapi3.NewSecurityRequirements()
1082

@@ -19,3 +91,4 @@ func convertSecurityRequiremnt(requirements []*options.SecurityRequirement) *ope
1991

2092
return oAPIReqs
2193
}
94+

protoc-gen-openapiv3/internal/genopenapiv3/file_generator.go

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,10 @@ type fileGenerator struct {
1919
}
2020

2121
func (fg *fileGenerator) generateFileDoc(file *descriptor.File) *openapi3.T {
22-
var ok bool
23-
fg.doc, ok = fg.extractFileOptions(file)
24-
if !ok {
25-
fg.doc = &openapi3.T{
26-
OpenAPI: OpenAPIVersion,
27-
}
28-
}
2922

30-
fg.doc.Components = new(openapi3.Components)
23+
fg.doc = convertFileOptions(file)
24+
25+
fg.doc.Components = &openapi3.Components{}
3126
fg.doc.Components.Schemas = make(openapi3.Schemas)
3227
fg.doc.Components.RequestBodies = make(openapi3.RequestBodies)
3328

@@ -250,7 +245,7 @@ func (fg *fileGenerator) getEnumSchema(enum *descriptor.Enum) *openapi3.SchemaRe
250245
}
251246

252247
func (fg *fileGenerator) generateEnumSchema(enum *descriptor.Enum) *openapi3.Schema {
253-
var enumValues []interface{}
248+
var enumValues []any
254249
for _, value := range enum.GetValue() {
255250
enumValues = append(enumValues, value.GetName())
256251
}

protoc-gen-openapiv3/internal/genopenapiv3/file_options.go

Lines changed: 0 additions & 81 deletions
This file was deleted.

protoc-gen-openapiv3/internal/genopenapiv3/generator.go

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,12 @@ func (g *generator) Generate(targets []*descriptor.File) ([]*descriptor.Response
3535
return nil, fmt.Errorf("could not load prequisite proto files in registry: %w", err)
3636
}
3737

38-
respFiles := make([]*descriptor.ResponseFile, len(targets))
39-
for i, t := range targets {
38+
respFiles := make([]*descriptor.ResponseFile, 0, len(targets))
39+
docs := make([]*openapi3.T, 0, len(targets))
40+
for _, t := range targets {
4041
fileGenerator := &fileGenerator{generator: g, doc: &openapi3.T{}}
4142
doc := fileGenerator.generateFileDoc(t)
43+
docs = append(docs, doc)
4244

4345
contentBytes, err := g.format.MarshalOpenAPIDoc(doc)
4446
if err != nil {
@@ -49,15 +51,32 @@ func (g *generator) Generate(targets []*descriptor.File) ([]*descriptor.Response
4951
ext := filepath.Ext(base)
5052
fileName := fmt.Sprintf("%s.openapiv3.%s", base[:len(base)-len(ext)], g.format)
5153

52-
respFiles[i] = &descriptor.ResponseFile{
53-
GoPkg: t.GoPkg,
54+
respFiles = append(respFiles, &descriptor.ResponseFile{
5455
CodeGeneratorResponse_File: &pluginpb.CodeGeneratorResponse_File{
5556
Name: proto.String(fileName),
5657
Content: proto.String(string(contentBytes)),
5758
},
58-
}
59+
})
60+
61+
}
62+
63+
mergedDocs, err := MergeOpenAPISpecs(docs...)
64+
if err != nil {
65+
return nil, fmt.Errorf("could not merge docs: %w", err)
5966
}
6067

68+
contentBytes, err := g.format.MarshalOpenAPIDoc(mergedDocs)
69+
if err != nil {
70+
return nil, err
71+
}
72+
73+
respFiles = append(respFiles, &descriptor.ResponseFile{
74+
CodeGeneratorResponse_File: &pluginpb.CodeGeneratorResponse_File{
75+
Name: proto.String(fmt.Sprintf("merged.openapiv3.%s", g.format)),
76+
Content: proto.String(string(contentBytes)),
77+
},
78+
})
79+
6180
return respFiles, nil
6281
}
6382

@@ -98,7 +117,7 @@ func (g *generator) loadPrequisiteProtos() error {
98117
}
99118

100119
func (g *generator) defaultResponse() (*descriptor.Message, error) {
101-
return g.reg.LookupMsg("", ".google.rpc.Status")
120+
return g.reg.LookupMsg("", statusProtoFQMN)
102121
}
103122

104123
func extractOperationOptionFromMethodDescriptor(meth *descriptorpb.MethodDescriptorProto) (*options.Operation, error) {

0 commit comments

Comments
 (0)