feat: 增加文档数据初始化逻辑
This commit is contained in:
@@ -19,108 +19,130 @@ import (
|
|||||||
"github.com/getkin/kin-openapi/openapi3"
|
"github.com/getkin/kin-openapi/openapi3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewGenerate 生成文档实例
|
var (
|
||||||
func NewGenerate() *Generate {
|
DocManager = &Generate{
|
||||||
return &Generate{
|
docTable: make(map[string]*openapi3.T),
|
||||||
doc: &openapi3.T{
|
|
||||||
Extensions: map[string]any{},
|
|
||||||
OpenAPI: "3.1.0",
|
|
||||||
Components: &openapi3.Components{
|
|
||||||
Extensions: map[string]any{},
|
|
||||||
Origin: &openapi3.Origin{
|
|
||||||
Key: &openapi3.Location{
|
|
||||||
Line: 0,
|
|
||||||
Column: 0,
|
|
||||||
},
|
|
||||||
Fields: make(map[string]openapi3.Location),
|
|
||||||
},
|
|
||||||
Schemas: map[string]*openapi3.SchemaRef{},
|
|
||||||
Parameters: map[string]*openapi3.ParameterRef{},
|
|
||||||
Headers: map[string]*openapi3.HeaderRef{},
|
|
||||||
RequestBodies: map[string]*openapi3.RequestBodyRef{},
|
|
||||||
Responses: map[string]*openapi3.ResponseRef{},
|
|
||||||
SecuritySchemes: map[string]*openapi3.SecuritySchemeRef{},
|
|
||||||
Examples: map[string]*openapi3.ExampleRef{},
|
|
||||||
Links: map[string]*openapi3.LinkRef{},
|
|
||||||
Callbacks: map[string]*openapi3.CallbackRef{},
|
|
||||||
},
|
|
||||||
Info: &openapi3.Info{
|
|
||||||
Extensions: map[string]any{},
|
|
||||||
Origin: &openapi3.Origin{
|
|
||||||
Key: &openapi3.Location{
|
|
||||||
Line: 0,
|
|
||||||
Column: 0,
|
|
||||||
},
|
|
||||||
Fields: make(map[string]openapi3.Location),
|
|
||||||
},
|
|
||||||
Title: "服务 API接口 文档",
|
|
||||||
Description: "服务 API接口 文档",
|
|
||||||
TermsOfService: "",
|
|
||||||
Contact: &openapi3.Contact{
|
|
||||||
Extensions: map[string]any{},
|
|
||||||
Origin: &openapi3.Origin{
|
|
||||||
Key: &openapi3.Location{
|
|
||||||
Line: 0,
|
|
||||||
Column: 0,
|
|
||||||
},
|
|
||||||
Fields: make(map[string]openapi3.Location),
|
|
||||||
},
|
|
||||||
Name: "developer",
|
|
||||||
URL: "",
|
|
||||||
Email: "developer@test.com",
|
|
||||||
},
|
|
||||||
License: &openapi3.License{
|
|
||||||
Extensions: map[string]any{},
|
|
||||||
Origin: &openapi3.Origin{
|
|
||||||
Key: &openapi3.Location{
|
|
||||||
Line: 0,
|
|
||||||
Column: 0,
|
|
||||||
},
|
|
||||||
Fields: make(map[string]openapi3.Location),
|
|
||||||
},
|
|
||||||
Name: consts.LicenseApache20,
|
|
||||||
URL: consts.LicenseUrlTable[consts.LicenseApache20],
|
|
||||||
},
|
|
||||||
Version: "0.0.1",
|
|
||||||
},
|
|
||||||
Paths: &openapi3.Paths{
|
|
||||||
Extensions: map[string]any{},
|
|
||||||
Origin: &openapi3.Origin{
|
|
||||||
Key: &openapi3.Location{
|
|
||||||
Line: 0,
|
|
||||||
Column: 0,
|
|
||||||
},
|
|
||||||
Fields: make(map[string]openapi3.Location),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Security: []openapi3.SecurityRequirement{},
|
|
||||||
Servers: []*openapi3.Server{
|
|
||||||
{
|
|
||||||
Extensions: nil,
|
|
||||||
Origin: nil,
|
|
||||||
URL: "http://127.0.0.1:8080/v1",
|
|
||||||
Description: "开发环境",
|
|
||||||
Variables: nil,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Tags: []*openapi3.Tag{},
|
|
||||||
/*ExternalDocs: &openapi3.ExternalDocs{
|
|
||||||
Extensions: map[string]any{},
|
|
||||||
Origin: nil,
|
|
||||||
Description: "",
|
|
||||||
URL: "",
|
|
||||||
},*/
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewOpenApiDoc 生成文档实例
|
||||||
|
func NewOpenApiDoc(optionFunc ...OptionFunc) *openapi3.T {
|
||||||
|
t := &openapi3.T{
|
||||||
|
Extensions: map[string]any{},
|
||||||
|
OpenAPI: "3.1.0",
|
||||||
|
Components: &openapi3.Components{
|
||||||
|
Extensions: map[string]any{},
|
||||||
|
Origin: &openapi3.Origin{
|
||||||
|
Key: &openapi3.Location{
|
||||||
|
Line: 0,
|
||||||
|
Column: 0,
|
||||||
|
},
|
||||||
|
Fields: make(map[string]openapi3.Location),
|
||||||
|
},
|
||||||
|
Schemas: map[string]*openapi3.SchemaRef{},
|
||||||
|
Parameters: map[string]*openapi3.ParameterRef{},
|
||||||
|
Headers: map[string]*openapi3.HeaderRef{},
|
||||||
|
RequestBodies: map[string]*openapi3.RequestBodyRef{},
|
||||||
|
Responses: map[string]*openapi3.ResponseRef{},
|
||||||
|
SecuritySchemes: map[string]*openapi3.SecuritySchemeRef{},
|
||||||
|
Examples: map[string]*openapi3.ExampleRef{},
|
||||||
|
Links: map[string]*openapi3.LinkRef{},
|
||||||
|
Callbacks: map[string]*openapi3.CallbackRef{},
|
||||||
|
},
|
||||||
|
Info: &openapi3.Info{
|
||||||
|
Extensions: map[string]any{},
|
||||||
|
Origin: &openapi3.Origin{
|
||||||
|
Key: &openapi3.Location{
|
||||||
|
Line: 0,
|
||||||
|
Column: 0,
|
||||||
|
},
|
||||||
|
Fields: make(map[string]openapi3.Location),
|
||||||
|
},
|
||||||
|
Title: "服务 API接口 文档",
|
||||||
|
Description: "服务 API接口 文档",
|
||||||
|
TermsOfService: "",
|
||||||
|
Contact: &openapi3.Contact{
|
||||||
|
Extensions: map[string]any{},
|
||||||
|
Origin: &openapi3.Origin{
|
||||||
|
Key: &openapi3.Location{
|
||||||
|
Line: 0,
|
||||||
|
Column: 0,
|
||||||
|
},
|
||||||
|
Fields: make(map[string]openapi3.Location),
|
||||||
|
},
|
||||||
|
Name: "developer",
|
||||||
|
URL: "",
|
||||||
|
Email: "developer@test.com",
|
||||||
|
},
|
||||||
|
License: &openapi3.License{
|
||||||
|
Extensions: map[string]any{},
|
||||||
|
Origin: &openapi3.Origin{
|
||||||
|
Key: &openapi3.Location{
|
||||||
|
Line: 0,
|
||||||
|
Column: 0,
|
||||||
|
},
|
||||||
|
Fields: make(map[string]openapi3.Location),
|
||||||
|
},
|
||||||
|
Name: consts.LicenseApache20,
|
||||||
|
URL: consts.LicenseUrlTable[consts.LicenseApache20],
|
||||||
|
},
|
||||||
|
Version: "0.0.1",
|
||||||
|
},
|
||||||
|
Paths: &openapi3.Paths{
|
||||||
|
Extensions: map[string]any{},
|
||||||
|
Origin: &openapi3.Origin{
|
||||||
|
Key: &openapi3.Location{
|
||||||
|
Line: 0,
|
||||||
|
Column: 0,
|
||||||
|
},
|
||||||
|
Fields: make(map[string]openapi3.Location),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Security: []openapi3.SecurityRequirement{},
|
||||||
|
Servers: []*openapi3.Server{
|
||||||
|
{
|
||||||
|
Extensions: nil,
|
||||||
|
Origin: nil,
|
||||||
|
URL: "http://127.0.0.1:8080",
|
||||||
|
Description: "开发环境",
|
||||||
|
Variables: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Tags: []*openapi3.Tag{},
|
||||||
|
/*ExternalDocs: &openapi3.ExternalDocs{
|
||||||
|
Extensions: map[string]any{},
|
||||||
|
Origin: nil,
|
||||||
|
Description: "",
|
||||||
|
URL: "",
|
||||||
|
},*/
|
||||||
|
}
|
||||||
|
for _, item := range optionFunc {
|
||||||
|
item(t)
|
||||||
|
}
|
||||||
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate 生成 OpenApi 标准规范的文档
|
// Generate 生成 OpenApi 标准规范的文档
|
||||||
type Generate struct {
|
type Generate struct {
|
||||||
doc *openapi3.T
|
docTable map[string]*openapi3.T
|
||||||
|
}
|
||||||
|
|
||||||
|
// DocData 获取一个文档数据
|
||||||
|
func (g *Generate) DocData(docFlag string) *openapi3.T {
|
||||||
|
return g.docTable[docFlag]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Generate) NewOpenApiDoc(docFlag string, docOption ...OptionFunc) *openapi3.T {
|
||||||
|
t := NewOpenApiDoc()
|
||||||
|
for _, item := range docOption {
|
||||||
|
item(t)
|
||||||
|
}
|
||||||
|
g.docTable[docFlag] = t
|
||||||
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddApiDoc 添加接口文档
|
// AddApiDoc 添加接口文档
|
||||||
func (g *Generate) AddApiDoc(apiMeta define.UriConfig, request any, response any) error {
|
func (g *Generate) AddApiDoc(docFlag string, apiMeta define.UriConfig, request any, response any) error {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
requestType reflect.Type
|
requestType reflect.Type
|
||||||
@@ -144,7 +166,7 @@ func (g *Generate) AddApiDoc(apiMeta define.UriConfig, request any, response any
|
|||||||
}
|
}
|
||||||
|
|
||||||
schemaData := GenerateOpenAPISchema(requestType)
|
schemaData := GenerateOpenAPISchema(requestType)
|
||||||
apiOperate, isRead := g.initApiConfig(apiMeta)
|
apiOperate, isRead := g.initApiConfig(docFlag, apiMeta)
|
||||||
requestTypeStr := requestType.String()
|
requestTypeStr := requestType.String()
|
||||||
if isRead {
|
if isRead {
|
||||||
for paramName, paramConfig := range schemaData.Value.Properties {
|
for paramName, paramConfig := range schemaData.Value.Properties {
|
||||||
@@ -196,12 +218,12 @@ func (g *Generate) AddApiDoc(apiMeta define.UriConfig, request any, response any
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 初始化接口配置
|
// 初始化接口配置
|
||||||
if _, exist := g.doc.Components.Schemas[requestTypeStr]; !exist {
|
if _, exist := g.docTable[docFlag].Components.Schemas[requestTypeStr]; !exist {
|
||||||
g.doc.Components.Schemas[requestTypeStr] = schemaData
|
g.docTable[docFlag].Components.Schemas[requestTypeStr] = schemaData
|
||||||
}
|
}
|
||||||
responseTypeStr := responseType.String()
|
responseTypeStr := responseType.String()
|
||||||
if _, exist := g.doc.Components.Schemas[responseTypeStr]; !exist {
|
if _, exist := g.docTable[docFlag].Components.Schemas[responseTypeStr]; !exist {
|
||||||
g.doc.Components.Schemas[responseTypeStr] = GenerateOpenAPISchema(responseType)
|
g.docTable[docFlag].Components.Schemas[responseTypeStr] = GenerateOpenAPISchema(responseType)
|
||||||
}
|
}
|
||||||
desc := "请求成功"
|
desc := "请求成功"
|
||||||
apiOperate.Responses.Set(fmt.Sprintf("%v", http.StatusOK), &openapi3.ResponseRef{
|
apiOperate.Responses.Set(fmt.Sprintf("%v", http.StatusOK), &openapi3.ResponseRef{
|
||||||
@@ -217,7 +239,7 @@ func (g *Generate) AddApiDoc(apiMeta define.UriConfig, request any, response any
|
|||||||
consts.MimeTypeJson: {
|
consts.MimeTypeJson: {
|
||||||
Extensions: nil,
|
Extensions: nil,
|
||||||
Origin: nil,
|
Origin: nil,
|
||||||
Schema: g.doc.Components.Schemas[responseTypeStr],
|
Schema: g.docTable[docFlag].Components.Schemas[responseTypeStr],
|
||||||
Example: nil,
|
Example: nil,
|
||||||
Examples: nil,
|
Examples: nil,
|
||||||
Encoding: nil,
|
Encoding: nil,
|
||||||
@@ -230,9 +252,9 @@ func (g *Generate) AddApiDoc(apiMeta define.UriConfig, request any, response any
|
|||||||
}
|
}
|
||||||
|
|
||||||
// initApiConfig 初始化接口配置, 并返回 operation 以及 是否读请求
|
// initApiConfig 初始化接口配置, 并返回 operation 以及 是否读请求
|
||||||
func (g *Generate) initApiConfig(apiMeta define.UriConfig) (*openapi3.Operation, bool) {
|
func (g *Generate) initApiConfig(docFlag string, apiMeta define.UriConfig) (*openapi3.Operation, bool) {
|
||||||
if nil == g.doc.Paths.Value(apiMeta.Path) {
|
if nil == g.docTable[docFlag].Paths.Value(apiMeta.Path) {
|
||||||
g.doc.Paths.Set(apiMeta.Path, &openapi3.PathItem{
|
g.docTable[docFlag].Paths.Set(apiMeta.Path, &openapi3.PathItem{
|
||||||
Extensions: nil,
|
Extensions: nil,
|
||||||
Origin: nil,
|
Origin: nil,
|
||||||
Ref: "",
|
Ref: "",
|
||||||
@@ -261,29 +283,29 @@ func (g *Generate) initApiConfig(apiMeta define.UriConfig) (*openapi3.Operation,
|
|||||||
isRead := false
|
isRead := false
|
||||||
switch apiMeta.RequestMethod {
|
switch apiMeta.RequestMethod {
|
||||||
case http.MethodGet:
|
case http.MethodGet:
|
||||||
g.doc.Paths.Value(apiMeta.Path).Get = newOperate
|
g.docTable[docFlag].Paths.Value(apiMeta.Path).Get = newOperate
|
||||||
isRead = true
|
isRead = true
|
||||||
case http.MethodHead:
|
case http.MethodHead:
|
||||||
g.doc.Paths.Value(apiMeta.Path).Head = newOperate
|
g.docTable[docFlag].Paths.Value(apiMeta.Path).Head = newOperate
|
||||||
isRead = true
|
isRead = true
|
||||||
case http.MethodConnect:
|
case http.MethodConnect:
|
||||||
g.doc.Paths.Value(apiMeta.Path).Connect = newOperate
|
g.docTable[docFlag].Paths.Value(apiMeta.Path).Connect = newOperate
|
||||||
isRead = true
|
isRead = true
|
||||||
case http.MethodOptions:
|
case http.MethodOptions:
|
||||||
g.doc.Paths.Value(apiMeta.Path).Options = newOperate
|
g.docTable[docFlag].Paths.Value(apiMeta.Path).Options = newOperate
|
||||||
isRead = true
|
isRead = true
|
||||||
case http.MethodTrace:
|
case http.MethodTrace:
|
||||||
g.doc.Paths.Value(apiMeta.Path).Trace = newOperate
|
g.docTable[docFlag].Paths.Value(apiMeta.Path).Trace = newOperate
|
||||||
isRead = true
|
isRead = true
|
||||||
// 读请求
|
// 读请求
|
||||||
case http.MethodPost:
|
case http.MethodPost:
|
||||||
g.doc.Paths.Value(apiMeta.Path).Post = newOperate
|
g.docTable[docFlag].Paths.Value(apiMeta.Path).Post = newOperate
|
||||||
case http.MethodPut:
|
case http.MethodPut:
|
||||||
g.doc.Paths.Value(apiMeta.Path).Put = newOperate
|
g.docTable[docFlag].Paths.Value(apiMeta.Path).Put = newOperate
|
||||||
case http.MethodPatch:
|
case http.MethodPatch:
|
||||||
g.doc.Paths.Value(apiMeta.Path).Patch = newOperate
|
g.docTable[docFlag].Paths.Value(apiMeta.Path).Patch = newOperate
|
||||||
case http.MethodDelete:
|
case http.MethodDelete:
|
||||||
g.doc.Paths.Value(apiMeta.Path).Delete = newOperate
|
g.docTable[docFlag].Paths.Value(apiMeta.Path).Delete = newOperate
|
||||||
// 写请求
|
// 写请求
|
||||||
}
|
}
|
||||||
return newOperate, isRead
|
return newOperate, isRead
|
||||||
|
|||||||
@@ -34,20 +34,21 @@ func TestGenerate_AddApiDoc(t *testing.T) {
|
|||||||
UpdatedAt *time.Time `json:"updated_at,omitempty" description:"更新时间"`
|
UpdatedAt *time.Time `json:"updated_at,omitempty" description:"更新时间"`
|
||||||
Category *Category `json:"category,omitempty" description:"分类"`
|
Category *Category `json:"category,omitempty" description:"分类"`
|
||||||
}
|
}
|
||||||
instance := NewGenerate()
|
docFlag := "demo"
|
||||||
instance.AddApiDoc(define.UriConfig{
|
DocManager.NewOpenApiDoc(docFlag)
|
||||||
|
DocManager.AddApiDoc(docFlag, define.UriConfig{
|
||||||
Path: "/a/b/c",
|
Path: "/a/b/c",
|
||||||
RequestMethod: http.MethodGet,
|
RequestMethod: http.MethodGet,
|
||||||
TagList: []string{"test"},
|
TagList: []string{"test"},
|
||||||
Desc: "测试接口",
|
Desc: "测试接口",
|
||||||
}, Category{}, Product{})
|
}, Category{}, Product{})
|
||||||
instance.AddApiDoc(define.UriConfig{
|
DocManager.AddApiDoc(docFlag, define.UriConfig{
|
||||||
Path: "/a/b/c",
|
Path: "/a/b/c",
|
||||||
RequestMethod: http.MethodPost,
|
RequestMethod: http.MethodPost,
|
||||||
TagList: []string{"test"},
|
TagList: []string{"test"},
|
||||||
Desc: "测试接口",
|
Desc: "测试接口",
|
||||||
}, Category{}, Product{})
|
}, Category{}, Product{})
|
||||||
// 输出 JSON
|
// 输出 JSON
|
||||||
data, _ := json.MarshalIndent(instance.doc, "", " ")
|
data, _ := json.MarshalIndent(DocManager.docTable[docFlag], "", " ")
|
||||||
fmt.Println(string(data))
|
fmt.Println(string(data))
|
||||||
}
|
}
|
||||||
|
|||||||
33
openapi/option.go
Normal file
33
openapi/option.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
// Package openapi ...
|
||||||
|
//
|
||||||
|
// Description : openapi ...
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 2026-01-06 22:48
|
||||||
|
package openapi
|
||||||
|
|
||||||
|
import "github.com/getkin/kin-openapi/openapi3"
|
||||||
|
|
||||||
|
// OptionFunc 设置文档选项
|
||||||
|
type OptionFunc func(t *openapi3.T)
|
||||||
|
|
||||||
|
// WithServers 设置文档服务器
|
||||||
|
func WithServers(serverList openapi3.Servers) OptionFunc {
|
||||||
|
return func(t *openapi3.T) {
|
||||||
|
if len(serverList) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Servers = serverList
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithInfo 文档基础信息
|
||||||
|
func WithInfo(info *openapi3.Info) OptionFunc {
|
||||||
|
return func(t *openapi3.T) {
|
||||||
|
if nil == info {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Info = info
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user