Skip to content

Commit 5592b8d

Browse files
feat: add merged spec document
1 parent 629f88b commit 5592b8d

File tree

6 files changed

+387
-97
lines changed

6 files changed

+387
-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: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,76 @@ import (
55
"github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv3/options"
66
)
77

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

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

2090
return oAPIReqs
2191
}
92+

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)