Skip to content

Commit

Permalink
refactor: 更新依赖的 openapi
Browse files Browse the repository at this point in the history
  • Loading branch information
caixw committed Dec 5, 2023
1 parent f03228f commit c3507c4
Show file tree
Hide file tree
Showing 12 changed files with 50 additions and 53 deletions.
2 changes: 1 addition & 1 deletion cmd/web/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.21

require (
github.com/caixw/gobuild v1.7.4
github.com/getkin/kin-openapi v0.120.0
github.com/getkin/kin-openapi v0.122.0
github.com/issue9/assert/v3 v3.1.0
github.com/issue9/cmdopt v0.13.0
github.com/issue9/errwrap v0.3.1
Expand Down
4 changes: 2 additions & 2 deletions cmd/web/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/getkin/kin-openapi v0.120.0 h1:MqJcNJFrMDFNc07iwE8iFC5eT2k/NPUFDIpNeiZv8Jg=
github.com/getkin/kin-openapi v0.120.0/go.mod h1:PCWw/lfBrJY4HcdqE3jj+QFkaFK8ABoqo7PvqVhXXqw=
github.com/getkin/kin-openapi v0.122.0 h1:WB9Jbl0Hp/T79/JF9xlSW5Kl9uYdk/AWD0yAd9HOM10=
github.com/getkin/kin-openapi v0.122.0/go.mod h1:PCWw/lfBrJY4HcdqE3jj+QFkaFK8ABoqo7PvqVhXXqw=
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
Expand Down
47 changes: 21 additions & 26 deletions cmd/web/restdoc/openapi/openapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package openapi

import (
"encoding/json"
"maps"
"os"
"path/filepath"
"sync"
Expand All @@ -25,19 +26,17 @@ type OpenAPI struct {
func New(ver string) *OpenAPI {
c := openapi3.NewComponents()
c.Schemas = make(openapi3.Schemas)
c.Responses = make(openapi3.Responses)
c.Responses = make(openapi3.ResponseBodies)
c.SecuritySchemes = make(openapi3.SecuritySchemes)

t := &openapi3.T{
return &OpenAPI{doc: &openapi3.T{
OpenAPI: ver,
Components: &c,
Servers: make(openapi3.Servers, 0, 5),
Paths: make(openapi3.Paths, 100),
Paths: openapi3.NewPathsWithCapacity(100),
Security: make(openapi3.SecurityRequirements, 0, 5),
Tags: make(openapi3.Tags, 0, 10),
}

return &OpenAPI{doc: t}
}}
}

func (doc *OpenAPI) Doc() *openapi3.T { return doc.doc }
Expand All @@ -48,12 +47,10 @@ func (doc *OpenAPI) Doc() *openapi3.T { return doc.doc }
func (doc *OpenAPI) SaveAs(path string) error {
var m func(any) ([]byte, error)
switch filepath.Ext(path) {
case ".yaml", ".yml":
case ".yaml", ".yml": // BUG: 依赖的 openapi3.Paths 不支持输出 yaml?
m = yaml.Marshal
case ".json":
m = func(v any) ([]byte, error) {
return json.MarshalIndent(v, "", "\t")
}
m = func(v any) ([]byte, error) { return json.MarshalIndent(v, "", "\t") }
default:
return web.NewLocaleError("only support yaml and json")
}
Expand All @@ -69,22 +66,20 @@ func (doc *OpenAPI) Merge(d *openapi3.T) {
doc.Doc().Servers = append(doc.Doc().Servers, d.Servers...)
doc.Doc().Security = append(doc.Doc().Security, d.Security...)
doc.Doc().Tags = append(doc.Doc().Tags, d.Tags...)
cloneMap(d.Paths, doc.Doc().Paths)
if d.Components != nil {
cloneMap(d.Components.Schemas, doc.Doc().Components.Schemas)
cloneMap(d.Components.Parameters, doc.Doc().Components.Parameters)
cloneMap(d.Components.Headers, doc.Doc().Components.Headers)
cloneMap(d.Components.RequestBodies, doc.Doc().Components.RequestBodies)
cloneMap(d.Components.Responses, doc.Doc().Components.Responses)
cloneMap(d.Components.SecuritySchemes, doc.Doc().Components.SecuritySchemes)
cloneMap(d.Components.Examples, doc.Doc().Components.Examples)
cloneMap(d.Components.Links, doc.Doc().Components.Links)
cloneMap(d.Components.Callbacks, doc.Doc().Components.Callbacks)
if d.Paths != nil && d.Paths.Len() > 0 {
for k, v := range d.Paths.Map() {
doc.Doc().Paths.Set(k, v)
}
}
}

func cloneMap[K comparable, V any](src, dest map[K]V) {
for k, v := range src {
dest[k] = v
if d.Components != nil {
maps.Copy(doc.Doc().Components.Schemas, d.Components.Schemas)
maps.Copy(doc.Doc().Components.Parameters, d.Components.Parameters)
maps.Copy(doc.Doc().Components.Headers, d.Components.Headers)
maps.Copy(doc.Doc().Components.RequestBodies, d.Components.RequestBodies)
maps.Copy(doc.Doc().Components.Responses, d.Components.Responses)
maps.Copy(doc.Doc().Components.SecuritySchemes, d.Components.SecuritySchemes)
maps.Copy(doc.Doc().Components.Examples, d.Components.Examples)
maps.Copy(doc.Doc().Components.Links, d.Components.Links)
maps.Copy(doc.Doc().Components.Callbacks, d.Components.Callbacks)
}
}
9 changes: 6 additions & 3 deletions cmd/web/restdoc/openapi/openapi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package openapi

import (
"net/http"
"testing"

"github.com/getkin/kin-openapi/openapi3"
Expand All @@ -23,6 +24,10 @@ func TestOpenAPI_SaveAs(t *testing.T) {
doc := New("3.0")
a.NotNil(doc)

o := openapi3.NewOperation()
o.Responses = openapi3.NewResponses()
doc.AddAPI("/pet", o, http.MethodGet)

a.NotError(doc.SaveAs("./openapi.out.yaml"))
a.NotError(doc.SaveAs("./openapi.out.json"))
a.ErrorString(doc.SaveAs("./openapi.out.xml"), "only support yaml and json")
Expand All @@ -33,9 +38,7 @@ func TestOpenAPI_Merge(t *testing.T) {

d2 := &openapi3.T{}
d2.Tags = append(d2.Tags, &openapi3.Tag{Name: "t1"})
d2.Paths = openapi3.Paths{
"/p1": &openapi3.PathItem{},
}
d2.Paths = openapi3.NewPaths(openapi3.WithPath("/p1", &openapi3.PathItem{}))
d2.Components = &openapi3.Components{
Schemas: openapi3.Schemas{
"Object": &openapi3.SchemaRef{Value: &openapi3.Schema{Type: "object"}},
Expand Down
2 changes: 1 addition & 1 deletion cmd/web/restdoc/openapi/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func (doc *OpenAPI) addAPI(path, method string, o *openapi3.Operation) {
return
}

p := doc.doc.Paths[path]
p := doc.doc.Paths.Find(path)
if index := slices.IndexFunc(p.Parameters, isPathParams); index >= 0 {
return
}
Expand Down
12 changes: 6 additions & 6 deletions cmd/web/restdoc/openapi/path_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,29 @@ func TestOpenAPI_AddAPI(t *testing.T) {
o := openapi3.NewOperation()
o.Parameters = append(o.Parameters, &openapi3.ParameterRef{Value: openapi3.NewPathParameter("p1")})
doc.AddAPI("/path/{p1}", o, "GET")
a.Length(doc.Doc().Paths["/path/{p1}"].Parameters, 1).
a.Length(doc.Doc().Paths.Find("/path/{p1}").Parameters, 1).
Length(o.Parameters, 0) // 上移至 path item

o = openapi3.NewOperation()
o.Parameters = append(o.Parameters, &openapi3.ParameterRef{Value: openapi3.NewPathParameter("p1")})
doc.AddAPI("/path/{p1}", o, "PUT")
a.Length(doc.Doc().Paths["/path/{p1}"].Parameters, 1).
a.Length(doc.Doc().Paths.Find("/path/{p1}").Parameters, 1).
Length(o.Parameters, 1) // path item 上已经有了,不再上移

// 非路径参数
o = openapi3.NewOperation()
o.Parameters = append(o.Parameters, &openapi3.ParameterRef{Value: openapi3.NewQueryParameter("q1")})
doc.AddAPI("/path/q1", o, "PUT,PATCH")
a.Length(doc.Doc().Paths["/path/q1"].Parameters, 0).
a.Length(doc.Doc().Paths.Find("/path/q1").Parameters, 0).
Length(o.Parameters, 1).
NotNil(doc.Doc().Paths["/path/q1"].Put).
NotNil(doc.Doc().Paths["/path/q1"].Patch)
NotNil(doc.Doc().Paths.Find("/path/q1").Put).
NotNil(doc.Doc().Paths.Find("/path/q1").Patch)

// any
o = openapi3.NewOperation()
o.Parameters = append(o.Parameters, &openapi3.ParameterRef{Value: openapi3.NewQueryParameter("q1")})
doc.AddAPI("/path/any", o, "Any")
p := doc.Doc().Paths["/path/any"]
p := doc.Doc().Paths.Find("/path/any")
a.NotNil(p.Put).
NotNil(p.Patch).
NotNil(p.Delete).
Expand Down
2 changes: 1 addition & 1 deletion cmd/web/restdoc/parser/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func TestParser_parseAPI(t *testing.T) {
"@path id id id desc",
}
p.parseAPI(doc, "github.com/issue9/web", "POST /admins/{id}", lines, 5, "example.go")
path := doc.Doc().Paths["/admins/{id}"]
path := doc.Doc().Paths.Find("/admins/{id}")
a.NotNil(path).
NotNil(path.Post).
Nil(path.Delete).
Expand Down
8 changes: 4 additions & 4 deletions cmd/web/restdoc/parser/body.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,20 +103,20 @@ func (p *Parser) parseResponseHeader(resps map[string]*openapi3.Response, suffix
// g 是否将定义为全局的对象也写入 o
func (p *Parser) addResponses(o *openapi3.Operation, resps map[string]*openapi3.Response, g bool) {
if l := len(resps) + len(p.resps); o.Responses == nil && l > 0 {
o.Responses = make(openapi3.Responses, l)
o.Responses = openapi3.NewResponsesWithCapacity(l)
}

if g { // 全局的定义在前,才会被本地定义覆盖。
for key, resp := range p.resps {
o.Responses[key] = &openapi3.ResponseRef{Ref: responsesRef + key, Value: resp}
o.Responses.Set(key, &openapi3.ResponseRef{Ref: responsesRef + key, Value: resp})
}
}

for status, r := range resps {
if _, found := o.Responses[status]; found {
if o.Responses.Value(status) != nil {
p.l.Warning(web.Phrase("override global response %s", status))
}
o.Responses[status] = &openapi3.ResponseRef{Value: r}
o.Responses.Set(status, &openapi3.ResponseRef{Value: r})
}
}

Expand Down
3 changes: 1 addition & 2 deletions cmd/web/restdoc/parser/callback.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,8 @@ func (p *Parser) parseCallback(t *openapi.OpenAPI, o *openapi3.Operation, currPa
}
p.addResponses(opt, resps, false)

callback := openapi3.Callback{path: pi}
o.Callbacks[name] = &openapi3.CallbackRef{
Value: &callback,
Value: openapi3.NewCallback(openapi3.WithCallback(path, pi)),
}

return delta
Expand Down
8 changes: 4 additions & 4 deletions cmd/web/restdoc/parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func TestParser_Parse(t *testing.T) {
a.NotNil(d.Doc().Info).
Equal(d.Doc().Info.Version, "1.0.0")

login := d.Doc().Paths["/prefix/login"].Post
login := d.Doc().Paths.Find("/prefix/login").Post
a.NotNil(login).
Length(login.Parameters, 6).
Equal(login.Parameters[3].Value.Name, "sex").
Expand All @@ -38,11 +38,11 @@ func TestParser_Parse(t *testing.T) {
Equal(login.Parameters[2].Value.Schema.Value.Type, openapi3.TypeArray).
Equal(login.Parameters[2].Value.Schema.Value.Items.Value.Type, openapi3.TypeInteger).
NotNil(login.RequestBody).
Length(login.Responses, 5). // 包含默认的 default
Equal(login.Responses.Len(), 5). // 包含默认的 default
Length(login.Callbacks, 1).
NotNil((*login.Callbacks["onData"].Value)["{$request.query.url}"].Post)
NotNil((login.Callbacks["onData"].Value).Value("{$request.query.url}").Post)

a.NotError(d.SaveAs("./testdata/openapi.out.yaml"))
a.NotError(d.SaveAs("./testdata/openapi.out.json"))
}

func TestIsIgnoreTag(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions cmd/web/restdoc/parser/restdoc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func TestBuildContact(t *testing.T) {
Equal(c.Name, "name")
}

func TestParseOpenAPI(t *testing.T) {
func TestParser_parseOpenAPI(t *testing.T) {
a := assert.New(t, false)

l := loggertest.New(a)
Expand All @@ -132,5 +132,5 @@ func TestParseOpenAPI(t *testing.T) {

p.parseOpenAPI(d, "./testdata/openapi.yaml", "test.go", 5)
a.Nil(d.Doc().Info).
Length(d.Doc().Paths, 1)
Equal(d.Doc().Paths.Len(), 1)
}
2 changes: 1 addition & 1 deletion cmd/web/restdoc/restdoc.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const (
replaceUsage = web.StringPhrase("parse replace direct, only valid when d is true")
)

const defaultOutput = "./restdoc.yaml"
const defaultOutput = "./restdoc.json"

func Init(opt *cmdopt.CmdOpt, p *localeutil.Printer) {
opt.New("doc", title.LocaleString(p), usage.LocaleString(p), func(fs *flag.FlagSet) cmdopt.DoFunc {
Expand Down

0 comments on commit c3507c4

Please sign in to comment.