trpc.group/trpc-go/trpc-cmdline@v1.0.9/util/apidocs/method.go (about)

     1  // Tencent is pleased to support the open source community by making tRPC available.
     2  //
     3  // Copyright (C) 2023 THL A29 Limited, a Tencent company.
     4  // All rights reserved.
     5  //
     6  // If you have downloaded a copy of the tRPC source code from Tencent,
     7  // please note that tRPC source code is licensed under the  Apache 2.0 License,
     8  // A copy of the Apache 2.0 License is included in this file.
     9  
    10  package apidocs
    11  
    12  import "sort"
    13  
    14  // MethodStruct defines the detailed information of a method in apidocs.
    15  type MethodStruct struct {
    16  	Summary     string                 `json:"summary"`               // Comments of method.
    17  	OperationID string                 `json:"operationId"`           // Name of method.
    18  	Responses   map[string]MediaStruct `json:"responses"`             // Response.
    19  	Parameters  []*ParametersStruct    `json:"parameters"`            // Parameters.
    20  	Tags        []string               `json:"tags"`                  // The service to which the method belongs.
    21  	Description string                 `json:"description,omitempty"` // Description of the method.
    22  }
    23  
    24  // Methods is the set of methods.
    25  type Methods struct {
    26  	Elements map[string]*MethodStruct
    27  	Rank     map[string]int
    28  }
    29  
    30  // Put inserts an element into the ordered map, and records the element's rank in "Rank".
    31  func (methods *Methods) Put(key string, value *MethodStruct) {
    32  	methods.Elements[key] = value
    33  
    34  	if methods.Rank != nil {
    35  		if _, ok := methods.Rank[key]; !ok {
    36  			methods.Rank[key] = len(methods.Elements)
    37  		}
    38  	}
    39  }
    40  
    41  // UnmarshalJSON deserializes JSON data.
    42  func (methods *Methods) UnmarshalJSON(b []byte) error {
    43  	return OrderedUnmarshalJSON(b, &methods.Elements, &methods.Rank)
    44  }
    45  
    46  // MarshalJSON serializes the method to JSON.
    47  func (methods Methods) MarshalJSON() ([]byte, error) {
    48  	return OrderedMarshalJSON(methods.Elements, methods.Rank)
    49  }
    50  
    51  func (methods *Methods) orderedEach(f func(k string, m *MethodStruct)) {
    52  	if methods == nil {
    53  		return
    54  	}
    55  
    56  	var keys []string
    57  	for k := range methods.Elements {
    58  		keys = append(keys, k)
    59  	}
    60  
    61  	if methods.Rank != nil {
    62  		sort.Slice(keys, func(i, j int) bool {
    63  			return methods.Rank[keys[i]] < methods.Rank[keys[j]]
    64  		})
    65  	} else {
    66  		sort.Strings(keys)
    67  	}
    68  
    69  	for _, k := range keys {
    70  		f(k, methods.Elements[k])
    71  	}
    72  }
    73  
    74  func (m MethodStruct) refs() []string {
    75  	var refs []string
    76  	for _, responses := range m.Responses {
    77  		if len(responses.Schema.Ref) > 0 {
    78  			refs = append(refs, GetNameByRef(responses.Schema.Ref))
    79  		}
    80  	}
    81  	for _, parameter := range m.Parameters {
    82  		if parameter.Schema != nil && len(parameter.Schema.Ref) > 0 {
    83  			refs = append(refs, GetNameByRef(parameter.Schema.Ref))
    84  		}
    85  		if parameter.Items != nil {
    86  			refs = append(refs, parameter.Items.refs(make(map[string]bool))...)
    87  		}
    88  	}
    89  	return refs
    90  }
    91  
    92  // GetMethodX converts MethodStruct to OpenAPI v3 interface.
    93  func (m MethodStruct) GetMethodX() *MethodStructX {
    94  	methodX := &MethodStructX{
    95  		Summary:     m.Summary,
    96  		OperationID: m.OperationID,
    97  		Responses:   make(map[string]BodyContentStruct),
    98  		RequestBody: nil,
    99  		Tags:        m.Tags,
   100  		Description: m.Description,
   101  	}
   102  
   103  	// Returned values.
   104  	for status, r := range m.Responses {
   105  		resp := BodyContentStruct{
   106  			Description: r.Description,
   107  			Content: map[string]MediaStruct{
   108  				"application/json": {
   109  					Schema: r.Schema,
   110  				},
   111  			},
   112  		}
   113  		methodX.Responses[status] = resp
   114  	}
   115  
   116  	// Parameters.
   117  	var props []*PropertyStruct
   118  	for _, param := range m.Parameters {
   119  		if param.In != "body" {
   120  			methodX.Parameters = append(methodX.Parameters, param.GetParametersStructX())
   121  			continue
   122  		}
   123  
   124  		if param.Schema != nil && param.Schema.Ref != "" {
   125  			methodX.RequestBody = param.GetRequestBody()
   126  			continue
   127  		}
   128  
   129  		props = append(props, param.GetProperty())
   130  	}
   131  
   132  	if len(props) != 0 {
   133  		methodX.RequestBody = &BodyContentStruct{
   134  			Content: map[string]MediaStruct{
   135  				"application/json": {
   136  					Schema: SchemaStruct{
   137  						Properties: props,
   138  					},
   139  				},
   140  			},
   141  		}
   142  	}
   143  
   144  	return methodX
   145  }
   146  
   147  // GetMethodsX converts MethodStruct to OpenAPI v3 interface.
   148  func (methods Methods) GetMethodsX() MethodsX {
   149  	methodsX := MethodsX{Elements: make(map[string]*MethodStructX)}
   150  	methodsX.Rank = methods.Rank
   151  	methods.orderedEach(func(name string, method *MethodStruct) {
   152  		methodsX.Elements[name] = method.GetMethodX()
   153  	})
   154  	return methodsX
   155  }