344 lines
10 KiB
Go
344 lines
10 KiB
Go
/*
|
|
* Copyright 2025 coze-dev Authors
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package pluginutil
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"github.com/getkin/kin-openapi/openapi3"
|
|
|
|
"github.com/coze-dev/coze-studio/backend/domain/plugin/entity"
|
|
|
|
"github.com/coze-dev/coze-studio/backend/api/model/crossdomain/plugin"
|
|
common "github.com/coze-dev/coze-studio/backend/api/model/plugin_develop_common"
|
|
"github.com/coze-dev/coze-studio/backend/domain/plugin/entity"
|
|
"github.com/coze-dev/coze-studio/backend/pkg/errorx"
|
|
"github.com/coze-dev/coze-studio/backend/types/errno"
|
|
)
|
|
|
|
func APIParamsToOpenapiOperation(reqParams, respParams []*common.APIParameter) (*openapi3.Operation, error) {
|
|
op := &openapi3.Operation{}
|
|
|
|
hasSetReqBody := false
|
|
hasSetParams := false
|
|
|
|
for _, apiParam := range reqParams {
|
|
if apiParam.Location != common.ParameterLocation_Body {
|
|
if !hasSetParams {
|
|
hasSetParams = true
|
|
op.Parameters = []*openapi3.ParameterRef{}
|
|
}
|
|
|
|
_apiParam, err := toOpenapiParameter(apiParam)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
op.Parameters = append(op.Parameters, &openapi3.ParameterRef{
|
|
Value: _apiParam,
|
|
})
|
|
|
|
continue
|
|
}
|
|
|
|
var mType *openapi3.MediaType
|
|
if hasSetReqBody {
|
|
mType = op.RequestBody.Value.Content[plugin.MediaTypeJson]
|
|
} else {
|
|
hasSetReqBody = true
|
|
mType = &openapi3.MediaType{
|
|
Schema: &openapi3.SchemaRef{
|
|
Value: &openapi3.Schema{
|
|
Type: openapi3.TypeObject,
|
|
Properties: map[string]*openapi3.SchemaRef{},
|
|
},
|
|
},
|
|
}
|
|
op.RequestBody = &openapi3.RequestBodyRef{
|
|
Value: &openapi3.RequestBody{
|
|
Content: map[string]*openapi3.MediaType{
|
|
plugin.MediaTypeJson: mType,
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
_apiParam, err := toOpenapi3Schema(apiParam)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
mType.Schema.Value.Properties[apiParam.Name] = &openapi3.SchemaRef{
|
|
Value: _apiParam,
|
|
}
|
|
if apiParam.IsRequired {
|
|
mType.Schema.Value.Required = append(mType.Schema.Value.Required, apiParam.Name)
|
|
}
|
|
}
|
|
|
|
if reqParams != nil {
|
|
if !hasSetParams {
|
|
op.Parameters = []*openapi3.ParameterRef{}
|
|
}
|
|
if !hasSetReqBody {
|
|
op.RequestBody = entity.DefaultOpenapi3RequestBody()
|
|
}
|
|
}
|
|
|
|
hasSetRespBody := false
|
|
|
|
for _, apiParam := range respParams {
|
|
if !hasSetRespBody {
|
|
hasSetRespBody = true
|
|
op.Responses = map[string]*openapi3.ResponseRef{
|
|
strconv.Itoa(http.StatusOK): {
|
|
Value: &openapi3.Response{
|
|
Content: map[string]*openapi3.MediaType{
|
|
plugin.MediaTypeJson: {
|
|
Schema: &openapi3.SchemaRef{
|
|
Value: &openapi3.Schema{
|
|
Type: openapi3.TypeObject,
|
|
Properties: map[string]*openapi3.SchemaRef{},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
_apiParam, err := toOpenapi3Schema(apiParam)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
resp, _ := op.Responses[strconv.Itoa(http.StatusOK)]
|
|
mType, _ := resp.Value.Content[plugin.MediaTypeJson] // only support application/json
|
|
mType.Schema.Value.Properties[apiParam.Name] = &openapi3.SchemaRef{
|
|
Value: _apiParam,
|
|
}
|
|
|
|
if apiParam.IsRequired {
|
|
mType.Schema.Value.Required = append(mType.Schema.Value.Required, apiParam.Name)
|
|
}
|
|
}
|
|
|
|
if respParams != nil && !hasSetRespBody {
|
|
op.Responses = entity.DefaultOpenapi3Responses()
|
|
}
|
|
|
|
return op, nil
|
|
}
|
|
|
|
func toOpenapiParameter(apiParam *common.APIParameter) (*openapi3.Parameter, error) {
|
|
paramType, ok := plugin.ToOpenapiParamType(apiParam.Type)
|
|
if !ok {
|
|
return nil, errorx.New(errno.ErrPluginInvalidParamCode,
|
|
errorx.KVf(errno.PluginMsgKey, "the type '%s' of field '%s' is invalid", apiParam.Type, apiParam.Name))
|
|
}
|
|
|
|
if paramType == openapi3.TypeObject {
|
|
return nil, errorx.New(errno.ErrPluginInvalidParamCode,
|
|
errorx.KVf(errno.PluginMsgKey, "the type of field '%s' cannot be 'object'", apiParam.Name))
|
|
}
|
|
|
|
paramSchema := &openapi3.Schema{
|
|
Type: paramType,
|
|
Default: apiParam.GlobalDefault,
|
|
Extensions: map[string]interface{}{
|
|
plugin.APISchemaExtendGlobalDisable: apiParam.GlobalDisable,
|
|
},
|
|
}
|
|
|
|
if paramType == openapi3.TypeArray {
|
|
if apiParam.Location == common.ParameterLocation_Path {
|
|
return nil, errorx.New(errno.ErrPluginInvalidParamCode,
|
|
errorx.KVf(errno.PluginMsgKey, "the type of field '%s' cannot be 'array'", apiParam.Name))
|
|
}
|
|
if len(apiParam.SubParameters) == 0 {
|
|
return nil, errorx.New(errno.ErrPluginInvalidParamCode,
|
|
errorx.KVf(errno.PluginMsgKey, "the sub parameters of field '%s' is required", apiParam.Name))
|
|
}
|
|
|
|
arrayItem := apiParam.SubParameters[0]
|
|
arrayItemType, ok := plugin.ToOpenapiParamType(arrayItem.Type)
|
|
if !ok {
|
|
return nil, errorx.New(errno.ErrPluginInvalidParamCode,
|
|
errorx.KVf(errno.PluginMsgKey, "the item type '%s' of field '%s' is invalid", arrayItemType, apiParam.Name))
|
|
}
|
|
|
|
if arrayItemType == openapi3.TypeObject || arrayItemType == openapi3.TypeArray {
|
|
return nil, errorx.New(errno.ErrPluginInvalidParamCode,
|
|
errorx.KVf(errno.PluginMsgKey, "the item type of field '%s' cannot be 'array' or 'object'", apiParam.Name))
|
|
}
|
|
|
|
itemSchema := &openapi3.Schema{
|
|
Type: arrayItemType,
|
|
Description: arrayItem.Desc,
|
|
Extensions: map[string]any{},
|
|
}
|
|
|
|
if arrayItem.GetAssistType() > 0 {
|
|
aType, ok := plugin.ToAPIAssistType(arrayItem.GetAssistType())
|
|
if !ok {
|
|
return nil, errorx.New(errno.ErrPluginInvalidParamCode,
|
|
errorx.KVf(errno.PluginMsgKey, "the assist type '%s' of field '%s' is invalid", arrayItem.GetAssistType(), apiParam.Name))
|
|
}
|
|
itemSchema.Extensions[plugin.APISchemaExtendAssistType] = aType
|
|
format, ok := plugin.AssistTypeToFormat(aType)
|
|
if !ok {
|
|
return nil, errorx.New(errno.ErrPluginInvalidParamCode,
|
|
errorx.KVf(errno.PluginMsgKey, "the assist type '%s' of field '%s' is invalid", aType, apiParam.Name))
|
|
}
|
|
itemSchema.Format = format
|
|
}
|
|
|
|
paramSchema.Items = &openapi3.SchemaRef{
|
|
Value: itemSchema,
|
|
}
|
|
}
|
|
|
|
if apiParam.LocalDefault != nil && *apiParam.LocalDefault != "" {
|
|
paramSchema.Default = apiParam.LocalDefault
|
|
}
|
|
if apiParam.LocalDisable {
|
|
paramSchema.Extensions[plugin.APISchemaExtendLocalDisable] = true
|
|
}
|
|
if apiParam.VariableRef != nil && *apiParam.VariableRef != "" {
|
|
paramSchema.Extensions[plugin.APISchemaExtendVariableRef] = apiParam.VariableRef
|
|
}
|
|
|
|
if apiParam.GetAssistType() > 0 {
|
|
aType, ok := plugin.ToAPIAssistType(apiParam.GetAssistType())
|
|
if !ok {
|
|
return nil, errorx.New(errno.ErrPluginInvalidParamCode,
|
|
errorx.KVf(errno.PluginMsgKey, "the assist type '%s' of field '%s' is invalid", apiParam.GetAssistType(), apiParam.Name))
|
|
}
|
|
paramSchema.Extensions[plugin.APISchemaExtendAssistType] = aType
|
|
format, ok := plugin.AssistTypeToFormat(aType)
|
|
if !ok {
|
|
return nil, errorx.New(errno.ErrPluginInvalidParamCode,
|
|
errorx.KVf(errno.PluginMsgKey, "the assist type '%s' of field '%s' is invalid", aType, apiParam.Name))
|
|
}
|
|
paramSchema.Format = format
|
|
}
|
|
|
|
loc, ok := plugin.ToHTTPParamLocation(apiParam.Location)
|
|
if !ok {
|
|
return nil, errorx.New(errno.ErrPluginInvalidParamCode,
|
|
errorx.KVf(errno.PluginMsgKey, "the location '%s' of field '%s' is invalid ", apiParam.Location, apiParam.Name))
|
|
}
|
|
|
|
param := &openapi3.Parameter{
|
|
Description: apiParam.Desc,
|
|
Name: apiParam.Name,
|
|
In: string(loc),
|
|
Required: apiParam.IsRequired,
|
|
Schema: &openapi3.SchemaRef{
|
|
Value: paramSchema,
|
|
},
|
|
}
|
|
|
|
return param, nil
|
|
}
|
|
|
|
func toOpenapi3Schema(apiParam *common.APIParameter) (*openapi3.Schema, error) {
|
|
paramType, ok := plugin.ToOpenapiParamType(apiParam.Type)
|
|
if !ok {
|
|
return nil, errorx.New(errno.ErrPluginInvalidParamCode,
|
|
errorx.KVf(errno.PluginMsgKey, "the type '%s' of field '%s' is invalid", apiParam.Type, apiParam.Name))
|
|
}
|
|
|
|
sc := &openapi3.Schema{
|
|
Description: apiParam.Desc,
|
|
Type: paramType,
|
|
Default: apiParam.GlobalDefault,
|
|
Extensions: map[string]interface{}{
|
|
plugin.APISchemaExtendGlobalDisable: apiParam.GlobalDisable,
|
|
},
|
|
}
|
|
if apiParam.LocalDefault != nil && *apiParam.LocalDefault != "" {
|
|
sc.Default = apiParam.LocalDefault
|
|
}
|
|
if apiParam.LocalDisable {
|
|
sc.Extensions[plugin.APISchemaExtendLocalDisable] = true
|
|
}
|
|
if apiParam.VariableRef != nil && *apiParam.VariableRef != "" {
|
|
sc.Extensions[plugin.APISchemaExtendVariableRef] = apiParam.VariableRef
|
|
}
|
|
|
|
if apiParam.GetAssistType() > 0 {
|
|
aType, ok := plugin.ToAPIAssistType(apiParam.GetAssistType())
|
|
if !ok {
|
|
return nil, errorx.New(errno.ErrPluginInvalidParamCode,
|
|
errorx.KVf(errno.PluginMsgKey, "the assist type '%s' of field '%s' is invalid", apiParam.GetAssistType(), apiParam.Name))
|
|
}
|
|
sc.Extensions[plugin.APISchemaExtendAssistType] = aType
|
|
format, ok := plugin.AssistTypeToFormat(aType)
|
|
if !ok {
|
|
return nil, errorx.New(errno.ErrPluginInvalidParamCode,
|
|
errorx.KVf(errno.PluginMsgKey, "the assist type '%s' of field '%s' is invalid", aType, apiParam.Name))
|
|
}
|
|
sc.Format = format
|
|
}
|
|
|
|
switch paramType {
|
|
case openapi3.TypeObject:
|
|
sc.Properties = map[string]*openapi3.SchemaRef{}
|
|
for _, subParam := range apiParam.SubParameters {
|
|
_subParam, err := toOpenapi3Schema(subParam)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
sc.Properties[subParam.Name] = &openapi3.SchemaRef{
|
|
Value: _subParam,
|
|
}
|
|
if subParam.IsRequired {
|
|
sc.Required = append(sc.Required, subParam.Name)
|
|
}
|
|
}
|
|
|
|
return sc, nil
|
|
|
|
case openapi3.TypeArray:
|
|
if len(apiParam.SubParameters) == 0 {
|
|
return nil, errorx.New(errno.ErrPluginInvalidParamCode,
|
|
errorx.KVf(errno.PluginMsgKey, "the sub-parameters of field '%s' are required", apiParam.Name))
|
|
}
|
|
|
|
arrayItem := apiParam.SubParameters[0]
|
|
itemType, ok := plugin.ToOpenapiParamType(arrayItem.Type)
|
|
if !ok {
|
|
return nil, errorx.New(errno.ErrPluginInvalidParamCode,
|
|
errorx.KVf(errno.PluginMsgKey, "the item type '%s' of field '%s' is invalid", itemType, apiParam.Name))
|
|
}
|
|
|
|
subParam, err := toOpenapi3Schema(arrayItem)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
sc.Items = &openapi3.SchemaRef{
|
|
Value: subParam,
|
|
}
|
|
|
|
return sc, nil
|
|
}
|
|
|
|
return sc, nil
|
|
}
|