mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-11-05 03:12:27 -06:00
[bugfix] Fix Swagger spec and add test script (#2698)
* Add Swagger spec test script * Fix Swagger spec errors not related to statuses with polls * Add API tests that post a status with a poll * Fix creating a status with a poll from form params * Fix Swagger spec errors related to statuses with polls (this is the last error) * Fix Swagger spec warnings not related to unused definitions * Suppress a duplicate list update params definition that was somehow causing wrong param names * Add Swagger test to CI - updates Drone config - vendorizes go-swagger - fixes a file extension issue that caused the test script to generate JSON instead of YAML with the vendorized version * Put `Sample: ` on its own line everywhere * Remove unused id param from emojiCategoriesGet * Add 5 more pairs of profile fields to account update API Swagger * Remove Swagger prefix from dummy fields It makes the generated code look weird * Manually annotate params for statusCreate operation * Fix all remaining Swagger spec warnings - Change some models into operation parameters - Ignore models that already correspond to manually documented operation parameters but can't be trivially changed (those with file fields) * Documented that creating a status with scheduled_at isn't implemented yet * sign drone.yml * Fix filter API Swagger errors * fixup! Fix filter API Swagger errors --------- Co-authored-by: tobi <tobi.smethurst@protonmail.com>
This commit is contained in:
parent
68c8fe67cc
commit
fc3741365c
672 changed files with 135624 additions and 713 deletions
202
vendor/github.com/go-swagger/go-swagger/LICENSE
generated
vendored
Normal file
202
vendor/github.com/go-swagger/go-swagger/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
||||
5
vendor/github.com/go-swagger/go-swagger/cmd/swagger/.gitignore
generated
vendored
Normal file
5
vendor/github.com/go-swagger/go-swagger/cmd/swagger/.gitignore
generated
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
swagger
|
||||
swagger.json
|
||||
models
|
||||
operations
|
||||
cmd
|
||||
145
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff.go
generated
vendored
Normal file
145
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff.go
generated
vendored
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"errors"
|
||||
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-swagger/go-swagger/cmd/swagger/commands/diff"
|
||||
)
|
||||
|
||||
// JSONFormat for json
|
||||
const JSONFormat = "json"
|
||||
|
||||
// DiffCommand is a command that generates the diff of two swagger specs.
|
||||
//
|
||||
// There are no specific options for this expansion.
|
||||
type DiffCommand struct {
|
||||
OnlyBreakingChanges bool `long:"break" short:"b" description:"When present, only shows incompatible changes"`
|
||||
Format string `long:"format" short:"f" description:"When present, writes output as json" default:"txt" choice:"txt" choice:"json"`
|
||||
IgnoreFile string `long:"ignore" short:"i" description:"Exception file of diffs to ignore (copy output from json diff format)" default:"none specified"`
|
||||
Destination string `long:"dest" short:"d" description:"Output destination file or stdout" default:"stdout"`
|
||||
Args struct {
|
||||
OldSpec string `positional-arg-name:"{old spec}"`
|
||||
NewSpec string `positional-arg-name:"{new spec}"`
|
||||
} `required:"2" positional-args:"specs" description:"Input specs to be diff-ed"`
|
||||
}
|
||||
|
||||
// Execute diffs the two specs provided
|
||||
func (c *DiffCommand) Execute(_ []string) error {
|
||||
if c.Args.OldSpec == "" || c.Args.NewSpec == "" {
|
||||
return errors.New(`missing arguments for diff command (use --help for more info)`)
|
||||
}
|
||||
|
||||
c.printInfo()
|
||||
|
||||
var (
|
||||
output io.WriteCloser
|
||||
err error
|
||||
)
|
||||
if c.Destination != "stdout" {
|
||||
output, err = os.OpenFile(c.Destination, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %w", c.Destination, err)
|
||||
}
|
||||
defer func() {
|
||||
_ = output.Close()
|
||||
}()
|
||||
} else {
|
||||
output = os.Stdout
|
||||
}
|
||||
|
||||
diffs, err := c.getDiffs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ignores, err := c.readIgnores()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
diffs = diffs.FilterIgnores(ignores)
|
||||
if len(ignores) > 0 {
|
||||
log.Printf("Diff Report Ignored Items from IgnoreFile")
|
||||
for _, eachItem := range ignores {
|
||||
log.Printf("%s", eachItem.String())
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
input io.Reader
|
||||
warn error
|
||||
)
|
||||
if c.Format != JSONFormat && c.OnlyBreakingChanges {
|
||||
input, err, warn = diffs.ReportCompatibility()
|
||||
} else {
|
||||
input, err, warn = diffs.ReportAllDiffs(c.Format == JSONFormat)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = io.Copy(output, input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return warn
|
||||
}
|
||||
|
||||
func (c *DiffCommand) readIgnores() (diff.SpecDifferences, error) {
|
||||
ignoreFile := c.IgnoreFile
|
||||
ignoreDiffs := diff.SpecDifferences{}
|
||||
|
||||
if ignoreFile == "none specified" || ignoreFile == "" {
|
||||
return ignoreDiffs, nil
|
||||
}
|
||||
// Open our jsonFile
|
||||
jsonFile, err := os.Open(ignoreFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %w", ignoreFile, err)
|
||||
}
|
||||
defer func() {
|
||||
_ = jsonFile.Close()
|
||||
}()
|
||||
byteValue, err := io.ReadAll(jsonFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("reading %s: %w", ignoreFile, err)
|
||||
}
|
||||
err = json.Unmarshal(byteValue, &ignoreDiffs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ignoreDiffs, nil
|
||||
}
|
||||
|
||||
func (c *DiffCommand) getDiffs() (diff.SpecDifferences, error) {
|
||||
oldSpecPath, newSpecPath := c.Args.OldSpec, c.Args.NewSpec
|
||||
swaggerDoc1 := oldSpecPath
|
||||
specDoc1, err := loads.Spec(swaggerDoc1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
swaggerDoc2 := newSpecPath
|
||||
specDoc2, err := loads.Spec(swaggerDoc2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return diff.Compare(specDoc1.Spec(), specDoc2.Spec())
|
||||
}
|
||||
|
||||
func (c *DiffCommand) printInfo() {
|
||||
log.Println("Run Config:")
|
||||
log.Printf("Spec1: %s", c.Args.OldSpec)
|
||||
log.Printf("Spec2: %s", c.Args.NewSpec)
|
||||
log.Printf("ReportOnlyBreakingChanges (-c) :%v", c.OnlyBreakingChanges)
|
||||
log.Printf("OutputFormat (-f) :%s", c.Format)
|
||||
log.Printf("IgnoreFile (-i) :%s", c.IgnoreFile)
|
||||
log.Printf("Diff Report Destination (-d) :%s", c.Destination)
|
||||
}
|
||||
106
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/array_diff.go
generated
vendored
Normal file
106
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/array_diff.go
generated
vendored
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
package diff
|
||||
|
||||
// This is a simple DSL for diffing arrays
|
||||
|
||||
// fromArrayStruct utility struct to encompass diffing of string arrays
|
||||
type fromArrayStruct struct {
|
||||
from []string
|
||||
}
|
||||
|
||||
// fromStringArray starts a fluent diff expression
|
||||
func fromStringArray(from []string) fromArrayStruct {
|
||||
return fromArrayStruct{from}
|
||||
}
|
||||
|
||||
// DiffsTo completes a fluent diff expression
|
||||
func (f fromArrayStruct) DiffsTo(toArray []string) (added, deleted, common []string) {
|
||||
inFrom := 1
|
||||
inTo := 2
|
||||
|
||||
if f.from == nil {
|
||||
return toArray, []string{}, []string{}
|
||||
}
|
||||
|
||||
m := make(map[string]int, len(toArray))
|
||||
added = make([]string, 0, len(toArray))
|
||||
deleted = make([]string, 0, len(f.from))
|
||||
common = make([]string, 0, len(f.from))
|
||||
|
||||
for _, item := range f.from {
|
||||
m[item] = inFrom
|
||||
}
|
||||
|
||||
for _, item := range toArray {
|
||||
if _, ok := m[item]; ok {
|
||||
m[item] |= inTo
|
||||
} else {
|
||||
m[item] = inTo
|
||||
}
|
||||
}
|
||||
for key, val := range m {
|
||||
switch val {
|
||||
case inFrom:
|
||||
deleted = append(deleted, key)
|
||||
case inTo:
|
||||
added = append(added, key)
|
||||
default:
|
||||
common = append(common, key)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// fromMapStruct utility struct to encompass diffing of string arrays
|
||||
type fromMapStruct struct {
|
||||
srcMap map[string]interface{}
|
||||
}
|
||||
|
||||
// fromStringMap starts a comparison by declaring a source map
|
||||
func fromStringMap(srcMap map[string]interface{}) fromMapStruct {
|
||||
return fromMapStruct{srcMap}
|
||||
}
|
||||
|
||||
// Pair stores a pair of items which share a key in two maps
|
||||
type Pair struct {
|
||||
First interface{}
|
||||
Second interface{}
|
||||
}
|
||||
|
||||
// DiffsTo - generates diffs for a comparison
|
||||
func (f fromMapStruct) DiffsTo(destMap map[string]interface{}) (added, deleted, common map[string]interface{}) {
|
||||
added = make(map[string]interface{})
|
||||
deleted = make(map[string]interface{})
|
||||
common = make(map[string]interface{})
|
||||
|
||||
inSrc := 1
|
||||
inDest := 2
|
||||
|
||||
m := make(map[string]int)
|
||||
|
||||
// enter values for all items in the source array
|
||||
for key := range f.srcMap {
|
||||
m[key] = inSrc
|
||||
}
|
||||
|
||||
// now either set or 'boolean or' a new flag if in the second collection
|
||||
for key := range destMap {
|
||||
if _, ok := m[key]; ok {
|
||||
m[key] |= inDest
|
||||
} else {
|
||||
m[key] = inDest
|
||||
}
|
||||
}
|
||||
// finally inspect the values and generate the left,right and shared collections
|
||||
// for the shared items, store both values in case there's a diff
|
||||
for key, val := range m {
|
||||
switch val {
|
||||
case inSrc:
|
||||
deleted[key] = f.srcMap[key]
|
||||
case inDest:
|
||||
added[key] = destMap[key]
|
||||
default:
|
||||
common[key] = Pair{f.srcMap[key], destMap[key]}
|
||||
}
|
||||
}
|
||||
return added, deleted, common
|
||||
}
|
||||
266
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/checks.go
generated
vendored
Normal file
266
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/checks.go
generated
vendored
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
package diff
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
// CompareEnums returns added, deleted enum values
|
||||
func CompareEnums(left, right []interface{}) []TypeDiff {
|
||||
diffs := []TypeDiff{}
|
||||
|
||||
leftStrs := []string{}
|
||||
rightStrs := []string{}
|
||||
for _, eachLeft := range left {
|
||||
leftStrs = append(leftStrs, fmt.Sprintf("%v", eachLeft))
|
||||
}
|
||||
for _, eachRight := range right {
|
||||
rightStrs = append(rightStrs, fmt.Sprintf("%v", eachRight))
|
||||
}
|
||||
added, deleted, _ := fromStringArray(leftStrs).DiffsTo(rightStrs)
|
||||
if len(added) > 0 {
|
||||
typeChange := strings.Join(added, ",")
|
||||
diffs = append(diffs, TypeDiff{Change: AddedEnumValue, Description: typeChange})
|
||||
}
|
||||
if len(deleted) > 0 {
|
||||
typeChange := strings.Join(deleted, ",")
|
||||
diffs = append(diffs, TypeDiff{Change: DeletedEnumValue, Description: typeChange})
|
||||
}
|
||||
|
||||
return diffs
|
||||
}
|
||||
|
||||
// CompareProperties recursive property comparison
|
||||
func CompareProperties(location DifferenceLocation, schema1 *spec.Schema, schema2 *spec.Schema, getRefFn1 SchemaFromRefFn, getRefFn2 SchemaFromRefFn, cmp CompareSchemaFn) []SpecDifference {
|
||||
propDiffs := []SpecDifference{}
|
||||
|
||||
if schema1.Properties == nil && schema2.Properties == nil {
|
||||
return propDiffs
|
||||
}
|
||||
|
||||
schema1Props := propertiesFor(schema1, getRefFn1)
|
||||
schema2Props := propertiesFor(schema2, getRefFn2)
|
||||
// find deleted and changed properties
|
||||
|
||||
for eachProp1Name, eachProp1 := range schema1Props {
|
||||
eachProp1 := eachProp1
|
||||
childLoc := addChildDiffNode(location, eachProp1Name, eachProp1.Schema)
|
||||
|
||||
if eachProp2, ok := schema2Props[eachProp1Name]; ok {
|
||||
diffs := CheckToFromRequired(eachProp1.Required, eachProp2.Required)
|
||||
if len(diffs) > 0 {
|
||||
for _, diff := range diffs {
|
||||
propDiffs = append(propDiffs, SpecDifference{DifferenceLocation: childLoc, Code: diff.Change})
|
||||
}
|
||||
}
|
||||
cmp(childLoc, eachProp1.Schema, eachProp2.Schema)
|
||||
} else {
|
||||
propDiffs = append(propDiffs, SpecDifference{DifferenceLocation: childLoc, Code: DeletedProperty})
|
||||
}
|
||||
}
|
||||
|
||||
// find added properties
|
||||
for eachProp2Name, eachProp2 := range schema2.Properties {
|
||||
eachProp2 := eachProp2
|
||||
if _, ok := schema1.Properties[eachProp2Name]; !ok {
|
||||
childLoc := addChildDiffNode(location, eachProp2Name, &eachProp2)
|
||||
propDiffs = append(propDiffs, SpecDifference{DifferenceLocation: childLoc, Code: AddedProperty})
|
||||
}
|
||||
}
|
||||
return propDiffs
|
||||
|
||||
}
|
||||
|
||||
// CompareFloatValues compares a float data item
|
||||
func CompareFloatValues(fieldName string, val1 *float64, val2 *float64, ifGreaterCode SpecChangeCode, ifLessCode SpecChangeCode) []TypeDiff {
|
||||
diffs := []TypeDiff{}
|
||||
if val1 != nil && val2 != nil {
|
||||
if *val2 > *val1 {
|
||||
diffs = append(diffs, TypeDiff{Change: ifGreaterCode, Description: fmt.Sprintf("%s %f->%f", fieldName, *val1, *val2)})
|
||||
} else if *val2 < *val1 {
|
||||
diffs = append(diffs, TypeDiff{Change: ifLessCode, Description: fmt.Sprintf("%s %f->%f", fieldName, *val1, *val2)})
|
||||
}
|
||||
} else {
|
||||
if val1 != val2 {
|
||||
if val1 != nil {
|
||||
diffs = append(diffs, TypeDiff{Change: DeletedConstraint, Description: fmt.Sprintf("%s(%f)", fieldName, *val1)})
|
||||
} else {
|
||||
diffs = append(diffs, TypeDiff{Change: AddedConstraint, Description: fmt.Sprintf("%s(%f)", fieldName, *val2)})
|
||||
}
|
||||
}
|
||||
}
|
||||
return diffs
|
||||
}
|
||||
|
||||
// CompareIntValues compares to int data items
|
||||
func CompareIntValues(fieldName string, val1 *int64, val2 *int64, ifGreaterCode SpecChangeCode, ifLessCode SpecChangeCode) []TypeDiff {
|
||||
diffs := []TypeDiff{}
|
||||
if val1 != nil && val2 != nil {
|
||||
if *val2 > *val1 {
|
||||
diffs = append(diffs, TypeDiff{Change: ifGreaterCode, Description: fmt.Sprintf("%s %d->%d", fieldName, *val1, *val2)})
|
||||
} else if *val2 < *val1 {
|
||||
diffs = append(diffs, TypeDiff{Change: ifLessCode, Description: fmt.Sprintf("%s %d->%d", fieldName, *val1, *val2)})
|
||||
}
|
||||
} else {
|
||||
if val1 != val2 {
|
||||
if val1 != nil {
|
||||
diffs = append(diffs, TypeDiff{Change: DeletedConstraint, Description: fmt.Sprintf("%s(%d)", fieldName, *val1)})
|
||||
} else {
|
||||
diffs = append(diffs, TypeDiff{Change: AddedConstraint, Description: fmt.Sprintf("%s(%d)", fieldName, *val2)})
|
||||
}
|
||||
}
|
||||
}
|
||||
return diffs
|
||||
}
|
||||
|
||||
// CheckToFromPrimitiveType check for diff to or from a primitive
|
||||
func CheckToFromPrimitiveType(diffs []TypeDiff, type1, type2 interface{}) []TypeDiff {
|
||||
|
||||
type1IsPrimitive := isPrimitive(type1)
|
||||
type2IsPrimitive := isPrimitive(type2)
|
||||
|
||||
// Primitive to Obj or Obj to Primitive
|
||||
if type1IsPrimitive != type2IsPrimitive {
|
||||
typeStr1, isarray1 := getSchemaType(type1)
|
||||
typeStr2, isarray2 := getSchemaType(type2)
|
||||
return addTypeDiff(diffs, TypeDiff{Change: ChangedType, FromType: formatTypeString(typeStr1, isarray1), ToType: formatTypeString(typeStr2, isarray2)})
|
||||
}
|
||||
|
||||
return diffs
|
||||
}
|
||||
|
||||
// CheckRefChange has the property ref changed
|
||||
func CheckRefChange(diffs []TypeDiff, type1, type2 interface{}) (diffReturn []TypeDiff) {
|
||||
|
||||
diffReturn = diffs
|
||||
if isRefType(type1) && isRefType(type2) {
|
||||
// both refs but to different objects (TODO detect renamed object)
|
||||
ref1 := definitionFromRef(getRef(type1))
|
||||
ref2 := definitionFromRef(getRef(type2))
|
||||
if ref1 != ref2 {
|
||||
diffReturn = addTypeDiff(diffReturn, TypeDiff{Change: RefTargetChanged, FromType: getSchemaTypeStr(type1), ToType: getSchemaTypeStr(type2)})
|
||||
}
|
||||
} else if isRefType(type1) != isRefType(type2) {
|
||||
diffReturn = addTypeDiff(diffReturn, TypeDiff{Change: ChangedType, FromType: getSchemaTypeStr(type1), ToType: getSchemaTypeStr(type2)})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// checkNumericTypeChanges checks for changes to or from a numeric type
|
||||
func checkNumericTypeChanges(diffs []TypeDiff, type1, type2 *spec.SchemaProps) []TypeDiff {
|
||||
// Number
|
||||
_, type1IsNumeric := numberWideness[type1.Type[0]]
|
||||
_, type2IsNumeric := numberWideness[type2.Type[0]]
|
||||
|
||||
if type1IsNumeric && type2IsNumeric {
|
||||
foundDiff := false
|
||||
if type1.ExclusiveMaximum && !type2.ExclusiveMaximum {
|
||||
diffs = addTypeDiff(diffs, TypeDiff{Change: WidenedType, Description: fmt.Sprintf("Exclusive Maximum Removed:%v->%v", type1.ExclusiveMaximum, type2.ExclusiveMaximum)})
|
||||
foundDiff = true
|
||||
}
|
||||
if !type1.ExclusiveMaximum && type2.ExclusiveMaximum {
|
||||
diffs = addTypeDiff(diffs, TypeDiff{Change: NarrowedType, Description: fmt.Sprintf("Exclusive Maximum Added:%v->%v", type1.ExclusiveMaximum, type2.ExclusiveMaximum)})
|
||||
foundDiff = true
|
||||
}
|
||||
if type1.ExclusiveMinimum && !type2.ExclusiveMinimum {
|
||||
diffs = addTypeDiff(diffs, TypeDiff{Change: WidenedType, Description: fmt.Sprintf("Exclusive Minimum Removed:%v->%v", type1.ExclusiveMaximum, type2.ExclusiveMaximum)})
|
||||
foundDiff = true
|
||||
}
|
||||
if !type1.ExclusiveMinimum && type2.ExclusiveMinimum {
|
||||
diffs = addTypeDiff(diffs, TypeDiff{Change: NarrowedType, Description: fmt.Sprintf("Exclusive Minimum Added:%v->%v", type1.ExclusiveMinimum, type2.ExclusiveMinimum)})
|
||||
foundDiff = true
|
||||
}
|
||||
if !foundDiff {
|
||||
maxDiffs := CompareFloatValues("Maximum", type1.Maximum, type2.Maximum, WidenedType, NarrowedType)
|
||||
diffs = append(diffs, maxDiffs...)
|
||||
minDiffs := CompareFloatValues("Minimum", type1.Minimum, type2.Minimum, NarrowedType, WidenedType)
|
||||
diffs = append(diffs, minDiffs...)
|
||||
}
|
||||
}
|
||||
return diffs
|
||||
}
|
||||
|
||||
// CheckStringTypeChanges checks for changes to or from a string type
|
||||
func CheckStringTypeChanges(diffs []TypeDiff, type1, type2 *spec.SchemaProps) []TypeDiff {
|
||||
// string changes
|
||||
if type1.Type[0] == StringType &&
|
||||
type2.Type[0] == StringType {
|
||||
minLengthDiffs := CompareIntValues("MinLength", type1.MinLength, type2.MinLength, NarrowedType, WidenedType)
|
||||
diffs = append(diffs, minLengthDiffs...)
|
||||
maxLengthDiffs := CompareIntValues("MaxLength", type1.MinLength, type2.MinLength, WidenedType, NarrowedType)
|
||||
diffs = append(diffs, maxLengthDiffs...)
|
||||
if type1.Pattern != type2.Pattern {
|
||||
diffs = addTypeDiff(diffs, TypeDiff{Change: ChangedType, Description: fmt.Sprintf("Pattern Changed:%s->%s", type1.Pattern, type2.Pattern)})
|
||||
}
|
||||
if type1.Type[0] == StringType {
|
||||
if len(type1.Enum) > 0 {
|
||||
enumDiffs := CompareEnums(type1.Enum, type2.Enum)
|
||||
diffs = append(diffs, enumDiffs...)
|
||||
}
|
||||
}
|
||||
}
|
||||
return diffs
|
||||
}
|
||||
|
||||
// CheckToFromRequired checks for changes to or from a required property
|
||||
func CheckToFromRequired(required1, required2 bool) (diffs []TypeDiff) {
|
||||
if required1 != required2 {
|
||||
code := ChangedOptionalToRequired
|
||||
if required1 {
|
||||
code = ChangedRequiredToOptional
|
||||
}
|
||||
diffs = addTypeDiff(diffs, TypeDiff{Change: code})
|
||||
}
|
||||
return diffs
|
||||
}
|
||||
|
||||
const objType = "object"
|
||||
|
||||
func getTypeHierarchyChange(type1, type2 string) TypeDiff {
|
||||
fromType := type1
|
||||
if fromType == "" {
|
||||
fromType = objType
|
||||
}
|
||||
toType := type2
|
||||
if toType == "" {
|
||||
toType = objType
|
||||
}
|
||||
diffDescription := fmt.Sprintf("%s -> %s", fromType, toType)
|
||||
if isStringType(type1) && !isStringType(type2) {
|
||||
return TypeDiff{Change: NarrowedType, Description: diffDescription}
|
||||
}
|
||||
if !isStringType(type1) && isStringType(type2) {
|
||||
return TypeDiff{Change: WidenedType, Description: diffDescription}
|
||||
}
|
||||
type1Wideness, type1IsNumeric := numberWideness[type1]
|
||||
type2Wideness, type2IsNumeric := numberWideness[type2]
|
||||
if type1IsNumeric && type2IsNumeric {
|
||||
if type1Wideness == type2Wideness {
|
||||
return TypeDiff{Change: ChangedToCompatibleType, Description: diffDescription}
|
||||
}
|
||||
if type1Wideness > type2Wideness {
|
||||
return TypeDiff{Change: NarrowedType, Description: diffDescription}
|
||||
}
|
||||
if type1Wideness < type2Wideness {
|
||||
return TypeDiff{Change: WidenedType, Description: diffDescription}
|
||||
}
|
||||
}
|
||||
return TypeDiff{Change: ChangedType, Description: diffDescription}
|
||||
}
|
||||
|
||||
func isRefType(item interface{}) bool {
|
||||
switch s := item.(type) {
|
||||
case spec.Refable:
|
||||
return s.Ref.String() != ""
|
||||
case *spec.Schema:
|
||||
return s.Ref.String() != ""
|
||||
case *spec.SchemaProps:
|
||||
return s.Ref.String() != ""
|
||||
case *spec.SimpleSchema:
|
||||
return false
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
111
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/compatibility.go
generated
vendored
Normal file
111
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/compatibility.go
generated
vendored
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
package diff
|
||||
|
||||
// CompatibilityPolicy decides which changes are breaking and which are not
|
||||
type CompatibilityPolicy struct {
|
||||
ForResponse map[SpecChangeCode]Compatibility
|
||||
ForRequest map[SpecChangeCode]Compatibility
|
||||
ForChange map[SpecChangeCode]Compatibility
|
||||
}
|
||||
|
||||
var compatibility CompatibilityPolicy
|
||||
|
||||
func init() {
|
||||
compatibility = CompatibilityPolicy{
|
||||
ForResponse: map[SpecChangeCode]Compatibility{
|
||||
AddedRequiredProperty: Breaking,
|
||||
DeletedProperty: Breaking,
|
||||
AddedProperty: NonBreaking,
|
||||
DeletedResponse: Breaking,
|
||||
AddedResponse: NonBreaking,
|
||||
WidenedType: NonBreaking,
|
||||
NarrowedType: NonBreaking,
|
||||
ChangedType: Breaking,
|
||||
ChangedToCompatibleType: NonBreaking,
|
||||
AddedEnumValue: Breaking,
|
||||
DeletedEnumValue: NonBreaking,
|
||||
AddedResponseHeader: NonBreaking,
|
||||
ChangedResponseHeader: Breaking,
|
||||
DeletedResponseHeader: Breaking,
|
||||
ChangedDescripton: NonBreaking,
|
||||
AddedDescripton: NonBreaking,
|
||||
DeletedDescripton: NonBreaking,
|
||||
ChangedTag: NonBreaking,
|
||||
AddedTag: NonBreaking,
|
||||
DeletedTag: NonBreaking,
|
||||
DeletedConstraint: Breaking,
|
||||
AddedConstraint: NonBreaking,
|
||||
DeletedExtension: Warning,
|
||||
AddedExtension: Warning,
|
||||
},
|
||||
ForRequest: map[SpecChangeCode]Compatibility{
|
||||
AddedRequiredProperty: Breaking,
|
||||
DeletedProperty: Breaking,
|
||||
AddedProperty: Breaking,
|
||||
AddedOptionalParam: NonBreaking,
|
||||
AddedRequiredParam: Breaking,
|
||||
DeletedOptionalParam: NonBreaking,
|
||||
DeletedRequiredParam: NonBreaking,
|
||||
WidenedType: NonBreaking,
|
||||
NarrowedType: Breaking,
|
||||
ChangedType: Breaking,
|
||||
ChangedToCompatibleType: NonBreaking,
|
||||
ChangedOptionalToRequired: Breaking,
|
||||
ChangedRequiredToOptional: NonBreaking,
|
||||
AddedEnumValue: NonBreaking,
|
||||
DeletedEnumValue: Breaking,
|
||||
ChangedDescripton: NonBreaking,
|
||||
AddedDescripton: NonBreaking,
|
||||
DeletedDescripton: NonBreaking,
|
||||
ChangedTag: NonBreaking,
|
||||
AddedTag: NonBreaking,
|
||||
DeletedTag: NonBreaking,
|
||||
DeletedConstraint: NonBreaking,
|
||||
AddedConstraint: Breaking,
|
||||
ChangedDefault: Warning,
|
||||
AddedDefault: Warning,
|
||||
DeletedDefault: Warning,
|
||||
ChangedExample: NonBreaking,
|
||||
AddedExample: NonBreaking,
|
||||
DeletedExample: NonBreaking,
|
||||
ChangedCollectionFormat: Breaking,
|
||||
DeletedExtension: Warning,
|
||||
AddedExtension: Warning,
|
||||
},
|
||||
ForChange: map[SpecChangeCode]Compatibility{
|
||||
NoChangeDetected: NonBreaking,
|
||||
AddedEndpoint: NonBreaking,
|
||||
DeletedEndpoint: Breaking,
|
||||
DeletedDeprecatedEndpoint: NonBreaking,
|
||||
AddedConsumesFormat: NonBreaking,
|
||||
DeletedConsumesFormat: Breaking,
|
||||
AddedProducesFormat: NonBreaking,
|
||||
DeletedProducesFormat: Breaking,
|
||||
AddedSchemes: NonBreaking,
|
||||
DeletedSchemes: Breaking,
|
||||
ChangedHostURL: Breaking,
|
||||
ChangedBasePath: Breaking,
|
||||
ChangedDescripton: NonBreaking,
|
||||
AddedDescripton: NonBreaking,
|
||||
DeletedDescripton: NonBreaking,
|
||||
ChangedTag: NonBreaking,
|
||||
AddedTag: NonBreaking,
|
||||
DeletedTag: NonBreaking,
|
||||
RefTargetChanged: Breaking,
|
||||
RefTargetRenamed: NonBreaking,
|
||||
AddedDefinition: NonBreaking,
|
||||
DeletedDefinition: NonBreaking,
|
||||
DeletedExtension: Warning,
|
||||
AddedExtension: Warning,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func getCompatibilityForChange(diffCode SpecChangeCode, where DataDirection) Compatibility {
|
||||
if compat, commonChange := compatibility.ForChange[diffCode]; commonChange {
|
||||
return compat
|
||||
}
|
||||
if where == Request {
|
||||
return compatibility.ForRequest[diffCode]
|
||||
}
|
||||
return compatibility.ForResponse[diffCode]
|
||||
}
|
||||
22
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/difference_location.go
generated
vendored
Normal file
22
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/difference_location.go
generated
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
package diff
|
||||
|
||||
// DifferenceLocation indicates where the difference occurs
|
||||
type DifferenceLocation struct {
|
||||
URL string `json:"url"`
|
||||
Method string `json:"method,omitempty"`
|
||||
Response int `json:"response,omitempty"`
|
||||
Node *Node `json:"node,omitempty"`
|
||||
}
|
||||
|
||||
// AddNode returns a copy of this location with the leaf node added
|
||||
func (dl DifferenceLocation) AddNode(node *Node) DifferenceLocation {
|
||||
newLoc := dl
|
||||
|
||||
if newLoc.Node != nil {
|
||||
newLoc.Node = newLoc.Node.Copy()
|
||||
newLoc.Node.AddLeafNode(node)
|
||||
} else {
|
||||
newLoc.Node = node
|
||||
}
|
||||
return newLoc
|
||||
}
|
||||
337
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/difftypes.go
generated
vendored
Normal file
337
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/difftypes.go
generated
vendored
Normal file
|
|
@ -0,0 +1,337 @@
|
|||
package diff
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
)
|
||||
|
||||
// SpecChangeCode enumerates the various types of diffs from one spec to another
|
||||
type SpecChangeCode int
|
||||
|
||||
const (
|
||||
// NoChangeDetected - the specs have no changes
|
||||
NoChangeDetected SpecChangeCode = iota
|
||||
// DeletedProperty - A message property has been deleted in the new spec
|
||||
DeletedProperty
|
||||
// AddedProperty - A message property has been added in the new spec
|
||||
AddedProperty
|
||||
// AddedRequiredProperty - A required message property has been added in the new spec
|
||||
AddedRequiredProperty
|
||||
// DeletedOptionalParam - An endpoint parameter has been deleted in the new spec
|
||||
DeletedOptionalParam
|
||||
// ChangedDescripton - Changed a description
|
||||
ChangedDescripton
|
||||
// AddedDescripton - Added a description
|
||||
AddedDescripton
|
||||
// DeletedDescripton - Deleted a description
|
||||
DeletedDescripton
|
||||
// ChangedTag - Changed a tag
|
||||
ChangedTag
|
||||
// AddedTag - Added a tag
|
||||
AddedTag
|
||||
// DeletedTag - Deleted a tag
|
||||
DeletedTag
|
||||
// DeletedResponse - An endpoint response has been deleted in the new spec
|
||||
DeletedResponse
|
||||
// DeletedEndpoint - An endpoint has been deleted in the new spec
|
||||
DeletedEndpoint
|
||||
// DeletedDeprecatedEndpoint - A deprecated endpoint has been deleted in the new spec
|
||||
DeletedDeprecatedEndpoint
|
||||
// AddedRequiredParam - A required parameter has been added in the new spec
|
||||
AddedRequiredParam
|
||||
// DeletedRequiredParam - A required parameter has been deleted in the new spec
|
||||
DeletedRequiredParam
|
||||
// AddedEndpoint - An endpoint has been added in the new spec
|
||||
AddedEndpoint
|
||||
// WidenedType - An type has been changed to a more permissive type eg int->string
|
||||
WidenedType
|
||||
// NarrowedType - An type has been changed to a less permissive type eg string->int
|
||||
NarrowedType
|
||||
// ChangedToCompatibleType - An type has been changed to a compatible type eg password->string
|
||||
ChangedToCompatibleType
|
||||
// ChangedType - An type has been changed to a type whose relative compatibility cannot be determined
|
||||
ChangedType
|
||||
// AddedEnumValue - An enum type has had a new potential value added to it
|
||||
AddedEnumValue
|
||||
// DeletedEnumValue - An enum type has had a existing value removed from it
|
||||
DeletedEnumValue
|
||||
// AddedOptionalParam - A new optional parameter has been added to the new spec
|
||||
AddedOptionalParam
|
||||
// ChangedOptionalToRequired - An optional parameter is now required in the new spec
|
||||
ChangedOptionalToRequired
|
||||
// ChangedRequiredToOptional - An required parameter is now optional in the new spec
|
||||
ChangedRequiredToOptional
|
||||
// AddedResponse An endpoint has new response code in the new spec
|
||||
AddedResponse
|
||||
// AddedConsumesFormat - a new consumes format (json/xml/yaml etc) has been added in the new spec
|
||||
AddedConsumesFormat
|
||||
// DeletedConsumesFormat - an existing format has been removed in the new spec
|
||||
DeletedConsumesFormat
|
||||
// AddedProducesFormat - a new produces format (json/xml/yaml etc) has been added in the new spec
|
||||
AddedProducesFormat
|
||||
// DeletedProducesFormat - an existing produces format has been removed in the new spec
|
||||
DeletedProducesFormat
|
||||
// AddedSchemes - a new scheme has been added to the new spec
|
||||
AddedSchemes
|
||||
// DeletedSchemes - a scheme has been removed from the new spec
|
||||
DeletedSchemes
|
||||
// ChangedHostURL - the host url has been changed. If this is used in the client generation, then clients will break.
|
||||
ChangedHostURL
|
||||
// ChangedBasePath - the host base path has been changed. If this is used in the client generation, then clients will break.
|
||||
ChangedBasePath
|
||||
// AddedResponseHeader Added a header Item
|
||||
AddedResponseHeader
|
||||
// ChangedResponseHeader Added a header Item
|
||||
ChangedResponseHeader
|
||||
// DeletedResponseHeader Added a header Item
|
||||
DeletedResponseHeader
|
||||
// RefTargetChanged Changed a ref to point to a different object
|
||||
RefTargetChanged
|
||||
// RefTargetRenamed Renamed a ref to point to the same object
|
||||
RefTargetRenamed
|
||||
// DeletedConstraint Deleted a schema constraint
|
||||
DeletedConstraint
|
||||
// AddedConstraint Added a schema constraint
|
||||
AddedConstraint
|
||||
// DeletedDefinition removed one of the definitions
|
||||
DeletedDefinition
|
||||
// AddedDefinition removed one of the definitions
|
||||
AddedDefinition
|
||||
// ChangedDefault - Changed default value
|
||||
ChangedDefault
|
||||
// AddedDefault - Added a default value
|
||||
AddedDefault
|
||||
// DeletedDefault - Deleted a default value
|
||||
DeletedDefault
|
||||
// ChangedExample - Changed an example value
|
||||
ChangedExample
|
||||
// AddedExample - Added an example value
|
||||
AddedExample
|
||||
// DeletedExample - Deleted an example value
|
||||
DeletedExample
|
||||
// ChangedCollectionFormat - A collectionFormat has been changed to a collectionFormat whose relative compatibility cannot be determined
|
||||
ChangedCollectionFormat
|
||||
// DeletedExtension deleted an extension
|
||||
DeletedExtension
|
||||
// AddedExtension added an extension
|
||||
AddedExtension
|
||||
)
|
||||
|
||||
var toLongStringSpecChangeCode = map[SpecChangeCode]string{
|
||||
NoChangeDetected: "No Change detected",
|
||||
AddedEndpoint: "Added endpoint",
|
||||
DeletedEndpoint: "Deleted endpoint",
|
||||
DeletedDeprecatedEndpoint: "Deleted a deprecated endpoint",
|
||||
AddedRequiredProperty: "Added required property",
|
||||
DeletedProperty: "Deleted property",
|
||||
ChangedDescripton: "Changed a description",
|
||||
AddedDescripton: "Added a description",
|
||||
DeletedDescripton: "Deleted a description",
|
||||
ChangedTag: "Changed a tag",
|
||||
AddedTag: "Added a tag",
|
||||
DeletedTag: "Deleted a tag",
|
||||
AddedProperty: "Added property",
|
||||
AddedOptionalParam: "Added optional param",
|
||||
AddedRequiredParam: "Added required param",
|
||||
DeletedOptionalParam: "Deleted optional param",
|
||||
DeletedRequiredParam: "Deleted required param",
|
||||
DeletedResponse: "Deleted response",
|
||||
AddedResponse: "Added response",
|
||||
WidenedType: "Widened type",
|
||||
NarrowedType: "Narrowed type",
|
||||
ChangedType: "Changed type",
|
||||
ChangedToCompatibleType: "Changed type to equivalent type",
|
||||
ChangedOptionalToRequired: "Changed optional param to required",
|
||||
ChangedRequiredToOptional: "Changed required param to optional",
|
||||
AddedEnumValue: "Added possible enumeration(s)",
|
||||
DeletedEnumValue: "Deleted possible enumeration(s)",
|
||||
AddedConsumesFormat: "Added a consumes format",
|
||||
DeletedConsumesFormat: "Deleted a consumes format",
|
||||
AddedProducesFormat: "Added produces format",
|
||||
DeletedProducesFormat: "Deleted produces format",
|
||||
AddedSchemes: "Added schemes",
|
||||
DeletedSchemes: "Deleted schemes",
|
||||
ChangedHostURL: "Changed host URL",
|
||||
ChangedBasePath: "Changed base path",
|
||||
AddedResponseHeader: "Added response header",
|
||||
ChangedResponseHeader: "Changed response header",
|
||||
DeletedResponseHeader: "Deleted response header",
|
||||
RefTargetChanged: "Changed ref to different object",
|
||||
RefTargetRenamed: "Changed ref to renamed object",
|
||||
DeletedConstraint: "Deleted a schema constraint",
|
||||
AddedConstraint: "Added a schema constraint",
|
||||
DeletedDefinition: "Deleted a schema definition",
|
||||
AddedDefinition: "Added a schema definition",
|
||||
ChangedDefault: "Default value is changed",
|
||||
AddedDefault: "Default value is added",
|
||||
DeletedDefault: "Default value is removed",
|
||||
ChangedExample: "Example value is changed",
|
||||
AddedExample: "Example value is added",
|
||||
DeletedExample: "Example value is removed",
|
||||
ChangedCollectionFormat: "Changed collection format",
|
||||
DeletedExtension: "Deleted Extension",
|
||||
AddedExtension: "Added Extension",
|
||||
}
|
||||
|
||||
var toStringSpecChangeCode = map[SpecChangeCode]string{
|
||||
AddedEndpoint: "AddedEndpoint",
|
||||
NoChangeDetected: "NoChangeDetected",
|
||||
DeletedEndpoint: "DeletedEndpoint",
|
||||
DeletedDeprecatedEndpoint: "DeletedDeprecatedEndpoint",
|
||||
AddedRequiredProperty: "AddedRequiredProperty",
|
||||
DeletedProperty: "DeletedProperty",
|
||||
AddedProperty: "AddedProperty",
|
||||
ChangedDescripton: "ChangedDescription",
|
||||
AddedDescripton: "AddedDescription",
|
||||
DeletedDescripton: "DeletedDescription",
|
||||
ChangedTag: "ChangedTag",
|
||||
AddedTag: "AddedTag",
|
||||
DeletedTag: "DeletedTag",
|
||||
AddedOptionalParam: "AddedOptionalParam",
|
||||
AddedRequiredParam: "AddedRequiredParam",
|
||||
DeletedOptionalParam: "DeletedRequiredParam",
|
||||
DeletedRequiredParam: "Deleted required param",
|
||||
DeletedResponse: "DeletedResponse",
|
||||
AddedResponse: "AddedResponse",
|
||||
WidenedType: "WidenedType",
|
||||
NarrowedType: "NarrowedType",
|
||||
ChangedType: "ChangedType",
|
||||
ChangedToCompatibleType: "ChangedToCompatibleType",
|
||||
ChangedOptionalToRequired: "ChangedOptionalToRequiredParam",
|
||||
ChangedRequiredToOptional: "ChangedRequiredToOptionalParam",
|
||||
AddedEnumValue: "AddedEnumValue",
|
||||
DeletedEnumValue: "DeletedEnumValue",
|
||||
AddedConsumesFormat: "AddedConsumesFormat",
|
||||
DeletedConsumesFormat: "DeletedConsumesFormat",
|
||||
AddedProducesFormat: "AddedProducesFormat",
|
||||
DeletedProducesFormat: "DeletedProducesFormat",
|
||||
AddedSchemes: "AddedSchemes",
|
||||
DeletedSchemes: "DeletedSchemes",
|
||||
ChangedHostURL: "ChangedHostURL",
|
||||
ChangedBasePath: "ChangedBasePath",
|
||||
AddedResponseHeader: "AddedResponseHeader",
|
||||
ChangedResponseHeader: "ChangedResponseHeader",
|
||||
DeletedResponseHeader: "DeletedResponseHeader",
|
||||
RefTargetChanged: "RefTargetChanged",
|
||||
RefTargetRenamed: "RefTargetRenamed",
|
||||
DeletedConstraint: "DeletedConstraint",
|
||||
AddedConstraint: "AddedConstraint",
|
||||
DeletedDefinition: "DeletedDefinition",
|
||||
AddedDefinition: "AddedDefinition",
|
||||
ChangedDefault: "ChangedDefault",
|
||||
AddedDefault: "AddedDefault",
|
||||
DeletedDefault: "DeletedDefault",
|
||||
ChangedExample: "ChangedExample",
|
||||
AddedExample: "AddedExample",
|
||||
DeletedExample: "DeletedExample",
|
||||
ChangedCollectionFormat: "ChangedCollectionFormat",
|
||||
DeletedExtension: "DeletedExtension",
|
||||
AddedExtension: "AddedExtension",
|
||||
}
|
||||
|
||||
var toIDSpecChangeCode = map[string]SpecChangeCode{}
|
||||
|
||||
// Description returns an english version of this error
|
||||
func (s SpecChangeCode) Description() (result string) {
|
||||
result, ok := toLongStringSpecChangeCode[s]
|
||||
if !ok {
|
||||
log.Printf("warning: No description for %v", s)
|
||||
result = "UNDEFINED"
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalJSON marshals the enum as a quoted json string
|
||||
func (s SpecChangeCode) MarshalJSON() ([]byte, error) {
|
||||
return stringAsQuotedBytes(toStringSpecChangeCode[s])
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmashalls a quoted json string to the enum value
|
||||
func (s *SpecChangeCode) UnmarshalJSON(b []byte) error {
|
||||
str, err := readStringFromByteStream(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Note that if the string cannot be found then it will return an error to the caller.
|
||||
val, ok := toIDSpecChangeCode[str]
|
||||
|
||||
if ok {
|
||||
*s = val
|
||||
} else {
|
||||
return fmt.Errorf("unknown enum value. cannot unmarshal '%s'", str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Compatibility - whether this is a breaking or non-breaking change
|
||||
type Compatibility int
|
||||
|
||||
const (
|
||||
// Breaking this change could break existing clients
|
||||
Breaking Compatibility = iota
|
||||
// NonBreaking This is a backwards-compatible API change
|
||||
NonBreaking
|
||||
// Warning changes are technically non-breaking but can cause behavior changes in client and thus should be reported differently
|
||||
Warning
|
||||
)
|
||||
|
||||
func (s Compatibility) String() string {
|
||||
return toStringCompatibility[s]
|
||||
}
|
||||
|
||||
var toStringCompatibility = map[Compatibility]string{
|
||||
Breaking: "Breaking",
|
||||
NonBreaking: "NonBreaking",
|
||||
Warning: "Warning",
|
||||
}
|
||||
|
||||
var toIDCompatibility = map[string]Compatibility{}
|
||||
|
||||
// MarshalJSON marshals the enum as a quoted json string
|
||||
func (s Compatibility) MarshalJSON() ([]byte, error) {
|
||||
return stringAsQuotedBytes(toStringCompatibility[s])
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmashals a quoted json string to the enum value
|
||||
func (s *Compatibility) UnmarshalJSON(b []byte) error {
|
||||
str, err := readStringFromByteStream(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Note that if the string cannot be found then it will return an error to the caller.
|
||||
val, ok := toIDCompatibility[str]
|
||||
|
||||
if ok {
|
||||
*s = val
|
||||
} else {
|
||||
return fmt.Errorf("unknown enum value. cannot unmarshal '%s'", str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func stringAsQuotedBytes(str string) ([]byte, error) {
|
||||
buffer := bytes.NewBufferString(`"`)
|
||||
buffer.WriteString(str)
|
||||
buffer.WriteString(`"`)
|
||||
return buffer.Bytes(), nil
|
||||
}
|
||||
|
||||
func readStringFromByteStream(b []byte) (string, error) {
|
||||
var j string
|
||||
err := json.Unmarshal(b, &j)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return j, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
for key, val := range toStringSpecChangeCode {
|
||||
toIDSpecChangeCode[val] = key
|
||||
}
|
||||
for key, val := range toStringCompatibility {
|
||||
toIDCompatibility[val] = key
|
||||
}
|
||||
}
|
||||
82
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/node.go
generated
vendored
Normal file
82
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/node.go
generated
vendored
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
package diff
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
// Node is the position od a diff in a spec
|
||||
type Node struct {
|
||||
Field string `json:"name,omitempty"`
|
||||
TypeName string `json:"type,omitempty"`
|
||||
IsArray bool `json:"is_array,omitempty"`
|
||||
ChildNode *Node `json:"child,omitempty"`
|
||||
}
|
||||
|
||||
// String std string render
|
||||
func (n *Node) String() string {
|
||||
name := n.Field
|
||||
if n.IsArray {
|
||||
name = fmt.Sprintf("%s<array[%s]>", name, n.TypeName)
|
||||
} else if len(n.TypeName) > 0 {
|
||||
name = fmt.Sprintf("%s<%s>", name, n.TypeName)
|
||||
}
|
||||
if n.ChildNode != nil {
|
||||
return fmt.Sprintf("%s.%s", name, n.ChildNode.String())
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// AddLeafNode Adds (recursive) a Child to the first non-nil child found
|
||||
func (n *Node) AddLeafNode(toAdd *Node) *Node {
|
||||
|
||||
if n.ChildNode == nil {
|
||||
n.ChildNode = toAdd
|
||||
} else {
|
||||
n.ChildNode.AddLeafNode(toAdd)
|
||||
}
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
// Copy deep copy of this node and children
|
||||
func (n Node) Copy() *Node {
|
||||
newChild := n.ChildNode
|
||||
if newChild != nil {
|
||||
newChild = newChild.Copy()
|
||||
}
|
||||
newNode := Node{
|
||||
Field: n.Field,
|
||||
TypeName: n.TypeName,
|
||||
IsArray: n.IsArray,
|
||||
ChildNode: newChild,
|
||||
}
|
||||
|
||||
return &newNode
|
||||
}
|
||||
|
||||
func getSchemaDiffNode(name string, schema interface{}) *Node {
|
||||
node := Node{
|
||||
Field: name,
|
||||
}
|
||||
if schema != nil {
|
||||
switch s := schema.(type) {
|
||||
case spec.Refable:
|
||||
node.TypeName, node.IsArray = getSchemaType(s)
|
||||
case *spec.Schema:
|
||||
node.TypeName, node.IsArray = getSchemaType(s.SchemaProps)
|
||||
case spec.SimpleSchema:
|
||||
node.TypeName, node.IsArray = getSchemaType(s)
|
||||
case *spec.SimpleSchema:
|
||||
node.TypeName, node.IsArray = getSchemaType(s)
|
||||
case *spec.SchemaProps:
|
||||
node.TypeName, node.IsArray = getSchemaType(s)
|
||||
case spec.SchemaProps:
|
||||
node.TypeName, node.IsArray = getSchemaType(&s)
|
||||
default:
|
||||
node.TypeName = fmt.Sprintf("Unknown type %v", schema)
|
||||
}
|
||||
}
|
||||
return &node
|
||||
}
|
||||
118
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/reporting.go
generated
vendored
Normal file
118
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/reporting.go
generated
vendored
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
package diff
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
// ArrayType const for array
|
||||
var ArrayType = "array"
|
||||
|
||||
// ObjectType const for object
|
||||
var ObjectType = "object"
|
||||
|
||||
// Compare returns the result of analysing breaking and non breaking changes
|
||||
// between to Swagger specs
|
||||
func Compare(spec1, spec2 *spec.Swagger) (diffs SpecDifferences, err error) {
|
||||
analyser := NewSpecAnalyser()
|
||||
err = analyser.Analyse(spec1, spec2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
diffs = analyser.Diffs
|
||||
return
|
||||
}
|
||||
|
||||
// PathItemOp - combines path and operation into a single keyed entity
|
||||
type PathItemOp struct {
|
||||
ParentPathItem *spec.PathItem `json:"pathitem"`
|
||||
Operation *spec.Operation `json:"operation"`
|
||||
Extensions spec.Extensions `json:"extensions"`
|
||||
}
|
||||
|
||||
// URLMethod - combines url and method into a single keyed entity
|
||||
type URLMethod struct {
|
||||
Path string `json:"path"`
|
||||
Method string `json:"method"`
|
||||
}
|
||||
|
||||
// DataDirection indicates the direction of change Request vs Response
|
||||
type DataDirection int
|
||||
|
||||
const (
|
||||
// Request Used for messages/param diffs in a request
|
||||
Request DataDirection = iota
|
||||
// Response Used for messages/param diffs in a response
|
||||
Response
|
||||
)
|
||||
|
||||
func getParams(pathParams, opParams []spec.Parameter, location string) map[string]spec.Parameter {
|
||||
params := map[string]spec.Parameter{}
|
||||
// add shared path params
|
||||
for _, eachParam := range pathParams {
|
||||
if eachParam.In == location {
|
||||
params[eachParam.Name] = eachParam
|
||||
}
|
||||
}
|
||||
// add any overridden params
|
||||
for _, eachParam := range opParams {
|
||||
if eachParam.In == location {
|
||||
params[eachParam.Name] = eachParam
|
||||
}
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
func getNameOnlyDiffNode(forLocation string) *Node {
|
||||
node := Node{
|
||||
Field: forLocation,
|
||||
}
|
||||
return &node
|
||||
}
|
||||
|
||||
func primitiveTypeString(typeName, typeFormat string) string {
|
||||
if typeFormat != "" {
|
||||
return fmt.Sprintf("%s.%s", typeName, typeFormat)
|
||||
}
|
||||
return typeName
|
||||
}
|
||||
|
||||
// TypeDiff - describes a primitive type change
|
||||
type TypeDiff struct {
|
||||
Change SpecChangeCode `json:"change-type,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
FromType string `json:"from-type,omitempty"`
|
||||
ToType string `json:"to-type,omitempty"`
|
||||
}
|
||||
|
||||
// didn't use 'width' so as not to confuse with bit width
|
||||
var numberWideness = map[string]int{
|
||||
"number": 3,
|
||||
"number.double": 3,
|
||||
"double": 3,
|
||||
"number.float": 2,
|
||||
"float": 2,
|
||||
"long": 1,
|
||||
"integer.int64": 1,
|
||||
"integer": 0,
|
||||
"integer.int32": 0,
|
||||
}
|
||||
|
||||
func prettyprint(b []byte) (io.ReadWriter, error) {
|
||||
var out bytes.Buffer
|
||||
err := json.Indent(&out, b, "", " ")
|
||||
return &out, err
|
||||
}
|
||||
|
||||
// JSONMarshal allows the item to be correctly rendered to json
|
||||
func JSONMarshal(t interface{}) ([]byte, error) {
|
||||
buffer := &bytes.Buffer{}
|
||||
encoder := json.NewEncoder(buffer)
|
||||
encoder.SetEscapeHTML(false)
|
||||
err := encoder.Encode(t)
|
||||
return buffer.Bytes(), err
|
||||
}
|
||||
126
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/schema.go
generated
vendored
Normal file
126
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/schema.go
generated
vendored
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
package diff
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
func getTypeFromSchema(schema *spec.Schema) (typeName string, isArray bool) {
|
||||
refStr := definitionFromRef(schema.Ref)
|
||||
if len(refStr) > 0 {
|
||||
return refStr, false
|
||||
}
|
||||
typeName = schema.Type[0]
|
||||
if typeName == ArrayType {
|
||||
typeName, _ = getSchemaType(&schema.Items.Schema.SchemaProps)
|
||||
return typeName, true
|
||||
}
|
||||
return typeName, false
|
||||
|
||||
}
|
||||
|
||||
func getTypeFromSimpleSchema(schema *spec.SimpleSchema) (typeName string, isArray bool) {
|
||||
typeName = schema.Type
|
||||
format := schema.Format
|
||||
if len(format) > 0 {
|
||||
typeName = fmt.Sprintf("%s.%s", typeName, format)
|
||||
}
|
||||
if typeName == ArrayType {
|
||||
typeName, _ = getSchemaType(&schema.Items.SimpleSchema)
|
||||
return typeName, true
|
||||
}
|
||||
return typeName, false
|
||||
|
||||
}
|
||||
|
||||
func getTypeFromSchemaProps(schema *spec.SchemaProps) (typeName string, isArray bool) {
|
||||
refStr := definitionFromRef(schema.Ref)
|
||||
if len(refStr) > 0 {
|
||||
return refStr, false
|
||||
}
|
||||
if len(schema.Type) > 0 {
|
||||
typeName = schema.Type[0]
|
||||
format := schema.Format
|
||||
if len(format) > 0 {
|
||||
typeName = fmt.Sprintf("%s.%s", typeName, format)
|
||||
}
|
||||
if typeName == ArrayType {
|
||||
typeName, _ = getSchemaType(&schema.Items.Schema.SchemaProps)
|
||||
return typeName, true
|
||||
}
|
||||
}
|
||||
return typeName, false
|
||||
|
||||
}
|
||||
|
||||
func getSchemaTypeStr(item interface{}) string {
|
||||
typeStr, isArray := getSchemaType(item)
|
||||
return formatTypeString(typeStr, isArray)
|
||||
}
|
||||
|
||||
func getSchemaType(item interface{}) (typeName string, isArray bool) {
|
||||
|
||||
switch s := item.(type) {
|
||||
case *spec.Schema:
|
||||
typeName, isArray = getTypeFromSchema(s)
|
||||
case *spec.SchemaProps:
|
||||
typeName, isArray = getTypeFromSchemaProps(s)
|
||||
case spec.SchemaProps:
|
||||
typeName, isArray = getTypeFromSchemaProps(&s)
|
||||
case spec.SimpleSchema:
|
||||
typeName, isArray = getTypeFromSimpleSchema(&s)
|
||||
case *spec.SimpleSchema:
|
||||
typeName, isArray = getTypeFromSimpleSchema(s)
|
||||
default:
|
||||
typeName = "unknown"
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
func formatTypeString(typ string, isarray bool) string {
|
||||
if isarray {
|
||||
return fmt.Sprintf("<array[%s]>", typ)
|
||||
}
|
||||
return fmt.Sprintf("<%s>", typ)
|
||||
}
|
||||
|
||||
func definitionFromRef(ref spec.Ref) string {
|
||||
url := ref.GetURL()
|
||||
if url == nil {
|
||||
return ""
|
||||
}
|
||||
fragmentParts := strings.Split(url.Fragment, "/")
|
||||
numParts := len(fragmentParts)
|
||||
|
||||
return fragmentParts[numParts-1]
|
||||
}
|
||||
|
||||
func isArray(item interface{}) bool {
|
||||
switch s := item.(type) {
|
||||
case *spec.Schema:
|
||||
return isArrayType(s.Type)
|
||||
case *spec.SchemaProps:
|
||||
return isArrayType(s.Type)
|
||||
case *spec.SimpleSchema:
|
||||
return isArrayType(spec.StringOrArray{s.Type})
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func isPrimitive(item interface{}) bool {
|
||||
switch s := item.(type) {
|
||||
case *spec.Schema:
|
||||
return isPrimitiveType(s.Type)
|
||||
case *spec.SchemaProps:
|
||||
return isPrimitiveType(s.Type)
|
||||
case spec.StringOrArray:
|
||||
return isPrimitiveType(s)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
759
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/spec_analyser.go
generated
vendored
Normal file
759
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/spec_analyser.go
generated
vendored
Normal file
|
|
@ -0,0 +1,759 @@
|
|||
package diff
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
// StringType For identifying string types
|
||||
const StringType = "string"
|
||||
|
||||
// URLMethodResponse encapsulates these three elements to act as a map key
|
||||
type URLMethodResponse struct {
|
||||
Path string `json:"path"`
|
||||
Method string `json:"method"`
|
||||
Response string `json:"response"`
|
||||
}
|
||||
|
||||
// MarshalText - for serializing as a map key
|
||||
func (p URLMethod) MarshalText() (text []byte, err error) {
|
||||
return []byte(fmt.Sprintf("%s %s", p.Path, p.Method)), nil
|
||||
}
|
||||
|
||||
// URLMethods allows iteration of endpoints based on url and method
|
||||
type URLMethods map[URLMethod]*PathItemOp
|
||||
|
||||
// SpecAnalyser contains all the differences for a Spec
|
||||
type SpecAnalyser struct {
|
||||
Diffs SpecDifferences
|
||||
urlMethods1 URLMethods
|
||||
urlMethods2 URLMethods
|
||||
Definitions1 spec.Definitions
|
||||
Definitions2 spec.Definitions
|
||||
Info1 *spec.Info
|
||||
Info2 *spec.Info
|
||||
ReferencedDefinitions map[string]bool
|
||||
|
||||
schemasCompared map[string]struct{}
|
||||
}
|
||||
|
||||
// NewSpecAnalyser returns an empty SpecDiffs
|
||||
func NewSpecAnalyser() *SpecAnalyser {
|
||||
return &SpecAnalyser{
|
||||
Diffs: SpecDifferences{},
|
||||
ReferencedDefinitions: map[string]bool{},
|
||||
}
|
||||
}
|
||||
|
||||
// Analyse the differences in two specs
|
||||
func (sd *SpecAnalyser) Analyse(spec1, spec2 *spec.Swagger) error {
|
||||
sd.schemasCompared = make(map[string]struct{})
|
||||
sd.Definitions1 = spec1.Definitions
|
||||
sd.Definitions2 = spec2.Definitions
|
||||
sd.Info1 = spec1.Info
|
||||
sd.Info2 = spec2.Info
|
||||
sd.urlMethods1 = getURLMethodsFor(spec1)
|
||||
sd.urlMethods2 = getURLMethodsFor(spec2)
|
||||
|
||||
sd.analyseSpecMetadata(spec1, spec2)
|
||||
sd.analyseEndpoints()
|
||||
sd.analyseRequestParams()
|
||||
sd.analyseEndpointData()
|
||||
sd.analyseResponseParams()
|
||||
sd.analyseExtensions(spec1, spec2)
|
||||
sd.AnalyseDefinitions()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) analyseSpecMetadata(spec1, spec2 *spec.Swagger) {
|
||||
// breaking if it no longer consumes any formats
|
||||
added, deleted, _ := fromStringArray(spec1.Consumes).DiffsTo(spec2.Consumes)
|
||||
|
||||
node := getNameOnlyDiffNode("Spec")
|
||||
location := DifferenceLocation{Node: node}
|
||||
consumesLoation := location.AddNode(getNameOnlyDiffNode("consumes"))
|
||||
|
||||
for _, eachAdded := range added {
|
||||
sd.Diffs = sd.Diffs.addDiff(
|
||||
SpecDifference{DifferenceLocation: consumesLoation, Code: AddedConsumesFormat, Compatibility: NonBreaking, DiffInfo: eachAdded})
|
||||
}
|
||||
for _, eachDeleted := range deleted {
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: consumesLoation, Code: DeletedConsumesFormat, Compatibility: Breaking, DiffInfo: eachDeleted})
|
||||
}
|
||||
|
||||
// // breaking if it no longer produces any formats
|
||||
added, deleted, _ = fromStringArray(spec1.Produces).DiffsTo(spec2.Produces)
|
||||
producesLocation := location.AddNode(getNameOnlyDiffNode("produces"))
|
||||
for _, eachAdded := range added {
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: producesLocation, Code: AddedProducesFormat, Compatibility: NonBreaking, DiffInfo: eachAdded})
|
||||
}
|
||||
for _, eachDeleted := range deleted {
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: producesLocation, Code: DeletedProducesFormat, Compatibility: Breaking, DiffInfo: eachDeleted})
|
||||
}
|
||||
|
||||
// // breaking if it no longer supports a scheme
|
||||
added, deleted, _ = fromStringArray(spec1.Schemes).DiffsTo(spec2.Schemes)
|
||||
schemesLocation := location.AddNode(getNameOnlyDiffNode("schemes"))
|
||||
|
||||
for _, eachAdded := range added {
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: schemesLocation, Code: AddedSchemes, Compatibility: NonBreaking, DiffInfo: eachAdded})
|
||||
}
|
||||
for _, eachDeleted := range deleted {
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: schemesLocation, Code: DeletedSchemes, Compatibility: Breaking, DiffInfo: eachDeleted})
|
||||
}
|
||||
|
||||
// host should be able to change without any issues?
|
||||
sd.analyseMetaDataProperty(spec1.Info.Description, spec2.Info.Description, ChangedDescripton, NonBreaking)
|
||||
|
||||
// // host should be able to change without any issues?
|
||||
sd.analyseMetaDataProperty(spec1.Host, spec2.Host, ChangedHostURL, Breaking)
|
||||
// sd.Host = compareStrings(spec1.Host, spec2.Host)
|
||||
|
||||
// // Base Path change will break non generated clients
|
||||
sd.analyseMetaDataProperty(spec1.BasePath, spec2.BasePath, ChangedBasePath, Breaking)
|
||||
|
||||
// TODO: what to do about security?
|
||||
// Missing security scheme will break a client
|
||||
// Security []map[string][]string `json:"security,omitempty"`
|
||||
// Tags []Tag `json:"tags,omitempty"`
|
||||
// ExternalDocs *ExternalDocumentation `json:"externalDocs,omitempty"`
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) analyseEndpoints() {
|
||||
sd.findDeletedEndpoints()
|
||||
sd.findAddedEndpoints()
|
||||
}
|
||||
|
||||
// AnalyseDefinitions check for changes to definition objects not referenced in any endpoint
|
||||
func (sd *SpecAnalyser) AnalyseDefinitions() {
|
||||
alreadyReferenced := map[string]bool{}
|
||||
for k := range sd.ReferencedDefinitions {
|
||||
alreadyReferenced[k] = true
|
||||
}
|
||||
location := DifferenceLocation{Node: &Node{Field: "Spec Definitions"}}
|
||||
for name1, sch := range sd.Definitions1 {
|
||||
schema1 := sch
|
||||
if _, ok := alreadyReferenced[name1]; !ok {
|
||||
childLocation := location.AddNode(&Node{Field: name1})
|
||||
if schema2, ok := sd.Definitions2[name1]; ok {
|
||||
sd.compareSchema(childLocation, &schema1, &schema2)
|
||||
} else {
|
||||
sd.addDiffs(childLocation, []TypeDiff{{Change: DeletedDefinition}})
|
||||
}
|
||||
}
|
||||
}
|
||||
for name2 := range sd.Definitions2 {
|
||||
if _, ok := sd.Definitions1[name2]; !ok {
|
||||
childLocation := location.AddNode(&Node{Field: name2})
|
||||
sd.addDiffs(childLocation, []TypeDiff{{Change: AddedDefinition}})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) analyseEndpointData() {
|
||||
|
||||
for URLMethod, op2 := range sd.urlMethods2 {
|
||||
if op1, ok := sd.urlMethods1[URLMethod]; ok {
|
||||
addedTags, deletedTags, _ := fromStringArray(op1.Operation.Tags).DiffsTo(op2.Operation.Tags)
|
||||
location := DifferenceLocation{URL: URLMethod.Path, Method: URLMethod.Method}
|
||||
|
||||
for _, eachAddedTag := range addedTags {
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: location, Code: AddedTag, DiffInfo: fmt.Sprintf(`"%s"`, eachAddedTag)})
|
||||
}
|
||||
for _, eachDeletedTag := range deletedTags {
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: location, Code: DeletedTag, DiffInfo: fmt.Sprintf(`"%s"`, eachDeletedTag)})
|
||||
}
|
||||
|
||||
sd.compareDescripton(location, op1.Operation.Description, op2.Operation.Description)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) analyseRequestParams() {
|
||||
locations := []string{"query", "path", "body", "header", "formData"}
|
||||
|
||||
for _, paramLocation := range locations {
|
||||
rootNode := getNameOnlyDiffNode(strings.Title(paramLocation))
|
||||
for URLMethod, op2 := range sd.urlMethods2 {
|
||||
if op1, ok := sd.urlMethods1[URLMethod]; ok {
|
||||
|
||||
params1 := getParams(op1.ParentPathItem.Parameters, op1.Operation.Parameters, paramLocation)
|
||||
params2 := getParams(op2.ParentPathItem.Parameters, op2.Operation.Parameters, paramLocation)
|
||||
|
||||
location := DifferenceLocation{URL: URLMethod.Path, Method: URLMethod.Method, Node: rootNode}
|
||||
|
||||
// detect deleted params
|
||||
for paramName1, param1 := range params1 {
|
||||
if _, ok := params2[paramName1]; !ok {
|
||||
childLocation := location.AddNode(getSchemaDiffNode(paramName1, ¶m1.SimpleSchema))
|
||||
code := DeletedOptionalParam
|
||||
if param1.Required {
|
||||
code = DeletedRequiredParam
|
||||
}
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: childLocation, Code: code})
|
||||
}
|
||||
}
|
||||
// detect added changed params
|
||||
for paramName2, param2 := range params2 {
|
||||
// changed?
|
||||
if param1, ok := params1[paramName2]; ok {
|
||||
sd.compareParams(URLMethod, paramLocation, paramName2, param1, param2)
|
||||
} else {
|
||||
// Added
|
||||
childLocation := location.AddNode(getSchemaDiffNode(paramName2, ¶m2.SimpleSchema))
|
||||
code := AddedOptionalParam
|
||||
if param2.Required {
|
||||
code = AddedRequiredParam
|
||||
}
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: childLocation, Code: code})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) analyseResponseParams() {
|
||||
// Loop through url+methods in spec 2 - check deleted and changed
|
||||
for eachURLMethodFrom2, op2 := range sd.urlMethods2 {
|
||||
|
||||
// present in both specs? Use key from spec 2 to lookup in spec 1
|
||||
if op1, ok := sd.urlMethods1[eachURLMethodFrom2]; ok {
|
||||
// compare responses for url and method
|
||||
op1Responses := op1.Operation.Responses.StatusCodeResponses
|
||||
op2Responses := op2.Operation.Responses.StatusCodeResponses
|
||||
|
||||
// deleted responses
|
||||
for code1 := range op1Responses {
|
||||
if _, ok := op2Responses[code1]; !ok {
|
||||
location := DifferenceLocation{URL: eachURLMethodFrom2.Path, Method: eachURLMethodFrom2.Method, Response: code1, Node: getSchemaDiffNode("Body", op1Responses[code1].Schema)}
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: location, Code: DeletedResponse})
|
||||
}
|
||||
}
|
||||
// Added updated Response Codes
|
||||
for code2, op2Response := range op2Responses {
|
||||
if op1Response, ok := op1Responses[code2]; ok {
|
||||
op1Headers := op1Response.ResponseProps.Headers
|
||||
headerRootNode := getNameOnlyDiffNode("Headers")
|
||||
|
||||
// Iterate Spec2 Headers looking for added and updated
|
||||
location := DifferenceLocation{URL: eachURLMethodFrom2.Path, Method: eachURLMethodFrom2.Method, Response: code2, Node: headerRootNode}
|
||||
for op2HeaderName, op2Header := range op2Response.ResponseProps.Headers {
|
||||
if op1Header, ok := op1Headers[op2HeaderName]; ok {
|
||||
diffs := sd.CompareProps(forHeader(op1Header), forHeader(op2Header))
|
||||
sd.addDiffs(location, diffs)
|
||||
} else {
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{
|
||||
DifferenceLocation: location.AddNode(getSchemaDiffNode(op2HeaderName, &op2Header.SimpleSchema)),
|
||||
Code: AddedResponseHeader})
|
||||
}
|
||||
}
|
||||
for op1HeaderName := range op1Response.ResponseProps.Headers {
|
||||
if _, ok := op2Response.ResponseProps.Headers[op1HeaderName]; !ok {
|
||||
op1Header := op1Response.ResponseProps.Headers[op1HeaderName]
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{
|
||||
DifferenceLocation: location.AddNode(getSchemaDiffNode(op1HeaderName, &op1Header.SimpleSchema)),
|
||||
Code: DeletedResponseHeader})
|
||||
}
|
||||
}
|
||||
schem := op1Response.Schema
|
||||
node := getNameOnlyDiffNode("NoContent")
|
||||
if schem != nil {
|
||||
node = getSchemaDiffNode("Body", &schem.SchemaProps)
|
||||
}
|
||||
responseLocation := DifferenceLocation{URL: eachURLMethodFrom2.Path,
|
||||
Method: eachURLMethodFrom2.Method,
|
||||
Response: code2,
|
||||
Node: node}
|
||||
sd.compareDescripton(responseLocation, op1Response.Description, op2Response.Description)
|
||||
|
||||
if op1Response.Schema != nil {
|
||||
sd.compareSchema(
|
||||
DifferenceLocation{URL: eachURLMethodFrom2.Path, Method: eachURLMethodFrom2.Method, Response: code2, Node: getSchemaDiffNode("Body", op1Response.Schema)},
|
||||
op1Response.Schema,
|
||||
op2Response.Schema)
|
||||
}
|
||||
} else {
|
||||
// op2Response
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{
|
||||
DifferenceLocation: DifferenceLocation{URL: eachURLMethodFrom2.Path, Method: eachURLMethodFrom2.Method, Response: code2, Node: getSchemaDiffNode("Body", op2Response.Schema)},
|
||||
Code: AddedResponse})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) analyseExtensions(spec1, spec2 *spec.Swagger) {
|
||||
// root
|
||||
specLoc := DifferenceLocation{Node: &Node{Field: "Spec"}}
|
||||
sd.checkAddedExtensions(spec1.Extensions, spec2.Extensions, specLoc, "")
|
||||
sd.checkDeletedExtensions(spec1.Extensions, spec2.Extensions, specLoc, "")
|
||||
|
||||
sd.analyzeInfoExtensions()
|
||||
sd.analyzeTagExtensions(spec1, spec2)
|
||||
sd.analyzeSecurityDefinitionExtensions(spec1, spec2)
|
||||
|
||||
sd.analyzeOperationExtensions()
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) analyzeOperationExtensions() {
|
||||
for urlMethod, op2 := range sd.urlMethods2 {
|
||||
pathAndMethodLoc := DifferenceLocation{URL: urlMethod.Path, Method: urlMethod.Method}
|
||||
if op1, ok := sd.urlMethods1[urlMethod]; ok {
|
||||
sd.checkAddedExtensions(op1.Extensions, op2.Extensions, DifferenceLocation{URL: urlMethod.Path}, "")
|
||||
sd.checkAddedExtensions(op1.Operation.Responses.Extensions, op2.Operation.Responses.Extensions, pathAndMethodLoc, "Responses")
|
||||
sd.checkAddedExtensions(op1.Operation.Extensions, op2.Operation.Extensions, pathAndMethodLoc, "")
|
||||
|
||||
for code, resp := range op1.Operation.Responses.StatusCodeResponses {
|
||||
for hdr, h := range resp.Headers {
|
||||
op2StatusCode, ok := op2.Operation.Responses.StatusCodeResponses[code]
|
||||
if ok {
|
||||
if _, ok = op2StatusCode.Headers[hdr]; ok {
|
||||
sd.checkAddedExtensions(h.Extensions, op2StatusCode.Headers[hdr].Extensions, DifferenceLocation{URL: urlMethod.Path, Method: urlMethod.Method, Node: getNameOnlyDiffNode("Headers")}, hdr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resp2 := op2.Operation.Responses.StatusCodeResponses[code]
|
||||
sd.analyzeSchemaExtensions(resp.Schema, resp2.Schema, code, urlMethod)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for urlMethod, op1 := range sd.urlMethods1 {
|
||||
pathAndMethodLoc := DifferenceLocation{URL: urlMethod.Path, Method: urlMethod.Method}
|
||||
if op2, ok := sd.urlMethods2[urlMethod]; ok {
|
||||
sd.checkDeletedExtensions(op1.Extensions, op2.Extensions, DifferenceLocation{URL: urlMethod.Path}, "")
|
||||
sd.checkDeletedExtensions(op1.Operation.Responses.Extensions, op2.Operation.Responses.Extensions, pathAndMethodLoc, "Responses")
|
||||
sd.checkDeletedExtensions(op1.Operation.Extensions, op2.Operation.Extensions, pathAndMethodLoc, "")
|
||||
for code, resp := range op1.Operation.Responses.StatusCodeResponses {
|
||||
for hdr, h := range resp.Headers {
|
||||
op2StatusCode, ok := op2.Operation.Responses.StatusCodeResponses[code]
|
||||
if ok {
|
||||
if _, ok = op2StatusCode.Headers[hdr]; ok {
|
||||
sd.checkDeletedExtensions(h.Extensions, op2StatusCode.Headers[hdr].Extensions, DifferenceLocation{URL: urlMethod.Path, Method: urlMethod.Method, Node: getNameOnlyDiffNode("Headers")}, hdr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) analyzeSecurityDefinitionExtensions(spec1 *spec.Swagger, spec2 *spec.Swagger) {
|
||||
securityDefLoc := DifferenceLocation{Node: &Node{Field: "Security Definitions"}}
|
||||
for key, securityDef := range spec1.SecurityDefinitions {
|
||||
if securityDef2, ok := spec2.SecurityDefinitions[key]; ok {
|
||||
sd.checkAddedExtensions(securityDef.Extensions, securityDef2.Extensions, securityDefLoc, "")
|
||||
}
|
||||
}
|
||||
|
||||
for key, securityDef := range spec2.SecurityDefinitions {
|
||||
if securityDef1, ok := spec1.SecurityDefinitions[key]; ok {
|
||||
sd.checkDeletedExtensions(securityDef1.Extensions, securityDef.Extensions, securityDefLoc, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) analyzeSchemaExtensions(schema1, schema2 *spec.Schema, code int, urlMethod URLMethod) {
|
||||
if schema1 != nil && schema2 != nil {
|
||||
diffLoc := DifferenceLocation{Response: code, URL: urlMethod.Path, Method: urlMethod.Method, Node: getSchemaDiffNode("Body", schema2)}
|
||||
sd.checkAddedExtensions(schema1.Extensions, schema2.Extensions, diffLoc, "")
|
||||
sd.checkDeletedExtensions(schema1.Extensions, schema2.Extensions, diffLoc, "")
|
||||
if schema1.Items != nil && schema2.Items != nil {
|
||||
sd.analyzeSchemaExtensions(schema1.Items.Schema, schema2.Items.Schema, code, urlMethod)
|
||||
for i := range schema1.Items.Schemas {
|
||||
s1 := schema1.Items.Schemas[i]
|
||||
for j := range schema2.Items.Schemas {
|
||||
s2 := schema2.Items.Schemas[j]
|
||||
sd.analyzeSchemaExtensions(&s1, &s2, code, urlMethod)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) analyzeInfoExtensions() {
|
||||
if sd.Info1 != nil && sd.Info2 != nil {
|
||||
diffLocation := DifferenceLocation{Node: &Node{Field: "Spec Info"}}
|
||||
sd.checkAddedExtensions(sd.Info1.Extensions, sd.Info2.Extensions, diffLocation, "")
|
||||
sd.checkDeletedExtensions(sd.Info1.Extensions, sd.Info2.Extensions, diffLocation, "")
|
||||
if sd.Info1.Contact != nil && sd.Info2.Contact != nil {
|
||||
diffLocation = DifferenceLocation{Node: &Node{Field: "Spec Info.Contact"}}
|
||||
sd.checkAddedExtensions(sd.Info1.Contact.Extensions, sd.Info2.Contact.Extensions, diffLocation, "")
|
||||
sd.checkDeletedExtensions(sd.Info1.Contact.Extensions, sd.Info2.Contact.Extensions, diffLocation, "")
|
||||
}
|
||||
if sd.Info1.License != nil && sd.Info2.License != nil {
|
||||
diffLocation = DifferenceLocation{Node: &Node{Field: "Spec Info.License"}}
|
||||
sd.checkAddedExtensions(sd.Info1.License.Extensions, sd.Info2.License.Extensions, diffLocation, "")
|
||||
sd.checkDeletedExtensions(sd.Info1.License.Extensions, sd.Info2.License.Extensions, diffLocation, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) analyzeTagExtensions(spec1 *spec.Swagger, spec2 *spec.Swagger) {
|
||||
diffLocation := DifferenceLocation{Node: &Node{Field: "Spec Tags"}}
|
||||
for _, spec2Tag := range spec2.Tags {
|
||||
for _, spec1Tag := range spec1.Tags {
|
||||
if spec2Tag.Name == spec1Tag.Name {
|
||||
sd.checkAddedExtensions(spec1Tag.Extensions, spec2Tag.Extensions, diffLocation, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, spec1Tag := range spec1.Tags {
|
||||
for _, spec2Tag := range spec2.Tags {
|
||||
if spec1Tag.Name == spec2Tag.Name {
|
||||
sd.checkDeletedExtensions(spec1Tag.Extensions, spec2Tag.Extensions, diffLocation, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) checkAddedExtensions(extensions1 spec.Extensions, extensions2 spec.Extensions, diffLocation DifferenceLocation, fieldPrefix string) {
|
||||
for extKey := range extensions2 {
|
||||
if _, ok := extensions1[extKey]; !ok {
|
||||
if fieldPrefix != "" {
|
||||
extKey = fmt.Sprintf("%s.%s", fieldPrefix, extKey)
|
||||
}
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{
|
||||
DifferenceLocation: diffLocation.AddNode(&Node{Field: extKey}),
|
||||
Code: AddedExtension,
|
||||
Compatibility: Warning, // this could potentially be a breaking change
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) checkDeletedExtensions(extensions1 spec.Extensions, extensions2 spec.Extensions, diffLocation DifferenceLocation, fieldPrefix string) {
|
||||
for extKey := range extensions1 {
|
||||
if _, ok := extensions2[extKey]; !ok {
|
||||
if fieldPrefix != "" {
|
||||
extKey = fmt.Sprintf("%s.%s", fieldPrefix, extKey)
|
||||
}
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{
|
||||
DifferenceLocation: diffLocation.AddNode(&Node{Field: extKey}),
|
||||
Code: DeletedExtension,
|
||||
Compatibility: Warning, // this could potentially be a breaking change
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func addTypeDiff(diffs []TypeDiff, diff TypeDiff) []TypeDiff {
|
||||
if diff.Change != NoChangeDetected {
|
||||
diffs = append(diffs, diff)
|
||||
}
|
||||
return diffs
|
||||
}
|
||||
|
||||
// CompareProps computes type specific property diffs
|
||||
func (sd *SpecAnalyser) CompareProps(type1, type2 *spec.SchemaProps) []TypeDiff {
|
||||
|
||||
diffs := []TypeDiff{}
|
||||
|
||||
diffs = CheckToFromPrimitiveType(diffs, type1, type2)
|
||||
|
||||
if len(diffs) > 0 {
|
||||
return diffs
|
||||
}
|
||||
|
||||
if isArray(type1) {
|
||||
maxItemDiffs := CompareIntValues("MaxItems", type1.MaxItems, type2.MaxItems, WidenedType, NarrowedType)
|
||||
diffs = append(diffs, maxItemDiffs...)
|
||||
minItemsDiff := CompareIntValues("MinItems", type1.MinItems, type2.MinItems, NarrowedType, WidenedType)
|
||||
diffs = append(diffs, minItemsDiff...)
|
||||
}
|
||||
|
||||
if len(diffs) > 0 {
|
||||
return diffs
|
||||
}
|
||||
|
||||
diffs = CheckRefChange(diffs, type1, type2)
|
||||
if len(diffs) > 0 {
|
||||
return diffs
|
||||
}
|
||||
|
||||
if !(isPrimitiveType(type1.Type) && isPrimitiveType(type2.Type)) {
|
||||
return diffs
|
||||
}
|
||||
|
||||
// check primitive type hierarchy change eg string -> integer = NarrowedChange
|
||||
if type1.Type[0] != type2.Type[0] ||
|
||||
type1.Format != type2.Format {
|
||||
diff := getTypeHierarchyChange(primitiveTypeString(type1.Type[0], type1.Format), primitiveTypeString(type2.Type[0], type2.Format))
|
||||
diffs = addTypeDiff(diffs, diff)
|
||||
}
|
||||
|
||||
diffs = CheckStringTypeChanges(diffs, type1, type2)
|
||||
|
||||
if len(diffs) > 0 {
|
||||
return diffs
|
||||
}
|
||||
|
||||
diffs = checkNumericTypeChanges(diffs, type1, type2)
|
||||
|
||||
if len(diffs) > 0 {
|
||||
return diffs
|
||||
}
|
||||
|
||||
return diffs
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) compareParams(urlMethod URLMethod, location string, name string, param1, param2 spec.Parameter) {
|
||||
diffLocation := DifferenceLocation{URL: urlMethod.Path, Method: urlMethod.Method}
|
||||
|
||||
childLocation := diffLocation.AddNode(getNameOnlyDiffNode(strings.Title(location)))
|
||||
paramLocation := diffLocation.AddNode(getNameOnlyDiffNode(name))
|
||||
sd.compareDescripton(paramLocation, param1.Description, param2.Description)
|
||||
|
||||
if param1.Schema != nil && param2.Schema != nil {
|
||||
if len(name) > 0 {
|
||||
childLocation = childLocation.AddNode(getSchemaDiffNode(name, param2.Schema))
|
||||
}
|
||||
sd.compareSchema(childLocation, param1.Schema, param2.Schema)
|
||||
}
|
||||
|
||||
diffs := sd.CompareProps(forParam(param1), forParam(param2))
|
||||
|
||||
childLocation = childLocation.AddNode(getSchemaDiffNode(name, ¶m2.SimpleSchema))
|
||||
if len(diffs) > 0 {
|
||||
sd.addDiffs(childLocation, diffs)
|
||||
}
|
||||
|
||||
diffs = CheckToFromRequired(param1.Required, param2.Required)
|
||||
if len(diffs) > 0 {
|
||||
sd.addDiffs(childLocation, diffs)
|
||||
}
|
||||
|
||||
sd.compareSimpleSchema(childLocation, ¶m1.SimpleSchema, ¶m2.SimpleSchema)
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) addTypeDiff(location DifferenceLocation, diff *TypeDiff) {
|
||||
diffCopy := diff
|
||||
desc := diffCopy.Description
|
||||
if len(desc) == 0 {
|
||||
if diffCopy.FromType != diffCopy.ToType {
|
||||
desc = fmt.Sprintf("%s -> %s", diffCopy.FromType, diffCopy.ToType)
|
||||
}
|
||||
}
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{
|
||||
DifferenceLocation: location,
|
||||
Code: diffCopy.Change,
|
||||
DiffInfo: desc})
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) compareDescripton(location DifferenceLocation, desc1, desc2 string) {
|
||||
if desc1 != desc2 {
|
||||
code := ChangedDescripton
|
||||
if len(desc1) > 0 {
|
||||
code = DeletedDescripton
|
||||
} else if len(desc2) > 0 {
|
||||
code = AddedDescripton
|
||||
}
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: location, Code: code})
|
||||
}
|
||||
}
|
||||
|
||||
func isPrimitiveType(item spec.StringOrArray) bool {
|
||||
return len(item) > 0 && item[0] != ArrayType && item[0] != ObjectType
|
||||
}
|
||||
|
||||
func isArrayType(item spec.StringOrArray) bool {
|
||||
return len(item) > 0 && item[0] == ArrayType
|
||||
}
|
||||
func (sd *SpecAnalyser) getRefSchemaFromSpec1(ref spec.Ref) (*spec.Schema, string) {
|
||||
return sd.schemaFromRef(ref, &sd.Definitions1)
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) getRefSchemaFromSpec2(ref spec.Ref) (*spec.Schema, string) {
|
||||
return sd.schemaFromRef(ref, &sd.Definitions2)
|
||||
}
|
||||
|
||||
// CompareSchemaFn Fn spec for comparing schemas
|
||||
type CompareSchemaFn func(location DifferenceLocation, schema1, schema2 *spec.Schema)
|
||||
|
||||
func (sd *SpecAnalyser) compareSchema(location DifferenceLocation, schema1, schema2 *spec.Schema) {
|
||||
|
||||
refDiffs := []TypeDiff{}
|
||||
refDiffs = CheckRefChange(refDiffs, schema1, schema2)
|
||||
if len(refDiffs) > 0 {
|
||||
for _, d := range refDiffs {
|
||||
diff := d
|
||||
sd.addTypeDiff(location, &diff)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if isRefType(schema1) {
|
||||
key := schemaLocationKey(location)
|
||||
if _, ok := sd.schemasCompared[key]; ok {
|
||||
return
|
||||
}
|
||||
sd.schemasCompared[key] = struct{}{}
|
||||
schema1, _ = sd.schemaFromRef(getRef(schema1), &sd.Definitions1)
|
||||
}
|
||||
|
||||
if isRefType(schema2) {
|
||||
schema2, _ = sd.schemaFromRef(getRef(schema2), &sd.Definitions2)
|
||||
}
|
||||
|
||||
sd.compareDescripton(location, schema1.Description, schema2.Description)
|
||||
|
||||
typeDiffs := sd.CompareProps(&schema1.SchemaProps, &schema2.SchemaProps)
|
||||
if len(typeDiffs) > 0 {
|
||||
sd.addDiffs(location, typeDiffs)
|
||||
return
|
||||
}
|
||||
|
||||
if isArray(schema1) {
|
||||
if isArray(schema2) {
|
||||
sd.compareSchema(location, schema1.Items.Schema, schema2.Items.Schema)
|
||||
} else {
|
||||
sd.addDiffs(location, addTypeDiff([]TypeDiff{}, TypeDiff{Change: ChangedType, FromType: getSchemaTypeStr(schema1), ToType: getSchemaTypeStr(schema2)}))
|
||||
}
|
||||
}
|
||||
|
||||
diffs := CompareProperties(location, schema1, schema2, sd.getRefSchemaFromSpec1, sd.getRefSchemaFromSpec2, sd.compareSchema)
|
||||
for _, diff := range diffs {
|
||||
sd.Diffs = sd.Diffs.addDiff(diff)
|
||||
}
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) compareSimpleSchema(location DifferenceLocation, schema1, schema2 *spec.SimpleSchema) {
|
||||
// check optional/required
|
||||
if schema1.Nullable != schema2.Nullable {
|
||||
// If optional is made required
|
||||
if schema1.Nullable && !schema2.Nullable {
|
||||
sd.addDiffs(location, addTypeDiff([]TypeDiff{}, TypeDiff{Change: ChangedOptionalToRequired, FromType: getSchemaTypeStr(schema1), ToType: getSchemaTypeStr(schema2)}))
|
||||
} else if !schema1.Nullable && schema2.Nullable {
|
||||
// If required is made optional
|
||||
sd.addDiffs(location, addTypeDiff([]TypeDiff{}, TypeDiff{Change: ChangedRequiredToOptional, FromType: getSchemaTypeStr(schema1), ToType: getSchemaTypeStr(schema2)}))
|
||||
}
|
||||
}
|
||||
|
||||
if schema1.CollectionFormat != schema2.CollectionFormat {
|
||||
sd.addDiffs(location, addTypeDiff([]TypeDiff{}, TypeDiff{Change: ChangedCollectionFormat, FromType: getSchemaTypeStr(schema1), ToType: getSchemaTypeStr(schema2)}))
|
||||
}
|
||||
|
||||
if schema1.Default != schema2.Default {
|
||||
switch {
|
||||
case schema1.Default == nil && schema2.Default != nil:
|
||||
sd.addDiffs(location, addTypeDiff([]TypeDiff{}, TypeDiff{Change: AddedDefault, FromType: getSchemaTypeStr(schema1), ToType: getSchemaTypeStr(schema2)}))
|
||||
case schema1.Default != nil && schema2.Default == nil:
|
||||
sd.addDiffs(location, addTypeDiff([]TypeDiff{}, TypeDiff{Change: DeletedDefault, FromType: getSchemaTypeStr(schema1), ToType: getSchemaTypeStr(schema2)}))
|
||||
default:
|
||||
sd.addDiffs(location, addTypeDiff([]TypeDiff{}, TypeDiff{Change: ChangedDefault, FromType: getSchemaTypeStr(schema1), ToType: getSchemaTypeStr(schema2)}))
|
||||
}
|
||||
}
|
||||
|
||||
if schema1.Example != schema2.Example {
|
||||
switch {
|
||||
case schema1.Example == nil && schema2.Example != nil:
|
||||
sd.addDiffs(location, addTypeDiff([]TypeDiff{}, TypeDiff{Change: AddedExample, FromType: getSchemaTypeStr(schema1), ToType: getSchemaTypeStr(schema2)}))
|
||||
case schema1.Example != nil && schema2.Example == nil:
|
||||
sd.addDiffs(location, addTypeDiff([]TypeDiff{}, TypeDiff{Change: DeletedExample, FromType: getSchemaTypeStr(schema1), ToType: getSchemaTypeStr(schema2)}))
|
||||
default:
|
||||
sd.addDiffs(location, addTypeDiff([]TypeDiff{}, TypeDiff{Change: ChangedExample, FromType: getSchemaTypeStr(schema1), ToType: getSchemaTypeStr(schema2)}))
|
||||
}
|
||||
}
|
||||
|
||||
if isArray(schema1) {
|
||||
if isArray(schema2) {
|
||||
sd.compareSimpleSchema(location, &schema1.Items.SimpleSchema, &schema2.Items.SimpleSchema)
|
||||
} else {
|
||||
sd.addDiffs(location, addTypeDiff([]TypeDiff{}, TypeDiff{Change: ChangedType, FromType: getSchemaTypeStr(schema1), ToType: getSchemaTypeStr(schema2)}))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) addDiffs(location DifferenceLocation, diffs []TypeDiff) {
|
||||
for _, e := range diffs {
|
||||
eachTypeDiff := e
|
||||
if eachTypeDiff.Change != NoChangeDetected {
|
||||
sd.addTypeDiff(location, &eachTypeDiff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func addChildDiffNode(location DifferenceLocation, propName string, propSchema *spec.Schema) DifferenceLocation {
|
||||
newNode := location.Node
|
||||
childNode := fromSchemaProps(propName, &propSchema.SchemaProps)
|
||||
if newNode != nil {
|
||||
newNode = newNode.Copy()
|
||||
newNode.AddLeafNode(&childNode)
|
||||
} else {
|
||||
newNode = &childNode
|
||||
}
|
||||
return DifferenceLocation{
|
||||
URL: location.URL,
|
||||
Method: location.Method,
|
||||
Response: location.Response,
|
||||
Node: newNode,
|
||||
}
|
||||
}
|
||||
|
||||
func fromSchemaProps(fieldName string, props *spec.SchemaProps) Node {
|
||||
node := Node{}
|
||||
node.TypeName, node.IsArray = getSchemaType(props)
|
||||
node.Field = fieldName
|
||||
return node
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) findAddedEndpoints() {
|
||||
for URLMethod := range sd.urlMethods2 {
|
||||
if _, ok := sd.urlMethods1[URLMethod]; !ok {
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: DifferenceLocation{URL: URLMethod.Path, Method: URLMethod.Method}, Code: AddedEndpoint})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) findDeletedEndpoints() {
|
||||
for eachURLMethod, operation1 := range sd.urlMethods1 {
|
||||
code := DeletedEndpoint
|
||||
if (operation1.ParentPathItem.Options != nil && operation1.ParentPathItem.Options.Deprecated) ||
|
||||
(operation1.Operation.Deprecated) {
|
||||
code = DeletedDeprecatedEndpoint
|
||||
}
|
||||
if _, ok := sd.urlMethods2[eachURLMethod]; !ok {
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: DifferenceLocation{URL: eachURLMethod.Path, Method: eachURLMethod.Method}, Code: code})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) analyseMetaDataProperty(item1, item2 string, codeIfDiff SpecChangeCode, compatIfDiff Compatibility) {
|
||||
if item1 != item2 {
|
||||
diffSpec := fmt.Sprintf("%s -> %s", item1, item2)
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: DifferenceLocation{Node: &Node{Field: "Spec Metadata"}}, Code: codeIfDiff, Compatibility: compatIfDiff, DiffInfo: diffSpec})
|
||||
}
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) schemaFromRef(ref spec.Ref, defns *spec.Definitions) (actualSchema *spec.Schema, definitionName string) {
|
||||
definitionName = definitionFromRef(ref)
|
||||
foundSchema, ok := (*defns)[definitionName]
|
||||
if !ok {
|
||||
return nil, definitionName
|
||||
}
|
||||
sd.ReferencedDefinitions[definitionName] = true
|
||||
actualSchema = &foundSchema
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
func schemaLocationKey(location DifferenceLocation) string {
|
||||
return location.Method + location.URL + location.Node.Field + location.Node.TypeName
|
||||
}
|
||||
|
||||
// PropertyDefn combines a property with its required-ness
|
||||
type PropertyDefn struct {
|
||||
Schema *spec.Schema
|
||||
Required bool
|
||||
}
|
||||
|
||||
// PropertyMap a unified map including all AllOf fields
|
||||
type PropertyMap map[string]PropertyDefn
|
||||
216
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/spec_difference.go
generated
vendored
Normal file
216
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/spec_difference.go
generated
vendored
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
package diff
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// SpecDifference encapsulates the details of an individual diff in part of a spec
|
||||
type SpecDifference struct {
|
||||
DifferenceLocation DifferenceLocation `json:"location"`
|
||||
Code SpecChangeCode `json:"code"`
|
||||
Compatibility Compatibility `json:"compatibility"`
|
||||
DiffInfo string `json:"info,omitempty"`
|
||||
}
|
||||
|
||||
// SpecDifferences list of differences
|
||||
type SpecDifferences []SpecDifference
|
||||
|
||||
// Matches returns true if the diff matches another
|
||||
func (sd SpecDifference) Matches(other SpecDifference) bool {
|
||||
return sd.Code == other.Code &&
|
||||
sd.Compatibility == other.Compatibility &&
|
||||
sd.DiffInfo == other.DiffInfo &&
|
||||
equalLocations(sd.DifferenceLocation, other.DifferenceLocation)
|
||||
}
|
||||
|
||||
func equalLocations(a, b DifferenceLocation) bool {
|
||||
return a.Method == b.Method &&
|
||||
a.Response == b.Response &&
|
||||
a.URL == b.URL &&
|
||||
equalNodes(a.Node, b.Node)
|
||||
}
|
||||
|
||||
func equalNodes(a, b *Node) bool {
|
||||
if a == nil && b == nil {
|
||||
return true
|
||||
}
|
||||
if a == nil || b == nil {
|
||||
return false
|
||||
}
|
||||
return a.Field == b.Field &&
|
||||
a.IsArray == b.IsArray &&
|
||||
a.TypeName == b.TypeName &&
|
||||
equalNodes(a.ChildNode, b.ChildNode)
|
||||
|
||||
}
|
||||
|
||||
// BreakingChangeCount Calculates the breaking change count
|
||||
func (sd SpecDifferences) BreakingChangeCount() int {
|
||||
count := 0
|
||||
for _, eachDiff := range sd {
|
||||
if eachDiff.Compatibility == Breaking {
|
||||
count++
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
// WarningChangeCount Calculates the warning change count
|
||||
func (sd SpecDifferences) WarningChangeCount() int {
|
||||
count := 0
|
||||
for _, eachDiff := range sd {
|
||||
if eachDiff.Compatibility == Warning {
|
||||
count++
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
// FilterIgnores returns a copy of the list without the items in the specified ignore list
|
||||
func (sd SpecDifferences) FilterIgnores(ignores SpecDifferences) SpecDifferences {
|
||||
newDiffs := SpecDifferences{}
|
||||
for _, eachDiff := range sd {
|
||||
if !ignores.Contains(eachDiff) {
|
||||
newDiffs = newDiffs.addDiff(eachDiff)
|
||||
}
|
||||
}
|
||||
return newDiffs
|
||||
}
|
||||
|
||||
// Contains Returns true if the item contains the specified item
|
||||
func (sd SpecDifferences) Contains(diff SpecDifference) bool {
|
||||
for _, eachDiff := range sd {
|
||||
if eachDiff.Matches(diff) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// String std string renderer
|
||||
func (sd SpecDifference) String() string {
|
||||
isResponse := sd.DifferenceLocation.Response > 0
|
||||
hasMethod := len(sd.DifferenceLocation.Method) > 0
|
||||
hasURL := len(sd.DifferenceLocation.URL) > 0
|
||||
|
||||
prefix := ""
|
||||
direction := ""
|
||||
|
||||
if hasMethod {
|
||||
if hasURL {
|
||||
prefix = fmt.Sprintf("%s:%s", sd.DifferenceLocation.URL, sd.DifferenceLocation.Method)
|
||||
}
|
||||
if isResponse {
|
||||
prefix += fmt.Sprintf(" -> %d", sd.DifferenceLocation.Response)
|
||||
direction = "Response"
|
||||
} else {
|
||||
direction = "Request"
|
||||
}
|
||||
} else {
|
||||
prefix = sd.DifferenceLocation.URL
|
||||
}
|
||||
|
||||
paramOrPropertyLocation := ""
|
||||
if sd.DifferenceLocation.Node != nil {
|
||||
paramOrPropertyLocation = sd.DifferenceLocation.Node.String()
|
||||
}
|
||||
optionalInfo := ""
|
||||
if sd.DiffInfo != "" {
|
||||
optionalInfo = sd.DiffInfo
|
||||
}
|
||||
|
||||
items := []string{}
|
||||
for _, item := range []string{prefix, direction, paramOrPropertyLocation, sd.Code.Description(), optionalInfo} {
|
||||
if item != "" {
|
||||
items = append(items, item)
|
||||
}
|
||||
}
|
||||
return strings.Join(items, " - ")
|
||||
// return fmt.Sprintf("%s%s%s - %s%s", prefix, direction, paramOrPropertyLocation, sd.Code.Description(), optionalInfo)
|
||||
}
|
||||
|
||||
func (sd SpecDifferences) addDiff(diff SpecDifference) SpecDifferences {
|
||||
context := Request
|
||||
if diff.DifferenceLocation.Response > 0 {
|
||||
context = Response
|
||||
}
|
||||
diff.Compatibility = getCompatibilityForChange(diff.Code, context)
|
||||
|
||||
return append(sd, diff)
|
||||
}
|
||||
|
||||
// ReportCompatibility lists and spec
|
||||
func (sd *SpecDifferences) ReportCompatibility() (io.Reader, error, error) {
|
||||
var out bytes.Buffer
|
||||
breakingCount := sd.BreakingChangeCount()
|
||||
if breakingCount > 0 {
|
||||
if len(*sd) != breakingCount {
|
||||
fmt.Fprintln(&out, "")
|
||||
}
|
||||
fmt.Fprintln(&out, "BREAKING CHANGES:\n=================")
|
||||
_, _ = out.ReadFrom(sd.reportChanges(Breaking))
|
||||
msg := fmt.Sprintf("compatibility test FAILED: %d breaking changes detected", breakingCount)
|
||||
fmt.Fprintln(&out, msg)
|
||||
return &out, nil, errors.New(msg)
|
||||
}
|
||||
fmt.Fprintf(&out, "compatibility test OK. No breaking changes identified.\n")
|
||||
return &out, nil, nil
|
||||
}
|
||||
|
||||
func (sd SpecDifferences) reportChanges(compat Compatibility) io.Reader {
|
||||
toReportList := []string{}
|
||||
var out bytes.Buffer
|
||||
|
||||
for _, diff := range sd {
|
||||
if diff.Compatibility == compat {
|
||||
toReportList = append(toReportList, diff.String())
|
||||
}
|
||||
}
|
||||
|
||||
sort.Slice(toReportList, func(i, j int) bool {
|
||||
return toReportList[i] < toReportList[j]
|
||||
})
|
||||
|
||||
for _, eachDiff := range toReportList {
|
||||
fmt.Fprintln(&out, eachDiff)
|
||||
}
|
||||
return &out
|
||||
}
|
||||
|
||||
// ReportAllDiffs lists all the diffs between two specs
|
||||
func (sd SpecDifferences) ReportAllDiffs(fmtJSON bool) (io.Reader, error, error) {
|
||||
if fmtJSON {
|
||||
b, err := JSONMarshal(sd)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't print results: %v", err), nil
|
||||
}
|
||||
out, err := prettyprint(b)
|
||||
return out, err, nil
|
||||
}
|
||||
numDiffs := len(sd)
|
||||
if numDiffs == 0 {
|
||||
return bytes.NewBuffer([]byte("No changes identified\n")), nil, nil
|
||||
}
|
||||
|
||||
var out bytes.Buffer
|
||||
if numDiffs != sd.BreakingChangeCount() {
|
||||
fmt.Fprintln(&out, "NON-BREAKING CHANGES:\n=====================")
|
||||
_, _ = out.ReadFrom(sd.reportChanges(NonBreaking))
|
||||
if sd.WarningChangeCount() > 0 {
|
||||
fmt.Fprintln(&out, "\nNON-BREAKING CHANGES WITH WARNING:\n==================================")
|
||||
_, _ = out.ReadFrom(sd.reportChanges(Warning))
|
||||
}
|
||||
}
|
||||
|
||||
more, err, warn := sd.ReportCompatibility()
|
||||
if err != nil {
|
||||
return nil, err, warn
|
||||
}
|
||||
_, _ = out.ReadFrom(more)
|
||||
return &out, nil, warn
|
||||
}
|
||||
163
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/type_adapters.go
generated
vendored
Normal file
163
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/type_adapters.go
generated
vendored
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
package diff
|
||||
|
||||
import (
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
func forItems(items *spec.Items) *spec.Schema {
|
||||
if items == nil {
|
||||
return nil
|
||||
}
|
||||
valids := items.CommonValidations
|
||||
schema := spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{items.SimpleSchema.Type},
|
||||
Format: items.SimpleSchema.Format,
|
||||
Maximum: valids.Maximum,
|
||||
ExclusiveMaximum: valids.ExclusiveMaximum,
|
||||
Minimum: valids.Minimum,
|
||||
ExclusiveMinimum: valids.ExclusiveMinimum,
|
||||
MaxLength: valids.MaxLength,
|
||||
MinLength: valids.MinLength,
|
||||
Pattern: valids.Pattern,
|
||||
MaxItems: valids.MaxItems,
|
||||
MinItems: valids.MinItems,
|
||||
UniqueItems: valids.UniqueItems,
|
||||
MultipleOf: valids.MultipleOf,
|
||||
Enum: valids.Enum,
|
||||
},
|
||||
}
|
||||
return &schema
|
||||
}
|
||||
|
||||
func forHeader(header spec.Header) *spec.SchemaProps {
|
||||
return &spec.SchemaProps{
|
||||
Type: []string{header.Type},
|
||||
Format: header.Format,
|
||||
Items: &spec.SchemaOrArray{Schema: forItems(header.Items)},
|
||||
Maximum: header.Maximum,
|
||||
ExclusiveMaximum: header.ExclusiveMaximum,
|
||||
Minimum: header.Minimum,
|
||||
ExclusiveMinimum: header.ExclusiveMinimum,
|
||||
MaxLength: header.MaxLength,
|
||||
MinLength: header.MinLength,
|
||||
Pattern: header.Pattern,
|
||||
MaxItems: header.MaxItems,
|
||||
MinItems: header.MinItems,
|
||||
UniqueItems: header.UniqueItems,
|
||||
MultipleOf: header.MultipleOf,
|
||||
Enum: header.Enum,
|
||||
}
|
||||
}
|
||||
|
||||
func forParam(param spec.Parameter) *spec.SchemaProps {
|
||||
return &spec.SchemaProps{
|
||||
Type: []string{param.Type},
|
||||
Format: param.Format,
|
||||
Items: &spec.SchemaOrArray{Schema: forItems(param.Items)},
|
||||
Maximum: param.Maximum,
|
||||
ExclusiveMaximum: param.ExclusiveMaximum,
|
||||
Minimum: param.Minimum,
|
||||
ExclusiveMinimum: param.ExclusiveMinimum,
|
||||
MaxLength: param.MaxLength,
|
||||
MinLength: param.MinLength,
|
||||
Pattern: param.Pattern,
|
||||
MaxItems: param.MaxItems,
|
||||
MinItems: param.MinItems,
|
||||
UniqueItems: param.UniqueItems,
|
||||
MultipleOf: param.MultipleOf,
|
||||
Enum: param.Enum,
|
||||
}
|
||||
}
|
||||
|
||||
// OperationMap saves indexing operations in PathItems individually
|
||||
type OperationMap map[string]*spec.Operation
|
||||
|
||||
func toMap(item *spec.PathItem) OperationMap {
|
||||
m := make(OperationMap)
|
||||
|
||||
if item.Post != nil {
|
||||
m["post"] = item.Post
|
||||
}
|
||||
if item.Get != nil {
|
||||
m["get"] = item.Get
|
||||
}
|
||||
if item.Put != nil {
|
||||
m["put"] = item.Put
|
||||
}
|
||||
if item.Patch != nil {
|
||||
m["patch"] = item.Patch
|
||||
}
|
||||
if item.Head != nil {
|
||||
m["head"] = item.Head
|
||||
}
|
||||
if item.Options != nil {
|
||||
m["options"] = item.Options
|
||||
}
|
||||
if item.Delete != nil {
|
||||
m["delete"] = item.Delete
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func getURLMethodsFor(spec *spec.Swagger) URLMethods {
|
||||
returnURLMethods := URLMethods{}
|
||||
|
||||
for url, eachPath := range spec.Paths.Paths {
|
||||
eachPath := eachPath
|
||||
opsMap := toMap(&eachPath)
|
||||
for method, op := range opsMap {
|
||||
returnURLMethods[URLMethod{url, method}] = &PathItemOp{&eachPath, op, eachPath.Extensions}
|
||||
}
|
||||
}
|
||||
return returnURLMethods
|
||||
}
|
||||
|
||||
func isStringType(typeName string) bool {
|
||||
return typeName == "string" || typeName == "password"
|
||||
}
|
||||
|
||||
// SchemaFromRefFn define this to get a schema for a ref
|
||||
type SchemaFromRefFn func(spec.Ref) (*spec.Schema, string)
|
||||
|
||||
func propertiesFor(schema *spec.Schema, getRefFn SchemaFromRefFn) PropertyMap {
|
||||
if isRefType(schema) {
|
||||
schema, _ = getRefFn(schema.Ref)
|
||||
}
|
||||
props := PropertyMap{}
|
||||
|
||||
requiredProps := schema.Required
|
||||
requiredMap := map[string]bool{}
|
||||
for _, prop := range requiredProps {
|
||||
requiredMap[prop] = true
|
||||
}
|
||||
|
||||
if schema.Properties != nil {
|
||||
for name, prop := range schema.Properties {
|
||||
prop := prop
|
||||
required := requiredMap[name]
|
||||
props[name] = PropertyDefn{Schema: &prop, Required: required}
|
||||
}
|
||||
}
|
||||
for _, e := range schema.AllOf {
|
||||
eachAllOf := e
|
||||
allOfMap := propertiesFor(&eachAllOf, getRefFn)
|
||||
for name, prop := range allOfMap {
|
||||
props[name] = prop
|
||||
}
|
||||
}
|
||||
return props
|
||||
}
|
||||
|
||||
func getRef(item interface{}) spec.Ref {
|
||||
switch s := item.(type) {
|
||||
case *spec.Refable:
|
||||
return s.Ref
|
||||
case *spec.Schema:
|
||||
return s.Ref
|
||||
case *spec.SchemaProps:
|
||||
return s.Ref
|
||||
default:
|
||||
return spec.Ref{}
|
||||
}
|
||||
}
|
||||
81
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/expand.go
generated
vendored
Normal file
81
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/expand.go
generated
vendored
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/swag"
|
||||
flags "github.com/jessevdk/go-flags"
|
||||
)
|
||||
|
||||
// ExpandSpec is a command that expands the $refs in a swagger document.
|
||||
//
|
||||
// There are no specific options for this expansion.
|
||||
type ExpandSpec struct {
|
||||
Compact bool `long:"compact" description:"applies to JSON formatted specs. When present, doesn't prettify the json"`
|
||||
Output flags.Filename `long:"output" short:"o" description:"the file to write to"`
|
||||
Format string `long:"format" description:"the format for the spec document" default:"json" choice:"yaml" choice:"json"`
|
||||
}
|
||||
|
||||
// Execute expands the spec
|
||||
func (c *ExpandSpec) Execute(args []string) error {
|
||||
if len(args) != 1 {
|
||||
return errors.New("expand command requires the single swagger document url to be specified")
|
||||
}
|
||||
|
||||
swaggerDoc := args[0]
|
||||
specDoc, err := loads.Spec(swaggerDoc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
exp, err := specDoc.Expanded()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return writeToFile(exp.Spec(), !c.Compact, c.Format, string(c.Output))
|
||||
}
|
||||
|
||||
func writeToFile(swspec *spec.Swagger, pretty bool, format string, output string) error {
|
||||
var b []byte
|
||||
var err error
|
||||
asJSON := format == "json"
|
||||
|
||||
log.Println("format = ", format)
|
||||
switch {
|
||||
case pretty && asJSON:
|
||||
b, err = json.MarshalIndent(swspec, "", " ")
|
||||
case asJSON:
|
||||
b, err = json.Marshal(swspec)
|
||||
default:
|
||||
// marshals as YAML
|
||||
b, err = json.Marshal(swspec)
|
||||
if err == nil {
|
||||
var data swag.JSONMapSlice
|
||||
if erg := json.Unmarshal(b, &data); erg != nil {
|
||||
log.Fatalln(erg)
|
||||
}
|
||||
var bb interface{}
|
||||
bb, err = data.MarshalYAML()
|
||||
b = bb.([]byte)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if output == "" {
|
||||
fmt.Println(string(b))
|
||||
return nil
|
||||
}
|
||||
|
||||
return os.WriteFile(output, b, 0644) // #nosec
|
||||
}
|
||||
48
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/flatten.go
generated
vendored
Normal file
48
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/flatten.go
generated
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/go-openapi/analysis"
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-swagger/go-swagger/cmd/swagger/commands/generate"
|
||||
flags "github.com/jessevdk/go-flags"
|
||||
)
|
||||
|
||||
// FlattenSpec is a command that flattens a swagger document
|
||||
// which will expand the remote references in a spec and move inline schemas to definitions
|
||||
// after flattening there are no complex inlined anymore
|
||||
type FlattenSpec struct {
|
||||
Compact bool `long:"compact" description:"applies to JSON formatted specs. When present, doesn't prettify the json"`
|
||||
Output flags.Filename `long:"output" short:"o" description:"the file to write to"`
|
||||
Format string `long:"format" description:"the format for the spec document" default:"json" choice:"yaml" choice:"json"`
|
||||
generate.FlattenCmdOptions
|
||||
}
|
||||
|
||||
// Execute flattens the spec
|
||||
func (c *FlattenSpec) Execute(args []string) error {
|
||||
if len(args) != 1 {
|
||||
return errors.New("flatten command requires the single swagger document url to be specified")
|
||||
}
|
||||
|
||||
swaggerDoc := args[0]
|
||||
specDoc, err := loads.Spec(swaggerDoc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
flattenOpts := c.FlattenCmdOptions.SetFlattenOptions(&analysis.FlattenOpts{
|
||||
// defaults
|
||||
Minimal: true,
|
||||
Verbose: true,
|
||||
Expand: false,
|
||||
RemoveUnused: false,
|
||||
})
|
||||
flattenOpts.BasePath = specDoc.SpecFilePath()
|
||||
flattenOpts.Spec = analysis.New(specDoc.Spec())
|
||||
if err := analysis.Flatten(*flattenOpts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return writeToFile(specDoc.Spec(), !c.Compact, c.Format, string(c.Output))
|
||||
}
|
||||
29
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate.go
generated
vendored
Normal file
29
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate.go
generated
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// 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 commands
|
||||
|
||||
import "github.com/go-swagger/go-swagger/cmd/swagger/commands/generate"
|
||||
|
||||
// Generate command to group all generator commands together
|
||||
type Generate struct {
|
||||
Model *generate.Model `command:"model"`
|
||||
Operation *generate.Operation `command:"operation"`
|
||||
Support *generate.Support `command:"support"`
|
||||
Server *generate.Server `command:"server"`
|
||||
Spec *generate.SpecFile `command:"spec"`
|
||||
Client *generate.Client `command:"client"`
|
||||
Cli *generate.Cli `command:"cli"`
|
||||
Markdown *generate.Markdown `command:"markdown"`
|
||||
}
|
||||
26
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/cli.go
generated
vendored
Normal file
26
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/cli.go
generated
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
package generate
|
||||
|
||||
import "github.com/go-swagger/go-swagger/generator"
|
||||
|
||||
type Cli struct {
|
||||
// generate a cli includes all client code
|
||||
Client
|
||||
// cmd/<cli-app-name>/main.go will be generated. This ensures that go install will compile the app with desired name.
|
||||
CliAppName string `long:"cli-app-name" description:"the app name for the cli executable. useful for go install." default:"cli"`
|
||||
}
|
||||
|
||||
func (c Cli) apply(opts *generator.GenOpts) {
|
||||
c.Client.apply(opts)
|
||||
opts.IncludeCLi = true
|
||||
opts.CliPackage = "cli" // hardcoded for now, can be exposed via cmd opt later
|
||||
opts.CliAppName = c.CliAppName
|
||||
}
|
||||
|
||||
func (c *Cli) generate(opts *generator.GenOpts) error {
|
||||
return c.Client.generate(opts)
|
||||
}
|
||||
|
||||
// Execute runs this command
|
||||
func (c *Cli) Execute(args []string) error {
|
||||
return createSwagger(c)
|
||||
}
|
||||
86
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/client.go
generated
vendored
Normal file
86
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/client.go
generated
vendored
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// 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 generate
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/go-swagger/go-swagger/generator"
|
||||
)
|
||||
|
||||
type clientOptions struct {
|
||||
ClientPackage string `long:"client-package" short:"c" description:"the package to save the client specific code" default:"client"`
|
||||
}
|
||||
|
||||
func (co clientOptions) apply(opts *generator.GenOpts) {
|
||||
opts.ClientPackage = co.ClientPackage
|
||||
}
|
||||
|
||||
// Client the command to generate a swagger client
|
||||
type Client struct {
|
||||
WithShared
|
||||
WithModels
|
||||
WithOperations
|
||||
|
||||
clientOptions
|
||||
schemeOptions
|
||||
mediaOptions
|
||||
|
||||
SkipModels bool `long:"skip-models" description:"no models will be generated when this flag is specified"`
|
||||
SkipOperations bool `long:"skip-operations" description:"no operations will be generated when this flag is specified"`
|
||||
|
||||
Name string `long:"name" short:"A" description:"the name of the application, defaults to a mangled value of info.title"`
|
||||
}
|
||||
|
||||
func (c Client) apply(opts *generator.GenOpts) {
|
||||
c.Shared.apply(opts)
|
||||
c.Models.apply(opts)
|
||||
c.Operations.apply(opts)
|
||||
c.clientOptions.apply(opts)
|
||||
c.schemeOptions.apply(opts)
|
||||
c.mediaOptions.apply(opts)
|
||||
|
||||
opts.IncludeModel = !c.SkipModels
|
||||
opts.IncludeValidator = !c.SkipModels
|
||||
opts.IncludeHandler = !c.SkipOperations
|
||||
opts.IncludeParameters = !c.SkipOperations
|
||||
opts.IncludeResponses = !c.SkipOperations
|
||||
opts.Name = c.Name
|
||||
|
||||
opts.IsClient = true
|
||||
opts.IncludeSupport = true
|
||||
}
|
||||
|
||||
func (c *Client) generate(opts *generator.GenOpts) error {
|
||||
return generator.GenerateClient(c.Name, c.Models.Models, c.Operations.Operations, opts)
|
||||
}
|
||||
|
||||
func (c *Client) log(rp string) {
|
||||
log.Println(`Generation completed!
|
||||
|
||||
For this generation to compile you need to have some packages in your go.mod:
|
||||
|
||||
* github.com/go-openapi/errors
|
||||
* github.com/go-openapi/runtime
|
||||
* github.com/go-openapi/runtime/client
|
||||
* github.com/go-openapi/strfmt
|
||||
|
||||
You can get these now with: go mod tidy`)
|
||||
}
|
||||
|
||||
// Execute runs this command
|
||||
func (c *Client) Execute(args []string) error {
|
||||
return createSwagger(c)
|
||||
}
|
||||
17
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/contrib.go
generated
vendored
Normal file
17
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/contrib.go
generated
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
package generate
|
||||
|
||||
import (
|
||||
"github.com/go-swagger/go-swagger/generator"
|
||||
)
|
||||
|
||||
// contribOptionsOverride gives contributed templates the ability to override the options if they need
|
||||
func contribOptionsOverride(opts *generator.GenOpts) {
|
||||
// nolint: gocritic
|
||||
switch opts.Template {
|
||||
case "stratoscale":
|
||||
// Stratoscale template needs to regenerate the configureapi on every run.
|
||||
opts.RegenerateConfigureAPI = true
|
||||
// It also does not use the main.go
|
||||
opts.IncludeMain = false
|
||||
}
|
||||
}
|
||||
33
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/markdown.go
generated
vendored
Normal file
33
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/markdown.go
generated
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
package generate
|
||||
|
||||
import (
|
||||
"github.com/go-swagger/go-swagger/generator"
|
||||
"github.com/jessevdk/go-flags"
|
||||
)
|
||||
|
||||
// Markdown generates a markdown representation of the spec
|
||||
type Markdown struct {
|
||||
WithShared
|
||||
WithModels
|
||||
WithOperations
|
||||
|
||||
Output flags.Filename `long:"output" short:"" description:"the file to write the generated markdown." default:"markdown.md"`
|
||||
}
|
||||
|
||||
func (m Markdown) apply(opts *generator.GenOpts) {
|
||||
m.Shared.apply(opts)
|
||||
m.Models.apply(opts)
|
||||
m.Operations.apply(opts)
|
||||
}
|
||||
|
||||
func (m *Markdown) generate(opts *generator.GenOpts) error {
|
||||
return generator.GenerateMarkdown(string(m.Output), m.Models.Models, m.Operations.Operations, opts)
|
||||
}
|
||||
|
||||
func (m Markdown) log(rp string) {
|
||||
}
|
||||
|
||||
// Execute runs this command
|
||||
func (m *Markdown) Execute(args []string) error {
|
||||
return createSwagger(m)
|
||||
}
|
||||
98
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/model.go
generated
vendored
Normal file
98
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/model.go
generated
vendored
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// 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 generate
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
|
||||
"github.com/go-swagger/go-swagger/generator"
|
||||
)
|
||||
|
||||
type modelOptions struct {
|
||||
ModelPackage string `long:"model-package" short:"m" description:"the package to save the models" default:"models"`
|
||||
Models []string `long:"model" short:"M" description:"specify a model to include in generation, repeat for multiple (defaults to all)"`
|
||||
ExistingModels string `long:"existing-models" description:"use pre-generated models e.g. github.com/foobar/model"`
|
||||
StrictAdditionalProperties bool `long:"strict-additional-properties" description:"disallow extra properties when additionalProperties is set to false"`
|
||||
KeepSpecOrder bool `long:"keep-spec-order" description:"keep schema properties order identical to spec file"`
|
||||
AllDefinitions bool `long:"all-definitions" description:"generate all model definitions regardless of usage in operations" hidden:"deprecated"`
|
||||
StructTags []string `long:"struct-tags" description:"the struct tags to generate, repeat for multiple (defaults to json)"`
|
||||
}
|
||||
|
||||
func (mo modelOptions) apply(opts *generator.GenOpts) {
|
||||
opts.ModelPackage = mo.ModelPackage
|
||||
opts.Models = mo.Models
|
||||
opts.ExistingModels = mo.ExistingModels
|
||||
opts.StrictAdditionalProperties = mo.StrictAdditionalProperties
|
||||
opts.PropertiesSpecOrder = mo.KeepSpecOrder
|
||||
opts.IgnoreOperations = mo.AllDefinitions
|
||||
opts.StructTags = mo.StructTags
|
||||
}
|
||||
|
||||
// WithModels adds the model options group.
|
||||
//
|
||||
// This group is available to all commands that need some model generation.
|
||||
type WithModels struct {
|
||||
Models modelOptions `group:"Options for model generation"`
|
||||
}
|
||||
|
||||
// Model the generate model file command.
|
||||
//
|
||||
// Define the options that are specific to the "swagger generate model" command.
|
||||
type Model struct {
|
||||
WithShared
|
||||
WithModels
|
||||
|
||||
NoStruct bool `long:"skip-struct" description:"when present will not generate the model struct" hidden:"deprecated"`
|
||||
Name []string `long:"name" short:"n" description:"the model to generate, repeat for multiple (defaults to all). Same as --models"`
|
||||
AcceptDefinitionsOnly bool `long:"accept-definitions-only" description:"accepts a partial swagger spec with only the definitions key"`
|
||||
}
|
||||
|
||||
func (m Model) apply(opts *generator.GenOpts) {
|
||||
m.Shared.apply(opts)
|
||||
m.Models.apply(opts)
|
||||
|
||||
opts.IncludeModel = !m.NoStruct
|
||||
opts.IncludeValidator = !m.NoStruct
|
||||
opts.AcceptDefinitionsOnly = m.AcceptDefinitionsOnly
|
||||
}
|
||||
|
||||
func (m Model) log(rp string) {
|
||||
log.Println(`Generation completed!
|
||||
|
||||
For this generation to compile you need to have some packages in your go.mod:
|
||||
|
||||
* github.com/go-openapi/validate
|
||||
* github.com/go-openapi/strfmt
|
||||
|
||||
You can get these now with: go mod tidy`)
|
||||
}
|
||||
|
||||
func (m *Model) generate(opts *generator.GenOpts) error {
|
||||
return generator.GenerateModels(append(m.Name, m.Models.Models...), opts)
|
||||
}
|
||||
|
||||
// Execute generates a model file
|
||||
func (m *Model) Execute(args []string) error {
|
||||
|
||||
if m.Shared.DumpData && len(append(m.Name, m.Models.Models...)) > 1 {
|
||||
return errors.New("only 1 model at a time is supported for dumping data")
|
||||
}
|
||||
|
||||
if m.Models.ExistingModels != "" {
|
||||
log.Println("warning: Ignoring existing-models flag when generating models.")
|
||||
}
|
||||
return createSwagger(m)
|
||||
}
|
||||
104
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/operation.go
generated
vendored
Normal file
104
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/operation.go
generated
vendored
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// 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 generate
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
|
||||
"github.com/go-swagger/go-swagger/generator"
|
||||
)
|
||||
|
||||
type operationOptions struct {
|
||||
Operations []string `long:"operation" short:"O" description:"specify an operation to include, repeat for multiple (defaults to all)"`
|
||||
Tags []string `long:"tags" description:"the tags to include, if not specified defaults to all" group:"operations"`
|
||||
APIPackage string `long:"api-package" short:"a" description:"the package to save the operations" default:"operations"`
|
||||
WithEnumCI bool `long:"with-enum-ci" description:"allow case-insensitive enumerations"`
|
||||
|
||||
// tags handling
|
||||
SkipTagPackages bool `long:"skip-tag-packages" description:"skips the generation of tag-based operation packages, resulting in a flat generation"`
|
||||
}
|
||||
|
||||
func (oo operationOptions) apply(opts *generator.GenOpts) {
|
||||
opts.Operations = oo.Operations
|
||||
opts.Tags = oo.Tags
|
||||
opts.APIPackage = oo.APIPackage
|
||||
opts.AllowEnumCI = oo.WithEnumCI
|
||||
opts.SkipTagPackages = oo.SkipTagPackages
|
||||
}
|
||||
|
||||
// WithOperations adds the operations options group
|
||||
type WithOperations struct {
|
||||
Operations operationOptions `group:"Options for operation generation"`
|
||||
}
|
||||
|
||||
// Operation the generate operation files command
|
||||
type Operation struct {
|
||||
WithShared
|
||||
WithOperations
|
||||
|
||||
clientOptions
|
||||
serverOptions
|
||||
schemeOptions
|
||||
mediaOptions
|
||||
|
||||
ModelPackage string `long:"model-package" short:"m" description:"the package to save the models" default:"models"`
|
||||
|
||||
NoHandler bool `long:"skip-handler" description:"when present will not generate an operation handler"`
|
||||
NoStruct bool `long:"skip-parameters" description:"when present will not generate the parameter model struct"`
|
||||
NoResponses bool `long:"skip-responses" description:"when present will not generate the response model struct"`
|
||||
NoURLBuilder bool `long:"skip-url-builder" description:"when present will not generate a URL builder"`
|
||||
|
||||
Name []string `long:"name" short:"n" description:"the operations to generate, repeat for multiple (defaults to all). Same as --operations"`
|
||||
}
|
||||
|
||||
func (o Operation) apply(opts *generator.GenOpts) {
|
||||
o.Shared.apply(opts)
|
||||
o.Operations.apply(opts)
|
||||
o.clientOptions.apply(opts)
|
||||
o.serverOptions.apply(opts)
|
||||
o.schemeOptions.apply(opts)
|
||||
o.mediaOptions.apply(opts)
|
||||
|
||||
opts.ModelPackage = o.ModelPackage
|
||||
opts.IncludeHandler = !o.NoHandler
|
||||
opts.IncludeResponses = !o.NoResponses
|
||||
opts.IncludeParameters = !o.NoStruct
|
||||
opts.IncludeURLBuilder = !o.NoURLBuilder
|
||||
}
|
||||
|
||||
func (o *Operation) generate(opts *generator.GenOpts) error {
|
||||
return generator.GenerateServerOperation(append(o.Name, o.Operations.Operations...), opts)
|
||||
}
|
||||
|
||||
func (o Operation) log(rp string) {
|
||||
|
||||
log.Println(`Generation completed!
|
||||
|
||||
For this generation to compile you need to have some packages in your go.mod:
|
||||
|
||||
* github.com/go-openapi/runtime
|
||||
|
||||
You can get these now with: go mod tidy`)
|
||||
}
|
||||
|
||||
// Execute generates a model file
|
||||
func (o *Operation) Execute(args []string) error {
|
||||
if o.Shared.DumpData && len(append(o.Name, o.Operations.Operations...)) > 1 {
|
||||
return errors.New("only 1 operation at a time is supported for dumping data")
|
||||
}
|
||||
|
||||
return createSwagger(o)
|
||||
}
|
||||
119
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/server.go
generated
vendored
Normal file
119
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/server.go
generated
vendored
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// 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 generate
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/go-swagger/go-swagger/generator"
|
||||
)
|
||||
|
||||
type serverOptions struct {
|
||||
ServerPackage string `long:"server-package" short:"s" description:"the package to save the server specific code" default:"restapi"`
|
||||
MainTarget string `long:"main-package" short:"" description:"the location of the generated main. Defaults to cmd/{name}-server" default:""`
|
||||
ImplementationPackage string `long:"implementation-package" short:"" description:"the location of the backend implementation of the server, which will be autowired with api" default:""`
|
||||
}
|
||||
|
||||
func (cs serverOptions) apply(opts *generator.GenOpts) {
|
||||
opts.ServerPackage = cs.ServerPackage
|
||||
}
|
||||
|
||||
// Server the command to generate an entire server application
|
||||
type Server struct {
|
||||
WithShared
|
||||
WithModels
|
||||
WithOperations
|
||||
|
||||
serverOptions
|
||||
schemeOptions
|
||||
mediaOptions
|
||||
|
||||
SkipModels bool `long:"skip-models" description:"no models will be generated when this flag is specified"`
|
||||
SkipOperations bool `long:"skip-operations" description:"no operations will be generated when this flag is specified"`
|
||||
SkipSupport bool `long:"skip-support" description:"no supporting files will be generated when this flag is specified"`
|
||||
ExcludeMain bool `long:"exclude-main" description:"exclude main function, so just generate the library"`
|
||||
ExcludeSpec bool `long:"exclude-spec" description:"don't embed the swagger specification"`
|
||||
FlagStrategy string `long:"flag-strategy" description:"the strategy to provide flags for the server" default:"go-flags" choice:"go-flags" choice:"pflag" choice:"flag"` // nolint: staticcheck
|
||||
CompatibilityMode string `long:"compatibility-mode" description:"the compatibility mode for the tls server" default:"modern" choice:"modern" choice:"intermediate"` // nolint: staticcheck
|
||||
RegenerateConfigureAPI bool `long:"regenerate-configureapi" description:"Force regeneration of configureapi.go"`
|
||||
|
||||
Name string `long:"name" short:"A" description:"the name of the application, defaults to a mangled value of info.title"`
|
||||
// TODO(fredbi): CmdName string `long:"cmd-name" short:"A" description:"the name of the server command, when main is generated (defaults to {name}-server)"`
|
||||
|
||||
// deprecated flags
|
||||
WithContext bool `long:"with-context" description:"handlers get a context as first arg (deprecated)"`
|
||||
}
|
||||
|
||||
func (s Server) apply(opts *generator.GenOpts) {
|
||||
if s.WithContext {
|
||||
log.Printf("warning: deprecated option --with-context is ignored")
|
||||
}
|
||||
|
||||
s.Shared.apply(opts)
|
||||
s.Models.apply(opts)
|
||||
s.Operations.apply(opts)
|
||||
s.serverOptions.apply(opts)
|
||||
s.schemeOptions.apply(opts)
|
||||
s.mediaOptions.apply(opts)
|
||||
|
||||
opts.IncludeModel = !s.SkipModels
|
||||
opts.IncludeValidator = !s.SkipModels
|
||||
opts.IncludeHandler = !s.SkipOperations
|
||||
opts.IncludeParameters = !s.SkipOperations
|
||||
opts.IncludeResponses = !s.SkipOperations
|
||||
opts.IncludeURLBuilder = !s.SkipOperations
|
||||
opts.IncludeSupport = !s.SkipSupport
|
||||
opts.IncludeMain = !s.ExcludeMain
|
||||
opts.ExcludeSpec = s.ExcludeSpec
|
||||
opts.FlagStrategy = s.FlagStrategy
|
||||
opts.CompatibilityMode = s.CompatibilityMode
|
||||
opts.RegenerateConfigureAPI = s.RegenerateConfigureAPI
|
||||
|
||||
opts.Name = s.Name
|
||||
opts.MainPackage = s.MainTarget
|
||||
|
||||
opts.ImplementationPackage = s.ImplementationPackage
|
||||
}
|
||||
|
||||
func (s *Server) generate(opts *generator.GenOpts) error {
|
||||
return generator.GenerateServer(s.Name, s.Models.Models, s.Operations.Operations, opts)
|
||||
}
|
||||
|
||||
func (s Server) log(rp string) {
|
||||
var flagsPackage string
|
||||
switch {
|
||||
case strings.HasPrefix(s.FlagStrategy, "pflag"):
|
||||
flagsPackage = "github.com/spf13/pflag"
|
||||
case strings.HasPrefix(s.FlagStrategy, "flag"):
|
||||
flagsPackage = "flag"
|
||||
default:
|
||||
flagsPackage = "github.com/jessevdk/go-flags"
|
||||
}
|
||||
|
||||
log.Println(`Generation completed!
|
||||
|
||||
For this generation to compile you need to have some packages in your go.mod:
|
||||
|
||||
* github.com/go-openapi/runtime
|
||||
* ` + flagsPackage + `
|
||||
|
||||
You can get these now with: go mod tidy`)
|
||||
}
|
||||
|
||||
// Execute runs this command
|
||||
func (s *Server) Execute(args []string) error {
|
||||
return createSwagger(s)
|
||||
}
|
||||
240
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/shared.go
generated
vendored
Normal file
240
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/shared.go
generated
vendored
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
package generate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/analysis"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-swagger/go-swagger/generator"
|
||||
flags "github.com/jessevdk/go-flags"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// FlattenCmdOptions determines options to the flatten spec preprocessing
|
||||
type FlattenCmdOptions struct {
|
||||
WithExpand bool `long:"with-expand" description:"expands all $ref's in spec prior to generation (shorthand to --with-flatten=expand)" group:"shared"`
|
||||
WithFlatten []string `long:"with-flatten" description:"flattens all $ref's in spec prior to generation" choice:"minimal" choice:"full" choice:"expand" choice:"verbose" choice:"noverbose" choice:"remove-unused" default:"minimal" default:"verbose" group:"shared"` // nolint: staticcheck
|
||||
}
|
||||
|
||||
// SetFlattenOptions builds flatten options from command line args
|
||||
func (f *FlattenCmdOptions) SetFlattenOptions(dflt *analysis.FlattenOpts) (res *analysis.FlattenOpts) {
|
||||
res = &analysis.FlattenOpts{}
|
||||
if dflt != nil {
|
||||
*res = *dflt
|
||||
}
|
||||
if f == nil {
|
||||
return
|
||||
}
|
||||
verboseIsSet := false
|
||||
minimalIsSet := false
|
||||
expandIsSet := false
|
||||
if f.WithExpand {
|
||||
res.Expand = true
|
||||
expandIsSet = true
|
||||
}
|
||||
for _, opt := range f.WithFlatten {
|
||||
switch opt {
|
||||
case "verbose":
|
||||
res.Verbose = true
|
||||
verboseIsSet = true
|
||||
case "noverbose":
|
||||
if !verboseIsSet {
|
||||
// verbose flag takes precedence
|
||||
res.Verbose = false
|
||||
verboseIsSet = true
|
||||
}
|
||||
case "remove-unused":
|
||||
res.RemoveUnused = true
|
||||
case "expand":
|
||||
res.Expand = true
|
||||
expandIsSet = true
|
||||
case "full":
|
||||
if !minimalIsSet && !expandIsSet {
|
||||
// minimal flag takes precedence
|
||||
res.Minimal = false
|
||||
minimalIsSet = true
|
||||
}
|
||||
case "minimal":
|
||||
if !expandIsSet {
|
||||
// expand flag takes precedence
|
||||
res.Minimal = true
|
||||
minimalIsSet = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type sharedCommand interface {
|
||||
apply(*generator.GenOpts)
|
||||
getConfigFile() string
|
||||
generate(*generator.GenOpts) error
|
||||
log(string)
|
||||
}
|
||||
|
||||
type schemeOptions struct {
|
||||
Principal string `short:"P" long:"principal" description:"the model to use for the security principal"`
|
||||
DefaultScheme string `long:"default-scheme" description:"the default scheme for this API" default:"http"`
|
||||
|
||||
PrincipalIface bool `long:"principal-is-interface" description:"the security principal provided is an interface, not a struct"`
|
||||
}
|
||||
|
||||
func (so schemeOptions) apply(opts *generator.GenOpts) {
|
||||
opts.Principal = so.Principal
|
||||
opts.PrincipalCustomIface = so.PrincipalIface
|
||||
opts.DefaultScheme = so.DefaultScheme
|
||||
}
|
||||
|
||||
type mediaOptions struct {
|
||||
DefaultProduces string `long:"default-produces" description:"the default mime type that API operations produce" default:"application/json"`
|
||||
DefaultConsumes string `long:"default-consumes" description:"the default mime type that API operations consume" default:"application/json"`
|
||||
}
|
||||
|
||||
func (m mediaOptions) apply(opts *generator.GenOpts) {
|
||||
opts.DefaultProduces = m.DefaultProduces
|
||||
opts.DefaultConsumes = m.DefaultConsumes
|
||||
|
||||
const xmlIdentifier = "xml"
|
||||
opts.WithXML = strings.Contains(opts.DefaultProduces, xmlIdentifier) || strings.Contains(opts.DefaultConsumes, xmlIdentifier)
|
||||
}
|
||||
|
||||
// WithShared adds the shared options group
|
||||
type WithShared struct {
|
||||
Shared sharedOptions `group:"Options common to all code generation commands"`
|
||||
}
|
||||
|
||||
func (w WithShared) getConfigFile() string {
|
||||
return string(w.Shared.ConfigFile)
|
||||
}
|
||||
|
||||
type sharedOptionsCommon struct {
|
||||
Spec flags.Filename `long:"spec" short:"f" description:"the spec file to use (default swagger.{json,yml,yaml})" group:"shared"`
|
||||
Target flags.Filename `long:"target" short:"t" default:"./" description:"the base directory for generating the files" group:"shared"`
|
||||
Template string `long:"template" description:"load contributed templates" choice:"stratoscale" group:"shared"`
|
||||
TemplateDir flags.Filename `long:"template-dir" short:"T" description:"alternative template override directory" group:"shared"`
|
||||
ConfigFile flags.Filename `long:"config-file" short:"C" description:"configuration file to use for overriding template options" group:"shared"`
|
||||
CopyrightFile flags.Filename `long:"copyright-file" short:"r" description:"copyright file used to add copyright header" group:"shared"`
|
||||
AdditionalInitialisms []string `long:"additional-initialism" description:"consecutive capitals that should be considered intialisms" group:"shared"`
|
||||
AllowTemplateOverride bool `long:"allow-template-override" description:"allows overriding protected templates" group:"shared"`
|
||||
SkipValidation bool `long:"skip-validation" description:"skips validation of spec prior to generation" group:"shared"`
|
||||
DumpData bool `long:"dump-data" description:"when present dumps the json for the template generator instead of generating files" group:"shared"`
|
||||
StrictResponders bool `long:"strict-responders" description:"Use strict type for the handler return value"`
|
||||
FlattenCmdOptions
|
||||
}
|
||||
|
||||
func (s sharedOptionsCommon) apply(opts *generator.GenOpts) {
|
||||
opts.Spec = string(s.Spec)
|
||||
opts.Target = string(s.Target)
|
||||
opts.Template = s.Template
|
||||
opts.TemplateDir = string(s.TemplateDir)
|
||||
opts.AllowTemplateOverride = s.AllowTemplateOverride
|
||||
opts.ValidateSpec = !s.SkipValidation
|
||||
opts.DumpData = s.DumpData
|
||||
opts.FlattenOpts = s.FlattenCmdOptions.SetFlattenOptions(opts.FlattenOpts)
|
||||
opts.Copyright = string(s.CopyrightFile)
|
||||
opts.StrictResponders = s.StrictResponders
|
||||
|
||||
swag.AddInitialisms(s.AdditionalInitialisms...)
|
||||
}
|
||||
|
||||
func setCopyright(copyrightFile string) (string, error) {
|
||||
// read the Copyright from file path in opts
|
||||
if copyrightFile == "" {
|
||||
return "", nil
|
||||
}
|
||||
bytebuffer, err := os.ReadFile(copyrightFile)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(bytebuffer), nil
|
||||
}
|
||||
|
||||
func createSwagger(s sharedCommand) error {
|
||||
cfg, err := readConfig(s.getConfigFile())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
setDebug(cfg) // viper config Debug
|
||||
|
||||
opts := new(generator.GenOpts)
|
||||
s.apply(opts)
|
||||
|
||||
opts.Copyright, err = setCopyright(opts.Copyright)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not load copyright file: %v", err)
|
||||
}
|
||||
|
||||
if opts.Template != "" {
|
||||
contribOptionsOverride(opts)
|
||||
}
|
||||
|
||||
if err = opts.EnsureDefaults(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = configureOptsFromConfig(cfg, opts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = s.generate(opts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
basepath, err := filepath.Abs(".")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
targetAbs, err := filepath.Abs(opts.Target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rp, err := filepath.Rel(basepath, targetAbs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.log(rp)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func readConfig(filename string) (*viper.Viper, error) {
|
||||
if filename == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
abspath, err := filepath.Abs(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Println("trying to read config from", abspath)
|
||||
return generator.ReadConfig(abspath)
|
||||
}
|
||||
|
||||
func configureOptsFromConfig(cfg *viper.Viper, opts *generator.GenOpts) error {
|
||||
if cfg == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var def generator.LanguageDefinition
|
||||
if err := cfg.Unmarshal(&def); err != nil {
|
||||
return err
|
||||
}
|
||||
return def.ConfigureOpts(opts)
|
||||
}
|
||||
|
||||
func setDebug(cfg *viper.Viper) {
|
||||
// viper config debug
|
||||
if os.Getenv("DEBUG") != "" || os.Getenv("SWAGGER_DEBUG") != "" {
|
||||
if cfg != nil {
|
||||
cfg.Debug()
|
||||
} else {
|
||||
log.Println("No config read")
|
||||
}
|
||||
}
|
||||
}
|
||||
19
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/sharedopts_nonwin.go
generated
vendored
Normal file
19
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/sharedopts_nonwin.go
generated
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package generate
|
||||
|
||||
import (
|
||||
"github.com/go-swagger/go-swagger/generator"
|
||||
"github.com/jessevdk/go-flags"
|
||||
)
|
||||
|
||||
type sharedOptions struct {
|
||||
sharedOptionsCommon
|
||||
TemplatePlugin flags.Filename `long:"template-plugin" short:"p" description:"the template plugin to use" group:"shared"`
|
||||
}
|
||||
|
||||
func (s sharedOptions) apply(opts *generator.GenOpts) {
|
||||
opts.TemplatePlugin = string(s.TemplatePlugin)
|
||||
s.sharedOptionsCommon.apply(opts)
|
||||
}
|
||||
8
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/sharedopts_win.go
generated
vendored
Normal file
8
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/sharedopts_win.go
generated
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package generate
|
||||
|
||||
type sharedOptions struct {
|
||||
sharedOptionsCommon
|
||||
}
|
||||
125
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/spec.go
generated
vendored
Normal file
125
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/spec.go
generated
vendored
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
//go:build !go1.11
|
||||
// +build !go1.11
|
||||
|
||||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// 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 generate
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-swagger/go-swagger/scan"
|
||||
"github.com/jessevdk/go-flags"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// SpecFile command to generate a swagger spec from a go application
|
||||
type SpecFile struct {
|
||||
BasePath string `long:"base-path" short:"b" description:"the base path to use" default:"."`
|
||||
BuildTags string `long:"tags" short:"t" description:"build tags" default:""`
|
||||
ScanModels bool `long:"scan-models" short:"m" description:"includes models that were annotated with 'swagger:model'"`
|
||||
Compact bool `long:"compact" description:"when present, doesn't prettify the json"`
|
||||
Output flags.Filename `long:"output" short:"o" description:"the file to write to"`
|
||||
Input flags.Filename `long:"input" short:"i" description:"an input swagger file with which to merge"`
|
||||
Include []string `long:"include" short:"c" description:"include packages matching pattern"`
|
||||
Exclude []string `long:"exclude" short:"x" description:"exclude packages matching pattern"`
|
||||
IncludeTags []string `long:"include-tag" short:"" description:"include routes having specified tags (can be specified many times)"`
|
||||
ExcludeTags []string `long:"exclude-tag" short:"" description:"exclude routes having specified tags (can be specified many times)"`
|
||||
}
|
||||
|
||||
// Execute runs this command
|
||||
func (s *SpecFile) Execute(args []string) error {
|
||||
input, err := loadSpec(string(s.Input))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var opts scan.Opts
|
||||
opts.BasePath = s.BasePath
|
||||
opts.Input = input
|
||||
opts.ScanModels = s.ScanModels
|
||||
opts.BuildTags = s.BuildTags
|
||||
opts.Include = s.Include
|
||||
opts.Exclude = s.Exclude
|
||||
opts.IncludeTags = s.IncludeTags
|
||||
opts.ExcludeTags = s.ExcludeTags
|
||||
swspec, err := scan.Application(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return writeToFile(swspec, !s.Compact, string(s.Output))
|
||||
}
|
||||
|
||||
func loadSpec(input string) (*spec.Swagger, error) {
|
||||
if fi, err := os.Stat(input); err == nil {
|
||||
if fi.IsDir() {
|
||||
return nil, fmt.Errorf("expected %q to be a file not a directory", input)
|
||||
}
|
||||
sp, err := loads.Spec(input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return sp.Spec(), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func writeToFile(swspec *spec.Swagger, pretty bool, output string) error {
|
||||
var b []byte
|
||||
var err error
|
||||
|
||||
if strings.HasSuffix(output, "yml") || strings.HasSuffix(output, "yaml") {
|
||||
b, err = marshalToYAMLFormat(swspec)
|
||||
} else {
|
||||
b, err = marshalToJSONFormat(swspec, pretty)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if output == "" {
|
||||
fmt.Println(string(b))
|
||||
return nil
|
||||
}
|
||||
return os.WriteFile(output, b, 0644)
|
||||
}
|
||||
|
||||
func marshalToJSONFormat(swspec *spec.Swagger, pretty bool) ([]byte, error) {
|
||||
if pretty {
|
||||
return json.MarshalIndent(swspec, "", " ")
|
||||
}
|
||||
return json.Marshal(swspec)
|
||||
}
|
||||
|
||||
func marshalToYAMLFormat(swspec *spec.Swagger) ([]byte, error) {
|
||||
b, err := json.Marshal(swspec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var jsonObj interface{}
|
||||
if err := yaml.Unmarshal(b, &jsonObj); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return yaml.Marshal(jsonObj)
|
||||
}
|
||||
119
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/spec_go111.go
generated
vendored
Normal file
119
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/spec_go111.go
generated
vendored
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
//go:build go1.11
|
||||
// +build go1.11
|
||||
|
||||
package generate
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/go-swagger/go-swagger/codescan"
|
||||
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/jessevdk/go-flags"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// SpecFile command to generate a swagger spec from a go application
|
||||
type SpecFile struct {
|
||||
WorkDir string `long:"work-dir" short:"w" description:"the base path to use" default:"."`
|
||||
BuildTags string `long:"tags" short:"t" description:"build tags" default:""`
|
||||
ScanModels bool `long:"scan-models" short:"m" description:"includes models that were annotated with 'swagger:model'"`
|
||||
Compact bool `long:"compact" description:"when present, doesn't prettify the json"`
|
||||
Output flags.Filename `long:"output" short:"o" description:"the file to write to"`
|
||||
Input flags.Filename `long:"input" short:"i" description:"an input swagger file with which to merge"`
|
||||
Include []string `long:"include" short:"c" description:"include packages matching pattern"`
|
||||
Exclude []string `long:"exclude" short:"x" description:"exclude packages matching pattern"`
|
||||
IncludeTags []string `long:"include-tag" short:"" description:"include routes having specified tags (can be specified many times)"`
|
||||
ExcludeTags []string `long:"exclude-tag" short:"" description:"exclude routes having specified tags (can be specified many times)"`
|
||||
ExcludeDeps bool `long:"exclude-deps" short:"" description:"exclude all dependencies of project"`
|
||||
}
|
||||
|
||||
// Execute runs this command
|
||||
func (s *SpecFile) Execute(args []string) error {
|
||||
if len(args) == 0 { // by default consider all the paths under the working directory
|
||||
args = []string{"./..."}
|
||||
}
|
||||
|
||||
input, err := loadSpec(string(s.Input))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var opts codescan.Options
|
||||
opts.Packages = args
|
||||
opts.WorkDir = s.WorkDir
|
||||
opts.InputSpec = input
|
||||
opts.ScanModels = s.ScanModels
|
||||
opts.BuildTags = s.BuildTags
|
||||
opts.Include = s.Include
|
||||
opts.Exclude = s.Exclude
|
||||
opts.IncludeTags = s.IncludeTags
|
||||
opts.ExcludeTags = s.ExcludeTags
|
||||
opts.ExcludeDeps = s.ExcludeDeps
|
||||
swspec, err := codescan.Run(&opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return writeToFile(swspec, !s.Compact, string(s.Output))
|
||||
}
|
||||
|
||||
func loadSpec(input string) (*spec.Swagger, error) {
|
||||
if fi, err := os.Stat(input); err == nil {
|
||||
if fi.IsDir() {
|
||||
return nil, fmt.Errorf("expected %q to be a file not a directory", input)
|
||||
}
|
||||
sp, err := loads.Spec(input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return sp.Spec(), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func writeToFile(swspec *spec.Swagger, pretty bool, output string) error {
|
||||
var b []byte
|
||||
var err error
|
||||
|
||||
if strings.HasSuffix(output, "yml") || strings.HasSuffix(output, "yaml") {
|
||||
b, err = marshalToYAMLFormat(swspec)
|
||||
} else {
|
||||
b, err = marshalToJSONFormat(swspec, pretty)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if output == "" {
|
||||
fmt.Println(string(b))
|
||||
return nil
|
||||
}
|
||||
return os.WriteFile(output, b, 0644) // #nosec
|
||||
}
|
||||
|
||||
func marshalToJSONFormat(swspec *spec.Swagger, pretty bool) ([]byte, error) {
|
||||
if pretty {
|
||||
return json.MarshalIndent(swspec, "", " ")
|
||||
}
|
||||
return json.Marshal(swspec)
|
||||
}
|
||||
|
||||
func marshalToYAMLFormat(swspec *spec.Swagger) ([]byte, error) {
|
||||
b, err := json.Marshal(swspec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var jsonObj interface{}
|
||||
if err := yaml.Unmarshal(b, &jsonObj); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return yaml.Marshal(jsonObj)
|
||||
}
|
||||
67
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/support.go
generated
vendored
Normal file
67
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/support.go
generated
vendored
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// 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 generate
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/go-swagger/go-swagger/generator"
|
||||
)
|
||||
|
||||
// Support generates the supporting files
|
||||
type Support struct {
|
||||
WithShared
|
||||
WithModels
|
||||
WithOperations
|
||||
|
||||
clientOptions
|
||||
serverOptions
|
||||
schemeOptions
|
||||
mediaOptions
|
||||
|
||||
Name string `long:"name" short:"A" description:"the name of the application, defaults to a mangled value of info.title"`
|
||||
}
|
||||
|
||||
func (s *Support) apply(opts *generator.GenOpts) {
|
||||
s.Shared.apply(opts)
|
||||
s.Models.apply(opts)
|
||||
s.Operations.apply(opts)
|
||||
s.clientOptions.apply(opts)
|
||||
s.serverOptions.apply(opts)
|
||||
s.schemeOptions.apply(opts)
|
||||
s.mediaOptions.apply(opts)
|
||||
}
|
||||
|
||||
func (s *Support) generate(opts *generator.GenOpts) error {
|
||||
return generator.GenerateSupport(s.Name, s.Models.Models, s.Operations.Operations, opts)
|
||||
}
|
||||
|
||||
func (s Support) log(rp string) {
|
||||
|
||||
log.Println(`Generation completed!
|
||||
|
||||
For this generation to compile you need to have some packages in go.mod:
|
||||
|
||||
* github.com/go-openapi/runtime
|
||||
* github.com/asaskevich/govalidator
|
||||
* github.com/jessevdk/go-flags
|
||||
|
||||
You can get these now with: go mod tidy`)
|
||||
}
|
||||
|
||||
// Execute generates the supporting files file
|
||||
func (s *Support) Execute(args []string) error {
|
||||
return createSwagger(s)
|
||||
}
|
||||
13
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/initcmd.go
generated
vendored
Normal file
13
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/initcmd.go
generated
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
package commands
|
||||
|
||||
import "github.com/go-swagger/go-swagger/cmd/swagger/commands/initcmd"
|
||||
|
||||
// InitCmd is a command namespace for initializing things like a swagger spec.
|
||||
type InitCmd struct {
|
||||
Model *initcmd.Spec `command:"spec"`
|
||||
}
|
||||
|
||||
// Execute provides default empty implementation
|
||||
func (i *InitCmd) Execute(args []string) error {
|
||||
return nil
|
||||
}
|
||||
111
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/initcmd/spec.go
generated
vendored
Normal file
111
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/initcmd/spec.go
generated
vendored
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
package initcmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
// Spec a command struct for initializing a new swagger application.
|
||||
type Spec struct {
|
||||
Format string `long:"format" description:"the format for the spec document" default:"yaml" choice:"yaml" choice:"json"`
|
||||
Title string `long:"title" description:"the title of the API"`
|
||||
Description string `long:"description" description:"the description of the API"`
|
||||
Version string `long:"version" description:"the version of the API" default:"0.1.0"`
|
||||
Terms string `long:"terms" description:"the terms of services"`
|
||||
Consumes []string `long:"consumes" description:"add a content type to the global consumes definitions, can repeat" default:"application/json"`
|
||||
Produces []string `long:"produces" description:"add a content type to the global produces definitions, can repeat" default:"application/json"`
|
||||
Schemes []string `long:"scheme" description:"add a scheme to the global schemes definition, can repeat" default:"http"`
|
||||
Contact struct {
|
||||
Name string `long:"contact.name" description:"name of the primary contact for the API"`
|
||||
URL string `long:"contact.url" description:"url of the primary contact for the API"`
|
||||
Email string `long:"contact.email" description:"email of the primary contact for the API"`
|
||||
}
|
||||
License struct {
|
||||
Name string `long:"license.name" description:"name of the license for the API"`
|
||||
URL string `long:"license.url" description:"url of the license for the API"`
|
||||
}
|
||||
}
|
||||
|
||||
// Execute this command
|
||||
func (s *Spec) Execute(args []string) error {
|
||||
targetPath := "."
|
||||
if len(args) > 0 {
|
||||
targetPath = args[0]
|
||||
}
|
||||
realPath, err := filepath.Abs(targetPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var file *os.File
|
||||
switch s.Format {
|
||||
case "json":
|
||||
file, err = os.Create(filepath.Join(realPath, "swagger.json"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case "yaml", "yml":
|
||||
file, err = os.Create(filepath.Join(realPath, "swagger.yml"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("invalid format: %s", s.Format)
|
||||
}
|
||||
defer file.Close()
|
||||
log.Println("creating specification document in", filepath.Join(targetPath, file.Name()))
|
||||
|
||||
var doc spec.Swagger
|
||||
info := new(spec.Info)
|
||||
doc.Info = info
|
||||
|
||||
doc.Swagger = "2.0"
|
||||
doc.Paths = new(spec.Paths)
|
||||
doc.Definitions = make(spec.Definitions)
|
||||
|
||||
info.Title = s.Title
|
||||
if info.Title == "" {
|
||||
info.Title = swag.ToHumanNameTitle(filepath.Base(realPath))
|
||||
}
|
||||
info.Description = s.Description
|
||||
info.Version = s.Version
|
||||
info.TermsOfService = s.Terms
|
||||
if s.Contact.Name != "" || s.Contact.Email != "" || s.Contact.URL != "" {
|
||||
var contact spec.ContactInfo
|
||||
contact.Name = s.Contact.Name
|
||||
contact.Email = s.Contact.Email
|
||||
contact.URL = s.Contact.URL
|
||||
info.Contact = &contact
|
||||
}
|
||||
if s.License.Name != "" || s.License.URL != "" {
|
||||
var license spec.License
|
||||
license.Name = s.License.Name
|
||||
license.URL = s.License.URL
|
||||
info.License = &license
|
||||
}
|
||||
|
||||
doc.Consumes = append(doc.Consumes, s.Consumes...)
|
||||
doc.Produces = append(doc.Produces, s.Produces...)
|
||||
doc.Schemes = append(doc.Schemes, s.Schemes...)
|
||||
|
||||
if s.Format == "json" {
|
||||
enc := json.NewEncoder(file)
|
||||
return enc.Encode(doc)
|
||||
}
|
||||
|
||||
b, err := yaml.Marshal(swag.ToDynamicJSON(doc))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := file.Write(b); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
117
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/mixin.go
generated
vendored
Normal file
117
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/mixin.go
generated
vendored
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/go-openapi/analysis"
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-openapi/spec"
|
||||
flags "github.com/jessevdk/go-flags"
|
||||
|
||||
"github.com/go-swagger/go-swagger/generator"
|
||||
)
|
||||
|
||||
const (
|
||||
// Output messages
|
||||
nothingToDo = "nothing to do. Need some swagger files to merge.\nUSAGE: swagger mixin [-c <expected#Collisions>] <primary-swagger-file> <mixin-swagger-file...>"
|
||||
ignoreConflictsAndCollisionsSpecified = "both the flags ignore conflicts and collisions were specified. These have conflicting meaning so please only specify one"
|
||||
)
|
||||
|
||||
// MixinSpec holds command line flag definitions specific to the mixin
|
||||
// command. The flags are defined using struct field tags with the
|
||||
// "github.com/jessevdk/go-flags" format.
|
||||
type MixinSpec struct {
|
||||
ExpectedCollisionCount uint `short:"c" description:"expected # of rejected mixin paths, defs, etc due to existing key. Non-zero exit if does not match actual."`
|
||||
Compact bool `long:"compact" description:"applies to JSON formatted specs. When present, doesn't prettify the json"`
|
||||
Output flags.Filename `long:"output" short:"o" description:"the file to write to"`
|
||||
KeepSpecOrder bool `long:"keep-spec-order" description:"Keep schema properties order identical to spec file"`
|
||||
Format string `long:"format" description:"the format for the spec document" default:"json" choice:"yaml" choice:"json"`
|
||||
IgnoreConflicts bool `long:"ignore-conflicts" description:"Ignore conflict"`
|
||||
}
|
||||
|
||||
// Execute runs the mixin command which merges Swagger 2.0 specs into
|
||||
// one spec
|
||||
//
|
||||
// Use cases include adding independently versioned metadata APIs to
|
||||
// application APIs for microservices.
|
||||
//
|
||||
// Typically, multiple APIs to the same service instance is not a
|
||||
// problem for client generation as you can create more than one
|
||||
// client to the service from the same calling process (one for each
|
||||
// API). However, merging clients can improve clarity of client code
|
||||
// by having a single client to given service vs several.
|
||||
//
|
||||
// Server skeleton generation, ie generating the model & marshaling
|
||||
// code, http server instance etc. from Swagger, becomes easier with a
|
||||
// merged spec for some tools & target-languages. Server code
|
||||
// generation tools that natively support hosting multiple specs in
|
||||
// one server process will not need this tool.
|
||||
func (c *MixinSpec) Execute(args []string) error {
|
||||
|
||||
if len(args) < 2 {
|
||||
return errors.New(nothingToDo)
|
||||
}
|
||||
if c.IgnoreConflicts && c.ExpectedCollisionCount != 0 {
|
||||
return errors.New(ignoreConflictsAndCollisionsSpecified)
|
||||
}
|
||||
|
||||
log.Printf("args[0] = %v\n", args[0])
|
||||
log.Printf("args[1:] = %v\n", args[1:])
|
||||
collisions, err := c.MixinFiles(args[0], args[1:], os.Stdout)
|
||||
|
||||
for _, warn := range collisions {
|
||||
log.Println(warn)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.IgnoreConflicts {
|
||||
return nil
|
||||
}
|
||||
if len(collisions) != int(c.ExpectedCollisionCount) {
|
||||
if len(collisions) != 0 {
|
||||
// use bash $? to get actual # collisions
|
||||
// (but has to be non-zero)
|
||||
os.Exit(len(collisions))
|
||||
}
|
||||
os.Exit(254)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MixinFiles is a convenience function for Mixin that reads the given
|
||||
// swagger files, adds the mixins to primary, calls
|
||||
// FixEmptyResponseDescriptions on the primary, and writes the primary
|
||||
// with mixins to the given writer in JSON. Returns the warning
|
||||
// messages for collisions that occurred during mixin process and any
|
||||
// error.
|
||||
func (c *MixinSpec) MixinFiles(primaryFile string, mixinFiles []string, w io.Writer) ([]string, error) {
|
||||
|
||||
primaryDoc, err := loads.Spec(primaryFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
primary := primaryDoc.Spec()
|
||||
|
||||
var mixins []*spec.Swagger
|
||||
for _, mixinFile := range mixinFiles {
|
||||
if c.KeepSpecOrder {
|
||||
mixinFile = generator.WithAutoXOrder(mixinFile)
|
||||
}
|
||||
mixin, lerr := loads.Spec(mixinFile)
|
||||
if lerr != nil {
|
||||
return nil, lerr
|
||||
}
|
||||
mixins = append(mixins, mixin.Spec())
|
||||
}
|
||||
|
||||
collisions := analysis.Mixin(primary, mixins...)
|
||||
analysis.FixEmptyResponseDescriptions(primary)
|
||||
|
||||
return collisions, writeToFile(primary, !c.Compact, c.Format, string(c.Output))
|
||||
}
|
||||
117
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/serve.go
generated
vendored
Normal file
117
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/serve.go
generated
vendored
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"path"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/gorilla/handlers"
|
||||
"github.com/toqueteos/webbrowser"
|
||||
)
|
||||
|
||||
// ServeCmd to serve a swagger spec with docs ui
|
||||
type ServeCmd struct {
|
||||
BasePath string `long:"base-path" description:"the base path to serve the spec and UI at"`
|
||||
Flavor string `short:"F" long:"flavor" description:"the flavor of docs, can be swagger or redoc" default:"redoc" choice:"redoc" choice:"swagger"`
|
||||
DocURL string `long:"doc-url" description:"override the url which takes a url query param to render the doc ui"`
|
||||
NoOpen bool `long:"no-open" description:"when present won't open the the browser to show the url"`
|
||||
NoUI bool `long:"no-ui" description:"when present, only the swagger spec will be served"`
|
||||
Flatten bool `long:"flatten" description:"when present, flatten the swagger spec before serving it"`
|
||||
Port int `long:"port" short:"p" description:"the port to serve this site" env:"PORT"`
|
||||
Host string `long:"host" description:"the interface to serve this site, defaults to 0.0.0.0" default:"0.0.0.0" env:"HOST"`
|
||||
Path string `long:"path" description:"the uri path at which the docs will be served" default:"docs"`
|
||||
}
|
||||
|
||||
// Execute the serve command
|
||||
func (s *ServeCmd) Execute(args []string) error {
|
||||
if len(args) == 0 {
|
||||
return errors.New("specify the spec to serve as argument to the serve command")
|
||||
}
|
||||
|
||||
specDoc, err := loads.Spec(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if s.Flatten {
|
||||
specDoc, err = specDoc.Expanded(&spec.ExpandOptions{
|
||||
SkipSchemas: false,
|
||||
ContinueOnError: true,
|
||||
AbsoluteCircularRef: true,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
b, err := json.MarshalIndent(specDoc.Spec(), "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
basePath := s.BasePath
|
||||
if basePath == "" {
|
||||
basePath = "/"
|
||||
}
|
||||
|
||||
listener, err := net.Listen("tcp4", net.JoinHostPort(s.Host, strconv.Itoa(s.Port)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sh, sp, err := swag.SplitHostPort(listener.Addr().String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if sh == "0.0.0.0" {
|
||||
sh = "localhost"
|
||||
}
|
||||
|
||||
visit := s.DocURL
|
||||
handler := http.NotFoundHandler()
|
||||
if !s.NoUI {
|
||||
if s.Flavor == "redoc" {
|
||||
handler = middleware.Redoc(middleware.RedocOpts{
|
||||
BasePath: basePath,
|
||||
SpecURL: path.Join(basePath, "swagger.json"),
|
||||
Path: s.Path,
|
||||
}, handler)
|
||||
visit = fmt.Sprintf("http://%s:%d%s", sh, sp, path.Join(basePath, "docs"))
|
||||
} else if visit != "" || s.Flavor == "swagger" {
|
||||
handler = middleware.SwaggerUI(middleware.SwaggerUIOpts{
|
||||
BasePath: basePath,
|
||||
SpecURL: path.Join(basePath, "swagger.json"),
|
||||
Path: s.Path,
|
||||
}, handler)
|
||||
visit = fmt.Sprintf("http://%s:%d%s", sh, sp, path.Join(basePath, s.Path))
|
||||
}
|
||||
}
|
||||
|
||||
handler = handlers.CORS()(middleware.Spec(basePath, b, handler))
|
||||
errFuture := make(chan error)
|
||||
go func() {
|
||||
docServer := new(http.Server)
|
||||
docServer.SetKeepAlivesEnabled(true)
|
||||
docServer.Handler = handler
|
||||
|
||||
errFuture <- docServer.Serve(listener)
|
||||
}()
|
||||
|
||||
if !s.NoOpen && !s.NoUI {
|
||||
err := webbrowser.Open(visit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
log.Println("serving docs at", visit)
|
||||
return <-errFuture
|
||||
}
|
||||
83
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/validate.go
generated
vendored
Normal file
83
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/validate.go
generated
vendored
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// 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 commands
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/validate"
|
||||
)
|
||||
|
||||
const (
|
||||
// Output messages
|
||||
missingArgMsg = "the validate command requires the swagger document url to be specified"
|
||||
validSpecMsg = "\nThe swagger spec at %q is valid against swagger specification %s\n"
|
||||
invalidSpecMsg = "\nThe swagger spec at %q is invalid against swagger specification %s.\nSee errors below:\n"
|
||||
warningSpecMsg = "\nThe swagger spec at %q showed up some valid but possibly unwanted constructs."
|
||||
)
|
||||
|
||||
// ValidateSpec is a command that validates a swagger document
|
||||
// against the swagger specification
|
||||
type ValidateSpec struct {
|
||||
// SchemaURL string `long:"schema" description:"The schema url to use" default:"http://swagger.io/v2/schema.json"`
|
||||
SkipWarnings bool `long:"skip-warnings" description:"when present will not show up warnings upon validation"`
|
||||
StopOnError bool `long:"stop-on-error" description:"when present will not continue validation after critical errors are found"`
|
||||
}
|
||||
|
||||
// Execute validates the spec
|
||||
func (c *ValidateSpec) Execute(args []string) error {
|
||||
if len(args) == 0 {
|
||||
return errors.New(missingArgMsg)
|
||||
}
|
||||
|
||||
swaggerDoc := args[0]
|
||||
|
||||
specDoc, err := loads.Spec(swaggerDoc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Attempts to report about all errors
|
||||
validate.SetContinueOnErrors(!c.StopOnError)
|
||||
|
||||
v := validate.NewSpecValidator(specDoc.Schema(), strfmt.Default)
|
||||
result, _ := v.Validate(specDoc) // returns fully detailed result with errors and warnings
|
||||
|
||||
if result.IsValid() {
|
||||
log.Printf(validSpecMsg, swaggerDoc, specDoc.Version())
|
||||
}
|
||||
if result.HasWarnings() {
|
||||
log.Printf(warningSpecMsg, swaggerDoc)
|
||||
if !c.SkipWarnings {
|
||||
log.Printf("See warnings below:\n")
|
||||
for _, desc := range result.Warnings {
|
||||
log.Printf("- WARNING: %s\n", desc.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
if result.HasErrors() {
|
||||
str := fmt.Sprintf(invalidSpecMsg, swaggerDoc, specDoc.Version())
|
||||
for _, desc := range result.Errors {
|
||||
str += fmt.Sprintf("- %s\n", desc.Error())
|
||||
}
|
||||
return errors.New(str)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
37
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/version.go
generated
vendored
Normal file
37
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/version.go
generated
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime/debug"
|
||||
)
|
||||
|
||||
var (
|
||||
// Version for the swagger command
|
||||
Version string
|
||||
// Commit for the swagger command
|
||||
Commit string
|
||||
)
|
||||
|
||||
// PrintVersion the command
|
||||
type PrintVersion struct {
|
||||
}
|
||||
|
||||
// Execute this command
|
||||
func (p *PrintVersion) Execute(args []string) error {
|
||||
if Version == "" {
|
||||
if info, available := debug.ReadBuildInfo(); available && info.Main.Version != "(devel)" {
|
||||
// built from source, with module (e.g. go get)
|
||||
fmt.Println("version:", info.Main.Version)
|
||||
fmt.Println("commit:", fmt.Sprintf("(unknown, mod sum: %q)", info.Main.Sum))
|
||||
return nil
|
||||
}
|
||||
// built from source, local repo
|
||||
fmt.Println("dev")
|
||||
return nil
|
||||
}
|
||||
// released version
|
||||
fmt.Println("version:", Version)
|
||||
fmt.Println("commit:", Commit)
|
||||
|
||||
return nil
|
||||
}
|
||||
143
vendor/github.com/go-swagger/go-swagger/cmd/swagger/swagger.go
generated
vendored
Normal file
143
vendor/github.com/go-swagger/go-swagger/cmd/swagger/swagger.go
generated
vendored
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// 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 main
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/go-swagger/go-swagger/cmd/swagger/commands"
|
||||
flags "github.com/jessevdk/go-flags"
|
||||
)
|
||||
|
||||
var opts struct {
|
||||
// General options applicable to all commands
|
||||
Quiet func() `long:"quiet" short:"q" description:"silence logs"`
|
||||
LogFile func(string) `long:"log-output" description:"redirect logs to file" value-name:"LOG-FILE"`
|
||||
// Version bool `long:"version" short:"v" description:"print the version of the command"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
// TODO: reactivate 'defer catch all' once product is stable
|
||||
// Recovering from internal panics
|
||||
// Stack may be printed in Debug mode
|
||||
// Need import "runtime/debug".
|
||||
// defer func() {
|
||||
// r := recover()
|
||||
// if r != nil {
|
||||
// log.Printf("Fatal error:", r)
|
||||
// if Debug {
|
||||
// debug.PrintStack()
|
||||
// }
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// }()
|
||||
|
||||
parser := flags.NewParser(&opts, flags.Default)
|
||||
parser.ShortDescription = "helps you keep your API well described"
|
||||
parser.LongDescription = `
|
||||
Swagger tries to support you as best as possible when building APIs.
|
||||
|
||||
It aims to represent the contract of your API with a language agnostic description of your application in json or yaml.
|
||||
`
|
||||
_, err := parser.AddCommand("validate", "validate the swagger document", "validate the provided swagger document against a swagger spec", &commands.ValidateSpec{})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = parser.AddCommand("init", "initialize a spec document", "initialize a swagger spec document", &commands.InitCmd{})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = parser.AddCommand("version", "print the version", "print the version of the swagger command", &commands.PrintVersion{})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = parser.AddCommand("serve", "serve spec and docs", "serve a spec and swagger or redoc documentation ui", &commands.ServeCmd{})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = parser.AddCommand("expand", "expand $ref fields in a swagger spec", "expands the $refs in a swagger document to inline schemas", &commands.ExpandSpec{})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = parser.AddCommand("flatten", "flattens a swagger document", "expand the remote references in a spec and move inline schemas to definitions, after flattening there are no complex inlined anymore", &commands.FlattenSpec{})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = parser.AddCommand("mixin", "merge swagger documents", "merge additional specs into first/primary spec by copying their paths and definitions", &commands.MixinSpec{})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = parser.AddCommand("diff", "diff swagger documents", "diff specs showing which changes will break existing clients", &commands.DiffCommand{})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
genpar, err := parser.AddCommand("generate", "generate go code", "generate go code for the swagger spec file", &commands.Generate{})
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
for _, cmd := range genpar.Commands() {
|
||||
switch cmd.Name {
|
||||
case "spec":
|
||||
cmd.ShortDescription = "generate a swagger spec document from a go application"
|
||||
cmd.LongDescription = cmd.ShortDescription
|
||||
case "client":
|
||||
cmd.ShortDescription = "generate all the files for a client library"
|
||||
cmd.LongDescription = cmd.ShortDescription
|
||||
case "server":
|
||||
cmd.ShortDescription = "generate all the files for a server application"
|
||||
cmd.LongDescription = cmd.ShortDescription
|
||||
case "model":
|
||||
cmd.ShortDescription = "generate one or more models from the swagger spec"
|
||||
cmd.LongDescription = cmd.ShortDescription
|
||||
case "support":
|
||||
cmd.ShortDescription = "generate supporting files like the main function and the api builder"
|
||||
cmd.LongDescription = cmd.ShortDescription
|
||||
case "operation":
|
||||
cmd.ShortDescription = "generate one or more server operations from the swagger spec"
|
||||
cmd.LongDescription = cmd.ShortDescription
|
||||
case "markdown":
|
||||
cmd.ShortDescription = "generate a markdown representation from the swagger spec"
|
||||
cmd.LongDescription = cmd.ShortDescription
|
||||
case "cli":
|
||||
cmd.ShortDescription = "generate a command line client tool from the swagger spec"
|
||||
cmd.LongDescription = cmd.ShortDescription
|
||||
}
|
||||
}
|
||||
|
||||
opts.Quiet = func() {
|
||||
log.SetOutput(io.Discard)
|
||||
}
|
||||
opts.LogFile = func(logfile string) {
|
||||
f, err := os.OpenFile(logfile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
|
||||
if err != nil {
|
||||
log.Fatalf("cannot write to file %s: %v", logfile, err)
|
||||
}
|
||||
log.SetOutput(f)
|
||||
}
|
||||
|
||||
if _, err := parser.Parse(); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
3
vendor/github.com/go-swagger/go-swagger/codescan/README.md
generated
vendored
Normal file
3
vendor/github.com/go-swagger/go-swagger/codescan/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# codescan
|
||||
|
||||
Version of the go source parser with support for go modules, from go1.11 onwards.
|
||||
674
vendor/github.com/go-swagger/go-swagger/codescan/application.go
generated
vendored
Normal file
674
vendor/github.com/go-swagger/go-swagger/codescan/application.go
generated
vendored
Normal file
|
|
@ -0,0 +1,674 @@
|
|||
package codescan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
|
||||
"golang.org/x/tools/go/packages"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
const pkgLoadMode = packages.NeedName | packages.NeedFiles | packages.NeedImports | packages.NeedDeps | packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo
|
||||
|
||||
func safeConvert(str string) bool {
|
||||
b, err := swag.ConvertBool(str)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// Debug is true when process is run with DEBUG=1 env var
|
||||
var Debug = safeConvert(os.Getenv("DEBUG"))
|
||||
|
||||
type node uint32
|
||||
|
||||
const (
|
||||
metaNode node = 1 << iota
|
||||
routeNode
|
||||
operationNode
|
||||
modelNode
|
||||
parametersNode
|
||||
responseNode
|
||||
)
|
||||
|
||||
// Options for the scanner
|
||||
type Options struct {
|
||||
Packages []string
|
||||
InputSpec *spec.Swagger
|
||||
ScanModels bool
|
||||
WorkDir string
|
||||
BuildTags string
|
||||
ExcludeDeps bool
|
||||
Include []string
|
||||
Exclude []string
|
||||
IncludeTags []string
|
||||
ExcludeTags []string
|
||||
}
|
||||
|
||||
type scanCtx struct {
|
||||
pkgs []*packages.Package
|
||||
app *typeIndex
|
||||
}
|
||||
|
||||
func sliceToSet(names []string) map[string]bool {
|
||||
result := make(map[string]bool)
|
||||
for _, v := range names {
|
||||
result[v] = true
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Run the scanner to produce a spec with the options provided
|
||||
func Run(opts *Options) (*spec.Swagger, error) {
|
||||
sc, err := newScanCtx(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sb := newSpecBuilder(opts.InputSpec, sc, opts.ScanModels)
|
||||
return sb.Build()
|
||||
}
|
||||
|
||||
func newScanCtx(opts *Options) (*scanCtx, error) {
|
||||
cfg := &packages.Config{
|
||||
Dir: opts.WorkDir,
|
||||
Mode: pkgLoadMode,
|
||||
Tests: false,
|
||||
}
|
||||
if opts.BuildTags != "" {
|
||||
cfg.BuildFlags = []string{"-tags", opts.BuildTags}
|
||||
}
|
||||
|
||||
pkgs, err := packages.Load(cfg, opts.Packages...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
app, err := newTypeIndex(pkgs, opts.ExcludeDeps,
|
||||
sliceToSet(opts.IncludeTags), sliceToSet(opts.ExcludeTags),
|
||||
opts.Include, opts.Exclude)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &scanCtx{
|
||||
pkgs: pkgs,
|
||||
app: app,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type entityDecl struct {
|
||||
Comments *ast.CommentGroup
|
||||
Type *types.Named
|
||||
Ident *ast.Ident
|
||||
Spec *ast.TypeSpec
|
||||
File *ast.File
|
||||
Pkg *packages.Package
|
||||
hasModelAnnotation bool
|
||||
hasResponseAnnotation bool
|
||||
hasParameterAnnotation bool
|
||||
}
|
||||
|
||||
func (d *entityDecl) Names() (name, goName string) {
|
||||
goName = d.Ident.Name
|
||||
name = goName
|
||||
if d.Comments == nil {
|
||||
return
|
||||
}
|
||||
|
||||
DECLS:
|
||||
for _, cmt := range d.Comments.List {
|
||||
for _, ln := range strings.Split(cmt.Text, "\n") {
|
||||
matches := rxModelOverride.FindStringSubmatch(ln)
|
||||
if len(matches) > 0 {
|
||||
d.hasModelAnnotation = true
|
||||
}
|
||||
if len(matches) > 1 && len(matches[1]) > 0 {
|
||||
name = matches[1]
|
||||
break DECLS
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *entityDecl) ResponseNames() (name, goName string) {
|
||||
goName = d.Ident.Name
|
||||
name = goName
|
||||
if d.Comments == nil {
|
||||
return
|
||||
}
|
||||
|
||||
DECLS:
|
||||
for _, cmt := range d.Comments.List {
|
||||
for _, ln := range strings.Split(cmt.Text, "\n") {
|
||||
matches := rxResponseOverride.FindStringSubmatch(ln)
|
||||
if len(matches) > 0 {
|
||||
d.hasResponseAnnotation = true
|
||||
}
|
||||
if len(matches) > 1 && len(matches[1]) > 0 {
|
||||
name = matches[1]
|
||||
break DECLS
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *entityDecl) OperationIDS() (result []string) {
|
||||
if d == nil || d.Comments == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, cmt := range d.Comments.List {
|
||||
for _, ln := range strings.Split(cmt.Text, "\n") {
|
||||
matches := rxParametersOverride.FindStringSubmatch(ln)
|
||||
if len(matches) > 0 {
|
||||
d.hasParameterAnnotation = true
|
||||
}
|
||||
if len(matches) > 1 && len(matches[1]) > 0 {
|
||||
for _, pt := range strings.Split(matches[1], " ") {
|
||||
tr := strings.TrimSpace(pt)
|
||||
if len(tr) > 0 {
|
||||
result = append(result, tr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *entityDecl) HasModelAnnotation() bool {
|
||||
if d.hasModelAnnotation {
|
||||
return true
|
||||
}
|
||||
if d.Comments == nil {
|
||||
return false
|
||||
}
|
||||
for _, cmt := range d.Comments.List {
|
||||
for _, ln := range strings.Split(cmt.Text, "\n") {
|
||||
matches := rxModelOverride.FindStringSubmatch(ln)
|
||||
if len(matches) > 0 {
|
||||
d.hasModelAnnotation = true
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (d *entityDecl) HasResponseAnnotation() bool {
|
||||
if d.hasResponseAnnotation {
|
||||
return true
|
||||
}
|
||||
if d.Comments == nil {
|
||||
return false
|
||||
}
|
||||
for _, cmt := range d.Comments.List {
|
||||
for _, ln := range strings.Split(cmt.Text, "\n") {
|
||||
matches := rxResponseOverride.FindStringSubmatch(ln)
|
||||
if len(matches) > 0 {
|
||||
d.hasResponseAnnotation = true
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (d *entityDecl) HasParameterAnnotation() bool {
|
||||
if d.hasParameterAnnotation {
|
||||
return true
|
||||
}
|
||||
if d.Comments == nil {
|
||||
return false
|
||||
}
|
||||
for _, cmt := range d.Comments.List {
|
||||
for _, ln := range strings.Split(cmt.Text, "\n") {
|
||||
matches := rxParametersOverride.FindStringSubmatch(ln)
|
||||
if len(matches) > 0 {
|
||||
d.hasParameterAnnotation = true
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *scanCtx) FindDecl(pkgPath, name string) (*entityDecl, bool) {
|
||||
if pkg, ok := s.app.AllPackages[pkgPath]; ok {
|
||||
for _, file := range pkg.Syntax {
|
||||
for _, d := range file.Decls {
|
||||
gd, ok := d.(*ast.GenDecl)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, sp := range gd.Specs {
|
||||
if ts, ok := sp.(*ast.TypeSpec); ok && ts.Name.Name == name {
|
||||
def, ok := pkg.TypesInfo.Defs[ts.Name]
|
||||
if !ok {
|
||||
debugLog("couldn't find type info for %s", ts.Name)
|
||||
continue
|
||||
}
|
||||
nt, isNamed := def.Type().(*types.Named)
|
||||
if !isNamed {
|
||||
debugLog("%s is not a named type but a %T", ts.Name, def.Type())
|
||||
continue
|
||||
}
|
||||
|
||||
comments := ts.Doc // type ( /* doc */ Foo struct{} )
|
||||
if comments == nil {
|
||||
comments = gd.Doc // /* doc */ type ( Foo struct{} )
|
||||
}
|
||||
|
||||
decl := &entityDecl{
|
||||
Comments: comments,
|
||||
Type: nt,
|
||||
Ident: ts.Name,
|
||||
Spec: ts,
|
||||
File: file,
|
||||
Pkg: pkg,
|
||||
}
|
||||
return decl, true
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (s *scanCtx) FindModel(pkgPath, name string) (*entityDecl, bool) {
|
||||
for _, cand := range s.app.Models {
|
||||
ct := cand.Type.Obj()
|
||||
if ct.Name() == name && ct.Pkg().Path() == pkgPath {
|
||||
return cand, true
|
||||
}
|
||||
}
|
||||
if decl, found := s.FindDecl(pkgPath, name); found {
|
||||
s.app.ExtraModels[decl.Ident] = decl
|
||||
return decl, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (s *scanCtx) PkgForPath(pkgPath string) (*packages.Package, bool) {
|
||||
v, ok := s.app.AllPackages[pkgPath]
|
||||
return v, ok
|
||||
}
|
||||
|
||||
func (s *scanCtx) DeclForType(t types.Type) (*entityDecl, bool) {
|
||||
switch tpe := t.(type) {
|
||||
case *types.Pointer:
|
||||
return s.DeclForType(tpe.Elem())
|
||||
case *types.Named:
|
||||
return s.FindDecl(tpe.Obj().Pkg().Path(), tpe.Obj().Name())
|
||||
|
||||
default:
|
||||
log.Printf("unknown type to find the package for [%T]: %s", t, t.String())
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
|
||||
func (s *scanCtx) PkgForType(t types.Type) (*packages.Package, bool) {
|
||||
switch tpe := t.(type) {
|
||||
// case *types.Basic:
|
||||
// case *types.Struct:
|
||||
// case *types.Pointer:
|
||||
// case *types.Interface:
|
||||
// case *types.Array:
|
||||
// case *types.Slice:
|
||||
// case *types.Map:
|
||||
case *types.Named:
|
||||
v, ok := s.app.AllPackages[tpe.Obj().Pkg().Path()]
|
||||
return v, ok
|
||||
default:
|
||||
log.Printf("unknown type to find the package for [%T]: %s", t, t.String())
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
|
||||
func (s *scanCtx) FindComments(pkg *packages.Package, name string) (*ast.CommentGroup, bool) {
|
||||
for _, f := range pkg.Syntax {
|
||||
for _, d := range f.Decls {
|
||||
gd, ok := d.(*ast.GenDecl)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, s := range gd.Specs {
|
||||
if ts, ok := s.(*ast.TypeSpec); ok {
|
||||
if ts.Name.Name == name {
|
||||
return gd.Doc, true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (s *scanCtx) FindEnumValues(pkg *packages.Package, enumName string) (list []interface{}, descList []string, _ bool) {
|
||||
for _, f := range pkg.Syntax {
|
||||
for _, d := range f.Decls {
|
||||
gd, ok := d.(*ast.GenDecl)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if gd.Tok != token.CONST {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, s := range gd.Specs {
|
||||
if vs, ok := s.(*ast.ValueSpec); ok {
|
||||
if vsIdent, ok := vs.Type.(*ast.Ident); ok {
|
||||
if vsIdent.Name == enumName {
|
||||
if len(vs.Values) > 0 {
|
||||
if bl, ok := vs.Values[0].(*ast.BasicLit); ok {
|
||||
blValue := getEnumBasicLitValue(bl)
|
||||
list = append(list, blValue)
|
||||
|
||||
// build the enum description
|
||||
var (
|
||||
desc = &strings.Builder{}
|
||||
namesLen = len(vs.Names)
|
||||
)
|
||||
desc.WriteString(fmt.Sprintf("%v ", blValue))
|
||||
for i, name := range vs.Names {
|
||||
desc.WriteString(name.Name)
|
||||
if i < namesLen-1 {
|
||||
desc.WriteString(" ")
|
||||
}
|
||||
}
|
||||
if vs.Doc != nil {
|
||||
docListLen := len(vs.Doc.List)
|
||||
if docListLen > 0 {
|
||||
desc.WriteString(" ")
|
||||
}
|
||||
for i, doc := range vs.Doc.List {
|
||||
if doc.Text != "" {
|
||||
var text = strings.TrimPrefix(doc.Text, "//")
|
||||
desc.WriteString(text)
|
||||
if i < docListLen-1 {
|
||||
desc.WriteString(" ")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
descList = append(descList, desc.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return list, descList, true
|
||||
}
|
||||
|
||||
func newTypeIndex(pkgs []*packages.Package,
|
||||
excludeDeps bool, includeTags, excludeTags map[string]bool,
|
||||
includePkgs, excludePkgs []string) (*typeIndex, error) {
|
||||
|
||||
ac := &typeIndex{
|
||||
AllPackages: make(map[string]*packages.Package),
|
||||
Models: make(map[*ast.Ident]*entityDecl),
|
||||
ExtraModels: make(map[*ast.Ident]*entityDecl),
|
||||
excludeDeps: excludeDeps,
|
||||
includeTags: includeTags,
|
||||
excludeTags: excludeTags,
|
||||
includePkgs: includePkgs,
|
||||
excludePkgs: excludePkgs,
|
||||
}
|
||||
if err := ac.build(pkgs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ac, nil
|
||||
}
|
||||
|
||||
type typeIndex struct {
|
||||
AllPackages map[string]*packages.Package
|
||||
Models map[*ast.Ident]*entityDecl
|
||||
ExtraModels map[*ast.Ident]*entityDecl
|
||||
Meta []metaSection
|
||||
Routes []parsedPathContent
|
||||
Operations []parsedPathContent
|
||||
Parameters []*entityDecl
|
||||
Responses []*entityDecl
|
||||
excludeDeps bool
|
||||
includeTags map[string]bool
|
||||
excludeTags map[string]bool
|
||||
includePkgs []string
|
||||
excludePkgs []string
|
||||
}
|
||||
|
||||
func (a *typeIndex) build(pkgs []*packages.Package) error {
|
||||
for _, pkg := range pkgs {
|
||||
if _, known := a.AllPackages[pkg.PkgPath]; known {
|
||||
continue
|
||||
}
|
||||
a.AllPackages[pkg.PkgPath] = pkg
|
||||
if err := a.processPackage(pkg); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := a.walkImports(pkg); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *typeIndex) processPackage(pkg *packages.Package) error {
|
||||
if !shouldAcceptPkg(pkg.PkgPath, a.includePkgs, a.excludePkgs) {
|
||||
debugLog("package %s is ignored due to rules", pkg.Name)
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, file := range pkg.Syntax {
|
||||
n, err := a.detectNodes(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if n&metaNode != 0 {
|
||||
a.Meta = append(a.Meta, metaSection{Comments: file.Doc})
|
||||
}
|
||||
|
||||
if n&operationNode != 0 {
|
||||
for _, cmts := range file.Comments {
|
||||
pp := parsePathAnnotation(rxOperation, cmts.List)
|
||||
if pp.Method == "" {
|
||||
continue // not a valid operation
|
||||
}
|
||||
if !shouldAcceptTag(pp.Tags, a.includeTags, a.excludeTags) {
|
||||
debugLog("operation %s %s is ignored due to tag rules", pp.Method, pp.Path)
|
||||
continue
|
||||
}
|
||||
a.Operations = append(a.Operations, pp)
|
||||
}
|
||||
}
|
||||
|
||||
if n&routeNode != 0 {
|
||||
for _, cmts := range file.Comments {
|
||||
pp := parsePathAnnotation(rxRoute, cmts.List)
|
||||
if pp.Method == "" {
|
||||
continue // not a valid operation
|
||||
}
|
||||
if !shouldAcceptTag(pp.Tags, a.includeTags, a.excludeTags) {
|
||||
debugLog("operation %s %s is ignored due to tag rules", pp.Method, pp.Path)
|
||||
continue
|
||||
}
|
||||
a.Routes = append(a.Routes, pp)
|
||||
}
|
||||
}
|
||||
|
||||
for _, dt := range file.Decls {
|
||||
switch fd := dt.(type) {
|
||||
case *ast.BadDecl:
|
||||
continue
|
||||
case *ast.FuncDecl:
|
||||
if fd.Body == nil {
|
||||
continue
|
||||
}
|
||||
for _, stmt := range fd.Body.List {
|
||||
if dstm, ok := stmt.(*ast.DeclStmt); ok {
|
||||
if gd, isGD := dstm.Decl.(*ast.GenDecl); isGD {
|
||||
a.processDecl(pkg, file, n, gd)
|
||||
}
|
||||
}
|
||||
}
|
||||
case *ast.GenDecl:
|
||||
a.processDecl(pkg, file, n, fd)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *typeIndex) processDecl(pkg *packages.Package, file *ast.File, n node, gd *ast.GenDecl) {
|
||||
for _, sp := range gd.Specs {
|
||||
switch ts := sp.(type) {
|
||||
case *ast.ValueSpec:
|
||||
debugLog("saw value spec: %v", ts.Names)
|
||||
return
|
||||
case *ast.ImportSpec:
|
||||
debugLog("saw import spec: %v", ts.Name)
|
||||
return
|
||||
case *ast.TypeSpec:
|
||||
def, ok := pkg.TypesInfo.Defs[ts.Name]
|
||||
if !ok {
|
||||
debugLog("couldn't find type info for %s", ts.Name)
|
||||
continue
|
||||
}
|
||||
nt, isNamed := def.Type().(*types.Named)
|
||||
if !isNamed {
|
||||
debugLog("%s is not a named type but a %T", ts.Name, def.Type())
|
||||
continue
|
||||
}
|
||||
|
||||
comments := ts.Doc // type ( /* doc */ Foo struct{} )
|
||||
if comments == nil {
|
||||
comments = gd.Doc // /* doc */ type ( Foo struct{} )
|
||||
}
|
||||
|
||||
decl := &entityDecl{
|
||||
Comments: comments,
|
||||
Type: nt,
|
||||
Ident: ts.Name,
|
||||
Spec: ts,
|
||||
File: file,
|
||||
Pkg: pkg,
|
||||
}
|
||||
key := ts.Name
|
||||
if n&modelNode != 0 && decl.HasModelAnnotation() {
|
||||
a.Models[key] = decl
|
||||
}
|
||||
if n¶metersNode != 0 && decl.HasParameterAnnotation() {
|
||||
a.Parameters = append(a.Parameters, decl)
|
||||
}
|
||||
if n&responseNode != 0 && decl.HasResponseAnnotation() {
|
||||
a.Responses = append(a.Responses, decl)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *typeIndex) walkImports(pkg *packages.Package) error {
|
||||
if a.excludeDeps {
|
||||
return nil
|
||||
}
|
||||
for _, v := range pkg.Imports {
|
||||
if _, known := a.AllPackages[v.PkgPath]; known {
|
||||
continue
|
||||
}
|
||||
|
||||
a.AllPackages[v.PkgPath] = v
|
||||
if err := a.processPackage(v); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := a.walkImports(v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *typeIndex) detectNodes(file *ast.File) (node, error) {
|
||||
var n node
|
||||
for _, comments := range file.Comments {
|
||||
var seenStruct string
|
||||
for _, cline := range comments.List {
|
||||
if cline == nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
for _, cline := range comments.List {
|
||||
if cline == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
matches := rxSwaggerAnnotation.FindStringSubmatch(cline.Text)
|
||||
if len(matches) < 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
switch matches[1] {
|
||||
case "route":
|
||||
n |= routeNode
|
||||
case "operation":
|
||||
n |= operationNode
|
||||
case "model":
|
||||
n |= modelNode
|
||||
if seenStruct == "" || seenStruct == matches[1] {
|
||||
seenStruct = matches[1]
|
||||
} else {
|
||||
return 0, fmt.Errorf("classifier: already annotated as %s, can't also be %q - %s", seenStruct, matches[1], cline.Text)
|
||||
}
|
||||
case "meta":
|
||||
n |= metaNode
|
||||
case "parameters":
|
||||
n |= parametersNode
|
||||
if seenStruct == "" || seenStruct == matches[1] {
|
||||
seenStruct = matches[1]
|
||||
} else {
|
||||
return 0, fmt.Errorf("classifier: already annotated as %s, can't also be %q - %s", seenStruct, matches[1], cline.Text)
|
||||
}
|
||||
case "response":
|
||||
n |= responseNode
|
||||
if seenStruct == "" || seenStruct == matches[1] {
|
||||
seenStruct = matches[1]
|
||||
} else {
|
||||
return 0, fmt.Errorf("classifier: already annotated as %s, can't also be %q - %s", seenStruct, matches[1], cline.Text)
|
||||
}
|
||||
case "strfmt", "name", "discriminated", "file", "enum", "default", "alias", "type":
|
||||
// TODO: perhaps collect these and pass along to avoid lookups later on
|
||||
case "allOf":
|
||||
case "ignore":
|
||||
default:
|
||||
return 0, fmt.Errorf("classifier: unknown swagger annotation %q", matches[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func debugLog(format string, args ...interface{}) {
|
||||
if Debug {
|
||||
log.Printf(format, args...)
|
||||
}
|
||||
}
|
||||
6
vendor/github.com/go-swagger/go-swagger/codescan/doc.go
generated
vendored
Normal file
6
vendor/github.com/go-swagger/go-swagger/codescan/doc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
/*
|
||||
Package codescan provides a scanner for go files that produces a swagger spec document.
|
||||
|
||||
This package is intendnd for go1.11 onwards, and does support go modules.
|
||||
*/
|
||||
package codescan
|
||||
32
vendor/github.com/go-swagger/go-swagger/codescan/enum.go
generated
vendored
Normal file
32
vendor/github.com/go-swagger/go-swagger/codescan/enum.go
generated
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
package codescan
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
func getEnumBasicLitValue(basicLit *ast.BasicLit) interface{} {
|
||||
switch basicLit.Kind.String() {
|
||||
case "INT":
|
||||
if result, err := strconv.ParseInt(basicLit.Value, 10, 64); err == nil {
|
||||
return result
|
||||
}
|
||||
case "FLOAT":
|
||||
if result, err := strconv.ParseFloat(basicLit.Value, 64); err == nil {
|
||||
return result
|
||||
}
|
||||
default:
|
||||
return strings.Trim(basicLit.Value, "\"")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
const extEnumDesc = "x-go-enum-desc"
|
||||
|
||||
func getEnumDesc(extensions spec.Extensions) (desc string) {
|
||||
desc, _ = extensions.GetString(extEnumDesc)
|
||||
return
|
||||
}
|
||||
252
vendor/github.com/go-swagger/go-swagger/codescan/meta.go
generated
vendored
Normal file
252
vendor/github.com/go-swagger/go-swagger/codescan/meta.go
generated
vendored
Normal file
|
|
@ -0,0 +1,252 @@
|
|||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// 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 codescan
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"net/mail"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
type metaSection struct {
|
||||
Comments *ast.CommentGroup
|
||||
}
|
||||
|
||||
func metaTOSSetter(meta *spec.Info) func([]string) {
|
||||
return func(lines []string) {
|
||||
meta.TermsOfService = joinDropLast(lines)
|
||||
}
|
||||
}
|
||||
|
||||
func metaConsumesSetter(meta *spec.Swagger) func([]string) {
|
||||
return func(consumes []string) { meta.Consumes = consumes }
|
||||
}
|
||||
|
||||
func metaProducesSetter(meta *spec.Swagger) func([]string) {
|
||||
return func(produces []string) { meta.Produces = produces }
|
||||
}
|
||||
|
||||
func metaSchemeSetter(meta *spec.Swagger) func([]string) {
|
||||
return func(schemes []string) { meta.Schemes = schemes }
|
||||
}
|
||||
|
||||
func metaSecuritySetter(meta *spec.Swagger) func([]map[string][]string) {
|
||||
return func(secDefs []map[string][]string) { meta.Security = secDefs }
|
||||
}
|
||||
|
||||
func metaSecurityDefinitionsSetter(meta *spec.Swagger) func(json.RawMessage) error {
|
||||
return func(jsonValue json.RawMessage) error {
|
||||
var jsonData spec.SecurityDefinitions
|
||||
err := json.Unmarshal(jsonValue, &jsonData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
meta.SecurityDefinitions = jsonData
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func metaVendorExtensibleSetter(meta *spec.Swagger) func(json.RawMessage) error {
|
||||
return func(jsonValue json.RawMessage) error {
|
||||
var jsonData spec.Extensions
|
||||
err := json.Unmarshal(jsonValue, &jsonData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for k := range jsonData {
|
||||
if !rxAllowedExtensions.MatchString(k) {
|
||||
return fmt.Errorf("invalid schema extension name, should start from `x-`: %s", k)
|
||||
}
|
||||
}
|
||||
meta.Extensions = jsonData
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func infoVendorExtensibleSetter(meta *spec.Swagger) func(json.RawMessage) error {
|
||||
return func(jsonValue json.RawMessage) error {
|
||||
var jsonData spec.Extensions
|
||||
err := json.Unmarshal(jsonValue, &jsonData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for k := range jsonData {
|
||||
if !rxAllowedExtensions.MatchString(k) {
|
||||
return fmt.Errorf("invalid schema extension name, should start from `x-`: %s", k)
|
||||
}
|
||||
}
|
||||
meta.Info.Extensions = jsonData
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func newMetaParser(swspec *spec.Swagger) *sectionedParser {
|
||||
sp := new(sectionedParser)
|
||||
if swspec.Info == nil {
|
||||
swspec.Info = new(spec.Info)
|
||||
}
|
||||
info := swspec.Info
|
||||
sp.setTitle = func(lines []string) {
|
||||
tosave := joinDropLast(lines)
|
||||
if len(tosave) > 0 {
|
||||
tosave = rxStripTitleComments.ReplaceAllString(tosave, "")
|
||||
}
|
||||
info.Title = tosave
|
||||
}
|
||||
sp.setDescription = func(lines []string) { info.Description = joinDropLast(lines) }
|
||||
sp.taggers = []tagParser{
|
||||
newMultiLineTagParser("TOS", newMultilineDropEmptyParser(rxTOS, metaTOSSetter(info)), false),
|
||||
newMultiLineTagParser("Consumes", newMultilineDropEmptyParser(rxConsumes, metaConsumesSetter(swspec)), false),
|
||||
newMultiLineTagParser("Produces", newMultilineDropEmptyParser(rxProduces, metaProducesSetter(swspec)), false),
|
||||
newSingleLineTagParser("Schemes", newSetSchemes(metaSchemeSetter(swspec))),
|
||||
newMultiLineTagParser("Security", newSetSecurity(rxSecuritySchemes, metaSecuritySetter(swspec)), false),
|
||||
newMultiLineTagParser("SecurityDefinitions", newYamlParser(rxSecurity, metaSecurityDefinitionsSetter(swspec)), true),
|
||||
newSingleLineTagParser("Version", &setMetaSingle{swspec, rxVersion, setInfoVersion}),
|
||||
newSingleLineTagParser("Host", &setMetaSingle{swspec, rxHost, setSwaggerHost}),
|
||||
newSingleLineTagParser("BasePath", &setMetaSingle{swspec, rxBasePath, setSwaggerBasePath}),
|
||||
newSingleLineTagParser("Contact", &setMetaSingle{swspec, rxContact, setInfoContact}),
|
||||
newSingleLineTagParser("License", &setMetaSingle{swspec, rxLicense, setInfoLicense}),
|
||||
newMultiLineTagParser("YAMLInfoExtensionsBlock", newYamlParser(rxInfoExtensions, infoVendorExtensibleSetter(swspec)), true),
|
||||
newMultiLineTagParser("YAMLExtensionsBlock", newYamlParser(rxExtensions, metaVendorExtensibleSetter(swspec)), true),
|
||||
}
|
||||
return sp
|
||||
}
|
||||
|
||||
type setMetaSingle struct {
|
||||
spec *spec.Swagger
|
||||
rx *regexp.Regexp
|
||||
set func(spec *spec.Swagger, lines []string) error
|
||||
}
|
||||
|
||||
func (s *setMetaSingle) Matches(line string) bool {
|
||||
return s.rx.MatchString(line)
|
||||
}
|
||||
|
||||
func (s *setMetaSingle) Parse(lines []string) error {
|
||||
if len(lines) == 0 || (len(lines) == 1 && len(lines[0]) == 0) {
|
||||
return nil
|
||||
}
|
||||
matches := s.rx.FindStringSubmatch(lines[0])
|
||||
if len(matches) > 1 && len(matches[1]) > 0 {
|
||||
return s.set(s.spec, []string{matches[1]})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setSwaggerHost(swspec *spec.Swagger, lines []string) error {
|
||||
lns := lines
|
||||
if len(lns) == 0 || (len(lines) == 1 && len(lines[0]) == 0) {
|
||||
lns = []string{"localhost"}
|
||||
}
|
||||
swspec.Host = lns[0]
|
||||
return nil
|
||||
}
|
||||
|
||||
func setSwaggerBasePath(swspec *spec.Swagger, lines []string) error {
|
||||
var ln string
|
||||
if len(lines) > 0 {
|
||||
ln = lines[0]
|
||||
}
|
||||
swspec.BasePath = ln
|
||||
return nil
|
||||
}
|
||||
|
||||
func setInfoVersion(swspec *spec.Swagger, lines []string) error {
|
||||
if len(lines) == 0 {
|
||||
return nil
|
||||
}
|
||||
info := safeInfo(swspec)
|
||||
info.Version = strings.TrimSpace(lines[0])
|
||||
return nil
|
||||
}
|
||||
|
||||
func setInfoContact(swspec *spec.Swagger, lines []string) error {
|
||||
if len(lines) == 0 || (len(lines) == 1 && len(lines[0]) == 0) {
|
||||
return nil
|
||||
}
|
||||
contact, err := parseContactInfo(lines[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
info := safeInfo(swspec)
|
||||
info.Contact = contact
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseContactInfo(line string) (*spec.ContactInfo, error) {
|
||||
nameEmail, url := splitURL(line)
|
||||
var name, email string
|
||||
if len(nameEmail) > 0 {
|
||||
addr, err := mail.ParseAddress(nameEmail)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
name, email = addr.Name, addr.Address
|
||||
}
|
||||
return &spec.ContactInfo{
|
||||
ContactInfoProps: spec.ContactInfoProps{
|
||||
URL: url,
|
||||
Name: name,
|
||||
Email: email,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func setInfoLicense(swspec *spec.Swagger, lines []string) error {
|
||||
if len(lines) == 0 || (len(lines) == 1 && len(lines[0]) == 0) {
|
||||
return nil
|
||||
}
|
||||
info := safeInfo(swspec)
|
||||
line := lines[0]
|
||||
name, url := splitURL(line)
|
||||
info.License = &spec.License{
|
||||
LicenseProps: spec.LicenseProps{
|
||||
Name: name,
|
||||
URL: url,
|
||||
},
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func safeInfo(swspec *spec.Swagger) *spec.Info {
|
||||
if swspec.Info == nil {
|
||||
swspec.Info = new(spec.Info)
|
||||
}
|
||||
return swspec.Info
|
||||
}
|
||||
|
||||
// httpFTPScheme matches http://, https://, ws://, wss://
|
||||
var httpFTPScheme = regexp.MustCompile("(?:(?:ht|f)tp|ws)s?://")
|
||||
|
||||
func splitURL(line string) (notURL, url string) {
|
||||
str := strings.TrimSpace(line)
|
||||
parts := httpFTPScheme.FindStringIndex(str)
|
||||
if len(parts) == 0 {
|
||||
if len(str) > 0 {
|
||||
notURL = str
|
||||
}
|
||||
return
|
||||
}
|
||||
if len(parts) > 0 {
|
||||
notURL = strings.TrimSpace(str[:parts[0]])
|
||||
url = strings.TrimSpace(str[parts[0]:])
|
||||
}
|
||||
return
|
||||
}
|
||||
170
vendor/github.com/go-swagger/go-swagger/codescan/operations.go
generated
vendored
Normal file
170
vendor/github.com/go-swagger/go-swagger/codescan/operations.go
generated
vendored
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
package codescan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
type operationsBuilder struct {
|
||||
ctx *scanCtx
|
||||
path parsedPathContent
|
||||
operations map[string]*spec.Operation
|
||||
}
|
||||
|
||||
func (o *operationsBuilder) Build(tgt *spec.Paths) error {
|
||||
pthObj := tgt.Paths[o.path.Path]
|
||||
|
||||
op := setPathOperation(
|
||||
o.path.Method, o.path.ID,
|
||||
&pthObj, o.operations[o.path.ID])
|
||||
|
||||
op.Tags = o.path.Tags
|
||||
|
||||
sp := new(yamlSpecScanner)
|
||||
sp.setTitle = func(lines []string) { op.Summary = joinDropLast(lines) }
|
||||
sp.setDescription = func(lines []string) { op.Description = joinDropLast(lines) }
|
||||
|
||||
if err := sp.Parse(o.path.Remaining); err != nil {
|
||||
return fmt.Errorf("operation (%s): %v", op.ID, err)
|
||||
}
|
||||
if err := sp.UnmarshalSpec(op.UnmarshalJSON); err != nil {
|
||||
return fmt.Errorf("operation (%s): %v", op.ID, err)
|
||||
}
|
||||
|
||||
if tgt.Paths == nil {
|
||||
tgt.Paths = make(map[string]spec.PathItem)
|
||||
}
|
||||
|
||||
tgt.Paths[o.path.Path] = pthObj
|
||||
return nil
|
||||
}
|
||||
|
||||
type parsedPathContent struct {
|
||||
Method, Path, ID string
|
||||
Tags []string
|
||||
Remaining *ast.CommentGroup
|
||||
}
|
||||
|
||||
func parsePathAnnotation(annotation *regexp.Regexp, lines []*ast.Comment) (cnt parsedPathContent) {
|
||||
var justMatched bool
|
||||
|
||||
for _, cmt := range lines {
|
||||
txt := cmt.Text
|
||||
for _, line := range strings.Split(txt, "\n") {
|
||||
matches := annotation.FindStringSubmatch(line)
|
||||
if len(matches) > 3 {
|
||||
cnt.Method, cnt.Path, cnt.ID = matches[1], matches[2], matches[len(matches)-1]
|
||||
cnt.Tags = rxSpace.Split(matches[3], -1)
|
||||
if len(matches[3]) == 0 {
|
||||
cnt.Tags = nil
|
||||
}
|
||||
justMatched = true
|
||||
} else if cnt.Method != "" {
|
||||
if cnt.Remaining == nil {
|
||||
cnt.Remaining = new(ast.CommentGroup)
|
||||
}
|
||||
if !justMatched || strings.TrimSpace(rxStripComments.ReplaceAllString(line, "")) != "" {
|
||||
cc := new(ast.Comment)
|
||||
cc.Slash = cmt.Slash
|
||||
cc.Text = line
|
||||
cnt.Remaining.List = append(cnt.Remaining.List, cc)
|
||||
justMatched = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func setPathOperation(method, id string, pthObj *spec.PathItem, op *spec.Operation) *spec.Operation {
|
||||
if op == nil {
|
||||
op = new(spec.Operation)
|
||||
op.ID = id
|
||||
}
|
||||
|
||||
switch strings.ToUpper(method) {
|
||||
case "GET":
|
||||
if pthObj.Get != nil {
|
||||
if id == pthObj.Get.ID {
|
||||
op = pthObj.Get
|
||||
} else {
|
||||
pthObj.Get = op
|
||||
}
|
||||
} else {
|
||||
pthObj.Get = op
|
||||
}
|
||||
|
||||
case "POST":
|
||||
if pthObj.Post != nil {
|
||||
if id == pthObj.Post.ID {
|
||||
op = pthObj.Post
|
||||
} else {
|
||||
pthObj.Post = op
|
||||
}
|
||||
} else {
|
||||
pthObj.Post = op
|
||||
}
|
||||
|
||||
case "PUT":
|
||||
if pthObj.Put != nil {
|
||||
if id == pthObj.Put.ID {
|
||||
op = pthObj.Put
|
||||
} else {
|
||||
pthObj.Put = op
|
||||
}
|
||||
} else {
|
||||
pthObj.Put = op
|
||||
}
|
||||
|
||||
case "PATCH":
|
||||
if pthObj.Patch != nil {
|
||||
if id == pthObj.Patch.ID {
|
||||
op = pthObj.Patch
|
||||
} else {
|
||||
pthObj.Patch = op
|
||||
}
|
||||
} else {
|
||||
pthObj.Patch = op
|
||||
}
|
||||
|
||||
case "HEAD":
|
||||
if pthObj.Head != nil {
|
||||
if id == pthObj.Head.ID {
|
||||
op = pthObj.Head
|
||||
} else {
|
||||
pthObj.Head = op
|
||||
}
|
||||
} else {
|
||||
pthObj.Head = op
|
||||
}
|
||||
|
||||
case "DELETE":
|
||||
if pthObj.Delete != nil {
|
||||
if id == pthObj.Delete.ID {
|
||||
op = pthObj.Delete
|
||||
} else {
|
||||
pthObj.Delete = op
|
||||
}
|
||||
} else {
|
||||
pthObj.Delete = op
|
||||
}
|
||||
|
||||
case "OPTIONS":
|
||||
if pthObj.Options != nil {
|
||||
if id == pthObj.Options.ID {
|
||||
op = pthObj.Options
|
||||
} else {
|
||||
pthObj.Options = op
|
||||
}
|
||||
} else {
|
||||
pthObj.Options = op
|
||||
}
|
||||
}
|
||||
|
||||
return op
|
||||
}
|
||||
518
vendor/github.com/go-swagger/go-swagger/codescan/parameters.go
generated
vendored
Normal file
518
vendor/github.com/go-swagger/go-swagger/codescan/parameters.go
generated
vendored
Normal file
|
|
@ -0,0 +1,518 @@
|
|||
package codescan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/types"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/go/ast/astutil"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
type paramTypable struct {
|
||||
param *spec.Parameter
|
||||
}
|
||||
|
||||
func (pt paramTypable) Level() int { return 0 }
|
||||
|
||||
func (pt paramTypable) Typed(tpe, format string) {
|
||||
pt.param.Typed(tpe, format)
|
||||
}
|
||||
|
||||
func (pt paramTypable) SetRef(ref spec.Ref) {
|
||||
pt.param.Ref = ref
|
||||
}
|
||||
|
||||
func (pt paramTypable) Items() swaggerTypable {
|
||||
bdt, schema := bodyTypable(pt.param.In, pt.param.Schema)
|
||||
if bdt != nil {
|
||||
pt.param.Schema = schema
|
||||
return bdt
|
||||
}
|
||||
|
||||
if pt.param.Items == nil {
|
||||
pt.param.Items = new(spec.Items)
|
||||
}
|
||||
pt.param.Type = "array"
|
||||
return itemsTypable{pt.param.Items, 1}
|
||||
}
|
||||
|
||||
func (pt paramTypable) Schema() *spec.Schema {
|
||||
if pt.param.In != "body" {
|
||||
return nil
|
||||
}
|
||||
if pt.param.Schema == nil {
|
||||
pt.param.Schema = new(spec.Schema)
|
||||
}
|
||||
return pt.param.Schema
|
||||
}
|
||||
|
||||
func (pt paramTypable) AddExtension(key string, value interface{}) {
|
||||
if pt.param.In == "body" {
|
||||
pt.Schema().AddExtension(key, value)
|
||||
} else {
|
||||
pt.param.AddExtension(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
func (pt paramTypable) WithEnum(values ...interface{}) {
|
||||
pt.param.WithEnum(values...)
|
||||
}
|
||||
|
||||
func (pt paramTypable) WithEnumDescription(desc string) {
|
||||
if desc == "" {
|
||||
return
|
||||
}
|
||||
pt.param.AddExtension(extEnumDesc, desc)
|
||||
}
|
||||
|
||||
type itemsTypable struct {
|
||||
items *spec.Items
|
||||
level int
|
||||
}
|
||||
|
||||
func (pt itemsTypable) Level() int { return pt.level }
|
||||
|
||||
func (pt itemsTypable) Typed(tpe, format string) {
|
||||
pt.items.Typed(tpe, format)
|
||||
}
|
||||
|
||||
func (pt itemsTypable) SetRef(ref spec.Ref) {
|
||||
pt.items.Ref = ref
|
||||
}
|
||||
|
||||
func (pt itemsTypable) Schema() *spec.Schema {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pt itemsTypable) Items() swaggerTypable {
|
||||
if pt.items.Items == nil {
|
||||
pt.items.Items = new(spec.Items)
|
||||
}
|
||||
pt.items.Type = "array"
|
||||
return itemsTypable{pt.items.Items, pt.level + 1}
|
||||
}
|
||||
|
||||
func (pt itemsTypable) AddExtension(key string, value interface{}) {
|
||||
pt.items.AddExtension(key, value)
|
||||
}
|
||||
|
||||
func (pt itemsTypable) WithEnum(values ...interface{}) {
|
||||
pt.items.WithEnum(values...)
|
||||
}
|
||||
|
||||
func (pt itemsTypable) WithEnumDescription(_ string) {
|
||||
// no
|
||||
}
|
||||
|
||||
type paramValidations struct {
|
||||
current *spec.Parameter
|
||||
}
|
||||
|
||||
func (sv paramValidations) SetMaximum(val float64, exclusive bool) {
|
||||
sv.current.Maximum = &val
|
||||
sv.current.ExclusiveMaximum = exclusive
|
||||
}
|
||||
func (sv paramValidations) SetMinimum(val float64, exclusive bool) {
|
||||
sv.current.Minimum = &val
|
||||
sv.current.ExclusiveMinimum = exclusive
|
||||
}
|
||||
func (sv paramValidations) SetMultipleOf(val float64) { sv.current.MultipleOf = &val }
|
||||
func (sv paramValidations) SetMinItems(val int64) { sv.current.MinItems = &val }
|
||||
func (sv paramValidations) SetMaxItems(val int64) { sv.current.MaxItems = &val }
|
||||
func (sv paramValidations) SetMinLength(val int64) { sv.current.MinLength = &val }
|
||||
func (sv paramValidations) SetMaxLength(val int64) { sv.current.MaxLength = &val }
|
||||
func (sv paramValidations) SetPattern(val string) { sv.current.Pattern = val }
|
||||
func (sv paramValidations) SetUnique(val bool) { sv.current.UniqueItems = val }
|
||||
func (sv paramValidations) SetCollectionFormat(val string) { sv.current.CollectionFormat = val }
|
||||
func (sv paramValidations) SetEnum(val string) {
|
||||
sv.current.Enum = parseEnum(val, &spec.SimpleSchema{Type: sv.current.Type, Format: sv.current.Format})
|
||||
}
|
||||
func (sv paramValidations) SetDefault(val interface{}) { sv.current.Default = val }
|
||||
func (sv paramValidations) SetExample(val interface{}) { sv.current.Example = val }
|
||||
|
||||
type itemsValidations struct {
|
||||
current *spec.Items
|
||||
}
|
||||
|
||||
func (sv itemsValidations) SetMaximum(val float64, exclusive bool) {
|
||||
sv.current.Maximum = &val
|
||||
sv.current.ExclusiveMaximum = exclusive
|
||||
}
|
||||
func (sv itemsValidations) SetMinimum(val float64, exclusive bool) {
|
||||
sv.current.Minimum = &val
|
||||
sv.current.ExclusiveMinimum = exclusive
|
||||
}
|
||||
func (sv itemsValidations) SetMultipleOf(val float64) { sv.current.MultipleOf = &val }
|
||||
func (sv itemsValidations) SetMinItems(val int64) { sv.current.MinItems = &val }
|
||||
func (sv itemsValidations) SetMaxItems(val int64) { sv.current.MaxItems = &val }
|
||||
func (sv itemsValidations) SetMinLength(val int64) { sv.current.MinLength = &val }
|
||||
func (sv itemsValidations) SetMaxLength(val int64) { sv.current.MaxLength = &val }
|
||||
func (sv itemsValidations) SetPattern(val string) { sv.current.Pattern = val }
|
||||
func (sv itemsValidations) SetUnique(val bool) { sv.current.UniqueItems = val }
|
||||
func (sv itemsValidations) SetCollectionFormat(val string) { sv.current.CollectionFormat = val }
|
||||
func (sv itemsValidations) SetEnum(val string) {
|
||||
sv.current.Enum = parseEnum(val, &spec.SimpleSchema{Type: sv.current.Type, Format: sv.current.Format})
|
||||
}
|
||||
func (sv itemsValidations) SetDefault(val interface{}) { sv.current.Default = val }
|
||||
func (sv itemsValidations) SetExample(val interface{}) { sv.current.Example = val }
|
||||
|
||||
type parameterBuilder struct {
|
||||
ctx *scanCtx
|
||||
decl *entityDecl
|
||||
postDecls []*entityDecl
|
||||
}
|
||||
|
||||
func (p *parameterBuilder) Build(operations map[string]*spec.Operation) error {
|
||||
|
||||
// check if there is a swagger:parameters tag that is followed by one or more words,
|
||||
// these words are the ids of the operations this parameter struct applies to
|
||||
// once type name is found convert it to a schema, by looking up the schema in the
|
||||
// parameters dictionary that got passed into this parse method
|
||||
for _, opid := range p.decl.OperationIDS() {
|
||||
operation, ok := operations[opid]
|
||||
if !ok {
|
||||
operation = new(spec.Operation)
|
||||
operations[opid] = operation
|
||||
operation.ID = opid
|
||||
}
|
||||
debugLog("building parameters for: %s", opid)
|
||||
|
||||
// analyze struct body for fields etc
|
||||
// each exported struct field:
|
||||
// * gets a type mapped to a go primitive
|
||||
// * perhaps gets a format
|
||||
// * has to document the validations that apply for the type and the field
|
||||
// * when the struct field points to a model it becomes a ref: #/definitions/ModelName
|
||||
// * comments that aren't tags is used as the description
|
||||
if err := p.buildFromType(p.decl.Type, operation, make(map[string]spec.Parameter)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *parameterBuilder) buildFromType(otpe types.Type, op *spec.Operation, seen map[string]spec.Parameter) error {
|
||||
switch tpe := otpe.(type) {
|
||||
case *types.Pointer:
|
||||
return p.buildFromType(tpe.Elem(), op, seen)
|
||||
case *types.Named:
|
||||
o := tpe.Obj()
|
||||
switch stpe := o.Type().Underlying().(type) {
|
||||
case *types.Struct:
|
||||
debugLog("build from type %s: %T", tpe.Obj().Name(), otpe)
|
||||
if decl, found := p.ctx.DeclForType(o.Type()); found {
|
||||
return p.buildFromStruct(decl, stpe, op, seen)
|
||||
}
|
||||
return p.buildFromStruct(p.decl, stpe, op, seen)
|
||||
default:
|
||||
return errors.Errorf("unhandled type (%T): %s", stpe, o.Type().Underlying().String())
|
||||
}
|
||||
default:
|
||||
return errors.Errorf("unhandled type (%T): %s", otpe, tpe.String())
|
||||
}
|
||||
}
|
||||
|
||||
func (p *parameterBuilder) buildFromField(fld *types.Var, tpe types.Type, typable swaggerTypable, seen map[string]spec.Parameter) error {
|
||||
debugLog("build from field %s: %T", fld.Name(), tpe)
|
||||
switch ftpe := tpe.(type) {
|
||||
case *types.Basic:
|
||||
return swaggerSchemaForType(ftpe.Name(), typable)
|
||||
case *types.Struct:
|
||||
sb := schemaBuilder{
|
||||
decl: p.decl,
|
||||
ctx: p.ctx,
|
||||
}
|
||||
if err := sb.buildFromType(tpe, typable); err != nil {
|
||||
return err
|
||||
}
|
||||
p.postDecls = append(p.postDecls, sb.postDecls...)
|
||||
return nil
|
||||
case *types.Pointer:
|
||||
return p.buildFromField(fld, ftpe.Elem(), typable, seen)
|
||||
case *types.Interface:
|
||||
sb := schemaBuilder{
|
||||
decl: p.decl,
|
||||
ctx: p.ctx,
|
||||
}
|
||||
if err := sb.buildFromType(tpe, typable); err != nil {
|
||||
return err
|
||||
}
|
||||
p.postDecls = append(p.postDecls, sb.postDecls...)
|
||||
return nil
|
||||
case *types.Array:
|
||||
return p.buildFromField(fld, ftpe.Elem(), typable.Items(), seen)
|
||||
case *types.Slice:
|
||||
return p.buildFromField(fld, ftpe.Elem(), typable.Items(), seen)
|
||||
case *types.Map:
|
||||
schema := new(spec.Schema)
|
||||
typable.Schema().Typed("object", "").AdditionalProperties = &spec.SchemaOrBool{
|
||||
Schema: schema,
|
||||
}
|
||||
sb := schemaBuilder{
|
||||
decl: p.decl,
|
||||
ctx: p.ctx,
|
||||
}
|
||||
if err := sb.buildFromType(ftpe.Elem(), schemaTypable{schema, typable.Level() + 1}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
case *types.Named:
|
||||
if decl, found := p.ctx.DeclForType(ftpe.Obj().Type()); found {
|
||||
if decl.Type.Obj().Pkg().Path() == "time" && decl.Type.Obj().Name() == "Time" {
|
||||
typable.Typed("string", "date-time")
|
||||
return nil
|
||||
}
|
||||
if sfnm, isf := strfmtName(decl.Comments); isf {
|
||||
typable.Typed("string", sfnm)
|
||||
return nil
|
||||
}
|
||||
sb := &schemaBuilder{ctx: p.ctx, decl: decl}
|
||||
sb.inferNames()
|
||||
if err := sb.buildFromType(decl.Type, typable); err != nil {
|
||||
return err
|
||||
}
|
||||
p.postDecls = append(p.postDecls, sb.postDecls...)
|
||||
return nil
|
||||
}
|
||||
return errors.Errorf("unable to find package and source file for: %s", ftpe.String())
|
||||
default:
|
||||
return errors.Errorf("unknown type for %s: %T", fld.String(), fld.Type())
|
||||
}
|
||||
}
|
||||
|
||||
func spExtensionsSetter(ps *spec.Parameter) func(*spec.Extensions) {
|
||||
return func(exts *spec.Extensions) {
|
||||
for name, value := range *exts {
|
||||
addExtension(&ps.VendorExtensible, name, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *parameterBuilder) buildFromStruct(decl *entityDecl, tpe *types.Struct, op *spec.Operation, seen map[string]spec.Parameter) error {
|
||||
if tpe.NumFields() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var sequence []string
|
||||
|
||||
for i := 0; i < tpe.NumFields(); i++ {
|
||||
fld := tpe.Field(i)
|
||||
|
||||
if fld.Embedded() {
|
||||
if err := p.buildFromType(fld.Type(), op, seen); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if !fld.Exported() {
|
||||
debugLog("skipping field %s because it's not exported", fld.Name())
|
||||
continue
|
||||
}
|
||||
|
||||
tg := tpe.Tag(i)
|
||||
|
||||
var afld *ast.Field
|
||||
ans, _ := astutil.PathEnclosingInterval(decl.File, fld.Pos(), fld.Pos())
|
||||
for _, an := range ans {
|
||||
at, valid := an.(*ast.Field)
|
||||
if !valid {
|
||||
continue
|
||||
}
|
||||
|
||||
debugLog("field %s: %s(%T) [%q] ==> %s", fld.Name(), fld.Type().String(), fld.Type(), tg, at.Doc.Text())
|
||||
afld = at
|
||||
break
|
||||
}
|
||||
|
||||
if afld == nil {
|
||||
debugLog("can't find source associated with %s for %s", fld.String(), tpe.String())
|
||||
continue
|
||||
}
|
||||
|
||||
// if the field is annotated with swagger:ignore, ignore it
|
||||
if ignored(afld.Doc) {
|
||||
continue
|
||||
}
|
||||
|
||||
name, ignore, _, err := parseJSONTag(afld)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ignore {
|
||||
continue
|
||||
}
|
||||
|
||||
in := "query"
|
||||
// scan for param location first, this changes some behavior down the line
|
||||
if afld.Doc != nil {
|
||||
for _, cmt := range afld.Doc.List {
|
||||
for _, line := range strings.Split(cmt.Text, "\n") {
|
||||
matches := rxIn.FindStringSubmatch(line)
|
||||
if len(matches) > 0 && len(strings.TrimSpace(matches[1])) > 0 {
|
||||
in = strings.TrimSpace(matches[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ps := seen[name]
|
||||
ps.In = in
|
||||
var pty swaggerTypable = paramTypable{&ps}
|
||||
if in == "body" {
|
||||
pty = schemaTypable{pty.Schema(), 0}
|
||||
}
|
||||
if in == "formData" && afld.Doc != nil && fileParam(afld.Doc) {
|
||||
pty.Typed("file", "")
|
||||
} else if err := p.buildFromField(fld, fld.Type(), pty, seen); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if strfmtName, ok := strfmtName(afld.Doc); ok {
|
||||
ps.Typed("string", strfmtName)
|
||||
ps.Ref = spec.Ref{}
|
||||
ps.Items = nil
|
||||
}
|
||||
|
||||
sp := new(sectionedParser)
|
||||
sp.setDescription = func(lines []string) {
|
||||
ps.Description = joinDropLast(lines)
|
||||
enumDesc := getEnumDesc(ps.Extensions)
|
||||
if enumDesc != "" {
|
||||
ps.Description += "\n" + enumDesc
|
||||
}
|
||||
}
|
||||
if ps.Ref.String() == "" {
|
||||
sp.taggers = []tagParser{
|
||||
newSingleLineTagParser("in", &matchOnlyParam{&ps, rxIn}),
|
||||
newSingleLineTagParser("maximum", &setMaximum{paramValidations{&ps}, rxf(rxMaximumFmt, "")}),
|
||||
newSingleLineTagParser("minimum", &setMinimum{paramValidations{&ps}, rxf(rxMinimumFmt, "")}),
|
||||
newSingleLineTagParser("multipleOf", &setMultipleOf{paramValidations{&ps}, rxf(rxMultipleOfFmt, "")}),
|
||||
newSingleLineTagParser("minLength", &setMinLength{paramValidations{&ps}, rxf(rxMinLengthFmt, "")}),
|
||||
newSingleLineTagParser("maxLength", &setMaxLength{paramValidations{&ps}, rxf(rxMaxLengthFmt, "")}),
|
||||
newSingleLineTagParser("pattern", &setPattern{paramValidations{&ps}, rxf(rxPatternFmt, "")}),
|
||||
newSingleLineTagParser("collectionFormat", &setCollectionFormat{paramValidations{&ps}, rxf(rxCollectionFormatFmt, "")}),
|
||||
newSingleLineTagParser("minItems", &setMinItems{paramValidations{&ps}, rxf(rxMinItemsFmt, "")}),
|
||||
newSingleLineTagParser("maxItems", &setMaxItems{paramValidations{&ps}, rxf(rxMaxItemsFmt, "")}),
|
||||
newSingleLineTagParser("unique", &setUnique{paramValidations{&ps}, rxf(rxUniqueFmt, "")}),
|
||||
newSingleLineTagParser("enum", &setEnum{paramValidations{&ps}, rxf(rxEnumFmt, "")}),
|
||||
newSingleLineTagParser("default", &setDefault{&ps.SimpleSchema, paramValidations{&ps}, rxf(rxDefaultFmt, "")}),
|
||||
newSingleLineTagParser("example", &setExample{&ps.SimpleSchema, paramValidations{&ps}, rxf(rxExampleFmt, "")}),
|
||||
newSingleLineTagParser("required", &setRequiredParam{&ps}),
|
||||
newMultiLineTagParser("Extensions", newSetExtensions(spExtensionsSetter(&ps)), true),
|
||||
}
|
||||
|
||||
itemsTaggers := func(items *spec.Items, level int) []tagParser {
|
||||
// the expression is 1-index based not 0-index
|
||||
itemsPrefix := fmt.Sprintf(rxItemsPrefixFmt, level+1)
|
||||
|
||||
return []tagParser{
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dMaximum", level), &setMaximum{itemsValidations{items}, rxf(rxMaximumFmt, itemsPrefix)}),
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dMinimum", level), &setMinimum{itemsValidations{items}, rxf(rxMinimumFmt, itemsPrefix)}),
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dMultipleOf", level), &setMultipleOf{itemsValidations{items}, rxf(rxMultipleOfFmt, itemsPrefix)}),
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dMinLength", level), &setMinLength{itemsValidations{items}, rxf(rxMinLengthFmt, itemsPrefix)}),
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dMaxLength", level), &setMaxLength{itemsValidations{items}, rxf(rxMaxLengthFmt, itemsPrefix)}),
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dPattern", level), &setPattern{itemsValidations{items}, rxf(rxPatternFmt, itemsPrefix)}),
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dCollectionFormat", level), &setCollectionFormat{itemsValidations{items}, rxf(rxCollectionFormatFmt, itemsPrefix)}),
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dMinItems", level), &setMinItems{itemsValidations{items}, rxf(rxMinItemsFmt, itemsPrefix)}),
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dMaxItems", level), &setMaxItems{itemsValidations{items}, rxf(rxMaxItemsFmt, itemsPrefix)}),
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dUnique", level), &setUnique{itemsValidations{items}, rxf(rxUniqueFmt, itemsPrefix)}),
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dEnum", level), &setEnum{itemsValidations{items}, rxf(rxEnumFmt, itemsPrefix)}),
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dDefault", level), &setDefault{&items.SimpleSchema, itemsValidations{items}, rxf(rxDefaultFmt, itemsPrefix)}),
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dExample", level), &setExample{&items.SimpleSchema, itemsValidations{items}, rxf(rxExampleFmt, itemsPrefix)}),
|
||||
}
|
||||
}
|
||||
|
||||
var parseArrayTypes func(expr ast.Expr, items *spec.Items, level int) ([]tagParser, error)
|
||||
parseArrayTypes = func(expr ast.Expr, items *spec.Items, level int) ([]tagParser, error) {
|
||||
if items == nil {
|
||||
return []tagParser{}, nil
|
||||
}
|
||||
switch iftpe := expr.(type) {
|
||||
case *ast.ArrayType:
|
||||
eleTaggers := itemsTaggers(items, level)
|
||||
sp.taggers = append(eleTaggers, sp.taggers...)
|
||||
otherTaggers, err := parseArrayTypes(iftpe.Elt, items.Items, level+1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return otherTaggers, nil
|
||||
case *ast.SelectorExpr:
|
||||
otherTaggers, err := parseArrayTypes(iftpe.Sel, items.Items, level+1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return otherTaggers, nil
|
||||
case *ast.Ident:
|
||||
taggers := []tagParser{}
|
||||
if iftpe.Obj == nil {
|
||||
taggers = itemsTaggers(items, level)
|
||||
}
|
||||
otherTaggers, err := parseArrayTypes(expr, items.Items, level+1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append(taggers, otherTaggers...), nil
|
||||
case *ast.StarExpr:
|
||||
otherTaggers, err := parseArrayTypes(iftpe.X, items, level)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return otherTaggers, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown field type ele for %q", name)
|
||||
}
|
||||
}
|
||||
|
||||
// check if this is a primitive, if so parse the validations from the
|
||||
// doc comments of the slice declaration.
|
||||
if ftped, ok := afld.Type.(*ast.ArrayType); ok {
|
||||
taggers, err := parseArrayTypes(ftped.Elt, ps.Items, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sp.taggers = append(taggers, sp.taggers...)
|
||||
}
|
||||
|
||||
} else {
|
||||
sp.taggers = []tagParser{
|
||||
newSingleLineTagParser("in", &matchOnlyParam{&ps, rxIn}),
|
||||
newSingleLineTagParser("required", &matchOnlyParam{&ps, rxRequired}),
|
||||
newMultiLineTagParser("Extensions", newSetExtensions(spExtensionsSetter(&ps)), true),
|
||||
}
|
||||
}
|
||||
if err := sp.Parse(afld.Doc); err != nil {
|
||||
return err
|
||||
}
|
||||
if ps.In == "path" {
|
||||
ps.Required = true
|
||||
}
|
||||
|
||||
if ps.Name == "" {
|
||||
ps.Name = name
|
||||
}
|
||||
|
||||
if name != fld.Name() {
|
||||
addExtension(&ps.VendorExtensible, "x-go-name", fld.Name())
|
||||
}
|
||||
seen[name] = ps
|
||||
sequence = append(sequence, name)
|
||||
}
|
||||
|
||||
for _, k := range sequence {
|
||||
p := seen[k]
|
||||
for i, v := range op.Parameters {
|
||||
if v.Name == k {
|
||||
op.Parameters = append(op.Parameters[:i], op.Parameters[i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
op.Parameters = append(op.Parameters, p)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
1667
vendor/github.com/go-swagger/go-swagger/codescan/parser.go
generated
vendored
Normal file
1667
vendor/github.com/go-swagger/go-swagger/codescan/parser.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
51
vendor/github.com/go-swagger/go-swagger/codescan/parser_helpers.go
generated
vendored
Normal file
51
vendor/github.com/go-swagger/go-swagger/codescan/parser_helpers.go
generated
vendored
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
//go:build go1.19
|
||||
// +build go1.19
|
||||
|
||||
package codescan
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// a shared function that can be used to split given headers
|
||||
// into a title and description
|
||||
func collectScannerTitleDescription(headers []string) (title, desc []string) {
|
||||
hdrs := cleanupScannerLines(headers, rxUncommentHeaders, nil)
|
||||
|
||||
idx := -1
|
||||
for i, line := range hdrs {
|
||||
if strings.TrimSpace(line) == "" {
|
||||
idx = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if idx > -1 {
|
||||
title = hdrs[:idx]
|
||||
if len(title) > 0 {
|
||||
title[0] = rxTitleStart.ReplaceAllString(title[0], "")
|
||||
}
|
||||
if len(hdrs) > idx+1 {
|
||||
desc = hdrs[idx+1:]
|
||||
} else {
|
||||
desc = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if len(hdrs) > 0 {
|
||||
line := hdrs[0]
|
||||
switch {
|
||||
case rxPunctuationEnd.MatchString(line):
|
||||
title = []string{line}
|
||||
desc = hdrs[1:]
|
||||
case rxTitleStart.MatchString(line):
|
||||
title = []string{rxTitleStart.ReplaceAllString(line, "")}
|
||||
desc = hdrs[1:]
|
||||
default:
|
||||
desc = hdrs
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
42
vendor/github.com/go-swagger/go-swagger/codescan/parser_helpers_go118.go
generated
vendored
Normal file
42
vendor/github.com/go-swagger/go-swagger/codescan/parser_helpers_go118.go
generated
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
//go:build !go1.19
|
||||
// +build !go1.19
|
||||
|
||||
package codescan
|
||||
|
||||
import "strings"
|
||||
|
||||
// a shared function that can be used to split given headers
|
||||
// into a title and description
|
||||
func collectScannerTitleDescription(headers []string) (title, desc []string) {
|
||||
hdrs := cleanupScannerLines(headers, rxUncommentHeaders, nil)
|
||||
|
||||
idx := -1
|
||||
for i, line := range hdrs {
|
||||
if strings.TrimSpace(line) == "" {
|
||||
idx = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if idx > -1 {
|
||||
title = hdrs[:idx]
|
||||
if len(hdrs) > idx+1 {
|
||||
desc = hdrs[idx+1:]
|
||||
} else {
|
||||
desc = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if len(hdrs) > 0 {
|
||||
line := hdrs[0]
|
||||
if rxPunctuationEnd.MatchString(line) {
|
||||
title = []string{line}
|
||||
desc = hdrs[1:]
|
||||
} else {
|
||||
desc = hdrs
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
96
vendor/github.com/go-swagger/go-swagger/codescan/regexprs.go
generated
vendored
Normal file
96
vendor/github.com/go-swagger/go-swagger/codescan/regexprs.go
generated
vendored
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
package codescan
|
||||
|
||||
import "regexp"
|
||||
|
||||
const (
|
||||
rxMethod = "(\\p{L}+)"
|
||||
rxPath = "((?:/[\\p{L}\\p{N}\\p{Pd}\\p{Pc}{}\\-\\.\\?_~%!$&'()*+,;=:@/]*)+/?)"
|
||||
rxOpTags = "(\\p{L}[\\p{L}\\p{N}\\p{Pd}\\.\\p{Pc}\\p{Zs}]+)"
|
||||
rxOpID = "((?:\\p{L}[\\p{L}\\p{N}\\p{Pd}\\p{Pc}]+)+)"
|
||||
|
||||
rxMaximumFmt = "%s[Mm]ax(?:imum)?\\p{Zs}*:\\p{Zs}*([\\<=])?\\p{Zs}*([\\+-]?(?:\\p{N}+\\.)?\\p{N}+)$"
|
||||
rxMinimumFmt = "%s[Mm]in(?:imum)?\\p{Zs}*:\\p{Zs}*([\\>=])?\\p{Zs}*([\\+-]?(?:\\p{N}+\\.)?\\p{N}+)$"
|
||||
rxMultipleOfFmt = "%s[Mm]ultiple\\p{Zs}*[Oo]f\\p{Zs}*:\\p{Zs}*([\\+-]?(?:\\p{N}+\\.)?\\p{N}+)$"
|
||||
|
||||
rxMaxLengthFmt = "%s[Mm]ax(?:imum)?(?:\\p{Zs}*[\\p{Pd}\\p{Pc}]?[Ll]en(?:gth)?)\\p{Zs}*:\\p{Zs}*(\\p{N}+)$"
|
||||
rxMinLengthFmt = "%s[Mm]in(?:imum)?(?:\\p{Zs}*[\\p{Pd}\\p{Pc}]?[Ll]en(?:gth)?)\\p{Zs}*:\\p{Zs}*(\\p{N}+)$"
|
||||
rxPatternFmt = "%s[Pp]attern\\p{Zs}*:\\p{Zs}*(.*)$"
|
||||
rxCollectionFormatFmt = "%s[Cc]ollection(?:\\p{Zs}*[\\p{Pd}\\p{Pc}]?[Ff]ormat)\\p{Zs}*:\\p{Zs}*(.*)$"
|
||||
rxEnumFmt = "%s[Ee]num\\p{Zs}*:\\p{Zs}*(.*)$"
|
||||
rxDefaultFmt = "%s[Dd]efault\\p{Zs}*:\\p{Zs}*(.*)$"
|
||||
rxExampleFmt = "%s[Ee]xample\\p{Zs}*:\\p{Zs}*(.*)$"
|
||||
|
||||
rxMaxItemsFmt = "%s[Mm]ax(?:imum)?(?:\\p{Zs}*|[\\p{Pd}\\p{Pc}]|\\.)?[Ii]tems\\p{Zs}*:\\p{Zs}*(\\p{N}+)$"
|
||||
rxMinItemsFmt = "%s[Mm]in(?:imum)?(?:\\p{Zs}*|[\\p{Pd}\\p{Pc}]|\\.)?[Ii]tems\\p{Zs}*:\\p{Zs}*(\\p{N}+)$"
|
||||
rxUniqueFmt = "%s[Uu]nique\\p{Zs}*:\\p{Zs}*(true|false)$"
|
||||
|
||||
rxItemsPrefixFmt = "(?:[Ii]tems[\\.\\p{Zs}]*){%d}"
|
||||
)
|
||||
|
||||
var (
|
||||
rxSwaggerAnnotation = regexp.MustCompile(`swagger:([\p{L}\p{N}\p{Pd}\p{Pc}]+)`)
|
||||
rxFileUpload = regexp.MustCompile(`swagger:file`)
|
||||
rxStrFmt = regexp.MustCompile(`swagger:strfmt\p{Zs}*(\p{L}[\p{L}\p{N}\p{Pd}\p{Pc}]+)$`)
|
||||
rxAlias = regexp.MustCompile(`swagger:alias`)
|
||||
rxName = regexp.MustCompile(`swagger:name\p{Zs}*(\p{L}[\p{L}\p{N}\p{Pd}\p{Pc}\.]+)$`)
|
||||
rxAllOf = regexp.MustCompile(`swagger:allOf\p{Zs}*(\p{L}[\p{L}\p{N}\p{Pd}\p{Pc}\.]+)?$`)
|
||||
rxModelOverride = regexp.MustCompile(`swagger:model\p{Zs}*(\p{L}[\p{L}\p{N}\p{Pd}\p{Pc}]+)?$`)
|
||||
rxResponseOverride = regexp.MustCompile(`swagger:response\p{Zs}*(\p{L}[\p{L}\p{N}\p{Pd}\p{Pc}]+)?$`)
|
||||
rxParametersOverride = regexp.MustCompile(`swagger:parameters\p{Zs}*(\p{L}[\p{L}\p{N}\p{Pd}\p{Pc}\p{Zs}]+)$`)
|
||||
rxEnum = regexp.MustCompile(`swagger:enum\p{Zs}*(\p{L}[\p{L}\p{N}\p{Pd}\p{Pc}]+)$`)
|
||||
rxIgnoreOverride = regexp.MustCompile(`swagger:ignore\p{Zs}*(\p{L}[\p{L}\p{N}\p{Pd}\p{Pc}]+)?$`)
|
||||
rxDefault = regexp.MustCompile(`swagger:default\p{Zs}*(\p{L}[\p{L}\p{N}\p{Pd}\p{Pc}]+)$`)
|
||||
rxType = regexp.MustCompile(`swagger:type\p{Zs}*(\p{L}[\p{L}\p{N}\p{Pd}\p{Pc}]+)$`)
|
||||
rxRoute = regexp.MustCompile(
|
||||
"swagger:route\\p{Zs}*" +
|
||||
rxMethod +
|
||||
"\\p{Zs}*" +
|
||||
rxPath +
|
||||
"(?:\\p{Zs}+" +
|
||||
rxOpTags +
|
||||
")?\\p{Zs}+" +
|
||||
rxOpID + "\\p{Zs}*$")
|
||||
rxBeginYAMLSpec = regexp.MustCompile(`---\p{Zs}*$`)
|
||||
rxUncommentHeaders = regexp.MustCompile(`^[\p{Zs}\t/\*-]*\|?`)
|
||||
rxUncommentYAML = regexp.MustCompile(`^[\p{Zs}\t]*/*`)
|
||||
rxOperation = regexp.MustCompile(
|
||||
"swagger:operation\\p{Zs}*" +
|
||||
rxMethod +
|
||||
"\\p{Zs}*" +
|
||||
rxPath +
|
||||
"(?:\\p{Zs}+" +
|
||||
rxOpTags +
|
||||
")?\\p{Zs}+" +
|
||||
rxOpID + "\\p{Zs}*$")
|
||||
|
||||
rxSpace = regexp.MustCompile(`\p{Zs}+`)
|
||||
rxIndent = regexp.MustCompile(`[\p{Zs}\t]*/*[\p{Zs}\t]*[^\p{Zs}\t]`)
|
||||
rxNotIndent = regexp.MustCompile(`[^\p{Zs}\t]`)
|
||||
rxPunctuationEnd = regexp.MustCompile(`\p{Po}$`)
|
||||
rxTitleStart = regexp.MustCompile(`^[#]+\p{Zs}+`)
|
||||
rxStripComments = regexp.MustCompile(`^[^\p{L}\p{N}\p{Pd}\p{Pc}\+]*`)
|
||||
rxStripTitleComments = regexp.MustCompile(`^[^\p{L}]*[Pp]ackage\p{Zs}+[^\p{Zs}]+\p{Zs}*`)
|
||||
rxAllowedExtensions = regexp.MustCompile(`^[Xx]-`)
|
||||
|
||||
rxIn = regexp.MustCompile(`[Ii]n\p{Zs}*:\p{Zs}*(query|path|header|body|formData)$`)
|
||||
rxRequired = regexp.MustCompile(`[Rr]equired\p{Zs}*:\p{Zs}*(true|false)$`)
|
||||
rxDiscriminator = regexp.MustCompile(`[Dd]iscriminator\p{Zs}*:\p{Zs}*(true|false)$`)
|
||||
rxReadOnly = regexp.MustCompile(`[Rr]ead(?:\p{Zs}*|[\p{Pd}\p{Pc}])?[Oo]nly\p{Zs}*:\p{Zs}*(true|false)$`)
|
||||
rxConsumes = regexp.MustCompile(`[Cc]onsumes\p{Zs}*:`)
|
||||
rxProduces = regexp.MustCompile(`[Pp]roduces\p{Zs}*:`)
|
||||
rxSecuritySchemes = regexp.MustCompile(`[Ss]ecurity\p{Zs}*:`)
|
||||
rxSecurity = regexp.MustCompile(`[Ss]ecurity\p{Zs}*[Dd]efinitions:`)
|
||||
rxResponses = regexp.MustCompile(`[Rr]esponses\p{Zs}*:`)
|
||||
rxParameters = regexp.MustCompile(`[Pp]arameters\p{Zs}*:`)
|
||||
rxSchemes = regexp.MustCompile(`[Ss]chemes\p{Zs}*:\p{Zs}*((?:(?:https?|HTTPS?|wss?|WSS?)[\p{Zs},]*)+)$`)
|
||||
rxVersion = regexp.MustCompile(`[Vv]ersion\p{Zs}*:\p{Zs}*(.+)$`)
|
||||
rxHost = regexp.MustCompile(`[Hh]ost\p{Zs}*:\p{Zs}*(.+)$`)
|
||||
rxBasePath = regexp.MustCompile(`[Bb]ase\p{Zs}*-*[Pp]ath\p{Zs}*:\p{Zs}*` + rxPath + "$")
|
||||
rxLicense = regexp.MustCompile(`[Ll]icense\p{Zs}*:\p{Zs}*(.+)$`)
|
||||
rxContact = regexp.MustCompile(`[Cc]ontact\p{Zs}*-?(?:[Ii]info\p{Zs}*)?:\p{Zs}*(.+)$`)
|
||||
rxTOS = regexp.MustCompile(`[Tt](:?erms)?\p{Zs}*-?[Oo]f?\p{Zs}*-?[Ss](?:ervice)?\p{Zs}*:`)
|
||||
rxExtensions = regexp.MustCompile(`[Ee]xtensions\p{Zs}*:`)
|
||||
rxInfoExtensions = regexp.MustCompile(`[In]nfo\p{Zs}*[Ee]xtensions:`)
|
||||
rxDeprecated = regexp.MustCompile(`[Dd]eprecated\p{Zs}*:\p{Zs}*(true|false)$`)
|
||||
// currently unused: rxExample = regexp.MustCompile(`[Ex]ample\p{Zs}*:\p{Zs}*(.*)$`)
|
||||
)
|
||||
454
vendor/github.com/go-swagger/go-swagger/codescan/responses.go
generated
vendored
Normal file
454
vendor/github.com/go-swagger/go-swagger/codescan/responses.go
generated
vendored
Normal file
|
|
@ -0,0 +1,454 @@
|
|||
package codescan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/types"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"golang.org/x/tools/go/ast/astutil"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
type responseTypable struct {
|
||||
in string
|
||||
header *spec.Header
|
||||
response *spec.Response
|
||||
}
|
||||
|
||||
func (ht responseTypable) Level() int { return 0 }
|
||||
|
||||
func (ht responseTypable) Typed(tpe, format string) {
|
||||
ht.header.Typed(tpe, format)
|
||||
}
|
||||
|
||||
func bodyTypable(in string, schema *spec.Schema) (swaggerTypable, *spec.Schema) {
|
||||
if in == "body" {
|
||||
// get the schema for items on the schema property
|
||||
if schema == nil {
|
||||
schema = new(spec.Schema)
|
||||
}
|
||||
if schema.Items == nil {
|
||||
schema.Items = new(spec.SchemaOrArray)
|
||||
}
|
||||
if schema.Items.Schema == nil {
|
||||
schema.Items.Schema = new(spec.Schema)
|
||||
}
|
||||
schema.Typed("array", "")
|
||||
return schemaTypable{schema.Items.Schema, 1}, schema
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (ht responseTypable) Items() swaggerTypable {
|
||||
bdt, schema := bodyTypable(ht.in, ht.response.Schema)
|
||||
if bdt != nil {
|
||||
ht.response.Schema = schema
|
||||
return bdt
|
||||
}
|
||||
|
||||
if ht.header.Items == nil {
|
||||
ht.header.Items = new(spec.Items)
|
||||
}
|
||||
ht.header.Type = "array"
|
||||
return itemsTypable{ht.header.Items, 1}
|
||||
}
|
||||
|
||||
func (ht responseTypable) SetRef(ref spec.Ref) {
|
||||
// having trouble seeing the usefulness of this one here
|
||||
ht.Schema().Ref = ref
|
||||
}
|
||||
|
||||
func (ht responseTypable) Schema() *spec.Schema {
|
||||
if ht.response.Schema == nil {
|
||||
ht.response.Schema = new(spec.Schema)
|
||||
}
|
||||
return ht.response.Schema
|
||||
}
|
||||
|
||||
func (ht responseTypable) SetSchema(schema *spec.Schema) {
|
||||
ht.response.Schema = schema
|
||||
}
|
||||
|
||||
func (ht responseTypable) CollectionOf(items *spec.Items, format string) {
|
||||
ht.header.CollectionOf(items, format)
|
||||
}
|
||||
|
||||
func (ht responseTypable) AddExtension(key string, value interface{}) {
|
||||
ht.response.AddExtension(key, value)
|
||||
}
|
||||
|
||||
func (ht responseTypable) WithEnum(values ...interface{}) {
|
||||
ht.header.WithEnum(values)
|
||||
}
|
||||
|
||||
func (ht responseTypable) WithEnumDescription(_ string) {
|
||||
// no
|
||||
}
|
||||
|
||||
type headerValidations struct {
|
||||
current *spec.Header
|
||||
}
|
||||
|
||||
func (sv headerValidations) SetMaximum(val float64, exclusive bool) {
|
||||
sv.current.Maximum = &val
|
||||
sv.current.ExclusiveMaximum = exclusive
|
||||
}
|
||||
func (sv headerValidations) SetMinimum(val float64, exclusive bool) {
|
||||
sv.current.Minimum = &val
|
||||
sv.current.ExclusiveMinimum = exclusive
|
||||
}
|
||||
func (sv headerValidations) SetMultipleOf(val float64) { sv.current.MultipleOf = &val }
|
||||
func (sv headerValidations) SetMinItems(val int64) { sv.current.MinItems = &val }
|
||||
func (sv headerValidations) SetMaxItems(val int64) { sv.current.MaxItems = &val }
|
||||
func (sv headerValidations) SetMinLength(val int64) { sv.current.MinLength = &val }
|
||||
func (sv headerValidations) SetMaxLength(val int64) { sv.current.MaxLength = &val }
|
||||
func (sv headerValidations) SetPattern(val string) { sv.current.Pattern = val }
|
||||
func (sv headerValidations) SetUnique(val bool) { sv.current.UniqueItems = val }
|
||||
func (sv headerValidations) SetCollectionFormat(val string) { sv.current.CollectionFormat = val }
|
||||
func (sv headerValidations) SetEnum(val string) {
|
||||
sv.current.Enum = parseEnum(val, &spec.SimpleSchema{Type: sv.current.Type, Format: sv.current.Format})
|
||||
}
|
||||
func (sv headerValidations) SetDefault(val interface{}) { sv.current.Default = val }
|
||||
func (sv headerValidations) SetExample(val interface{}) { sv.current.Example = val }
|
||||
|
||||
type responseBuilder struct {
|
||||
ctx *scanCtx
|
||||
decl *entityDecl
|
||||
postDecls []*entityDecl
|
||||
}
|
||||
|
||||
func (r *responseBuilder) Build(responses map[string]spec.Response) error {
|
||||
// check if there is a swagger:response tag that is followed by one or more words,
|
||||
// these words are the ids of the operations this parameter struct applies to
|
||||
// once type name is found convert it to a schema, by looking up the schema in the
|
||||
// parameters dictionary that got passed into this parse method
|
||||
|
||||
name, _ := r.decl.ResponseNames()
|
||||
response := responses[name]
|
||||
debugLog("building response: %s", name)
|
||||
|
||||
// analyze doc comment for the model
|
||||
sp := new(sectionedParser)
|
||||
sp.setDescription = func(lines []string) { response.Description = joinDropLast(lines) }
|
||||
if err := sp.Parse(r.decl.Comments); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// analyze struct body for fields etc
|
||||
// each exported struct field:
|
||||
// * gets a type mapped to a go primitive
|
||||
// * perhaps gets a format
|
||||
// * has to document the validations that apply for the type and the field
|
||||
// * when the struct field points to a model it becomes a ref: #/definitions/ModelName
|
||||
// * comments that aren't tags is used as the description
|
||||
if err := r.buildFromType(r.decl.Type, &response, make(map[string]bool)); err != nil {
|
||||
return err
|
||||
}
|
||||
responses[name] = response
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *responseBuilder) buildFromField(fld *types.Var, tpe types.Type, typable swaggerTypable, seen map[string]bool) error {
|
||||
debugLog("build from field %s: %T", fld.Name(), tpe)
|
||||
switch ftpe := tpe.(type) {
|
||||
case *types.Basic:
|
||||
return swaggerSchemaForType(ftpe.Name(), typable)
|
||||
case *types.Struct:
|
||||
sb := schemaBuilder{
|
||||
decl: r.decl,
|
||||
ctx: r.ctx,
|
||||
}
|
||||
if err := sb.buildFromType(tpe, typable); err != nil {
|
||||
return err
|
||||
}
|
||||
r.postDecls = append(r.postDecls, sb.postDecls...)
|
||||
return nil
|
||||
case *types.Pointer:
|
||||
return r.buildFromField(fld, ftpe.Elem(), typable, seen)
|
||||
case *types.Interface:
|
||||
sb := schemaBuilder{
|
||||
decl: r.decl,
|
||||
ctx: r.ctx,
|
||||
}
|
||||
if err := sb.buildFromType(tpe, typable); err != nil {
|
||||
return err
|
||||
}
|
||||
r.postDecls = append(r.postDecls, sb.postDecls...)
|
||||
return nil
|
||||
case *types.Array:
|
||||
return r.buildFromField(fld, ftpe.Elem(), typable.Items(), seen)
|
||||
case *types.Slice:
|
||||
return r.buildFromField(fld, ftpe.Elem(), typable.Items(), seen)
|
||||
case *types.Map:
|
||||
schema := new(spec.Schema)
|
||||
typable.Schema().Typed("object", "").AdditionalProperties = &spec.SchemaOrBool{
|
||||
Schema: schema,
|
||||
}
|
||||
sb := schemaBuilder{
|
||||
decl: r.decl,
|
||||
ctx: r.ctx,
|
||||
}
|
||||
if err := sb.buildFromType(ftpe.Elem(), schemaTypable{schema, typable.Level() + 1}); err != nil {
|
||||
return err
|
||||
}
|
||||
r.postDecls = append(r.postDecls, sb.postDecls...)
|
||||
return nil
|
||||
case *types.Named:
|
||||
if decl, found := r.ctx.DeclForType(ftpe.Obj().Type()); found {
|
||||
if decl.Type.Obj().Pkg().Path() == "time" && decl.Type.Obj().Name() == "Time" {
|
||||
typable.Typed("string", "date-time")
|
||||
return nil
|
||||
}
|
||||
if sfnm, isf := strfmtName(decl.Comments); isf {
|
||||
typable.Typed("string", sfnm)
|
||||
return nil
|
||||
}
|
||||
sb := &schemaBuilder{ctx: r.ctx, decl: decl}
|
||||
sb.inferNames()
|
||||
if err := sb.buildFromType(decl.Type, typable); err != nil {
|
||||
return err
|
||||
}
|
||||
r.postDecls = append(r.postDecls, sb.postDecls...)
|
||||
return nil
|
||||
}
|
||||
return errors.Errorf("unable to find package and source file for: %s", ftpe.String())
|
||||
default:
|
||||
return errors.Errorf("unknown type for %s: %T", fld.String(), fld.Type())
|
||||
}
|
||||
}
|
||||
|
||||
func (r *responseBuilder) buildFromType(otpe types.Type, resp *spec.Response, seen map[string]bool) error {
|
||||
switch tpe := otpe.(type) {
|
||||
case *types.Pointer:
|
||||
return r.buildFromType(tpe.Elem(), resp, seen)
|
||||
case *types.Named:
|
||||
o := tpe.Obj()
|
||||
switch stpe := o.Type().Underlying().(type) {
|
||||
case *types.Struct:
|
||||
debugLog("build from type %s: %T", tpe.Obj().Name(), otpe)
|
||||
if decl, found := r.ctx.DeclForType(o.Type()); found {
|
||||
return r.buildFromStruct(decl, stpe, resp, seen)
|
||||
}
|
||||
return r.buildFromStruct(r.decl, stpe, resp, seen)
|
||||
default:
|
||||
if decl, found := r.ctx.DeclForType(o.Type()); found {
|
||||
var schema spec.Schema
|
||||
typable := schemaTypable{schema: &schema, level: 0}
|
||||
|
||||
if decl.Type.Obj().Pkg().Path() == "time" && decl.Type.Obj().Name() == "Time" {
|
||||
typable.Typed("string", "date-time")
|
||||
return nil
|
||||
}
|
||||
if sfnm, isf := strfmtName(decl.Comments); isf {
|
||||
typable.Typed("string", sfnm)
|
||||
return nil
|
||||
}
|
||||
sb := &schemaBuilder{ctx: r.ctx, decl: decl}
|
||||
sb.inferNames()
|
||||
if err := sb.buildFromType(tpe.Underlying(), typable); err != nil {
|
||||
return err
|
||||
}
|
||||
resp.WithSchema(&schema)
|
||||
r.postDecls = append(r.postDecls, sb.postDecls...)
|
||||
return nil
|
||||
}
|
||||
return errors.Errorf("responses can only be structs, did you mean for %s to be the response body?", otpe.String())
|
||||
}
|
||||
default:
|
||||
return errors.New("anonymous types are currently not supported for responses")
|
||||
}
|
||||
}
|
||||
|
||||
func (r *responseBuilder) buildFromStruct(decl *entityDecl, tpe *types.Struct, resp *spec.Response, seen map[string]bool) error {
|
||||
if tpe.NumFields() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := 0; i < tpe.NumFields(); i++ {
|
||||
fld := tpe.Field(i)
|
||||
if fld.Embedded() {
|
||||
|
||||
if err := r.buildFromType(fld.Type(), resp, seen); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
if fld.Anonymous() {
|
||||
debugLog("skipping anonymous field")
|
||||
continue
|
||||
}
|
||||
|
||||
tg := tpe.Tag(i)
|
||||
|
||||
var afld *ast.Field
|
||||
ans, _ := astutil.PathEnclosingInterval(decl.File, fld.Pos(), fld.Pos())
|
||||
for _, an := range ans {
|
||||
at, valid := an.(*ast.Field)
|
||||
if !valid {
|
||||
continue
|
||||
}
|
||||
|
||||
debugLog("field %s: %s(%T) [%q] ==> %s", fld.Name(), fld.Type().String(), fld.Type(), tg, at.Doc.Text())
|
||||
afld = at
|
||||
break
|
||||
}
|
||||
|
||||
if afld == nil {
|
||||
debugLog("can't find source associated with %s for %s", fld.String(), tpe.String())
|
||||
continue
|
||||
}
|
||||
|
||||
// if the field is annotated with swagger:ignore, ignore it
|
||||
if ignored(afld.Doc) {
|
||||
continue
|
||||
}
|
||||
|
||||
name, ignore, _, err := parseJSONTag(afld)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ignore {
|
||||
continue
|
||||
}
|
||||
|
||||
var in string
|
||||
// scan for param location first, this changes some behavior down the line
|
||||
if afld.Doc != nil {
|
||||
for _, cmt := range afld.Doc.List {
|
||||
for _, line := range strings.Split(cmt.Text, "\n") {
|
||||
matches := rxIn.FindStringSubmatch(line)
|
||||
if len(matches) > 0 && len(strings.TrimSpace(matches[1])) > 0 {
|
||||
in = strings.TrimSpace(matches[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ps := resp.Headers[name]
|
||||
|
||||
// support swagger:file for response
|
||||
// An API operation can return a file, such as an image or PDF. In this case,
|
||||
// define the response schema with type: file and specify the appropriate MIME types in the produces section.
|
||||
if afld.Doc != nil && fileParam(afld.Doc) {
|
||||
resp.Schema = &spec.Schema{}
|
||||
resp.Schema.Typed("file", "")
|
||||
} else if err := r.buildFromField(fld, fld.Type(), responseTypable{in, &ps, resp}, seen); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if strfmtName, ok := strfmtName(afld.Doc); ok {
|
||||
ps.Typed("string", strfmtName)
|
||||
}
|
||||
|
||||
sp := new(sectionedParser)
|
||||
sp.setDescription = func(lines []string) { ps.Description = joinDropLast(lines) }
|
||||
sp.taggers = []tagParser{
|
||||
newSingleLineTagParser("maximum", &setMaximum{headerValidations{&ps}, rxf(rxMaximumFmt, "")}),
|
||||
newSingleLineTagParser("minimum", &setMinimum{headerValidations{&ps}, rxf(rxMinimumFmt, "")}),
|
||||
newSingleLineTagParser("multipleOf", &setMultipleOf{headerValidations{&ps}, rxf(rxMultipleOfFmt, "")}),
|
||||
newSingleLineTagParser("minLength", &setMinLength{headerValidations{&ps}, rxf(rxMinLengthFmt, "")}),
|
||||
newSingleLineTagParser("maxLength", &setMaxLength{headerValidations{&ps}, rxf(rxMaxLengthFmt, "")}),
|
||||
newSingleLineTagParser("pattern", &setPattern{headerValidations{&ps}, rxf(rxPatternFmt, "")}),
|
||||
newSingleLineTagParser("collectionFormat", &setCollectionFormat{headerValidations{&ps}, rxf(rxCollectionFormatFmt, "")}),
|
||||
newSingleLineTagParser("minItems", &setMinItems{headerValidations{&ps}, rxf(rxMinItemsFmt, "")}),
|
||||
newSingleLineTagParser("maxItems", &setMaxItems{headerValidations{&ps}, rxf(rxMaxItemsFmt, "")}),
|
||||
newSingleLineTagParser("unique", &setUnique{headerValidations{&ps}, rxf(rxUniqueFmt, "")}),
|
||||
newSingleLineTagParser("enum", &setEnum{headerValidations{&ps}, rxf(rxEnumFmt, "")}),
|
||||
newSingleLineTagParser("default", &setDefault{&ps.SimpleSchema, headerValidations{&ps}, rxf(rxDefaultFmt, "")}),
|
||||
newSingleLineTagParser("example", &setExample{&ps.SimpleSchema, headerValidations{&ps}, rxf(rxExampleFmt, "")}),
|
||||
}
|
||||
itemsTaggers := func(items *spec.Items, level int) []tagParser {
|
||||
// the expression is 1-index based not 0-index
|
||||
itemsPrefix := fmt.Sprintf(rxItemsPrefixFmt, level+1)
|
||||
|
||||
return []tagParser{
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dMaximum", level), &setMaximum{itemsValidations{items}, rxf(rxMaximumFmt, itemsPrefix)}),
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dMinimum", level), &setMinimum{itemsValidations{items}, rxf(rxMinimumFmt, itemsPrefix)}),
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dMultipleOf", level), &setMultipleOf{itemsValidations{items}, rxf(rxMultipleOfFmt, itemsPrefix)}),
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dMinLength", level), &setMinLength{itemsValidations{items}, rxf(rxMinLengthFmt, itemsPrefix)}),
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dMaxLength", level), &setMaxLength{itemsValidations{items}, rxf(rxMaxLengthFmt, itemsPrefix)}),
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dPattern", level), &setPattern{itemsValidations{items}, rxf(rxPatternFmt, itemsPrefix)}),
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dCollectionFormat", level), &setCollectionFormat{itemsValidations{items}, rxf(rxCollectionFormatFmt, itemsPrefix)}),
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dMinItems", level), &setMinItems{itemsValidations{items}, rxf(rxMinItemsFmt, itemsPrefix)}),
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dMaxItems", level), &setMaxItems{itemsValidations{items}, rxf(rxMaxItemsFmt, itemsPrefix)}),
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dUnique", level), &setUnique{itemsValidations{items}, rxf(rxUniqueFmt, itemsPrefix)}),
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dEnum", level), &setEnum{itemsValidations{items}, rxf(rxEnumFmt, itemsPrefix)}),
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dDefault", level), &setDefault{&items.SimpleSchema, itemsValidations{items}, rxf(rxDefaultFmt, itemsPrefix)}),
|
||||
newSingleLineTagParser(fmt.Sprintf("items%dExample", level), &setExample{&items.SimpleSchema, itemsValidations{items}, rxf(rxExampleFmt, itemsPrefix)}),
|
||||
}
|
||||
}
|
||||
|
||||
var parseArrayTypes func(expr ast.Expr, items *spec.Items, level int) ([]tagParser, error)
|
||||
parseArrayTypes = func(expr ast.Expr, items *spec.Items, level int) ([]tagParser, error) {
|
||||
if items == nil {
|
||||
return []tagParser{}, nil
|
||||
}
|
||||
switch iftpe := expr.(type) {
|
||||
case *ast.ArrayType:
|
||||
eleTaggers := itemsTaggers(items, level)
|
||||
sp.taggers = append(eleTaggers, sp.taggers...)
|
||||
otherTaggers, err := parseArrayTypes(iftpe.Elt, items.Items, level+1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return otherTaggers, nil
|
||||
case *ast.Ident:
|
||||
taggers := []tagParser{}
|
||||
if iftpe.Obj == nil {
|
||||
taggers = itemsTaggers(items, level)
|
||||
}
|
||||
otherTaggers, err := parseArrayTypes(expr, items.Items, level+1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append(taggers, otherTaggers...), nil
|
||||
case *ast.SelectorExpr:
|
||||
otherTaggers, err := parseArrayTypes(iftpe.Sel, items.Items, level+1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return otherTaggers, nil
|
||||
case *ast.StarExpr:
|
||||
otherTaggers, err := parseArrayTypes(iftpe.X, items, level)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return otherTaggers, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown field type ele for %q", name)
|
||||
}
|
||||
}
|
||||
// check if this is a primitive, if so parse the validations from the
|
||||
// doc comments of the slice declaration.
|
||||
if ftped, ok := afld.Type.(*ast.ArrayType); ok {
|
||||
taggers, err := parseArrayTypes(ftped.Elt, ps.Items, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sp.taggers = append(taggers, sp.taggers...)
|
||||
}
|
||||
|
||||
if err := sp.Parse(afld.Doc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if in != "body" {
|
||||
seen[name] = true
|
||||
if resp.Headers == nil {
|
||||
resp.Headers = make(map[string]spec.Header)
|
||||
}
|
||||
resp.Headers[name] = ps
|
||||
}
|
||||
}
|
||||
|
||||
for k := range resp.Headers {
|
||||
if !seen[k] {
|
||||
delete(resp.Headers, k)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
263
vendor/github.com/go-swagger/go-swagger/codescan/route_params.go
generated
vendored
Normal file
263
vendor/github.com/go-swagger/go-swagger/codescan/route_params.go
generated
vendored
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
package codescan
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
const (
|
||||
// ParamDescriptionKey indicates the tag used to define a parameter description in swagger:route
|
||||
ParamDescriptionKey = "description"
|
||||
// ParamNameKey indicates the tag used to define a parameter name in swagger:route
|
||||
ParamNameKey = "name"
|
||||
// ParamInKey indicates the tag used to define a parameter location in swagger:route
|
||||
ParamInKey = "in"
|
||||
// ParamRequiredKey indicates the tag used to declare whether a parameter is required in swagger:route
|
||||
ParamRequiredKey = "required"
|
||||
// ParamTypeKey indicates the tag used to define the parameter type in swagger:route
|
||||
ParamTypeKey = "type"
|
||||
// ParamAllowEmptyKey indicates the tag used to indicate whether a parameter allows empty values in swagger:route
|
||||
ParamAllowEmptyKey = "allowempty"
|
||||
|
||||
// SchemaMinKey indicates the tag used to indicate the minimum value allowed for this type in swagger:route
|
||||
SchemaMinKey = "min"
|
||||
// SchemaMaxKey indicates the tag used to indicate the maximum value allowed for this type in swagger:route
|
||||
SchemaMaxKey = "max"
|
||||
// SchemaEnumKey indicates the tag used to specify the allowed values for this type in swagger:route
|
||||
SchemaEnumKey = "enum"
|
||||
// SchemaFormatKey indicates the expected format for this field in swagger:route
|
||||
SchemaFormatKey = "format"
|
||||
// SchemaDefaultKey indicates the default value for this field in swagger:route
|
||||
SchemaDefaultKey = "default"
|
||||
// SchemaMinLenKey indicates the minimum length this field in swagger:route
|
||||
SchemaMinLenKey = "minlength"
|
||||
// SchemaMaxLenKey indicates the minimum length this field in swagger:route
|
||||
SchemaMaxLenKey = "maxlength"
|
||||
|
||||
// TypeArray is the identifier for an array type in swagger:route
|
||||
TypeArray = "array"
|
||||
// TypeNumber is the identifier for a number type in swagger:route
|
||||
TypeNumber = "number"
|
||||
// TypeInteger is the identifier for an integer type in swagger:route
|
||||
TypeInteger = "integer"
|
||||
// TypeBoolean is the identifier for a boolean type in swagger:route
|
||||
TypeBoolean = "boolean"
|
||||
// TypeBool is the identifier for a boolean type in swagger:route
|
||||
TypeBool = "bool"
|
||||
// TypeObject is the identifier for an object type in swagger:route
|
||||
TypeObject = "object"
|
||||
// TypeString is the identifier for a string type in swagger:route
|
||||
TypeString = "string"
|
||||
)
|
||||
|
||||
var (
|
||||
validIn = []string{"path", "query", "header", "body", "form"}
|
||||
basicTypes = []string{TypeInteger, TypeNumber, TypeString, TypeBoolean, TypeBool, TypeArray}
|
||||
)
|
||||
|
||||
func newSetParams(params []*spec.Parameter, setter func([]*spec.Parameter)) *setOpParams {
|
||||
return &setOpParams{
|
||||
set: setter,
|
||||
parameters: params,
|
||||
}
|
||||
}
|
||||
|
||||
type setOpParams struct {
|
||||
set func([]*spec.Parameter)
|
||||
parameters []*spec.Parameter
|
||||
}
|
||||
|
||||
func (s *setOpParams) Matches(line string) bool {
|
||||
return rxParameters.MatchString(line)
|
||||
}
|
||||
|
||||
func (s *setOpParams) Parse(lines []string) error {
|
||||
if len(lines) == 0 || (len(lines) == 1 && len(lines[0]) == 0) {
|
||||
return nil
|
||||
}
|
||||
|
||||
var current *spec.Parameter
|
||||
var extraData map[string]string
|
||||
|
||||
for _, line := range lines {
|
||||
l := strings.TrimSpace(line)
|
||||
|
||||
if strings.HasPrefix(l, "+") {
|
||||
s.finalizeParam(current, extraData)
|
||||
current = new(spec.Parameter)
|
||||
extraData = make(map[string]string)
|
||||
l = strings.TrimPrefix(l, "+")
|
||||
}
|
||||
|
||||
kv := strings.SplitN(l, ":", 2)
|
||||
|
||||
if len(kv) <= 1 {
|
||||
continue
|
||||
}
|
||||
|
||||
key := strings.ToLower(strings.TrimSpace(kv[0]))
|
||||
value := strings.TrimSpace(kv[1])
|
||||
|
||||
if current == nil {
|
||||
return errors.New("invalid route/operation schema provided")
|
||||
}
|
||||
|
||||
switch key {
|
||||
case ParamDescriptionKey:
|
||||
current.Description = value
|
||||
case ParamNameKey:
|
||||
current.Name = value
|
||||
case ParamInKey:
|
||||
v := strings.ToLower(value)
|
||||
if contains(validIn, v) {
|
||||
current.In = v
|
||||
}
|
||||
case ParamRequiredKey:
|
||||
if v, err := strconv.ParseBool(value); err == nil {
|
||||
current.Required = v
|
||||
}
|
||||
case ParamTypeKey:
|
||||
if current.Schema == nil {
|
||||
current.Schema = new(spec.Schema)
|
||||
}
|
||||
if contains(basicTypes, value) {
|
||||
current.Type = strings.ToLower(value)
|
||||
if current.Type == TypeBool {
|
||||
current.Type = TypeBoolean
|
||||
}
|
||||
} else if ref, err := spec.NewRef("#/definitions/" + value); err == nil {
|
||||
current.Type = TypeObject
|
||||
current.Schema.Ref = ref
|
||||
}
|
||||
current.Schema.Type = spec.StringOrArray{current.Type}
|
||||
case ParamAllowEmptyKey:
|
||||
if v, err := strconv.ParseBool(value); err == nil {
|
||||
current.AllowEmptyValue = v
|
||||
}
|
||||
default:
|
||||
extraData[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
s.finalizeParam(current, extraData)
|
||||
s.set(s.parameters)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *setOpParams) finalizeParam(param *spec.Parameter, data map[string]string) {
|
||||
if param == nil {
|
||||
return
|
||||
}
|
||||
|
||||
processSchema(data, param)
|
||||
|
||||
// schema is only allowed for parameters in "body"
|
||||
// see https://swagger.io/specification/v2/#parameterObject
|
||||
switch {
|
||||
case param.In == "body":
|
||||
param.Type = ""
|
||||
|
||||
case param.Schema != nil:
|
||||
// convert schema into validations
|
||||
param.SetValidations(param.Schema.Validations())
|
||||
param.Default = param.Schema.Default
|
||||
param.Format = param.Schema.Format
|
||||
param.Schema = nil
|
||||
}
|
||||
|
||||
s.parameters = append(s.parameters, param)
|
||||
}
|
||||
|
||||
func processSchema(data map[string]string, param *spec.Parameter) {
|
||||
if param.Schema == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var enumValues []string
|
||||
|
||||
for key, value := range data {
|
||||
switch key {
|
||||
case SchemaMinKey:
|
||||
if t := getType(param.Schema); t == TypeNumber || t == TypeInteger {
|
||||
v, _ := strconv.ParseFloat(value, 64)
|
||||
param.Schema.Minimum = &v
|
||||
}
|
||||
case SchemaMaxKey:
|
||||
if t := getType(param.Schema); t == TypeNumber || t == TypeInteger {
|
||||
v, _ := strconv.ParseFloat(value, 64)
|
||||
param.Schema.Maximum = &v
|
||||
}
|
||||
case SchemaMinLenKey:
|
||||
if getType(param.Schema) == TypeArray {
|
||||
v, _ := strconv.ParseInt(value, 10, 64)
|
||||
param.Schema.MinLength = &v
|
||||
}
|
||||
case SchemaMaxLenKey:
|
||||
if getType(param.Schema) == TypeArray {
|
||||
v, _ := strconv.ParseInt(value, 10, 64)
|
||||
param.Schema.MaxLength = &v
|
||||
}
|
||||
case SchemaEnumKey:
|
||||
enumValues = strings.Split(value, ",")
|
||||
case SchemaFormatKey:
|
||||
param.Schema.Format = value
|
||||
case SchemaDefaultKey:
|
||||
param.Schema.Default = convert(param.Type, value)
|
||||
}
|
||||
}
|
||||
|
||||
if param.Description != "" {
|
||||
param.Schema.Description = param.Description
|
||||
}
|
||||
|
||||
convertEnum(param.Schema, enumValues)
|
||||
}
|
||||
|
||||
func convertEnum(schema *spec.Schema, enumValues []string) {
|
||||
if len(enumValues) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var finalEnum []interface{}
|
||||
for _, v := range enumValues {
|
||||
finalEnum = append(finalEnum, convert(schema.Type[0], strings.TrimSpace(v)))
|
||||
}
|
||||
schema.Enum = finalEnum
|
||||
}
|
||||
|
||||
func convert(typeStr, valueStr string) interface{} {
|
||||
switch typeStr {
|
||||
case TypeInteger:
|
||||
fallthrough
|
||||
case TypeNumber:
|
||||
if num, err := strconv.ParseFloat(valueStr, 64); err == nil {
|
||||
return num
|
||||
}
|
||||
case TypeBoolean:
|
||||
fallthrough
|
||||
case TypeBool:
|
||||
if b, err := strconv.ParseBool(valueStr); err == nil {
|
||||
return b
|
||||
}
|
||||
}
|
||||
return valueStr
|
||||
}
|
||||
|
||||
func getType(schema *spec.Schema) string {
|
||||
if len(schema.Type) == 0 {
|
||||
return ""
|
||||
}
|
||||
return schema.Type[0]
|
||||
}
|
||||
|
||||
func contains(arr []string, obj string) bool {
|
||||
for _, v := range arr {
|
||||
if v == obj {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
93
vendor/github.com/go-swagger/go-swagger/codescan/routes.go
generated
vendored
Normal file
93
vendor/github.com/go-swagger/go-swagger/codescan/routes.go
generated
vendored
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
package codescan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
func opConsumesSetter(op *spec.Operation) func([]string) {
|
||||
return func(consumes []string) { op.Consumes = consumes }
|
||||
}
|
||||
|
||||
func opProducesSetter(op *spec.Operation) func([]string) {
|
||||
return func(produces []string) { op.Produces = produces }
|
||||
}
|
||||
|
||||
func opSchemeSetter(op *spec.Operation) func([]string) {
|
||||
return func(schemes []string) { op.Schemes = schemes }
|
||||
}
|
||||
|
||||
func opSecurityDefsSetter(op *spec.Operation) func([]map[string][]string) {
|
||||
return func(securityDefs []map[string][]string) { op.Security = securityDefs }
|
||||
}
|
||||
|
||||
func opResponsesSetter(op *spec.Operation) func(*spec.Response, map[int]spec.Response) {
|
||||
return func(def *spec.Response, scr map[int]spec.Response) {
|
||||
if op.Responses == nil {
|
||||
op.Responses = new(spec.Responses)
|
||||
}
|
||||
op.Responses.Default = def
|
||||
op.Responses.StatusCodeResponses = scr
|
||||
}
|
||||
}
|
||||
|
||||
func opParamSetter(op *spec.Operation) func([]*spec.Parameter) {
|
||||
return func(params []*spec.Parameter) {
|
||||
for _, v := range params {
|
||||
op.AddParam(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func opExtensionsSetter(op *spec.Operation) func(*spec.Extensions) {
|
||||
return func(exts *spec.Extensions) {
|
||||
for name, value := range *exts {
|
||||
op.AddExtension(name, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type routesBuilder struct {
|
||||
ctx *scanCtx
|
||||
route parsedPathContent
|
||||
definitions map[string]spec.Schema
|
||||
operations map[string]*spec.Operation
|
||||
responses map[string]spec.Response
|
||||
parameters []*spec.Parameter
|
||||
}
|
||||
|
||||
func (r *routesBuilder) Build(tgt *spec.Paths) error {
|
||||
|
||||
pthObj := tgt.Paths[r.route.Path]
|
||||
op := setPathOperation(
|
||||
r.route.Method, r.route.ID,
|
||||
&pthObj, r.operations[r.route.ID])
|
||||
|
||||
op.Tags = r.route.Tags
|
||||
|
||||
sp := new(sectionedParser)
|
||||
sp.setTitle = func(lines []string) { op.Summary = joinDropLast(lines) }
|
||||
sp.setDescription = func(lines []string) { op.Description = joinDropLast(lines) }
|
||||
sr := newSetResponses(r.definitions, r.responses, opResponsesSetter(op))
|
||||
spa := newSetParams(r.parameters, opParamSetter(op))
|
||||
sp.taggers = []tagParser{
|
||||
newMultiLineTagParser("Consumes", newMultilineDropEmptyParser(rxConsumes, opConsumesSetter(op)), false),
|
||||
newMultiLineTagParser("Produces", newMultilineDropEmptyParser(rxProduces, opProducesSetter(op)), false),
|
||||
newSingleLineTagParser("Schemes", newSetSchemes(opSchemeSetter(op))),
|
||||
newMultiLineTagParser("Security", newSetSecurity(rxSecuritySchemes, opSecurityDefsSetter(op)), false),
|
||||
newMultiLineTagParser("Parameters", spa, false),
|
||||
newMultiLineTagParser("Responses", sr, false),
|
||||
newSingleLineTagParser("Deprecated", &setDeprecatedOp{op}),
|
||||
newMultiLineTagParser("Extensions", newSetExtensions(opExtensionsSetter(op)), true),
|
||||
}
|
||||
if err := sp.Parse(r.route.Remaining); err != nil {
|
||||
return fmt.Errorf("operation (%s): %v", op.ID, err)
|
||||
}
|
||||
|
||||
if tgt.Paths == nil {
|
||||
tgt.Paths = make(map[string]spec.PathItem)
|
||||
}
|
||||
tgt.Paths[r.route.Path] = pthObj
|
||||
return nil
|
||||
}
|
||||
1155
vendor/github.com/go-swagger/go-swagger/codescan/schema.go
generated
vendored
Normal file
1155
vendor/github.com/go-swagger/go-swagger/codescan/schema.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
258
vendor/github.com/go-swagger/go-swagger/codescan/spec.go
generated
vendored
Normal file
258
vendor/github.com/go-swagger/go-swagger/codescan/spec.go
generated
vendored
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
package codescan
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
func newSpecBuilder(input *spec.Swagger, sc *scanCtx, scanModels bool) *specBuilder {
|
||||
if input == nil {
|
||||
input = new(spec.Swagger)
|
||||
input.Swagger = "2.0"
|
||||
}
|
||||
|
||||
if input.Paths == nil {
|
||||
input.Paths = new(spec.Paths)
|
||||
}
|
||||
if input.Definitions == nil {
|
||||
input.Definitions = make(map[string]spec.Schema)
|
||||
}
|
||||
if input.Responses == nil {
|
||||
input.Responses = make(map[string]spec.Response)
|
||||
}
|
||||
if input.Extensions == nil {
|
||||
input.Extensions = make(spec.Extensions)
|
||||
}
|
||||
|
||||
return &specBuilder{
|
||||
ctx: sc,
|
||||
input: input,
|
||||
scanModels: scanModels,
|
||||
operations: collectOperationsFromInput(input),
|
||||
definitions: input.Definitions,
|
||||
responses: input.Responses,
|
||||
}
|
||||
}
|
||||
|
||||
type specBuilder struct {
|
||||
scanModels bool
|
||||
input *spec.Swagger
|
||||
ctx *scanCtx
|
||||
discovered []*entityDecl
|
||||
definitions map[string]spec.Schema
|
||||
responses map[string]spec.Response
|
||||
operations map[string]*spec.Operation
|
||||
}
|
||||
|
||||
func (s *specBuilder) Build() (*spec.Swagger, error) {
|
||||
if err := s.buildModels(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := s.buildParameters(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := s.buildRespones(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// build definitions dictionary
|
||||
if err := s.buildDiscovered(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := s.buildRoutes(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := s.buildOperations(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := s.buildMeta(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if s.input.Swagger == "" {
|
||||
s.input.Swagger = "2.0"
|
||||
}
|
||||
|
||||
return s.input, nil
|
||||
}
|
||||
|
||||
func (s *specBuilder) buildDiscovered() error {
|
||||
// loop over discovered until all the items are in definitions
|
||||
keepGoing := len(s.discovered) > 0
|
||||
for keepGoing {
|
||||
var queue []*entityDecl
|
||||
for _, d := range s.discovered {
|
||||
nm, _ := d.Names()
|
||||
if _, ok := s.definitions[nm]; !ok {
|
||||
queue = append(queue, d)
|
||||
}
|
||||
}
|
||||
s.discovered = nil
|
||||
for _, sd := range queue {
|
||||
if err := s.buildDiscoveredSchema(sd); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
keepGoing = len(s.discovered) > 0
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *specBuilder) buildDiscoveredSchema(decl *entityDecl) error {
|
||||
sb := &schemaBuilder{
|
||||
ctx: s.ctx,
|
||||
decl: decl,
|
||||
discovered: s.discovered,
|
||||
}
|
||||
if err := sb.Build(s.definitions); err != nil {
|
||||
return err
|
||||
}
|
||||
s.discovered = append(s.discovered, sb.postDecls...)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *specBuilder) buildMeta() error {
|
||||
// build swagger object
|
||||
for _, decl := range s.ctx.app.Meta {
|
||||
if err := newMetaParser(s.input).Parse(decl.Comments); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *specBuilder) buildOperations() error {
|
||||
for _, pp := range s.ctx.app.Operations {
|
||||
ob := &operationsBuilder{
|
||||
operations: s.operations,
|
||||
ctx: s.ctx,
|
||||
path: pp,
|
||||
}
|
||||
if err := ob.Build(s.input.Paths); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *specBuilder) buildRoutes() error {
|
||||
// build paths dictionary
|
||||
for _, pp := range s.ctx.app.Routes {
|
||||
rb := &routesBuilder{
|
||||
ctx: s.ctx,
|
||||
route: pp,
|
||||
responses: s.responses,
|
||||
operations: s.operations,
|
||||
definitions: s.definitions,
|
||||
}
|
||||
if err := rb.Build(s.input.Paths); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *specBuilder) buildRespones() error {
|
||||
// build responses dictionary
|
||||
for _, decl := range s.ctx.app.Responses {
|
||||
rb := &responseBuilder{
|
||||
ctx: s.ctx,
|
||||
decl: decl,
|
||||
}
|
||||
if err := rb.Build(s.responses); err != nil {
|
||||
return err
|
||||
}
|
||||
s.discovered = append(s.discovered, rb.postDecls...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *specBuilder) buildParameters() error {
|
||||
// build parameters dictionary
|
||||
for _, decl := range s.ctx.app.Parameters {
|
||||
pb := ¶meterBuilder{
|
||||
ctx: s.ctx,
|
||||
decl: decl,
|
||||
}
|
||||
if err := pb.Build(s.operations); err != nil {
|
||||
return err
|
||||
}
|
||||
s.discovered = append(s.discovered, pb.postDecls...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *specBuilder) buildModels() error {
|
||||
// build models dictionary
|
||||
if !s.scanModels {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, decl := range s.ctx.app.Models {
|
||||
if err := s.buildDiscoveredSchema(decl); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return s.joinExtraModels()
|
||||
}
|
||||
|
||||
func (s *specBuilder) joinExtraModels() error {
|
||||
tmp := make(map[*ast.Ident]*entityDecl, len(s.ctx.app.ExtraModels))
|
||||
for k, v := range s.ctx.app.ExtraModels {
|
||||
tmp[k] = v
|
||||
s.ctx.app.Models[k] = v
|
||||
delete(s.ctx.app.ExtraModels, k)
|
||||
}
|
||||
|
||||
// process extra models and see if there is any reference to a new extra one
|
||||
for _, decl := range tmp {
|
||||
if err := s.buildDiscoveredSchema(decl); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(s.ctx.app.ExtraModels) > 0 {
|
||||
return s.joinExtraModels()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func collectOperationsFromInput(input *spec.Swagger) map[string]*spec.Operation {
|
||||
operations := make(map[string]*spec.Operation)
|
||||
if input != nil && input.Paths != nil {
|
||||
for _, pth := range input.Paths.Paths {
|
||||
if pth.Get != nil {
|
||||
operations[pth.Get.ID] = pth.Get
|
||||
}
|
||||
if pth.Post != nil {
|
||||
operations[pth.Post.ID] = pth.Post
|
||||
}
|
||||
if pth.Put != nil {
|
||||
operations[pth.Put.ID] = pth.Put
|
||||
}
|
||||
if pth.Patch != nil {
|
||||
operations[pth.Patch.ID] = pth.Patch
|
||||
}
|
||||
if pth.Delete != nil {
|
||||
operations[pth.Delete.ID] = pth.Delete
|
||||
}
|
||||
if pth.Head != nil {
|
||||
operations[pth.Head.ID] = pth.Head
|
||||
}
|
||||
if pth.Options != nil {
|
||||
operations[pth.Options.ID] = pth.Options
|
||||
}
|
||||
}
|
||||
}
|
||||
return operations
|
||||
}
|
||||
1
vendor/github.com/go-swagger/go-swagger/generator/.gitignore
generated
vendored
Normal file
1
vendor/github.com/go-swagger/go-swagger/generator/.gitignore
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
generated/
|
||||
40
vendor/github.com/go-swagger/go-swagger/generator/bindata.go
generated
vendored
Normal file
40
vendor/github.com/go-swagger/go-swagger/generator/bindata.go
generated
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
package generator
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"io/fs"
|
||||
)
|
||||
|
||||
//go:embed templates
|
||||
var _bindata embed.FS
|
||||
|
||||
// AssetNames returns the names of the assets.
|
||||
func AssetNames() []string {
|
||||
names := make([]string, 0)
|
||||
_ = fs.WalkDir(_bindata, "templates", func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
names = append(names, path)
|
||||
return nil
|
||||
})
|
||||
return names
|
||||
}
|
||||
|
||||
// Asset loads and returns the asset for the given name.
|
||||
// It returns an error if the asset could not be found or
|
||||
// could not be loaded.
|
||||
func Asset(name string) ([]byte, error) {
|
||||
return _bindata.ReadFile(name)
|
||||
}
|
||||
|
||||
// MustAsset is like Asset but panics when Asset would return an error.
|
||||
// It simplifies safe initialization of global variables.
|
||||
func MustAsset(name string) []byte {
|
||||
a, err := Asset(name)
|
||||
if err != nil {
|
||||
panic("asset: Asset(" + name + "): " + err.Error())
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
120
vendor/github.com/go-swagger/go-swagger/generator/client.go
generated
vendored
Normal file
120
vendor/github.com/go-swagger/go-swagger/generator/client.go
generated
vendored
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// 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 generator
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
// GenerateClient generates a client library for a swagger spec document.
|
||||
func GenerateClient(name string, modelNames, operationIDs []string, opts *GenOpts) error {
|
||||
if err := opts.CheckOpts(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := opts.setTemplates(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
specDoc, analyzed, err := opts.analyzeSpec()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
models, err := gatherModels(specDoc, modelNames)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
operations := gatherOperations(analyzed, operationIDs)
|
||||
if len(operations) == 0 {
|
||||
return errors.New("no operations were selected")
|
||||
}
|
||||
|
||||
generator := appGenerator{
|
||||
Name: appNameOrDefault(specDoc, name, defaultClientName),
|
||||
SpecDoc: specDoc,
|
||||
Analyzed: analyzed,
|
||||
Models: models,
|
||||
Operations: operations,
|
||||
Target: opts.Target,
|
||||
DumpData: opts.DumpData,
|
||||
Package: opts.LanguageOpts.ManglePackageName(opts.ClientPackage, defaultClientTarget),
|
||||
APIPackage: opts.LanguageOpts.ManglePackagePath(opts.APIPackage, defaultOperationsTarget),
|
||||
ModelsPackage: opts.LanguageOpts.ManglePackagePath(opts.ModelPackage, defaultModelsTarget),
|
||||
ServerPackage: opts.LanguageOpts.ManglePackagePath(opts.ServerPackage, defaultServerTarget),
|
||||
ClientPackage: opts.LanguageOpts.ManglePackagePath(opts.ClientPackage, defaultClientTarget),
|
||||
OperationsPackage: opts.LanguageOpts.ManglePackagePath(opts.ClientPackage, defaultClientTarget),
|
||||
Principal: opts.PrincipalAlias(),
|
||||
DefaultScheme: opts.DefaultScheme,
|
||||
DefaultProduces: opts.DefaultProduces,
|
||||
DefaultConsumes: opts.DefaultConsumes,
|
||||
GenOpts: opts,
|
||||
}
|
||||
generator.Receiver = "o"
|
||||
return (&clientGenerator{generator}).Generate()
|
||||
}
|
||||
|
||||
type clientGenerator struct {
|
||||
appGenerator
|
||||
}
|
||||
|
||||
func (c *clientGenerator) Generate() error {
|
||||
app, err := c.makeCodegenApp()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.DumpData {
|
||||
return dumpData(swag.ToDynamicJSON(app))
|
||||
}
|
||||
|
||||
if c.GenOpts.IncludeModel {
|
||||
for _, m := range app.Models {
|
||||
if m.IsStream {
|
||||
continue
|
||||
}
|
||||
mod := m
|
||||
if err := c.GenOpts.renderDefinition(&mod); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if c.GenOpts.IncludeHandler {
|
||||
for _, g := range app.OperationGroups {
|
||||
opg := g
|
||||
for _, o := range opg.Operations {
|
||||
op := o
|
||||
if err := c.GenOpts.renderOperation(&op); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := c.GenOpts.renderOperationGroup(&opg); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if c.GenOpts.IncludeSupport {
|
||||
if err := c.GenOpts.renderApplication(&app); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
61
vendor/github.com/go-swagger/go-swagger/generator/config.go
generated
vendored
Normal file
61
vendor/github.com/go-swagger/go-swagger/generator/config.go
generated
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
package generator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// LanguageDefinition in the configuration file.
|
||||
type LanguageDefinition struct {
|
||||
Layout SectionOpts `mapstructure:"layout"`
|
||||
}
|
||||
|
||||
// ConfigureOpts for generation
|
||||
func (d *LanguageDefinition) ConfigureOpts(opts *GenOpts) error {
|
||||
opts.Sections = d.Layout
|
||||
if opts.LanguageOpts == nil {
|
||||
opts.LanguageOpts = GoLangOpts()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LanguageConfig structure that is obtained from parsing a config file
|
||||
type LanguageConfig map[string]LanguageDefinition
|
||||
|
||||
// ReadConfig at the specified path, when no path is specified it will look into
|
||||
// the current directory and load a .swagger.{yml,json,hcl,toml,properties} file
|
||||
// Returns a viper config or an error
|
||||
func ReadConfig(fpath string) (*viper.Viper, error) {
|
||||
v := viper.New()
|
||||
if fpath != "" {
|
||||
if !fileExists(fpath, "") {
|
||||
return nil, fmt.Errorf("can't find file for %q", fpath)
|
||||
}
|
||||
file, err := os.Open(fpath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() { _ = file.Close() }()
|
||||
ext := filepath.Ext(fpath)
|
||||
if len(ext) > 0 {
|
||||
ext = ext[1:]
|
||||
}
|
||||
v.SetConfigType(ext)
|
||||
if err := v.ReadConfig(file); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
v.SetConfigName(".swagger")
|
||||
v.AddConfigPath(".")
|
||||
if err := v.ReadInConfig(); err != nil {
|
||||
if _, ok := err.(viper.UnsupportedConfigError); !ok && v.ConfigFileUsed() != "" {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
64
vendor/github.com/go-swagger/go-swagger/generator/debug.go
generated
vendored
Normal file
64
vendor/github.com/go-swagger/go-swagger/generator/debug.go
generated
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// 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 generator
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
var (
|
||||
// Debug when the env var DEBUG or SWAGGER_DEBUG is not empty
|
||||
// the generators will be very noisy about what they are doing
|
||||
Debug = os.Getenv("DEBUG") != "" || os.Getenv("SWAGGER_DEBUG") != ""
|
||||
// generatorLogger is a debug logger for this package
|
||||
generatorLogger *log.Logger
|
||||
)
|
||||
|
||||
func debugOptions() {
|
||||
generatorLogger = log.New(os.Stdout, "generator:", log.LstdFlags)
|
||||
}
|
||||
|
||||
// debugLog wraps log.Printf with a debug-specific logger
|
||||
func debugLog(frmt string, args ...interface{}) {
|
||||
if Debug {
|
||||
_, file, pos, _ := runtime.Caller(1)
|
||||
generatorLogger.Printf("%s:%d: %s", filepath.Base(file), pos,
|
||||
fmt.Sprintf(frmt, args...))
|
||||
}
|
||||
}
|
||||
|
||||
// debugLogAsJSON unmarshals its last arg as pretty JSON
|
||||
func debugLogAsJSON(frmt string, args ...interface{}) {
|
||||
if Debug {
|
||||
var dfrmt string
|
||||
_, file, pos, _ := runtime.Caller(1)
|
||||
dargs := make([]interface{}, 0, len(args)+2)
|
||||
dargs = append(dargs, filepath.Base(file), pos)
|
||||
if len(args) > 0 {
|
||||
dfrmt = "%s:%d: " + frmt + "\n%s"
|
||||
bbb, _ := json.MarshalIndent(args[len(args)-1], "", " ")
|
||||
dargs = append(dargs, args[0:len(args)-1]...)
|
||||
dargs = append(dargs, string(bbb))
|
||||
} else {
|
||||
dfrmt = "%s:%d: " + frmt
|
||||
}
|
||||
generatorLogger.Printf(dfrmt, dargs...)
|
||||
}
|
||||
}
|
||||
75
vendor/github.com/go-swagger/go-swagger/generator/discriminators.go
generated
vendored
Normal file
75
vendor/github.com/go-swagger/go-swagger/generator/discriminators.go
generated
vendored
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
package generator
|
||||
|
||||
import (
|
||||
"github.com/go-openapi/analysis"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
type discInfo struct {
|
||||
Discriminators map[string]discor
|
||||
Discriminated map[string]discee
|
||||
}
|
||||
|
||||
type discor struct {
|
||||
FieldName string `json:"fieldName"`
|
||||
GoType string `json:"goType"`
|
||||
JSONName string `json:"jsonName"`
|
||||
Children []discee `json:"children"`
|
||||
}
|
||||
|
||||
type discee struct {
|
||||
FieldName string `json:"fieldName"`
|
||||
FieldValue string `json:"fieldValue"`
|
||||
GoType string `json:"goType"`
|
||||
JSONName string `json:"jsonName"`
|
||||
Ref spec.Ref `json:"ref"`
|
||||
ParentRef spec.Ref `json:"parentRef"`
|
||||
}
|
||||
|
||||
func discriminatorInfo(doc *analysis.Spec) *discInfo {
|
||||
baseTypes := make(map[string]discor)
|
||||
for _, sch := range doc.AllDefinitions() {
|
||||
if sch.Schema.Discriminator != "" {
|
||||
tpe, _ := sch.Schema.Extensions.GetString(xGoName)
|
||||
if tpe == "" {
|
||||
tpe = swag.ToGoName(sch.Name)
|
||||
}
|
||||
baseTypes[sch.Ref.String()] = discor{
|
||||
FieldName: sch.Schema.Discriminator,
|
||||
GoType: tpe,
|
||||
JSONName: sch.Name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
subTypes := make(map[string]discee)
|
||||
for _, sch := range doc.SchemasWithAllOf() {
|
||||
for _, ao := range sch.Schema.AllOf {
|
||||
if ao.Ref.String() != "" {
|
||||
if bt, ok := baseTypes[ao.Ref.String()]; ok {
|
||||
name, _ := sch.Schema.Extensions.GetString(xClass)
|
||||
if name == "" {
|
||||
name = sch.Name
|
||||
}
|
||||
tpe, _ := sch.Schema.Extensions.GetString(xGoName)
|
||||
if tpe == "" {
|
||||
tpe = swag.ToGoName(sch.Name)
|
||||
}
|
||||
dce := discee{
|
||||
FieldName: bt.FieldName,
|
||||
FieldValue: name,
|
||||
Ref: sch.Ref,
|
||||
ParentRef: ao.Ref,
|
||||
JSONName: sch.Name,
|
||||
GoType: tpe,
|
||||
}
|
||||
subTypes[sch.Ref.String()] = dce
|
||||
bt.Children = append(bt.Children, dce)
|
||||
baseTypes[ao.Ref.String()] = bt
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return &discInfo{Discriminators: baseTypes, Discriminated: subTypes}
|
||||
}
|
||||
78
vendor/github.com/go-swagger/go-swagger/generator/doc.go
generated
vendored
Normal file
78
vendor/github.com/go-swagger/go-swagger/generator/doc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// 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 generator provides the code generation library for go-swagger.
|
||||
|
||||
# Generating data types
|
||||
|
||||
The general idea is that you should rarely see interface{} in the generated code.
|
||||
You get a complete representation of a swagger document in somewhat idiomatic go.
|
||||
|
||||
To do so, there is a set of mapping patterns that are applied,
|
||||
to map a Swagger specification to go types:
|
||||
|
||||
definition of primitive => type alias/name
|
||||
definition of array => type alias/name
|
||||
definition of map => type alias/name
|
||||
|
||||
definition of object
|
||||
with properties => struct
|
||||
definition of $ref => type alias/name
|
||||
|
||||
object with only
|
||||
additional properties => map[string]T
|
||||
|
||||
object with additional
|
||||
properties and properties => custom serializer
|
||||
|
||||
schema with schema array
|
||||
in items => tuple (struct with properties, custom serializer)
|
||||
|
||||
schema with all of => struct
|
||||
|
||||
* allOf schema with $ref => embedded value
|
||||
* allOf schema with properties => properties are included in struct
|
||||
* adding an allOf schema with just "x-isnullable": true or
|
||||
"x-nullable": true turns the schema into a pointer when
|
||||
there are only other extension properties provided
|
||||
|
||||
NOTE: anyOf and oneOf JSON-schema constructs are not supported by Swagger 2.0
|
||||
|
||||
A property on a definition is a pointer when any one of the following conditions is met:
|
||||
|
||||
it is an object schema (struct)
|
||||
it has x-nullable or x-isnullable as vendor extension
|
||||
it is a primitive where the zero value is valid but would fail validation
|
||||
otherwise strings minLength > 0 or required results in non-pointer
|
||||
numbers min > 0, max < 0 and min < max
|
||||
|
||||
JSONSchema and by extension Swagger allow for items that have a fixed size array,
|
||||
with the schema describing the items at each index. This can be combined with additional items
|
||||
to form some kind of tuple with varargs.
|
||||
|
||||
To map this to go it creates a struct that has fixed names and a custom json serializer.
|
||||
|
||||
NOTE: the additionalItems keyword is not supported by Swagger 2.0. However, the generator and validator parts
|
||||
in go-swagger do.
|
||||
|
||||
# Documenting the generated code
|
||||
|
||||
The code that is generated also gets the doc comments that are used by the scanner
|
||||
to generate a spec from go code. So that after generation you should be able to reverse
|
||||
generate a spec from the code that was generated by your spec.
|
||||
|
||||
It should be equivalent to the original spec but might miss some default values and examples.
|
||||
*/
|
||||
package generator
|
||||
226
vendor/github.com/go-swagger/go-swagger/generator/formats.go
generated
vendored
Normal file
226
vendor/github.com/go-swagger/go-swagger/generator/formats.go
generated
vendored
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
// Copyright 2015 go-swagger maintainers
|
||||
//
|
||||
// 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 generator
|
||||
|
||||
// TODO: we may probably find a way to register most of this dynamically from strfmt
|
||||
|
||||
// map of function calls to be generated to get the zero value of a given type
|
||||
var zeroes = map[string]string{
|
||||
"bool": "false",
|
||||
"float32": "0",
|
||||
"float64": "0",
|
||||
"int": "0",
|
||||
"int8": "0",
|
||||
"int16": "0",
|
||||
"int32": "0",
|
||||
"int64": "0",
|
||||
"string": "\"\"",
|
||||
"uint": "0",
|
||||
"uint8": "0",
|
||||
"uint16": "0",
|
||||
"uint32": "0",
|
||||
"uint64": "0",
|
||||
// Extended formats (23 formats corresponding to the Default registry
|
||||
// provided by go-openapi/strfmt)
|
||||
"strfmt.Base64": "strfmt.Base64([]byte(nil))",
|
||||
"strfmt.CreditCard": "strfmt.CreditCard(\"\")",
|
||||
"strfmt.Date": "strfmt.Date{}",
|
||||
"strfmt.DateTime": "strfmt.DateTime{}",
|
||||
"strfmt.Duration": "strfmt.Duration(0)",
|
||||
"strfmt.Email": "strfmt.Email(\"\")",
|
||||
"strfmt.HexColor": "strfmt.HexColor(\"#000000\")",
|
||||
"strfmt.Hostname": "strfmt.Hostname(\"\")",
|
||||
"strfmt.IPv4": "strfmt.IPv4(\"\")",
|
||||
"strfmt.IPv6": "strfmt.IPv6(\"\")",
|
||||
"strfmt.ISBN": "strfmt.ISBN(\"\")",
|
||||
"strfmt.ISBN10": "strfmt.ISBN10(\"\")",
|
||||
"strfmt.ISBN13": "strfmt.ISBN13(\"\")",
|
||||
"strfmt.MAC": "strfmt.MAC(\"\")",
|
||||
"strfmt.ObjectId": "strfmt.ObjectId{}",
|
||||
"strfmt.Password": "strfmt.Password(\"\")",
|
||||
"strfmt.RGBColor": "strfmt.RGBColor(\"rgb(0,0,0)\")",
|
||||
"strfmt.SSN": "strfmt.SSN(\"\")",
|
||||
"strfmt.URI": "strfmt.URI(\"\")",
|
||||
"strfmt.UUID": "strfmt.UUID(\"\")",
|
||||
"strfmt.UUID3": "strfmt.UUID3(\"\")",
|
||||
"strfmt.UUID4": "strfmt.UUID4(\"\")",
|
||||
"strfmt.UUID5": "strfmt.UUID5(\"\")",
|
||||
// "file": "runtime.File",
|
||||
}
|
||||
|
||||
// conversion functions from string representation to a numerical or boolean
|
||||
// primitive type
|
||||
var stringConverters = map[string]string{
|
||||
"bool": "swag.ConvertBool",
|
||||
"float32": "swag.ConvertFloat32",
|
||||
"float64": "swag.ConvertFloat64",
|
||||
"int8": "swag.ConvertInt8",
|
||||
"int16": "swag.ConvertInt16",
|
||||
"int32": "swag.ConvertInt32",
|
||||
"int64": "swag.ConvertInt64",
|
||||
"uint8": "swag.ConvertUint8",
|
||||
"uint16": "swag.ConvertUint16",
|
||||
"uint32": "swag.ConvertUint32",
|
||||
"uint64": "swag.ConvertUint64",
|
||||
}
|
||||
|
||||
// formatting (string representation) functions from a native representation
|
||||
// of a numerical or boolean primitive type
|
||||
var stringFormatters = map[string]string{
|
||||
"bool": "swag.FormatBool",
|
||||
"float32": "swag.FormatFloat32",
|
||||
"float64": "swag.FormatFloat64",
|
||||
"int8": "swag.FormatInt8",
|
||||
"int16": "swag.FormatInt16",
|
||||
"int32": "swag.FormatInt32",
|
||||
"int64": "swag.FormatInt64",
|
||||
"uint8": "swag.FormatUint8",
|
||||
"uint16": "swag.FormatUint16",
|
||||
"uint32": "swag.FormatUint32",
|
||||
"uint64": "swag.FormatUint64",
|
||||
}
|
||||
|
||||
// typeMapping contains a mapping of type name to go type
|
||||
var typeMapping = map[string]string{
|
||||
// Standard formats with native, straightforward, mapping
|
||||
"string": "string",
|
||||
"boolean": "bool",
|
||||
"integer": "int64",
|
||||
"number": "float64",
|
||||
// For file producers
|
||||
"file": "runtime.File",
|
||||
}
|
||||
|
||||
// formatMapping contains a type-specific version of mapping of format to go type
|
||||
var formatMapping = map[string]map[string]string{
|
||||
"number": {
|
||||
"double": "float64",
|
||||
"float": "float32",
|
||||
"int": "int64",
|
||||
"int8": "int8",
|
||||
"int16": "int16",
|
||||
"int32": "int32",
|
||||
"int64": "int64",
|
||||
"uint": "uint64",
|
||||
"uint8": "uint8",
|
||||
"uint16": "uint16",
|
||||
"uint32": "uint32",
|
||||
"uint64": "uint64",
|
||||
},
|
||||
"integer": {
|
||||
"int": "int64",
|
||||
"int8": "int8",
|
||||
"int16": "int16",
|
||||
"int32": "int32",
|
||||
"int64": "int64",
|
||||
"uint": "uint64",
|
||||
"uint8": "uint8",
|
||||
"uint16": "uint16",
|
||||
"uint32": "uint32",
|
||||
"uint64": "uint64",
|
||||
},
|
||||
"string": {
|
||||
"char": "rune",
|
||||
// Extended format registry from go-openapi/strfmt.
|
||||
// Currently, 23 such formats are supported (default strftm registry),
|
||||
// plus the following aliases:
|
||||
// - "datetime" alias for the more official "date-time"
|
||||
// - "objectid" and "ObjectId" aliases for "bsonobjectid"
|
||||
"binary": "io.ReadCloser",
|
||||
"byte": "strfmt.Base64",
|
||||
"creditcard": "strfmt.CreditCard",
|
||||
"date": "strfmt.Date",
|
||||
"date-time": "strfmt.DateTime",
|
||||
"datetime": "strfmt.DateTime",
|
||||
"duration": "strfmt.Duration",
|
||||
"email": "strfmt.Email",
|
||||
"hexcolor": "strfmt.HexColor",
|
||||
"hostname": "strfmt.Hostname",
|
||||
"ipv4": "strfmt.IPv4",
|
||||
"ipv6": "strfmt.IPv6",
|
||||
"isbn": "strfmt.ISBN",
|
||||
"isbn10": "strfmt.ISBN10",
|
||||
"isbn13": "strfmt.ISBN13",
|
||||
"mac": "strfmt.MAC",
|
||||
"bsonobjectid": "strfmt.ObjectId",
|
||||
"objectid": "strfmt.ObjectId",
|
||||
"ObjectId": "strfmt.ObjectId", // NOTE: does it work with uppercase?
|
||||
"password": "strfmt.Password",
|
||||
"rgbcolor": "strfmt.RGBColor",
|
||||
"ssn": "strfmt.SSN",
|
||||
"uri": "strfmt.URI",
|
||||
"uuid": "strfmt.UUID",
|
||||
"uuid3": "strfmt.UUID3",
|
||||
"uuid4": "strfmt.UUID4",
|
||||
"uuid5": "strfmt.UUID5",
|
||||
// For file producers
|
||||
"file": "runtime.File",
|
||||
},
|
||||
}
|
||||
|
||||
// go primitive types
|
||||
var primitives = map[string]struct{}{
|
||||
"bool": {},
|
||||
"byte": {},
|
||||
"[]byte": {},
|
||||
"complex64": {},
|
||||
"complex128": {},
|
||||
"float32": {},
|
||||
"float64": {},
|
||||
"int": {},
|
||||
"int8": {},
|
||||
"int16": {},
|
||||
"int32": {},
|
||||
"int64": {},
|
||||
"rune": {},
|
||||
"string": {},
|
||||
"uint": {},
|
||||
"uint8": {},
|
||||
"uint16": {},
|
||||
"uint32": {},
|
||||
"uint64": {},
|
||||
}
|
||||
|
||||
// Formats with a custom formatter.
|
||||
// Currently, 23 such formats are supported
|
||||
var customFormatters = map[string]struct{}{
|
||||
"strfmt.Base64": {},
|
||||
"strfmt.CreditCard": {},
|
||||
"strfmt.Date": {},
|
||||
"strfmt.DateTime": {},
|
||||
"strfmt.Duration": {},
|
||||
"strfmt.Email": {},
|
||||
"strfmt.HexColor": {},
|
||||
"strfmt.Hostname": {},
|
||||
"strfmt.IPv4": {},
|
||||
"strfmt.IPv6": {},
|
||||
"strfmt.ISBN": {},
|
||||
"strfmt.ISBN10": {},
|
||||
"strfmt.ISBN13": {},
|
||||
"strfmt.MAC": {},
|
||||
"strfmt.ObjectId": {},
|
||||
"strfmt.Password": {},
|
||||
"strfmt.RGBColor": {},
|
||||
"strfmt.SSN": {},
|
||||
"strfmt.URI": {},
|
||||
"strfmt.UUID": {},
|
||||
"strfmt.UUID3": {},
|
||||
"strfmt.UUID4": {},
|
||||
"strfmt.UUID5": {},
|
||||
// the following interfaces do not generate validations
|
||||
"io.ReadCloser": {}, // for "format": "binary" (server side)
|
||||
"io.Writer": {}, // for "format": "binary" (client side)
|
||||
// NOTE: runtime.File is not a customFormatter
|
||||
}
|
||||
50
vendor/github.com/go-swagger/go-swagger/generator/genopts_nonwin.go
generated
vendored
Normal file
50
vendor/github.com/go-swagger/go-swagger/generator/genopts_nonwin.go
generated
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package generator
|
||||
|
||||
import (
|
||||
"log"
|
||||
"plugin"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
type GenOpts struct {
|
||||
GenOptsCommon
|
||||
TemplatePlugin string
|
||||
}
|
||||
|
||||
func (g *GenOpts) setTemplates() error {
|
||||
if g.TemplatePlugin != "" {
|
||||
if err := g.templates.LoadPlugin(g.TemplatePlugin); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return g.GenOptsCommon.setTemplates()
|
||||
}
|
||||
|
||||
// LoadPlugin will load the named plugin and inject its functions into the funcMap
|
||||
//
|
||||
// The plugin must implement a function matching the signature:
|
||||
// `func AddFuncs(f template.FuncMap)`
|
||||
// which can add any number of functions to the template repository funcMap.
|
||||
// Any existing sprig or go-swagger templates with the same name will be overridden.
|
||||
func (t *Repository) LoadPlugin(pluginPath string) error {
|
||||
log.Printf("Attempting to load template plugin: %s", pluginPath)
|
||||
|
||||
p, err := plugin.Open(pluginPath)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
f, err := p.Lookup("AddFuncs")
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
f.(func(template.FuncMap))(t.funcs)
|
||||
return nil
|
||||
}
|
||||
12
vendor/github.com/go-swagger/go-swagger/generator/genopts_win.go
generated
vendored
Normal file
12
vendor/github.com/go-swagger/go-swagger/generator/genopts_win.go
generated
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package generator
|
||||
|
||||
type GenOpts struct {
|
||||
GenOptsCommon
|
||||
}
|
||||
|
||||
func (g *GenOpts) setTemplates() error {
|
||||
return g.GenOptsCommon.setTemplates()
|
||||
}
|
||||
440
vendor/github.com/go-swagger/go-swagger/generator/language.go
generated
vendored
Normal file
440
vendor/github.com/go-swagger/go-swagger/generator/language.go
generated
vendored
Normal file
|
|
@ -0,0 +1,440 @@
|
|||
package generator
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
goruntime "runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
"golang.org/x/tools/imports"
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultLanguageFunc defines the default generation language
|
||||
DefaultLanguageFunc func() *LanguageOpts
|
||||
|
||||
moduleRe *regexp.Regexp
|
||||
)
|
||||
|
||||
func initLanguage() {
|
||||
DefaultLanguageFunc = GoLangOpts
|
||||
|
||||
moduleRe = regexp.MustCompile(`module[ \t]+([^\s]+)`)
|
||||
}
|
||||
|
||||
// LanguageOpts to describe a language to the code generator
|
||||
type LanguageOpts struct {
|
||||
ReservedWords []string
|
||||
BaseImportFunc func(string) string `json:"-"`
|
||||
ImportsFunc func(map[string]string) string `json:"-"`
|
||||
ArrayInitializerFunc func(interface{}) (string, error) `json:"-"`
|
||||
reservedWordsSet map[string]struct{}
|
||||
initialized bool
|
||||
formatFunc func(string, []byte) ([]byte, error)
|
||||
fileNameFunc func(string) string // language specific source file naming rules
|
||||
dirNameFunc func(string) string // language specific directory naming rules
|
||||
}
|
||||
|
||||
// Init the language option
|
||||
func (l *LanguageOpts) Init() {
|
||||
if l.initialized {
|
||||
return
|
||||
}
|
||||
l.initialized = true
|
||||
l.reservedWordsSet = make(map[string]struct{})
|
||||
for _, rw := range l.ReservedWords {
|
||||
l.reservedWordsSet[rw] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
// MangleName makes sure a reserved word gets a safe name
|
||||
func (l *LanguageOpts) MangleName(name, suffix string) string {
|
||||
if _, ok := l.reservedWordsSet[swag.ToFileName(name)]; !ok {
|
||||
return name
|
||||
}
|
||||
return strings.Join([]string{name, suffix}, "_")
|
||||
}
|
||||
|
||||
// MangleVarName makes sure a reserved word gets a safe name
|
||||
func (l *LanguageOpts) MangleVarName(name string) string {
|
||||
nm := swag.ToVarName(name)
|
||||
if _, ok := l.reservedWordsSet[nm]; !ok {
|
||||
return nm
|
||||
}
|
||||
return nm + "Var"
|
||||
}
|
||||
|
||||
// MangleFileName makes sure a file name gets a safe name
|
||||
func (l *LanguageOpts) MangleFileName(name string) string {
|
||||
if l.fileNameFunc != nil {
|
||||
return l.fileNameFunc(name)
|
||||
}
|
||||
return swag.ToFileName(name)
|
||||
}
|
||||
|
||||
// ManglePackageName makes sure a package gets a safe name.
|
||||
// In case of a file system path (e.g. name contains "/" or "\" on Windows), this return only the last element.
|
||||
func (l *LanguageOpts) ManglePackageName(name, suffix string) string {
|
||||
if name == "" {
|
||||
return suffix
|
||||
}
|
||||
if l.dirNameFunc != nil {
|
||||
name = l.dirNameFunc(name)
|
||||
}
|
||||
pth := filepath.ToSlash(filepath.Clean(name)) // preserve path
|
||||
pkg := importAlias(pth) // drop path
|
||||
return l.MangleName(swag.ToFileName(prefixForName(pkg)+pkg), suffix)
|
||||
}
|
||||
|
||||
// ManglePackagePath makes sure a full package path gets a safe name.
|
||||
// Only the last part of the path is altered.
|
||||
func (l *LanguageOpts) ManglePackagePath(name string, suffix string) string {
|
||||
if name == "" {
|
||||
return suffix
|
||||
}
|
||||
target := filepath.ToSlash(filepath.Clean(name)) // preserve path
|
||||
parts := strings.Split(target, "/")
|
||||
parts[len(parts)-1] = l.ManglePackageName(parts[len(parts)-1], suffix)
|
||||
return strings.Join(parts, "/")
|
||||
}
|
||||
|
||||
// FormatContent formats a file with a language specific formatter
|
||||
func (l *LanguageOpts) FormatContent(name string, content []byte) ([]byte, error) {
|
||||
if l.formatFunc != nil {
|
||||
return l.formatFunc(name, content)
|
||||
}
|
||||
return content, nil
|
||||
}
|
||||
|
||||
// imports generate the code to import some external packages, possibly aliased
|
||||
func (l *LanguageOpts) imports(imports map[string]string) string {
|
||||
if l.ImportsFunc != nil {
|
||||
return l.ImportsFunc(imports)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// arrayInitializer builds a litteral array
|
||||
func (l *LanguageOpts) arrayInitializer(data interface{}) (string, error) {
|
||||
if l.ArrayInitializerFunc != nil {
|
||||
return l.ArrayInitializerFunc(data)
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// baseImport figures out the base path to generate import statements
|
||||
func (l *LanguageOpts) baseImport(tgt string) string {
|
||||
if l.BaseImportFunc != nil {
|
||||
return l.BaseImportFunc(tgt)
|
||||
}
|
||||
debugLog("base import func is nil")
|
||||
return ""
|
||||
}
|
||||
|
||||
// GoLangOpts for rendering items as golang code
|
||||
func GoLangOpts() *LanguageOpts {
|
||||
var goOtherReservedSuffixes = map[string]bool{
|
||||
// see:
|
||||
// https://golang.org/src/go/build/syslist.go
|
||||
// https://golang.org/doc/install/source#environment
|
||||
|
||||
// goos
|
||||
"aix": true,
|
||||
"android": true,
|
||||
"darwin": true,
|
||||
"dragonfly": true,
|
||||
"freebsd": true,
|
||||
"hurd": true,
|
||||
"illumos": true,
|
||||
"js": true,
|
||||
"linux": true,
|
||||
"nacl": true,
|
||||
"netbsd": true,
|
||||
"openbsd": true,
|
||||
"plan9": true,
|
||||
"solaris": true,
|
||||
"windows": true,
|
||||
"zos": true,
|
||||
|
||||
// arch
|
||||
"386": true,
|
||||
"amd64": true,
|
||||
"amd64p32": true,
|
||||
"arm": true,
|
||||
"armbe": true,
|
||||
"arm64": true,
|
||||
"arm64be": true,
|
||||
"mips": true,
|
||||
"mipsle": true,
|
||||
"mips64": true,
|
||||
"mips64le": true,
|
||||
"mips64p32": true,
|
||||
"mips64p32le": true,
|
||||
"ppc": true,
|
||||
"ppc64": true,
|
||||
"ppc64le": true,
|
||||
"riscv": true,
|
||||
"riscv64": true,
|
||||
"s390": true,
|
||||
"s390x": true,
|
||||
"sparc": true,
|
||||
"sparc64": true,
|
||||
"wasm": true,
|
||||
|
||||
// other reserved suffixes
|
||||
"test": true,
|
||||
}
|
||||
|
||||
opts := new(LanguageOpts)
|
||||
opts.ReservedWords = []string{
|
||||
"break", "default", "func", "interface", "select",
|
||||
"case", "defer", "go", "map", "struct",
|
||||
"chan", "else", "goto", "package", "switch",
|
||||
"const", "fallthrough", "if", "range", "type",
|
||||
"continue", "for", "import", "return", "var",
|
||||
}
|
||||
|
||||
opts.formatFunc = func(ffn string, content []byte) ([]byte, error) {
|
||||
opts := new(imports.Options)
|
||||
opts.TabIndent = true
|
||||
opts.TabWidth = 2
|
||||
opts.Fragment = true
|
||||
opts.Comments = true
|
||||
return imports.Process(ffn, content, opts)
|
||||
}
|
||||
|
||||
opts.fileNameFunc = func(name string) string {
|
||||
// whenever a generated file name ends with a suffix
|
||||
// that is meaningful to go build, adds a "swagger"
|
||||
// suffix
|
||||
parts := strings.Split(swag.ToFileName(name), "_")
|
||||
if goOtherReservedSuffixes[parts[len(parts)-1]] {
|
||||
// file name ending with a reserved arch or os name
|
||||
// are appended an innocuous suffix "swagger"
|
||||
parts = append(parts, "swagger")
|
||||
}
|
||||
return strings.Join(parts, "_")
|
||||
}
|
||||
|
||||
opts.dirNameFunc = func(name string) string {
|
||||
// whenever a generated directory name is a special
|
||||
// golang directory, append an innocuous suffix
|
||||
switch name {
|
||||
case "vendor", "internal":
|
||||
return strings.Join([]string{name, "swagger"}, "_")
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
opts.ImportsFunc = func(imports map[string]string) string {
|
||||
if len(imports) == 0 {
|
||||
return ""
|
||||
}
|
||||
result := make([]string, 0, len(imports))
|
||||
for k, v := range imports {
|
||||
_, name := path.Split(v)
|
||||
if name != k {
|
||||
result = append(result, fmt.Sprintf("\t%s %q", k, v))
|
||||
} else {
|
||||
result = append(result, fmt.Sprintf("\t%q", v))
|
||||
}
|
||||
}
|
||||
sort.Strings(result)
|
||||
return strings.Join(result, "\n")
|
||||
}
|
||||
|
||||
opts.ArrayInitializerFunc = func(data interface{}) (string, error) {
|
||||
// ArrayInitializer constructs a Go literal initializer from interface{} literals.
|
||||
// e.g. []interface{}{"a", "b"} is transformed in {"a","b",}
|
||||
// e.g. map[string]interface{}{ "a": "x", "b": "y"} is transformed in {"a":"x","b":"y",}.
|
||||
//
|
||||
// NOTE: this is currently used to construct simple slice intializers for default values.
|
||||
// This allows for nicer slice initializers for slices of primitive types and avoid systematic use for json.Unmarshal().
|
||||
b, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(string(b), "}", ",}"), "[", "{"), "]", ",}"), "{,}", "{}"), nil
|
||||
}
|
||||
|
||||
opts.BaseImportFunc = func(tgt string) string {
|
||||
tgt = filepath.Clean(tgt)
|
||||
// On Windows, filepath.Abs("") behaves differently than on Unix.
|
||||
// Windows: yields an error, since Abs() does not know the volume.
|
||||
// UNIX: returns current working directory
|
||||
if tgt == "" {
|
||||
tgt = "."
|
||||
}
|
||||
tgtAbsPath, err := filepath.Abs(tgt)
|
||||
if err != nil {
|
||||
log.Fatalf("could not evaluate base import path with target \"%s\": %v", tgt, err)
|
||||
}
|
||||
|
||||
var tgtAbsPathExtended string
|
||||
tgtAbsPathExtended, err = filepath.EvalSymlinks(tgtAbsPath)
|
||||
if err != nil {
|
||||
log.Fatalf("could not evaluate base import path with target \"%s\" (with symlink resolution): %v", tgtAbsPath, err)
|
||||
}
|
||||
|
||||
gopath := os.Getenv("GOPATH")
|
||||
if gopath == "" {
|
||||
homeDir, herr := os.UserHomeDir()
|
||||
if herr != nil {
|
||||
log.Fatalln(herr)
|
||||
}
|
||||
gopath = filepath.Join(homeDir, "go")
|
||||
}
|
||||
|
||||
var pth string
|
||||
for _, gp := range filepath.SplitList(gopath) {
|
||||
if _, derr := os.Stat(filepath.Join(gp, "src")); os.IsNotExist(derr) {
|
||||
continue
|
||||
}
|
||||
// EvalSymLinks also calls the Clean
|
||||
gopathExtended, er := filepath.EvalSymlinks(gp)
|
||||
if er != nil {
|
||||
panic(er)
|
||||
}
|
||||
gopathExtended = filepath.Join(gopathExtended, "src")
|
||||
gp = filepath.Join(gp, "src")
|
||||
|
||||
// At this stage we have expanded and unexpanded target path. GOPATH is fully expanded.
|
||||
// Expanded means symlink free.
|
||||
// We compare both types of targetpath<s> with gopath.
|
||||
// If any one of them coincides with gopath , it is imperative that
|
||||
// target path lies inside gopath. How?
|
||||
// - Case 1: Irrespective of symlinks paths coincide. Both non-expanded paths.
|
||||
// - Case 2: Symlink in target path points to location inside GOPATH. (Expanded Target Path)
|
||||
// - Case 3: Symlink in target path points to directory outside GOPATH (Unexpanded target path)
|
||||
|
||||
// Case 1: - Do nothing case. If non-expanded paths match just generate base import path as if
|
||||
// there are no symlinks.
|
||||
|
||||
// Case 2: - Symlink in target path points to location inside GOPATH. (Expanded Target Path)
|
||||
// First if will fail. Second if will succeed.
|
||||
|
||||
// Case 3: - Symlink in target path points to directory outside GOPATH (Unexpanded target path)
|
||||
// First if will succeed and break.
|
||||
|
||||
// compares non expanded path for both
|
||||
if ok, relativepath := checkPrefixAndFetchRelativePath(tgtAbsPath, gp); ok {
|
||||
pth = relativepath
|
||||
break
|
||||
}
|
||||
|
||||
// Compares non-expanded target path
|
||||
if ok, relativepath := checkPrefixAndFetchRelativePath(tgtAbsPath, gopathExtended); ok {
|
||||
pth = relativepath
|
||||
break
|
||||
}
|
||||
|
||||
// Compares expanded target path.
|
||||
if ok, relativepath := checkPrefixAndFetchRelativePath(tgtAbsPathExtended, gopathExtended); ok {
|
||||
pth = relativepath
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mod, goModuleAbsPath, err := tryResolveModule(tgtAbsPath)
|
||||
switch {
|
||||
case err != nil:
|
||||
log.Fatalf("Failed to resolve module using go.mod file: %s", err)
|
||||
case mod != "":
|
||||
relTgt := relPathToRelGoPath(goModuleAbsPath, tgtAbsPath)
|
||||
if !strings.HasSuffix(mod, relTgt) {
|
||||
return filepath.ToSlash(mod + relTgt)
|
||||
}
|
||||
return filepath.ToSlash(mod)
|
||||
}
|
||||
|
||||
if pth == "" {
|
||||
log.Fatalln("target must reside inside a location in the $GOPATH/src or be a module")
|
||||
}
|
||||
return filepath.ToSlash(pth)
|
||||
}
|
||||
opts.Init()
|
||||
return opts
|
||||
}
|
||||
|
||||
// resolveGoModFile walks up the directory tree starting from 'dir' until it
|
||||
// finds a go.mod file. If go.mod is found it will return the related file
|
||||
// object. If no go.mod file is found it will return an error.
|
||||
func resolveGoModFile(dir string) (*os.File, string, error) {
|
||||
goModPath := filepath.Join(dir, "go.mod")
|
||||
f, err := os.Open(goModPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) && dir != filepath.Dir(dir) {
|
||||
return resolveGoModFile(filepath.Dir(dir))
|
||||
}
|
||||
return nil, "", err
|
||||
}
|
||||
return f, dir, nil
|
||||
}
|
||||
|
||||
// relPathToRelGoPath takes a relative os path and returns the relative go
|
||||
// package path. For unix nothing will change but for windows \ will be
|
||||
// converted to /.
|
||||
func relPathToRelGoPath(modAbsPath, absPath string) string {
|
||||
if absPath == "." {
|
||||
return ""
|
||||
}
|
||||
|
||||
path := strings.TrimPrefix(absPath, modAbsPath)
|
||||
pathItems := strings.Split(path, string(filepath.Separator))
|
||||
return strings.Join(pathItems, "/")
|
||||
}
|
||||
|
||||
func tryResolveModule(baseTargetPath string) (string, string, error) {
|
||||
f, goModAbsPath, err := resolveGoModFile(baseTargetPath)
|
||||
switch {
|
||||
case os.IsNotExist(err):
|
||||
return "", "", nil
|
||||
case err != nil:
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
src, err := io.ReadAll(f)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
match := moduleRe.FindSubmatch(src)
|
||||
if len(match) != 2 {
|
||||
return "", "", nil
|
||||
}
|
||||
|
||||
return string(match[1]), goModAbsPath, nil
|
||||
}
|
||||
|
||||
// 1. Checks if the child path and parent path coincide.
|
||||
// 2. If they do return child path relative to parent path.
|
||||
// 3. Everything else return false
|
||||
func checkPrefixAndFetchRelativePath(childpath string, parentpath string) (bool, string) {
|
||||
// Windows (local) file systems - NTFS, as well as FAT and variants
|
||||
// are case insensitive.
|
||||
cp, pp := childpath, parentpath
|
||||
if goruntime.GOOS == "windows" {
|
||||
cp = strings.ToLower(cp)
|
||||
pp = strings.ToLower(pp)
|
||||
}
|
||||
|
||||
if strings.HasPrefix(cp, pp) {
|
||||
pth, err := filepath.Rel(parentpath, childpath)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
return true, pth
|
||||
}
|
||||
|
||||
return false, ""
|
||||
|
||||
}
|
||||
191
vendor/github.com/go-swagger/go-swagger/generator/media.go
generated
vendored
Normal file
191
vendor/github.com/go-swagger/go-swagger/generator/media.go
generated
vendored
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
package generator
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
const jsonSerializer = "json"
|
||||
|
||||
var mediaTypeNames = map[*regexp.Regexp]string{
|
||||
regexp.MustCompile("application/.*json"): jsonSerializer,
|
||||
regexp.MustCompile("application/.*yaml"): "yaml",
|
||||
regexp.MustCompile("application/.*protobuf"): "protobuf",
|
||||
regexp.MustCompile("application/.*capnproto"): "capnproto",
|
||||
regexp.MustCompile("application/.*thrift"): "thrift",
|
||||
regexp.MustCompile("(?:application|text)/.*xml"): "xml",
|
||||
regexp.MustCompile("text/.*markdown"): "markdown",
|
||||
regexp.MustCompile("text/.*html"): "html",
|
||||
regexp.MustCompile("text/.*csv"): "csv",
|
||||
regexp.MustCompile("text/.*tsv"): "tsv",
|
||||
regexp.MustCompile("text/.*javascript"): "js",
|
||||
regexp.MustCompile("text/.*css"): "css",
|
||||
regexp.MustCompile("text/.*plain"): "txt",
|
||||
regexp.MustCompile("application/.*octet-stream"): "bin",
|
||||
regexp.MustCompile("application/.*tar"): "tar",
|
||||
regexp.MustCompile("application/.*gzip"): "gzip",
|
||||
regexp.MustCompile("application/.*gz"): "gzip",
|
||||
regexp.MustCompile("application/.*raw-stream"): "bin",
|
||||
regexp.MustCompile("application/x-www-form-urlencoded"): "urlform",
|
||||
regexp.MustCompile("application/javascript"): "txt",
|
||||
regexp.MustCompile("multipart/form-data"): "multipartform",
|
||||
regexp.MustCompile("image/.*"): "bin",
|
||||
regexp.MustCompile("audio/.*"): "bin",
|
||||
regexp.MustCompile("application/pdf"): "bin",
|
||||
}
|
||||
|
||||
var knownProducers = map[string]string{
|
||||
jsonSerializer: "runtime.JSONProducer()",
|
||||
"yaml": "yamlpc.YAMLProducer()",
|
||||
"xml": "runtime.XMLProducer()",
|
||||
"txt": "runtime.TextProducer()",
|
||||
"bin": "runtime.ByteStreamProducer()",
|
||||
"urlform": "runtime.DiscardProducer",
|
||||
"multipartform": "runtime.DiscardProducer",
|
||||
}
|
||||
|
||||
var knownConsumers = map[string]string{
|
||||
jsonSerializer: "runtime.JSONConsumer()",
|
||||
"yaml": "yamlpc.YAMLConsumer()",
|
||||
"xml": "runtime.XMLConsumer()",
|
||||
"txt": "runtime.TextConsumer()",
|
||||
"bin": "runtime.ByteStreamConsumer()",
|
||||
"urlform": "runtime.DiscardConsumer",
|
||||
"multipartform": "runtime.DiscardConsumer",
|
||||
}
|
||||
|
||||
func wellKnownMime(tn string) (string, bool) {
|
||||
for k, v := range mediaTypeNames {
|
||||
if k.MatchString(tn) {
|
||||
return v, true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
func mediaMime(orig string) string {
|
||||
return strings.SplitN(orig, ";", 2)[0]
|
||||
}
|
||||
|
||||
func mediaParameters(orig string) string {
|
||||
parts := strings.SplitN(orig, ";", 2)
|
||||
if len(parts) < 2 {
|
||||
return ""
|
||||
}
|
||||
return parts[1]
|
||||
}
|
||||
|
||||
func (a *appGenerator) makeSerializers(mediaTypes []string, known func(string) (string, bool)) (GenSerGroups, bool) {
|
||||
supportsJSON := false
|
||||
uniqueSerializers := make(map[string]*GenSerializer, len(mediaTypes))
|
||||
uniqueSerializerGroups := make(map[string]*GenSerGroup, len(mediaTypes))
|
||||
|
||||
// build all required serializers
|
||||
for _, media := range mediaTypes {
|
||||
key := mediaMime(media)
|
||||
nm, ok := wellKnownMime(key)
|
||||
if !ok {
|
||||
// keep this serializer named, even though its implementation is empty (cf. #1557)
|
||||
nm = key
|
||||
}
|
||||
name := swag.ToJSONName(nm)
|
||||
impl, _ := known(name)
|
||||
|
||||
ser, ok := uniqueSerializers[key]
|
||||
if !ok {
|
||||
ser = &GenSerializer{
|
||||
AppName: a.Name,
|
||||
ReceiverName: a.Receiver,
|
||||
Name: name,
|
||||
MediaType: key,
|
||||
Implementation: impl,
|
||||
Parameters: []string{},
|
||||
}
|
||||
uniqueSerializers[key] = ser
|
||||
}
|
||||
// provide all known parameters (currently unused by codegen templates)
|
||||
if params := strings.TrimSpace(mediaParameters(media)); params != "" {
|
||||
found := false
|
||||
for _, p := range ser.Parameters {
|
||||
if params == p {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
ser.Parameters = append(ser.Parameters, params)
|
||||
}
|
||||
}
|
||||
|
||||
uniqueSerializerGroups[name] = &GenSerGroup{
|
||||
GenSerializer: GenSerializer{
|
||||
AppName: a.Name,
|
||||
ReceiverName: a.Receiver,
|
||||
Name: name,
|
||||
Implementation: impl,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if len(uniqueSerializers) == 0 {
|
||||
impl, _ := known(jsonSerializer)
|
||||
uniqueSerializers[runtime.JSONMime] = &GenSerializer{
|
||||
AppName: a.Name,
|
||||
ReceiverName: a.Receiver,
|
||||
Name: jsonSerializer,
|
||||
MediaType: runtime.JSONMime,
|
||||
Implementation: impl,
|
||||
Parameters: []string{},
|
||||
}
|
||||
uniqueSerializerGroups[jsonSerializer] = &GenSerGroup{
|
||||
GenSerializer: GenSerializer{
|
||||
AppName: a.Name,
|
||||
ReceiverName: a.Receiver,
|
||||
Name: jsonSerializer,
|
||||
Implementation: impl,
|
||||
},
|
||||
}
|
||||
supportsJSON = true
|
||||
}
|
||||
|
||||
// group serializers by consumer/producer to serve several mime media types
|
||||
serializerGroups := make(GenSerGroups, 0, len(uniqueSerializers))
|
||||
|
||||
for _, group := range uniqueSerializerGroups {
|
||||
if group.Name == jsonSerializer {
|
||||
supportsJSON = true
|
||||
}
|
||||
serializers := make(GenSerializers, 0, len(uniqueSerializers))
|
||||
for _, ser := range uniqueSerializers {
|
||||
if group.Name == ser.Name {
|
||||
sort.Strings(ser.Parameters)
|
||||
serializers = append(serializers, *ser)
|
||||
}
|
||||
}
|
||||
sort.Sort(serializers)
|
||||
group.AllSerializers = serializers // provides the full list of mime media types for this serializer group
|
||||
serializerGroups = append(serializerGroups, *group)
|
||||
}
|
||||
sort.Sort(serializerGroups)
|
||||
return serializerGroups, supportsJSON
|
||||
}
|
||||
|
||||
func (a *appGenerator) makeConsumes() (GenSerGroups, bool) {
|
||||
// builds a codegen struct from all consumes in the spec
|
||||
return a.makeSerializers(a.Analyzed.RequiredConsumes(), func(media string) (string, bool) {
|
||||
c, ok := knownConsumers[media]
|
||||
return c, ok
|
||||
})
|
||||
}
|
||||
|
||||
func (a *appGenerator) makeProduces() (GenSerGroups, bool) {
|
||||
// builds a codegen struct from all produces in the spec
|
||||
return a.makeSerializers(a.Analyzed.RequiredProduces(), func(media string) (string, bool) {
|
||||
p, ok := knownProducers[media]
|
||||
return p, ok
|
||||
})
|
||||
}
|
||||
2118
vendor/github.com/go-swagger/go-swagger/generator/model.go
generated
vendored
Normal file
2118
vendor/github.com/go-swagger/go-swagger/generator/model.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
1303
vendor/github.com/go-swagger/go-swagger/generator/operation.go
generated
vendored
Normal file
1303
vendor/github.com/go-swagger/go-swagger/generator/operation.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
1096
vendor/github.com/go-swagger/go-swagger/generator/shared.go
generated
vendored
Normal file
1096
vendor/github.com/go-swagger/go-swagger/generator/shared.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
273
vendor/github.com/go-swagger/go-swagger/generator/spec.go
generated
vendored
Normal file
273
vendor/github.com/go-swagger/go-swagger/generator/spec.go
generated
vendored
Normal file
|
|
@ -0,0 +1,273 @@
|
|||
package generator
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/go-openapi/analysis"
|
||||
swaggererrors "github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/validate"
|
||||
|
||||
yamlv2 "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
func (g *GenOpts) validateAndFlattenSpec() (*loads.Document, error) {
|
||||
// Load spec document
|
||||
specDoc, err := loads.Spec(g.Spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If accepts definitions only, add dummy swagger header to pass validation
|
||||
if g.AcceptDefinitionsOnly {
|
||||
specDoc, err = applyDefaultSwagger(specDoc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Validate if needed
|
||||
if g.ValidateSpec {
|
||||
log.Printf("validating spec %v", g.Spec)
|
||||
validationErrors := validate.Spec(specDoc, strfmt.Default)
|
||||
if validationErrors != nil {
|
||||
str := fmt.Sprintf("The swagger spec at %q is invalid against swagger specification %s. see errors :\n",
|
||||
g.Spec, specDoc.Version())
|
||||
for _, desc := range validationErrors.(*swaggererrors.CompositeError).Errors {
|
||||
str += fmt.Sprintf("- %s\n", desc)
|
||||
}
|
||||
return nil, errors.New(str)
|
||||
}
|
||||
// TODO(fredbi): due to uncontrolled $ref state in spec, we need to reload the spec atm, or flatten won't
|
||||
// work properly (validate expansion alters the $ref cache in go-openapi/spec)
|
||||
specDoc, _ = loads.Spec(g.Spec)
|
||||
}
|
||||
|
||||
// Flatten spec
|
||||
//
|
||||
// Some preprocessing is required before codegen
|
||||
//
|
||||
// This ensures at least that $ref's in the spec document are canonical,
|
||||
// i.e all $ref are local to this file and point to some uniquely named definition.
|
||||
//
|
||||
// Default option is to ensure minimal flattening of $ref, bundling remote $refs and relocating arbitrary JSON
|
||||
// pointers as definitions.
|
||||
// This preprocessing may introduce duplicate names (e.g. remote $ref with same name). In this case, a definition
|
||||
// suffixed with "OAIGen" is produced.
|
||||
//
|
||||
// Full flattening option farther transforms the spec by moving every complex object (e.g. with some properties)
|
||||
// as a standalone definition.
|
||||
//
|
||||
// Eventually, an "expand spec" option is available. It is essentially useful for testing purposes.
|
||||
//
|
||||
// NOTE(fredbi): spec expansion may produce some unsupported constructs and is not yet protected against the
|
||||
// following cases:
|
||||
// - polymorphic types generation may fail with expansion (expand destructs the reuse intent of the $ref in allOf)
|
||||
// - name duplicates may occur and result in compilation failures
|
||||
//
|
||||
// The right place to fix these shortcomings is go-openapi/analysis.
|
||||
|
||||
g.FlattenOpts.BasePath = specDoc.SpecFilePath()
|
||||
g.FlattenOpts.Spec = analysis.New(specDoc.Spec())
|
||||
|
||||
g.printFlattenOpts()
|
||||
|
||||
if err = analysis.Flatten(*g.FlattenOpts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// yields the preprocessed spec document
|
||||
return specDoc, nil
|
||||
}
|
||||
|
||||
func (g *GenOpts) analyzeSpec() (*loads.Document, *analysis.Spec, error) {
|
||||
// load, validate and flatten
|
||||
specDoc, err := g.validateAndFlattenSpec()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// spec preprocessing option
|
||||
if g.PropertiesSpecOrder {
|
||||
g.Spec = WithAutoXOrder(g.Spec)
|
||||
specDoc, err = loads.Spec(g.Spec)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// analyze the spec
|
||||
analyzed := analysis.New(specDoc.Spec())
|
||||
|
||||
return specDoc, analyzed, nil
|
||||
}
|
||||
|
||||
func (g *GenOpts) printFlattenOpts() {
|
||||
var preprocessingOption string
|
||||
switch {
|
||||
case g.FlattenOpts.Expand:
|
||||
preprocessingOption = "expand"
|
||||
case g.FlattenOpts.Minimal:
|
||||
preprocessingOption = "minimal flattening"
|
||||
default:
|
||||
preprocessingOption = "full flattening"
|
||||
}
|
||||
log.Printf("preprocessing spec with option: %s", preprocessingOption)
|
||||
}
|
||||
|
||||
// findSwaggerSpec fetches a default swagger spec if none is provided
|
||||
func findSwaggerSpec(nm string) (string, error) {
|
||||
specs := []string{"swagger.json", "swagger.yml", "swagger.yaml"}
|
||||
if nm != "" {
|
||||
specs = []string{nm}
|
||||
}
|
||||
var name string
|
||||
for _, nn := range specs {
|
||||
f, err := os.Stat(nn)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
continue
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
if f.IsDir() {
|
||||
return "", fmt.Errorf("%s is a directory", nn)
|
||||
}
|
||||
name = nn
|
||||
break
|
||||
}
|
||||
if name == "" {
|
||||
return "", errors.New("couldn't find a swagger spec")
|
||||
}
|
||||
return name, nil
|
||||
}
|
||||
|
||||
// WithAutoXOrder amends the spec to specify property order as they appear
|
||||
// in the spec (supports yaml documents only).
|
||||
func WithAutoXOrder(specPath string) string {
|
||||
lookFor := func(ele interface{}, key string) (yamlv2.MapSlice, bool) {
|
||||
if slice, ok := ele.(yamlv2.MapSlice); ok {
|
||||
for _, v := range slice {
|
||||
if v.Key == key {
|
||||
if slice, ok := v.Value.(yamlv2.MapSlice); ok {
|
||||
return slice, ok
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
var addXOrder func(interface{})
|
||||
addXOrder = func(element interface{}) {
|
||||
if props, ok := lookFor(element, "properties"); ok {
|
||||
for i, prop := range props {
|
||||
if pSlice, ok := prop.Value.(yamlv2.MapSlice); ok {
|
||||
isObject := false
|
||||
xOrderIndex := -1 // find if x-order already exists
|
||||
|
||||
for i, v := range pSlice {
|
||||
if v.Key == "type" && v.Value == object {
|
||||
isObject = true
|
||||
}
|
||||
if v.Key == xOrder {
|
||||
xOrderIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if xOrderIndex > -1 { // override existing x-order
|
||||
pSlice[xOrderIndex] = yamlv2.MapItem{Key: xOrder, Value: i}
|
||||
} else { // append new x-order
|
||||
pSlice = append(pSlice, yamlv2.MapItem{Key: xOrder, Value: i})
|
||||
}
|
||||
prop.Value = pSlice
|
||||
props[i] = prop
|
||||
|
||||
if isObject {
|
||||
addXOrder(pSlice)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data, err := swag.LoadFromFileOrHTTP(specPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
yamlDoc, err := BytesToYAMLv2Doc(data)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if defs, ok := lookFor(yamlDoc, "definitions"); ok {
|
||||
for _, def := range defs {
|
||||
addXOrder(def.Value)
|
||||
}
|
||||
}
|
||||
|
||||
addXOrder(yamlDoc)
|
||||
|
||||
out, err := yamlv2.Marshal(yamlDoc)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
tmpDir, err := os.MkdirTemp("", "go-swagger-")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
tmpFile := filepath.Join(tmpDir, filepath.Base(specPath))
|
||||
if err := os.WriteFile(tmpFile, out, 0600); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return tmpFile
|
||||
}
|
||||
|
||||
// BytesToYAMLDoc converts a byte slice into a YAML document
|
||||
func BytesToYAMLv2Doc(data []byte) (interface{}, error) {
|
||||
var canary map[interface{}]interface{} // validate this is an object and not a different type
|
||||
if err := yamlv2.Unmarshal(data, &canary); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var document yamlv2.MapSlice // preserve order that is present in the document
|
||||
if err := yamlv2.Unmarshal(data, &document); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return document, nil
|
||||
}
|
||||
|
||||
func applyDefaultSwagger(doc *loads.Document) (*loads.Document, error) {
|
||||
// bake a minimal swagger spec to pass validation
|
||||
swspec := doc.Spec()
|
||||
if swspec.Swagger == "" {
|
||||
swspec.Swagger = "2.0"
|
||||
}
|
||||
if swspec.Info == nil {
|
||||
info := new(spec.Info)
|
||||
info.Version = "0.0.0"
|
||||
info.Title = "minimal"
|
||||
swspec.Info = info
|
||||
}
|
||||
if swspec.Paths == nil {
|
||||
swspec.Paths = &spec.Paths{}
|
||||
}
|
||||
// rewrite the document with the new addition
|
||||
jazon, err := json.Marshal(swspec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return loads.Analyzed(jazon, swspec.Swagger)
|
||||
}
|
||||
803
vendor/github.com/go-swagger/go-swagger/generator/structs.go
generated
vendored
Normal file
803
vendor/github.com/go-swagger/go-swagger/generator/structs.go
generated
vendored
Normal file
|
|
@ -0,0 +1,803 @@
|
|||
package generator
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/analysis"
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
// GenCommon contains common properties needed across
|
||||
// definitions, app and operations
|
||||
// TargetImportPath may be used by templates to import other (possibly
|
||||
// generated) packages in the generation path (e.g. relative to GOPATH).
|
||||
// TargetImportPath is NOT used by standard templates.
|
||||
type GenCommon struct {
|
||||
Copyright string
|
||||
TargetImportPath string
|
||||
}
|
||||
|
||||
// GenDefinition contains all the properties to generate a
|
||||
// definition from a swagger spec
|
||||
type GenDefinition struct {
|
||||
GenCommon
|
||||
GenSchema
|
||||
Package string
|
||||
Imports map[string]string
|
||||
DefaultImports map[string]string
|
||||
ExtraSchemas GenSchemaList
|
||||
DependsOn []string
|
||||
External bool
|
||||
}
|
||||
|
||||
// GenDefinitions represents a list of operations to generate
|
||||
// this implements a sort by operation id
|
||||
type GenDefinitions []GenDefinition
|
||||
|
||||
func (g GenDefinitions) Len() int { return len(g) }
|
||||
func (g GenDefinitions) Less(i, j int) bool { return g[i].Name < g[j].Name }
|
||||
func (g GenDefinitions) Swap(i, j int) { g[i], g[j] = g[j], g[i] }
|
||||
|
||||
// GenSchemaList is a list of schemas for generation.
|
||||
//
|
||||
// It can be sorted by name to get a stable struct layout for
|
||||
// version control and such
|
||||
type GenSchemaList []GenSchema
|
||||
|
||||
// GenSchema contains all the information needed to generate the code
|
||||
// for a schema
|
||||
type GenSchema struct {
|
||||
resolvedType
|
||||
sharedValidations
|
||||
Example string
|
||||
OriginalName string
|
||||
Name string
|
||||
Suffix string
|
||||
Path string
|
||||
ValueExpression string
|
||||
IndexVar string
|
||||
KeyVar string
|
||||
Title string
|
||||
Description string
|
||||
Location string
|
||||
ReceiverName string
|
||||
Items *GenSchema
|
||||
AllowsAdditionalItems bool
|
||||
HasAdditionalItems bool
|
||||
AdditionalItems *GenSchema
|
||||
Object *GenSchema
|
||||
XMLName string
|
||||
CustomTag string
|
||||
Properties GenSchemaList
|
||||
AllOf GenSchemaList
|
||||
HasAdditionalProperties bool
|
||||
IsAdditionalProperties bool
|
||||
AdditionalProperties *GenSchema
|
||||
StrictAdditionalProperties bool
|
||||
ReadOnly bool
|
||||
IsVirtual bool
|
||||
IsBaseType bool
|
||||
HasBaseType bool
|
||||
IsSubType bool
|
||||
IsExported bool
|
||||
DiscriminatorField string
|
||||
DiscriminatorValue string
|
||||
Discriminates map[string]string
|
||||
Parents []string
|
||||
IncludeValidator bool
|
||||
IncludeModel bool
|
||||
Default interface{}
|
||||
WantsMarshalBinary bool // do we generate MarshalBinary interface?
|
||||
StructTags []string
|
||||
ExtraImports map[string]string // non-standard imports detected when using external types
|
||||
ExternalDocs *spec.ExternalDocumentation
|
||||
}
|
||||
|
||||
func (g GenSchema) renderMarshalTag() string {
|
||||
if g.HasBaseType {
|
||||
return "-"
|
||||
}
|
||||
|
||||
var result strings.Builder
|
||||
|
||||
result.WriteString(g.OriginalName)
|
||||
|
||||
if !g.Required && g.IsEmptyOmitted {
|
||||
result.WriteString(",omitempty")
|
||||
}
|
||||
|
||||
if g.IsJSONString {
|
||||
result.WriteString(",string")
|
||||
}
|
||||
|
||||
return result.String()
|
||||
}
|
||||
|
||||
// PrintTags takes care of rendering tags for a struct field
|
||||
func (g GenSchema) PrintTags() string {
|
||||
tags := make(map[string]string, 3)
|
||||
orderedTags := make([]string, 0, 3)
|
||||
|
||||
tags["json"] = g.renderMarshalTag()
|
||||
orderedTags = append(orderedTags, "json")
|
||||
|
||||
if len(g.XMLName) > 0 {
|
||||
if !g.Required && g.IsEmptyOmitted {
|
||||
tags["xml"] = g.XMLName + ",omitempty"
|
||||
} else {
|
||||
tags["xml"] = g.XMLName
|
||||
}
|
||||
orderedTags = append(orderedTags, "xml")
|
||||
}
|
||||
|
||||
// Add extra struct tags, only if the tag hasn't already been set, i.e. example.
|
||||
// Extra struct tags have the same value has the `json` tag.
|
||||
for _, tag := range g.StructTags {
|
||||
if _, exists := tags[tag]; exists {
|
||||
// dedupe
|
||||
continue
|
||||
}
|
||||
|
||||
switch {
|
||||
case tag == "example" && len(g.Example) > 0:
|
||||
// only add example tag if it's contained in the struct tags
|
||||
tags["example"] = g.Example // json representation of the example object
|
||||
case tag == "description" && len(g.Description) > 0:
|
||||
tags["description"] = g.Description
|
||||
default:
|
||||
tags[tag] = tags["json"]
|
||||
}
|
||||
|
||||
orderedTags = append(orderedTags, tag)
|
||||
}
|
||||
|
||||
// Assemble the tags in key value pairs with the value properly quoted.
|
||||
kvPairs := make([]string, 0, len(orderedTags)+1)
|
||||
for _, key := range orderedTags {
|
||||
kvPairs = append(kvPairs, fmt.Sprintf("%s:%s", key, strconv.Quote(tags[key])))
|
||||
}
|
||||
|
||||
if len(g.CustomTag) > 0 {
|
||||
kvPairs = append(kvPairs, g.CustomTag)
|
||||
}
|
||||
|
||||
// Join the key value pairs by a space.
|
||||
completeTag := strings.Join(kvPairs, " ")
|
||||
|
||||
// If the values contain a backtick, we cannot render the tag using backticks because Go does not support
|
||||
// escaping backticks in raw string literals.
|
||||
valuesHaveBacktick := false
|
||||
for _, value := range tags {
|
||||
if !strconv.CanBackquote(value) {
|
||||
valuesHaveBacktick = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !valuesHaveBacktick {
|
||||
return fmt.Sprintf("`%s`", completeTag)
|
||||
}
|
||||
|
||||
// We have to escape the tag again to put it in a literal with double quotes as the tag format uses double quotes.
|
||||
return strconv.Quote(completeTag)
|
||||
}
|
||||
|
||||
// UnderlyingType tells the go type or the aliased go type
|
||||
func (g GenSchema) UnderlyingType() string {
|
||||
if g.IsAliased {
|
||||
return g.AliasedType
|
||||
}
|
||||
return g.GoType
|
||||
}
|
||||
|
||||
// ToString returns a string conversion expression for the schema
|
||||
func (g GenSchema) ToString() string {
|
||||
return g.resolvedType.ToString(g.ValueExpression)
|
||||
}
|
||||
|
||||
func (g GenSchemaList) Len() int { return len(g) }
|
||||
func (g GenSchemaList) Swap(i, j int) { g[i], g[j] = g[j], g[i] }
|
||||
func (g GenSchemaList) Less(i, j int) bool {
|
||||
a, okA := g[i].Extensions[xOrder].(float64)
|
||||
b, okB := g[j].Extensions[xOrder].(float64)
|
||||
|
||||
// If both properties have x-order defined, then the one with lower x-order is smaller
|
||||
if okA && okB {
|
||||
return a < b
|
||||
}
|
||||
|
||||
// If only the first property has x-order defined, then it is smaller
|
||||
if okA {
|
||||
return true
|
||||
}
|
||||
|
||||
// If only the second property has x-order defined, then it is smaller
|
||||
if okB {
|
||||
return false
|
||||
}
|
||||
|
||||
// If neither property has x-order defined, then the one with lower lexicographic name is smaller
|
||||
return g[i].Name < g[j].Name
|
||||
}
|
||||
|
||||
type sharedValidations struct {
|
||||
spec.SchemaValidations
|
||||
|
||||
HasValidations bool
|
||||
HasContextValidations bool
|
||||
Required bool
|
||||
HasSliceValidations bool
|
||||
ItemsEnum []interface{}
|
||||
|
||||
// NOTE: "patternProperties" and "dependencies" not supported by Swagger 2.0
|
||||
}
|
||||
|
||||
// GenResponse represents a response object for code generation
|
||||
type GenResponse struct {
|
||||
Package string
|
||||
ModelsPackage string
|
||||
ReceiverName string
|
||||
Name string
|
||||
Description string
|
||||
|
||||
IsSuccess bool
|
||||
|
||||
Code int
|
||||
Method string
|
||||
Path string
|
||||
Headers GenHeaders
|
||||
Schema *GenSchema
|
||||
AllowsForStreaming bool
|
||||
|
||||
Imports map[string]string
|
||||
DefaultImports map[string]string
|
||||
|
||||
Extensions map[string]interface{}
|
||||
|
||||
StrictResponders bool
|
||||
OperationName string
|
||||
Examples GenResponseExamples
|
||||
}
|
||||
|
||||
// GenResponseExamples is a sortable collection []GenResponseExample
|
||||
type GenResponseExamples []GenResponseExample
|
||||
|
||||
func (g GenResponseExamples) Len() int { return len(g) }
|
||||
func (g GenResponseExamples) Swap(i, j int) { g[i], g[j] = g[j], g[i] }
|
||||
func (g GenResponseExamples) Less(i, j int) bool { return g[i].MediaType < g[j].MediaType }
|
||||
|
||||
// GenResponseExample captures an example provided for a response for some mime type
|
||||
type GenResponseExample struct {
|
||||
MediaType string
|
||||
Example interface{}
|
||||
}
|
||||
|
||||
// GenHeader represents a header on a response for code generation
|
||||
type GenHeader struct {
|
||||
resolvedType
|
||||
sharedValidations
|
||||
|
||||
Package string
|
||||
ReceiverName string
|
||||
IndexVar string
|
||||
|
||||
ID string
|
||||
Name string
|
||||
Path string
|
||||
ValueExpression string
|
||||
|
||||
Title string
|
||||
Description string
|
||||
Default interface{}
|
||||
HasDefault bool
|
||||
|
||||
CollectionFormat string
|
||||
|
||||
Child *GenItems
|
||||
Parent *GenItems
|
||||
|
||||
Converter string
|
||||
Formatter string
|
||||
|
||||
ZeroValue string
|
||||
}
|
||||
|
||||
// ItemsDepth returns a string "items.items..." with as many items as the level of nesting of the array.
|
||||
// For a header objects it always returns "".
|
||||
func (h *GenHeader) ItemsDepth() string {
|
||||
// NOTE: this is currently used by templates to generate explicit comments in nested structures
|
||||
return ""
|
||||
}
|
||||
|
||||
// ToString returns a string conversion expression for the header
|
||||
func (h GenHeader) ToString() string {
|
||||
return h.resolvedType.ToString(h.ValueExpression)
|
||||
}
|
||||
|
||||
// GenHeaders is a sorted collection of headers for codegen
|
||||
type GenHeaders []GenHeader
|
||||
|
||||
func (g GenHeaders) Len() int { return len(g) }
|
||||
func (g GenHeaders) Swap(i, j int) { g[i], g[j] = g[j], g[i] }
|
||||
func (g GenHeaders) Less(i, j int) bool { return g[i].Name < g[j].Name }
|
||||
|
||||
// HasSomeDefaults returns true is at least one header has a default value set
|
||||
func (g GenHeaders) HasSomeDefaults() bool {
|
||||
// NOTE: this is currently used by templates to avoid empty constructs
|
||||
for _, header := range g {
|
||||
if header.HasDefault {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GenParameter is used to represent
|
||||
// a parameter or a header for code generation.
|
||||
type GenParameter struct {
|
||||
resolvedType
|
||||
sharedValidations
|
||||
|
||||
ID string
|
||||
Name string
|
||||
ModelsPackage string
|
||||
Path string
|
||||
ValueExpression string
|
||||
IndexVar string
|
||||
KeyVar string
|
||||
ReceiverName string
|
||||
Location string
|
||||
Title string
|
||||
Description string
|
||||
Converter string
|
||||
Formatter string
|
||||
|
||||
Schema *GenSchema
|
||||
|
||||
CollectionFormat string
|
||||
|
||||
Child *GenItems
|
||||
Parent *GenItems
|
||||
|
||||
// Unused
|
||||
// BodyParam *GenParameter
|
||||
|
||||
Default interface{}
|
||||
HasDefault bool
|
||||
ZeroValue string
|
||||
AllowEmptyValue bool
|
||||
|
||||
// validation strategy for Body params, which may mix model and simple constructs.
|
||||
// Distinguish the following cases:
|
||||
// - HasSimpleBodyParams: body is an inline simple type
|
||||
// - HasModelBodyParams: body is a model objectd
|
||||
// - HasSimpleBodyItems: body is an inline array of simple type
|
||||
// - HasModelBodyItems: body is an array of model objects
|
||||
// - HasSimpleBodyMap: body is a map of simple objects (possibly arrays)
|
||||
// - HasModelBodyMap: body is a map of model objects
|
||||
HasSimpleBodyParams bool
|
||||
HasModelBodyParams bool
|
||||
HasSimpleBodyItems bool
|
||||
HasModelBodyItems bool
|
||||
HasSimpleBodyMap bool
|
||||
HasModelBodyMap bool
|
||||
|
||||
Extensions map[string]interface{}
|
||||
}
|
||||
|
||||
// IsQueryParam returns true when this parameter is a query param
|
||||
func (g *GenParameter) IsQueryParam() bool {
|
||||
return g.Location == "query"
|
||||
}
|
||||
|
||||
// IsPathParam returns true when this parameter is a path param
|
||||
func (g *GenParameter) IsPathParam() bool {
|
||||
return g.Location == "path"
|
||||
}
|
||||
|
||||
// IsFormParam returns true when this parameter is a form param
|
||||
func (g *GenParameter) IsFormParam() bool {
|
||||
return g.Location == "formData"
|
||||
}
|
||||
|
||||
// IsHeaderParam returns true when this parameter is a header param
|
||||
func (g *GenParameter) IsHeaderParam() bool {
|
||||
return g.Location == "header"
|
||||
}
|
||||
|
||||
// IsBodyParam returns true when this parameter is a body param
|
||||
func (g *GenParameter) IsBodyParam() bool {
|
||||
return g.Location == "body"
|
||||
}
|
||||
|
||||
// IsFileParam returns true when this parameter is a file param
|
||||
func (g *GenParameter) IsFileParam() bool {
|
||||
return g.SwaggerType == "file"
|
||||
}
|
||||
|
||||
// ItemsDepth returns a string "items.items..." with as many items as the level of nesting of the array.
|
||||
// For a parameter object, it always returns "".
|
||||
func (g *GenParameter) ItemsDepth() string {
|
||||
// NOTE: this is currently used by templates to generate explicit comments in nested structures
|
||||
return ""
|
||||
}
|
||||
|
||||
// UnderlyingType tells the go type or the aliased go type
|
||||
func (g GenParameter) UnderlyingType() string {
|
||||
return g.GoType
|
||||
}
|
||||
|
||||
// ToString returns a string conversion expression for the parameter
|
||||
func (g GenParameter) ToString() string {
|
||||
return g.resolvedType.ToString(g.ValueExpression)
|
||||
}
|
||||
|
||||
// GenParameters represents a sorted parameter collection
|
||||
type GenParameters []GenParameter
|
||||
|
||||
func (g GenParameters) Len() int { return len(g) }
|
||||
func (g GenParameters) Less(i, j int) bool { return g[i].Name < g[j].Name }
|
||||
func (g GenParameters) Swap(i, j int) { g[i], g[j] = g[j], g[i] }
|
||||
|
||||
// HasSomeDefaults returns true is at least one parameter has a default value set
|
||||
func (g GenParameters) HasSomeDefaults() bool {
|
||||
// NOTE: this is currently used by templates to avoid empty constructs
|
||||
for _, param := range g {
|
||||
if param.HasDefault {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GenItems represents the collection items for a collection parameter
|
||||
type GenItems struct {
|
||||
sharedValidations
|
||||
resolvedType
|
||||
|
||||
Name string
|
||||
Path string
|
||||
ValueExpression string
|
||||
CollectionFormat string
|
||||
Child *GenItems
|
||||
Parent *GenItems
|
||||
Converter string
|
||||
Formatter string
|
||||
|
||||
Location string
|
||||
IndexVar string
|
||||
KeyVar string
|
||||
|
||||
// instructs generator to skip the splitting and parsing from CollectionFormat
|
||||
SkipParse bool
|
||||
// instructs generator that some nested structure needs an higher level loop index
|
||||
NeedsIndex bool
|
||||
}
|
||||
|
||||
// ItemsDepth returns a string "items.items..." with as many items as the level of nesting of the array.
|
||||
func (g *GenItems) ItemsDepth() string {
|
||||
// NOTE: this is currently used by templates to generate explicit comments in nested structures
|
||||
current := g
|
||||
i := 1
|
||||
for current.Parent != nil {
|
||||
i++
|
||||
current = current.Parent
|
||||
}
|
||||
return strings.Repeat("items.", i)
|
||||
}
|
||||
|
||||
// UnderlyingType tells the go type or the aliased go type
|
||||
func (g GenItems) UnderlyingType() string {
|
||||
return g.GoType
|
||||
}
|
||||
|
||||
// ToString returns a string conversion expression for the item
|
||||
func (g GenItems) ToString() string {
|
||||
return g.resolvedType.ToString(g.ValueExpression)
|
||||
}
|
||||
|
||||
// GenOperationGroup represents a named (tagged) group of operations
|
||||
type GenOperationGroup struct {
|
||||
GenCommon
|
||||
Name string
|
||||
Operations GenOperations
|
||||
|
||||
Summary string
|
||||
Description string
|
||||
Imports map[string]string
|
||||
DefaultImports map[string]string
|
||||
RootPackage string
|
||||
GenOpts *GenOpts
|
||||
PackageAlias string
|
||||
}
|
||||
|
||||
// GenOperationGroups is a sorted collection of operation groups
|
||||
type GenOperationGroups []GenOperationGroup
|
||||
|
||||
func (g GenOperationGroups) Len() int { return len(g) }
|
||||
func (g GenOperationGroups) Swap(i, j int) { g[i], g[j] = g[j], g[i] }
|
||||
func (g GenOperationGroups) Less(i, j int) bool { return g[i].Name < g[j].Name }
|
||||
|
||||
// GenStatusCodeResponses a container for status code responses
|
||||
type GenStatusCodeResponses []GenResponse
|
||||
|
||||
func (g GenStatusCodeResponses) Len() int { return len(g) }
|
||||
func (g GenStatusCodeResponses) Swap(i, j int) { g[i], g[j] = g[j], g[i] }
|
||||
func (g GenStatusCodeResponses) Less(i, j int) bool { return g[i].Code < g[j].Code }
|
||||
|
||||
// MarshalJSON marshals these responses to json
|
||||
//
|
||||
// This is used by DumpData.
|
||||
func (g GenStatusCodeResponses) MarshalJSON() ([]byte, error) {
|
||||
if g == nil {
|
||||
return nil, nil
|
||||
}
|
||||
responses := make(GenStatusCodeResponses, len(g))
|
||||
copy(responses, g)
|
||||
// order marshalled output
|
||||
sort.Sort(responses)
|
||||
|
||||
var buf bytes.Buffer
|
||||
buf.WriteRune('{')
|
||||
for i, v := range responses {
|
||||
rb, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if i > 0 {
|
||||
buf.WriteRune(',')
|
||||
}
|
||||
buf.WriteString(fmt.Sprintf("%q:", strconv.Itoa(v.Code)))
|
||||
buf.Write(rb)
|
||||
}
|
||||
buf.WriteRune('}')
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals this GenStatusCodeResponses from json
|
||||
func (g *GenStatusCodeResponses) UnmarshalJSON(data []byte) error {
|
||||
var dd map[string]GenResponse
|
||||
if err := json.Unmarshal(data, &dd); err != nil {
|
||||
return err
|
||||
}
|
||||
var gg GenStatusCodeResponses
|
||||
for _, v := range dd {
|
||||
gg = append(gg, v)
|
||||
}
|
||||
sort.Sort(gg)
|
||||
*g = gg
|
||||
return nil
|
||||
}
|
||||
|
||||
// GenOperation represents an operation for code generation
|
||||
type GenOperation struct {
|
||||
GenCommon
|
||||
Package string
|
||||
ReceiverName string
|
||||
Name string
|
||||
Summary string
|
||||
Description string
|
||||
Method string
|
||||
Path string
|
||||
BasePath string
|
||||
Tags []string
|
||||
UseTags bool
|
||||
RootPackage string
|
||||
|
||||
Imports map[string]string
|
||||
DefaultImports map[string]string
|
||||
ExtraSchemas GenSchemaList
|
||||
PackageAlias string
|
||||
|
||||
Authorized bool
|
||||
Security []GenSecurityRequirements // resolved security requirements for the operation
|
||||
SecurityDefinitions GenSecuritySchemes
|
||||
SecurityRequirements []analysis.SecurityRequirement // original security requirements as per the spec (for doc)
|
||||
Principal string
|
||||
PrincipalIsNullable bool
|
||||
|
||||
SuccessResponse *GenResponse
|
||||
SuccessResponses []GenResponse
|
||||
Responses GenStatusCodeResponses
|
||||
DefaultResponse *GenResponse
|
||||
|
||||
Params GenParameters
|
||||
QueryParams GenParameters
|
||||
PathParams GenParameters
|
||||
HeaderParams GenParameters
|
||||
FormParams GenParameters
|
||||
HasQueryParams bool
|
||||
HasPathParams bool
|
||||
HasHeaderParams bool
|
||||
HasFormParams bool
|
||||
HasFormValueParams bool
|
||||
HasFileParams bool
|
||||
HasBodyParams bool
|
||||
HasStreamingResponse bool
|
||||
|
||||
Schemes []string
|
||||
ExtraSchemes []string
|
||||
SchemeOverrides []string // original scheme overrides for operation, as per spec (for doc)
|
||||
ExtraSchemeOverrides []string // original extra scheme overrides for operation, as per spec (for doc)
|
||||
ProducesMediaTypes []string
|
||||
ConsumesMediaTypes []string
|
||||
TimeoutName string
|
||||
|
||||
Extensions map[string]interface{}
|
||||
|
||||
StrictResponders bool
|
||||
ExternalDocs *spec.ExternalDocumentation
|
||||
Produces []string // original produces for operation (for doc)
|
||||
Consumes []string // original consumes for operation (for doc)
|
||||
}
|
||||
|
||||
// GenOperations represents a list of operations to generate
|
||||
// this implements a sort by operation id
|
||||
type GenOperations []GenOperation
|
||||
|
||||
func (g GenOperations) Len() int { return len(g) }
|
||||
func (g GenOperations) Less(i, j int) bool { return g[i].Name < g[j].Name }
|
||||
func (g GenOperations) Swap(i, j int) { g[i], g[j] = g[j], g[i] }
|
||||
|
||||
// GenApp represents all the meta data needed to generate an application
|
||||
// from a swagger spec
|
||||
type GenApp struct {
|
||||
GenCommon
|
||||
APIPackage string
|
||||
ServerPackageAlias string
|
||||
ImplementationPackageAlias string
|
||||
APIPackageAlias string
|
||||
Package string
|
||||
ReceiverName string
|
||||
Name string
|
||||
Principal string
|
||||
PrincipalIsNullable bool
|
||||
DefaultConsumes string
|
||||
DefaultProduces string
|
||||
Host string
|
||||
BasePath string
|
||||
Info *spec.Info
|
||||
ExternalDocs *spec.ExternalDocumentation
|
||||
Tags []spec.Tag
|
||||
Imports map[string]string
|
||||
DefaultImports map[string]string
|
||||
Schemes []string
|
||||
ExtraSchemes []string
|
||||
Consumes GenSerGroups
|
||||
Produces GenSerGroups
|
||||
SecurityDefinitions GenSecuritySchemes
|
||||
SecurityRequirements []analysis.SecurityRequirement // original security requirements as per the spec (for doc)
|
||||
Models []GenDefinition
|
||||
Operations GenOperations
|
||||
OperationGroups GenOperationGroups
|
||||
SwaggerJSON string
|
||||
// Embedded specs: this is important for when the generated server adds routes.
|
||||
// NOTE: there is a distinct advantage to having this in runtime rather than generated code.
|
||||
// We are not ever going to generate the router.
|
||||
// If embedding spec is an issue (e.g. memory usage), this can be excluded with the --exclude-spec
|
||||
// generation option. Alternative methods to serve spec (e.g. from disk, ...) may be implemented by
|
||||
// adding a middleware to the generated API.
|
||||
FlatSwaggerJSON string
|
||||
ExcludeSpec bool
|
||||
GenOpts *GenOpts
|
||||
}
|
||||
|
||||
// UseGoStructFlags returns true when no strategy is specified or it is set to "go-flags"
|
||||
func (g *GenApp) UseGoStructFlags() bool {
|
||||
if g.GenOpts == nil {
|
||||
return true
|
||||
}
|
||||
return g.GenOpts.FlagStrategy == "" || g.GenOpts.FlagStrategy == "go-flags"
|
||||
}
|
||||
|
||||
// UsePFlags returns true when the flag strategy is set to pflag
|
||||
func (g *GenApp) UsePFlags() bool {
|
||||
return g.GenOpts != nil && strings.HasPrefix(g.GenOpts.FlagStrategy, "pflag")
|
||||
}
|
||||
|
||||
// UseFlags returns true when the flag strategy is set to flag
|
||||
func (g *GenApp) UseFlags() bool {
|
||||
return g.GenOpts != nil && strings.HasPrefix(g.GenOpts.FlagStrategy, "flag")
|
||||
}
|
||||
|
||||
// UseIntermediateMode for https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28default.29
|
||||
func (g *GenApp) UseIntermediateMode() bool {
|
||||
return g.GenOpts != nil && g.GenOpts.CompatibilityMode == "intermediate"
|
||||
}
|
||||
|
||||
// UseModernMode for https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility
|
||||
func (g *GenApp) UseModernMode() bool {
|
||||
return g.GenOpts == nil || g.GenOpts.CompatibilityMode == "" || g.GenOpts.CompatibilityMode == "modern"
|
||||
}
|
||||
|
||||
// GenSerGroups sorted representation of serializer groups
|
||||
type GenSerGroups []GenSerGroup
|
||||
|
||||
func (g GenSerGroups) Len() int { return len(g) }
|
||||
func (g GenSerGroups) Swap(i, j int) { g[i], g[j] = g[j], g[i] }
|
||||
func (g GenSerGroups) Less(i, j int) bool { return g[i].Name < g[j].Name }
|
||||
|
||||
// GenSerGroup represents a group of serializers: this links a serializer to a list of
|
||||
// prioritized media types (mime).
|
||||
type GenSerGroup struct {
|
||||
GenSerializer
|
||||
|
||||
// All media types for this serializer. The redundant representation allows for easier use in templates
|
||||
AllSerializers GenSerializers
|
||||
}
|
||||
|
||||
// GenSerializers sorted representation of serializers
|
||||
type GenSerializers []GenSerializer
|
||||
|
||||
func (g GenSerializers) Len() int { return len(g) }
|
||||
func (g GenSerializers) Swap(i, j int) { g[i], g[j] = g[j], g[i] }
|
||||
func (g GenSerializers) Less(i, j int) bool { return g[i].MediaType < g[j].MediaType }
|
||||
|
||||
// GenSerializer represents a single serializer for a particular media type
|
||||
type GenSerializer struct {
|
||||
AppName string // Application name
|
||||
ReceiverName string
|
||||
Name string // Name of the Producer/Consumer (e.g. json, yaml, txt, bin)
|
||||
MediaType string // mime
|
||||
Implementation string // func implementing the Producer/Consumer
|
||||
Parameters []string // parameters supported by this serializer
|
||||
}
|
||||
|
||||
// GenSecurityScheme represents a security scheme for code generation
|
||||
type GenSecurityScheme struct {
|
||||
AppName string
|
||||
ID string
|
||||
Name string
|
||||
ReceiverName string
|
||||
IsBasicAuth bool
|
||||
IsAPIKeyAuth bool
|
||||
IsOAuth2 bool
|
||||
Scopes []string
|
||||
Source string
|
||||
Principal string
|
||||
PrincipalIsNullable bool
|
||||
|
||||
// from spec.SecurityScheme
|
||||
Description string
|
||||
Type string
|
||||
In string
|
||||
Flow string
|
||||
AuthorizationURL string
|
||||
TokenURL string
|
||||
Extensions map[string]interface{}
|
||||
ScopesDesc []GenSecurityScope
|
||||
}
|
||||
|
||||
// GenSecuritySchemes sorted representation of serializers
|
||||
type GenSecuritySchemes []GenSecurityScheme
|
||||
|
||||
func (g GenSecuritySchemes) Len() int { return len(g) }
|
||||
func (g GenSecuritySchemes) Swap(i, j int) { g[i], g[j] = g[j], g[i] }
|
||||
func (g GenSecuritySchemes) Less(i, j int) bool { return g[i].ID < g[j].ID }
|
||||
|
||||
// GenSecurityRequirement represents a security requirement for an operation
|
||||
type GenSecurityRequirement struct {
|
||||
Name string
|
||||
Scopes []string
|
||||
}
|
||||
|
||||
// GenSecurityScope represents a scope descriptor for an OAuth2 security scheme
|
||||
type GenSecurityScope struct {
|
||||
Name string
|
||||
Description string
|
||||
}
|
||||
|
||||
// GenSecurityRequirements represents a compounded security requirement specification.
|
||||
// In a []GenSecurityRequirements complete requirements specification,
|
||||
// outer elements are interpreted as optional requirements (OR), and
|
||||
// inner elements are interpreted as jointly required (AND).
|
||||
type GenSecurityRequirements []GenSecurityRequirement
|
||||
|
||||
func (g GenSecurityRequirements) Len() int { return len(g) }
|
||||
func (g GenSecurityRequirements) Swap(i, j int) { g[i], g[j] = g[j], g[i] }
|
||||
func (g GenSecurityRequirements) Less(i, j int) bool { return g[i].Name < g[j].Name }
|
||||
546
vendor/github.com/go-swagger/go-swagger/generator/support.go
generated
vendored
Normal file
546
vendor/github.com/go-swagger/go-swagger/generator/support.go
generated
vendored
Normal file
|
|
@ -0,0 +1,546 @@
|
|||
// Copyright 2015 go-swagger maintainers
|
||||
|
||||
//
|
||||
// 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 generator
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
|
||||
"github.com/go-openapi/analysis"
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
// GenerateServer generates a server application
|
||||
func GenerateServer(name string, modelNames, operationIDs []string, opts *GenOpts) error {
|
||||
generator, err := newAppGenerator(name, modelNames, operationIDs, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return generator.Generate()
|
||||
}
|
||||
|
||||
// GenerateSupport generates the supporting files for an API
|
||||
func GenerateSupport(name string, modelNames, operationIDs []string, opts *GenOpts) error {
|
||||
generator, err := newAppGenerator(name, modelNames, operationIDs, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return generator.GenerateSupport(nil)
|
||||
}
|
||||
|
||||
// GenerateMarkdown documentation for a swagger specification
|
||||
func GenerateMarkdown(output string, modelNames, operationIDs []string, opts *GenOpts) error {
|
||||
if output == "." || output == "" {
|
||||
output = "markdown.md"
|
||||
}
|
||||
|
||||
if err := opts.EnsureDefaults(); err != nil {
|
||||
return err
|
||||
}
|
||||
MarkdownSectionOpts(opts, output)
|
||||
|
||||
generator, err := newAppGenerator("", modelNames, operationIDs, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return generator.GenerateMarkdown()
|
||||
}
|
||||
|
||||
func newAppGenerator(name string, modelNames, operationIDs []string, opts *GenOpts) (*appGenerator, error) {
|
||||
if err := opts.CheckOpts(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := opts.setTemplates(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
specDoc, analyzed, err := opts.analyzeSpec()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
models, err := gatherModels(specDoc, modelNames)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
operations := gatherOperations(analyzed, operationIDs)
|
||||
|
||||
if len(operations) == 0 && !opts.IgnoreOperations {
|
||||
return nil, errors.New("no operations were selected")
|
||||
}
|
||||
|
||||
opts.Name = appNameOrDefault(specDoc, name, defaultServerName)
|
||||
if opts.IncludeMain && opts.MainPackage == "" {
|
||||
// default target for the generated main
|
||||
opts.MainPackage = swag.ToCommandName(mainNameOrDefault(specDoc, name, defaultServerName) + "-server")
|
||||
}
|
||||
|
||||
apiPackage := opts.LanguageOpts.ManglePackagePath(opts.APIPackage, defaultOperationsTarget)
|
||||
return &appGenerator{
|
||||
Name: opts.Name,
|
||||
Receiver: "o",
|
||||
SpecDoc: specDoc,
|
||||
Analyzed: analyzed,
|
||||
Models: models,
|
||||
Operations: operations,
|
||||
Target: opts.Target,
|
||||
DumpData: opts.DumpData,
|
||||
Package: opts.LanguageOpts.ManglePackageName(apiPackage, defaultOperationsTarget),
|
||||
APIPackage: apiPackage,
|
||||
ModelsPackage: opts.LanguageOpts.ManglePackagePath(opts.ModelPackage, defaultModelsTarget),
|
||||
ServerPackage: opts.LanguageOpts.ManglePackagePath(opts.ServerPackage, defaultServerTarget),
|
||||
ClientPackage: opts.LanguageOpts.ManglePackagePath(opts.ClientPackage, defaultClientTarget),
|
||||
OperationsPackage: filepath.Join(opts.LanguageOpts.ManglePackagePath(opts.ServerPackage, defaultServerTarget), apiPackage),
|
||||
Principal: opts.PrincipalAlias(),
|
||||
DefaultScheme: opts.DefaultScheme,
|
||||
DefaultProduces: opts.DefaultProduces,
|
||||
DefaultConsumes: opts.DefaultConsumes,
|
||||
GenOpts: opts,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type appGenerator struct {
|
||||
Name string
|
||||
Receiver string
|
||||
SpecDoc *loads.Document
|
||||
Analyzed *analysis.Spec
|
||||
Package string
|
||||
APIPackage string
|
||||
ModelsPackage string
|
||||
ServerPackage string
|
||||
ClientPackage string
|
||||
OperationsPackage string
|
||||
MainPackage string
|
||||
Principal string
|
||||
Models map[string]spec.Schema
|
||||
Operations map[string]opRef
|
||||
Target string
|
||||
DumpData bool
|
||||
DefaultScheme string
|
||||
DefaultProduces string
|
||||
DefaultConsumes string
|
||||
GenOpts *GenOpts
|
||||
}
|
||||
|
||||
func (a *appGenerator) Generate() error {
|
||||
app, err := a.makeCodegenApp()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if a.DumpData {
|
||||
return dumpData(app)
|
||||
}
|
||||
|
||||
// NOTE: relative to previous implem with chan.
|
||||
// IPC removed concurrent execution because of the FuncMap that is being shared
|
||||
// templates are now lazy loaded so there is concurrent map access I can't guard
|
||||
if a.GenOpts.IncludeModel {
|
||||
log.Printf("rendering %d models", len(app.Models))
|
||||
for _, md := range app.Models {
|
||||
mod := md
|
||||
mod.IncludeModel = true
|
||||
mod.IncludeValidator = a.GenOpts.IncludeValidator
|
||||
if err := a.GenOpts.renderDefinition(&mod); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if a.GenOpts.IncludeHandler {
|
||||
log.Printf("rendering %d operation groups (tags)", app.OperationGroups.Len())
|
||||
for _, g := range app.OperationGroups {
|
||||
opg := g
|
||||
log.Printf("rendering %d operations for %s", opg.Operations.Len(), opg.Name)
|
||||
for _, p := range opg.Operations {
|
||||
op := p
|
||||
if err := a.GenOpts.renderOperation(&op); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// optional OperationGroups templates generation
|
||||
if err := a.GenOpts.renderOperationGroup(&opg); err != nil {
|
||||
return fmt.Errorf("error while rendering operation group: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if a.GenOpts.IncludeSupport {
|
||||
log.Printf("rendering support")
|
||||
if err := a.GenerateSupport(&app); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *appGenerator) GenerateSupport(ap *GenApp) error {
|
||||
app := ap
|
||||
if ap == nil {
|
||||
// allows for calling GenerateSupport standalone
|
||||
ca, err := a.makeCodegenApp()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
app = &ca
|
||||
}
|
||||
|
||||
baseImport := a.GenOpts.LanguageOpts.baseImport(a.Target)
|
||||
serverPath := path.Join(baseImport,
|
||||
a.GenOpts.LanguageOpts.ManglePackagePath(a.ServerPackage, defaultServerTarget))
|
||||
|
||||
pkgAlias := deconflictPkg(importAlias(serverPath), renameServerPackage)
|
||||
app.DefaultImports[pkgAlias] = serverPath
|
||||
app.ServerPackageAlias = pkgAlias
|
||||
|
||||
// add client import for cli generation
|
||||
clientPath := path.Join(baseImport,
|
||||
a.GenOpts.LanguageOpts.ManglePackagePath(a.ClientPackage, defaultClientTarget))
|
||||
clientPkgAlias := importAlias(clientPath)
|
||||
app.DefaultImports[clientPkgAlias] = clientPath
|
||||
|
||||
return a.GenOpts.renderApplication(app)
|
||||
}
|
||||
|
||||
func (a *appGenerator) GenerateMarkdown() error {
|
||||
app, err := a.makeCodegenApp()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return a.GenOpts.renderApplication(&app)
|
||||
}
|
||||
|
||||
func (a *appGenerator) makeSecuritySchemes() GenSecuritySchemes {
|
||||
requiredSecuritySchemes := make(map[string]spec.SecurityScheme, len(a.Analyzed.RequiredSecuritySchemes()))
|
||||
for _, scheme := range a.Analyzed.RequiredSecuritySchemes() {
|
||||
if req, ok := a.SpecDoc.Spec().SecurityDefinitions[scheme]; ok && req != nil {
|
||||
requiredSecuritySchemes[scheme] = *req
|
||||
}
|
||||
}
|
||||
return gatherSecuritySchemes(requiredSecuritySchemes, a.Name, a.Principal, a.Receiver, a.GenOpts.PrincipalIsNullable())
|
||||
}
|
||||
|
||||
func (a *appGenerator) makeCodegenApp() (GenApp, error) {
|
||||
log.Println("building a plan for generation")
|
||||
|
||||
sw := a.SpecDoc.Spec()
|
||||
receiver := a.Receiver
|
||||
|
||||
consumes, _ := a.makeConsumes()
|
||||
produces, _ := a.makeProduces()
|
||||
security := a.makeSecuritySchemes()
|
||||
|
||||
log.Println("generation target", a.Target)
|
||||
|
||||
baseImport := a.GenOpts.LanguageOpts.baseImport(a.Target)
|
||||
defaultImports := a.GenOpts.defaultImports()
|
||||
|
||||
imports := make(map[string]string, 50)
|
||||
alias := deconflictPkg(a.GenOpts.LanguageOpts.ManglePackageName(a.OperationsPackage, defaultOperationsTarget), renameAPIPackage)
|
||||
imports[alias] = path.Join(
|
||||
baseImport,
|
||||
a.GenOpts.LanguageOpts.ManglePackagePath(a.OperationsPackage, defaultOperationsTarget))
|
||||
|
||||
implAlias := ""
|
||||
if a.GenOpts.ImplementationPackage != "" {
|
||||
implAlias = deconflictPkg(a.GenOpts.LanguageOpts.ManglePackageName(a.GenOpts.ImplementationPackage, defaultImplementationTarget), renameImplementationPackage)
|
||||
imports[implAlias] = a.GenOpts.ImplementationPackage
|
||||
}
|
||||
|
||||
log.Printf("planning definitions (found: %d)", len(a.Models))
|
||||
|
||||
genModels := make(GenDefinitions, 0, len(a.Models))
|
||||
for mn, m := range a.Models {
|
||||
model, err := makeGenDefinition(
|
||||
mn,
|
||||
a.ModelsPackage,
|
||||
m,
|
||||
a.SpecDoc,
|
||||
a.GenOpts,
|
||||
)
|
||||
if err != nil {
|
||||
return GenApp{}, fmt.Errorf("error in model %s while planning definitions: %v", mn, err)
|
||||
}
|
||||
if model != nil {
|
||||
if !model.External {
|
||||
genModels = append(genModels, *model)
|
||||
}
|
||||
|
||||
// Copy model imports to operation imports
|
||||
// TODO(fredbi): mangle model pkg aliases
|
||||
for alias, pkg := range model.Imports {
|
||||
target := a.GenOpts.LanguageOpts.ManglePackageName(alias, "")
|
||||
imports[target] = pkg
|
||||
}
|
||||
}
|
||||
}
|
||||
sort.Sort(genModels)
|
||||
|
||||
log.Printf("planning operations (found: %d)", len(a.Operations))
|
||||
|
||||
genOps := make(GenOperations, 0, len(a.Operations))
|
||||
for operationName, opp := range a.Operations {
|
||||
o := opp.Op
|
||||
o.ID = operationName
|
||||
|
||||
bldr := codeGenOpBuilder{
|
||||
ModelsPackage: a.ModelsPackage,
|
||||
Principal: a.GenOpts.PrincipalAlias(),
|
||||
Target: a.Target,
|
||||
DefaultImports: defaultImports,
|
||||
Imports: imports,
|
||||
DefaultScheme: a.DefaultScheme,
|
||||
Doc: a.SpecDoc,
|
||||
Analyzed: a.Analyzed,
|
||||
BasePath: a.SpecDoc.BasePath(),
|
||||
GenOpts: a.GenOpts,
|
||||
Name: operationName,
|
||||
Operation: *o,
|
||||
Method: opp.Method,
|
||||
Path: opp.Path,
|
||||
IncludeValidator: a.GenOpts.IncludeValidator,
|
||||
APIPackage: a.APIPackage, // defaults to main operations package
|
||||
DefaultProduces: a.DefaultProduces,
|
||||
DefaultConsumes: a.DefaultConsumes,
|
||||
}
|
||||
|
||||
tag, tags, ok := bldr.analyzeTags()
|
||||
if !ok {
|
||||
continue // operation filtered according to CLI params
|
||||
}
|
||||
|
||||
bldr.Authed = len(a.Analyzed.SecurityRequirementsFor(o)) > 0
|
||||
bldr.Security = a.Analyzed.SecurityRequirementsFor(o)
|
||||
bldr.SecurityDefinitions = a.Analyzed.SecurityDefinitionsFor(o)
|
||||
bldr.RootAPIPackage = a.GenOpts.LanguageOpts.ManglePackageName(a.ServerPackage, defaultServerTarget)
|
||||
|
||||
st := o.Tags
|
||||
if a.GenOpts != nil {
|
||||
st = a.GenOpts.Tags
|
||||
}
|
||||
intersected := intersectTags(o.Tags, st)
|
||||
if len(st) > 0 && len(intersected) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
op, err := bldr.MakeOperation()
|
||||
if err != nil {
|
||||
return GenApp{}, err
|
||||
}
|
||||
|
||||
op.ReceiverName = receiver
|
||||
op.Tags = tags // ordered tags for this operation, possibly filtered by CLI params
|
||||
genOps = append(genOps, op)
|
||||
|
||||
if !a.GenOpts.SkipTagPackages && tag != "" {
|
||||
importPath := filepath.ToSlash(
|
||||
path.Join(
|
||||
baseImport,
|
||||
a.GenOpts.LanguageOpts.ManglePackagePath(a.OperationsPackage, defaultOperationsTarget),
|
||||
a.GenOpts.LanguageOpts.ManglePackageName(bldr.APIPackage, defaultOperationsTarget),
|
||||
))
|
||||
defaultImports[bldr.APIPackageAlias] = importPath
|
||||
}
|
||||
}
|
||||
sort.Sort(genOps)
|
||||
|
||||
opsGroupedByPackage := make(map[string]GenOperations, len(genOps))
|
||||
for _, operation := range genOps {
|
||||
opsGroupedByPackage[operation.PackageAlias] = append(opsGroupedByPackage[operation.PackageAlias], operation)
|
||||
}
|
||||
|
||||
log.Printf("grouping operations into packages (packages: %d)", len(opsGroupedByPackage))
|
||||
|
||||
opGroups := make(GenOperationGroups, 0, len(opsGroupedByPackage))
|
||||
for k, v := range opsGroupedByPackage {
|
||||
log.Printf("operations for package packages %q (found: %d)", k, len(v))
|
||||
sort.Sort(v)
|
||||
// trim duplicate extra schemas within the same package
|
||||
vv := make(GenOperations, 0, len(v))
|
||||
seenExtraSchema := make(map[string]bool)
|
||||
for _, op := range v {
|
||||
uniqueExtraSchemas := make(GenSchemaList, 0, len(op.ExtraSchemas))
|
||||
for _, xs := range op.ExtraSchemas {
|
||||
if _, alreadyThere := seenExtraSchema[xs.Name]; !alreadyThere {
|
||||
seenExtraSchema[xs.Name] = true
|
||||
uniqueExtraSchemas = append(uniqueExtraSchemas, xs)
|
||||
}
|
||||
}
|
||||
op.ExtraSchemas = uniqueExtraSchemas
|
||||
vv = append(vv, op)
|
||||
}
|
||||
var pkg string
|
||||
if len(vv) > 0 {
|
||||
pkg = vv[0].Package
|
||||
} else {
|
||||
pkg = k
|
||||
}
|
||||
|
||||
opGroup := GenOperationGroup{
|
||||
GenCommon: GenCommon{
|
||||
Copyright: a.GenOpts.Copyright,
|
||||
TargetImportPath: baseImport,
|
||||
},
|
||||
Name: pkg,
|
||||
PackageAlias: k,
|
||||
Operations: vv,
|
||||
DefaultImports: defaultImports,
|
||||
Imports: imports,
|
||||
RootPackage: a.APIPackage,
|
||||
GenOpts: a.GenOpts,
|
||||
}
|
||||
opGroups = append(opGroups, opGroup)
|
||||
}
|
||||
sort.Sort(opGroups)
|
||||
|
||||
log.Println("planning meta data and facades")
|
||||
|
||||
var collectedSchemes, extraSchemes []string
|
||||
for _, op := range genOps {
|
||||
collectedSchemes = concatUnique(collectedSchemes, op.Schemes)
|
||||
extraSchemes = concatUnique(extraSchemes, op.ExtraSchemes)
|
||||
}
|
||||
sort.Strings(collectedSchemes)
|
||||
sort.Strings(extraSchemes)
|
||||
|
||||
host := "localhost"
|
||||
if sw.Host != "" {
|
||||
host = sw.Host
|
||||
}
|
||||
|
||||
basePath := "/"
|
||||
if sw.BasePath != "" {
|
||||
basePath = sw.BasePath
|
||||
}
|
||||
|
||||
jsonb, _ := json.MarshalIndent(a.SpecDoc.OrigSpec(), "", " ")
|
||||
flatjsonb, _ := json.MarshalIndent(a.SpecDoc.Spec(), "", " ")
|
||||
|
||||
return GenApp{
|
||||
GenCommon: GenCommon{
|
||||
Copyright: a.GenOpts.Copyright,
|
||||
TargetImportPath: baseImport,
|
||||
},
|
||||
APIPackage: a.GenOpts.LanguageOpts.ManglePackageName(a.ServerPackage, defaultServerTarget),
|
||||
APIPackageAlias: alias,
|
||||
ImplementationPackageAlias: implAlias,
|
||||
Package: a.Package,
|
||||
ReceiverName: receiver,
|
||||
Name: a.Name,
|
||||
Host: host,
|
||||
BasePath: basePath,
|
||||
Schemes: schemeOrDefault(collectedSchemes, a.DefaultScheme),
|
||||
ExtraSchemes: extraSchemes,
|
||||
ExternalDocs: trimExternalDoc(sw.ExternalDocs),
|
||||
Tags: trimTags(sw.Tags),
|
||||
Info: trimInfo(sw.Info),
|
||||
Consumes: consumes,
|
||||
Produces: produces,
|
||||
DefaultConsumes: a.DefaultConsumes,
|
||||
DefaultProduces: a.DefaultProduces,
|
||||
DefaultImports: defaultImports,
|
||||
Imports: imports,
|
||||
SecurityDefinitions: security,
|
||||
SecurityRequirements: securityRequirements(a.SpecDoc.Spec().Security), // top level securityRequirements
|
||||
Models: genModels,
|
||||
Operations: genOps,
|
||||
OperationGroups: opGroups,
|
||||
Principal: a.GenOpts.PrincipalAlias(),
|
||||
SwaggerJSON: generateReadableSpec(jsonb),
|
||||
FlatSwaggerJSON: generateReadableSpec(flatjsonb),
|
||||
ExcludeSpec: a.GenOpts.ExcludeSpec,
|
||||
GenOpts: a.GenOpts,
|
||||
|
||||
PrincipalIsNullable: a.GenOpts.PrincipalIsNullable(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// generateReadableSpec makes swagger json spec as a string instead of bytes
|
||||
// the only character that needs to be escaped is '`' symbol, since it cannot be escaped in the GO string
|
||||
// that is quoted as `string data`. The function doesn't care about the beginning or the ending of the
|
||||
// string it escapes since all data that needs to be escaped is always in the middle of the swagger spec.
|
||||
func generateReadableSpec(spec []byte) string {
|
||||
buf := &bytes.Buffer{}
|
||||
for _, b := range string(spec) {
|
||||
if b == '`' {
|
||||
buf.WriteString("`+\"`\"+`")
|
||||
} else {
|
||||
buf.WriteRune(b)
|
||||
}
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func trimExternalDoc(in *spec.ExternalDocumentation) *spec.ExternalDocumentation {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &spec.ExternalDocumentation{
|
||||
URL: in.URL,
|
||||
Description: trimBOM(in.Description),
|
||||
}
|
||||
}
|
||||
|
||||
func trimInfo(in *spec.Info) *spec.Info {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &spec.Info{
|
||||
InfoProps: spec.InfoProps{
|
||||
Contact: in.Contact,
|
||||
Title: trimBOM(in.Title),
|
||||
Description: trimBOM(in.Description),
|
||||
TermsOfService: trimBOM(in.TermsOfService),
|
||||
License: in.License,
|
||||
Version: in.Version,
|
||||
},
|
||||
VendorExtensible: in.VendorExtensible,
|
||||
}
|
||||
}
|
||||
|
||||
func trimTags(in []spec.Tag) []spec.Tag {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
tags := make([]spec.Tag, 0, len(in))
|
||||
|
||||
for _, tag := range in {
|
||||
tags = append(tags, spec.Tag{
|
||||
TagProps: spec.TagProps{
|
||||
Name: tag.Name,
|
||||
Description: trimBOM(tag.Description),
|
||||
ExternalDocs: trimExternalDoc(tag.ExternalDocs),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return tags
|
||||
}
|
||||
855
vendor/github.com/go-swagger/go-swagger/generator/template_repo.go
generated
vendored
Normal file
855
vendor/github.com/go-swagger/go-swagger/generator/template_repo.go
generated
vendored
Normal file
|
|
@ -0,0 +1,855 @@
|
|||
package generator
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"text/template"
|
||||
"text/template/parse"
|
||||
"unicode"
|
||||
|
||||
"log"
|
||||
|
||||
"github.com/Masterminds/sprig/v3"
|
||||
"github.com/go-openapi/inflect"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/kr/pretty"
|
||||
)
|
||||
|
||||
var (
|
||||
assets map[string][]byte
|
||||
protectedTemplates map[string]bool
|
||||
|
||||
// FuncMapFunc yields a map with all functions for templates
|
||||
FuncMapFunc func(*LanguageOpts) template.FuncMap
|
||||
|
||||
templates *Repository
|
||||
|
||||
docFormat map[string]string
|
||||
)
|
||||
|
||||
func initTemplateRepo() {
|
||||
FuncMapFunc = DefaultFuncMap
|
||||
|
||||
// this makes the ToGoName func behave with the special
|
||||
// prefixing rule above
|
||||
swag.GoNamePrefixFunc = prefixForName
|
||||
|
||||
assets = defaultAssets()
|
||||
protectedTemplates = defaultProtectedTemplates()
|
||||
templates = NewRepository(FuncMapFunc(DefaultLanguageFunc()))
|
||||
|
||||
docFormat = map[string]string{
|
||||
"binary": "binary (byte stream)",
|
||||
"byte": "byte (base64 string)",
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultFuncMap yields a map with default functions for use in the templates.
|
||||
// These are available in every template
|
||||
func DefaultFuncMap(lang *LanguageOpts) template.FuncMap {
|
||||
f := sprig.TxtFuncMap()
|
||||
extra := template.FuncMap{
|
||||
"pascalize": pascalize,
|
||||
"camelize": swag.ToJSONName,
|
||||
"varname": lang.MangleVarName,
|
||||
"humanize": swag.ToHumanNameLower,
|
||||
"snakize": lang.MangleFileName,
|
||||
"toPackagePath": func(name string) string {
|
||||
return filepath.FromSlash(lang.ManglePackagePath(name, ""))
|
||||
},
|
||||
"toPackage": func(name string) string {
|
||||
return lang.ManglePackagePath(name, "")
|
||||
},
|
||||
"toPackageName": func(name string) string {
|
||||
return lang.ManglePackageName(name, "")
|
||||
},
|
||||
"dasherize": swag.ToCommandName,
|
||||
"pluralizeFirstWord": pluralizeFirstWord,
|
||||
"json": asJSON,
|
||||
"prettyjson": asPrettyJSON,
|
||||
"hasInsecure": func(arg []string) bool {
|
||||
return swag.ContainsStringsCI(arg, "http") || swag.ContainsStringsCI(arg, "ws")
|
||||
},
|
||||
"hasSecure": func(arg []string) bool {
|
||||
return swag.ContainsStringsCI(arg, "https") || swag.ContainsStringsCI(arg, "wss")
|
||||
},
|
||||
"dropPackage": dropPackage,
|
||||
"containsPkgStr": containsPkgStr,
|
||||
"contains": swag.ContainsStrings,
|
||||
"padSurround": padSurround,
|
||||
"joinFilePath": filepath.Join,
|
||||
"joinPath": path.Join,
|
||||
"comment": padComment,
|
||||
"blockcomment": blockComment,
|
||||
"inspect": pretty.Sprint,
|
||||
"cleanPath": path.Clean,
|
||||
"mediaTypeName": mediaMime,
|
||||
"arrayInitializer": lang.arrayInitializer,
|
||||
"hasPrefix": strings.HasPrefix,
|
||||
"stringContains": strings.Contains,
|
||||
"imports": lang.imports,
|
||||
"dict": dict,
|
||||
"isInteger": isInteger,
|
||||
"escapeBackticks": func(arg string) string {
|
||||
return strings.ReplaceAll(arg, "`", "`+\"`\"+`")
|
||||
},
|
||||
"paramDocType": func(param GenParameter) string {
|
||||
return resolvedDocType(param.SwaggerType, param.SwaggerFormat, param.Child)
|
||||
},
|
||||
"headerDocType": func(header GenHeader) string {
|
||||
return resolvedDocType(header.SwaggerType, header.SwaggerFormat, header.Child)
|
||||
},
|
||||
"schemaDocType": func(in interface{}) string {
|
||||
switch schema := in.(type) {
|
||||
case GenSchema:
|
||||
return resolvedDocSchemaType(schema.SwaggerType, schema.SwaggerFormat, schema.Items)
|
||||
case *GenSchema:
|
||||
if schema == nil {
|
||||
return ""
|
||||
}
|
||||
return resolvedDocSchemaType(schema.SwaggerType, schema.SwaggerFormat, schema.Items)
|
||||
case GenDefinition:
|
||||
return resolvedDocSchemaType(schema.SwaggerType, schema.SwaggerFormat, schema.Items)
|
||||
case *GenDefinition:
|
||||
if schema == nil {
|
||||
return ""
|
||||
}
|
||||
return resolvedDocSchemaType(schema.SwaggerType, schema.SwaggerFormat, schema.Items)
|
||||
default:
|
||||
panic("dev error: schemaDocType should be called with GenSchema or GenDefinition")
|
||||
}
|
||||
},
|
||||
"schemaDocMapType": func(schema GenSchema) string {
|
||||
return resolvedDocElemType("object", schema.SwaggerFormat, &schema.resolvedType)
|
||||
},
|
||||
"docCollectionFormat": resolvedDocCollectionFormat,
|
||||
"trimSpace": strings.TrimSpace,
|
||||
"httpStatus": httpStatus,
|
||||
"cleanupEnumVariant": cleanupEnumVariant,
|
||||
"gt0": gt0,
|
||||
}
|
||||
|
||||
for k, v := range extra {
|
||||
f[k] = v
|
||||
}
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
func defaultAssets() map[string][]byte {
|
||||
return map[string][]byte{
|
||||
// schema validation templates
|
||||
"validation/primitive.gotmpl": MustAsset("templates/validation/primitive.gotmpl"),
|
||||
"validation/customformat.gotmpl": MustAsset("templates/validation/customformat.gotmpl"),
|
||||
"validation/structfield.gotmpl": MustAsset("templates/validation/structfield.gotmpl"),
|
||||
"structfield.gotmpl": MustAsset("templates/structfield.gotmpl"),
|
||||
"schemavalidator.gotmpl": MustAsset("templates/schemavalidator.gotmpl"),
|
||||
"schemapolymorphic.gotmpl": MustAsset("templates/schemapolymorphic.gotmpl"),
|
||||
"schemaembedded.gotmpl": MustAsset("templates/schemaembedded.gotmpl"),
|
||||
"validation/minimum.gotmpl": MustAsset("templates/validation/minimum.gotmpl"),
|
||||
"validation/maximum.gotmpl": MustAsset("templates/validation/maximum.gotmpl"),
|
||||
"validation/multipleOf.gotmpl": MustAsset("templates/validation/multipleOf.gotmpl"),
|
||||
|
||||
// schema serialization templates
|
||||
"additionalpropertiesserializer.gotmpl": MustAsset("templates/serializers/additionalpropertiesserializer.gotmpl"),
|
||||
"aliasedserializer.gotmpl": MustAsset("templates/serializers/aliasedserializer.gotmpl"),
|
||||
"allofserializer.gotmpl": MustAsset("templates/serializers/allofserializer.gotmpl"),
|
||||
"basetypeserializer.gotmpl": MustAsset("templates/serializers/basetypeserializer.gotmpl"),
|
||||
"marshalbinaryserializer.gotmpl": MustAsset("templates/serializers/marshalbinaryserializer.gotmpl"),
|
||||
"schemaserializer.gotmpl": MustAsset("templates/serializers/schemaserializer.gotmpl"),
|
||||
"subtypeserializer.gotmpl": MustAsset("templates/serializers/subtypeserializer.gotmpl"),
|
||||
"tupleserializer.gotmpl": MustAsset("templates/serializers/tupleserializer.gotmpl"),
|
||||
|
||||
// schema generation template
|
||||
"docstring.gotmpl": MustAsset("templates/docstring.gotmpl"),
|
||||
"schematype.gotmpl": MustAsset("templates/schematype.gotmpl"),
|
||||
"schemabody.gotmpl": MustAsset("templates/schemabody.gotmpl"),
|
||||
"schema.gotmpl": MustAsset("templates/schema.gotmpl"),
|
||||
"model.gotmpl": MustAsset("templates/model.gotmpl"),
|
||||
"header.gotmpl": MustAsset("templates/header.gotmpl"),
|
||||
|
||||
// simple schema generation helpers templates
|
||||
"simpleschema/defaultsvar.gotmpl": MustAsset("templates/simpleschema/defaultsvar.gotmpl"),
|
||||
"simpleschema/defaultsinit.gotmpl": MustAsset("templates/simpleschema/defaultsinit.gotmpl"),
|
||||
|
||||
"swagger_json_embed.gotmpl": MustAsset("templates/swagger_json_embed.gotmpl"),
|
||||
|
||||
// server templates
|
||||
"server/parameter.gotmpl": MustAsset("templates/server/parameter.gotmpl"),
|
||||
"server/urlbuilder.gotmpl": MustAsset("templates/server/urlbuilder.gotmpl"),
|
||||
"server/responses.gotmpl": MustAsset("templates/server/responses.gotmpl"),
|
||||
"server/operation.gotmpl": MustAsset("templates/server/operation.gotmpl"),
|
||||
"server/builder.gotmpl": MustAsset("templates/server/builder.gotmpl"),
|
||||
"server/server.gotmpl": MustAsset("templates/server/server.gotmpl"),
|
||||
"server/configureapi.gotmpl": MustAsset("templates/server/configureapi.gotmpl"),
|
||||
"server/autoconfigureapi.gotmpl": MustAsset("templates/server/autoconfigureapi.gotmpl"),
|
||||
"server/main.gotmpl": MustAsset("templates/server/main.gotmpl"),
|
||||
"server/doc.gotmpl": MustAsset("templates/server/doc.gotmpl"),
|
||||
|
||||
// client templates
|
||||
"client/parameter.gotmpl": MustAsset("templates/client/parameter.gotmpl"),
|
||||
"client/response.gotmpl": MustAsset("templates/client/response.gotmpl"),
|
||||
"client/client.gotmpl": MustAsset("templates/client/client.gotmpl"),
|
||||
"client/facade.gotmpl": MustAsset("templates/client/facade.gotmpl"),
|
||||
|
||||
"markdown/docs.gotmpl": MustAsset("templates/markdown/docs.gotmpl"),
|
||||
|
||||
// cli templates
|
||||
"cli/cli.gotmpl": MustAsset("templates/cli/cli.gotmpl"),
|
||||
"cli/main.gotmpl": MustAsset("templates/cli/main.gotmpl"),
|
||||
"cli/modelcli.gotmpl": MustAsset("templates/cli/modelcli.gotmpl"),
|
||||
"cli/operation.gotmpl": MustAsset("templates/cli/operation.gotmpl"),
|
||||
"cli/registerflag.gotmpl": MustAsset("templates/cli/registerflag.gotmpl"),
|
||||
"cli/retrieveflag.gotmpl": MustAsset("templates/cli/retrieveflag.gotmpl"),
|
||||
"cli/schema.gotmpl": MustAsset("templates/cli/schema.gotmpl"),
|
||||
"cli/completion.gotmpl": MustAsset("templates/cli/completion.gotmpl"),
|
||||
}
|
||||
}
|
||||
|
||||
func defaultProtectedTemplates() map[string]bool {
|
||||
return map[string]bool{
|
||||
"dereffedSchemaType": true,
|
||||
"docstring": true,
|
||||
"header": true,
|
||||
"mapvalidator": true,
|
||||
"model": true,
|
||||
"modelvalidator": true,
|
||||
"objectvalidator": true,
|
||||
"primitivefieldvalidator": true,
|
||||
"privstructfield": true,
|
||||
"privtuplefield": true,
|
||||
"propertyValidationDocString": true,
|
||||
"propertyvalidator": true,
|
||||
"schema": true,
|
||||
"schemaBody": true,
|
||||
"schemaType": true,
|
||||
"schemabody": true,
|
||||
"schematype": true,
|
||||
"schemavalidator": true,
|
||||
"serverDoc": true,
|
||||
"slicevalidator": true,
|
||||
"structfield": true,
|
||||
"structfieldIface": true,
|
||||
"subTypeBody": true,
|
||||
"swaggerJsonEmbed": true,
|
||||
"tuplefield": true,
|
||||
"tuplefieldIface": true,
|
||||
"typeSchemaType": true,
|
||||
"simpleschemaDefaultsvar": true,
|
||||
"simpleschemaDefaultsinit": true,
|
||||
|
||||
// validation helpers
|
||||
"validationCustomformat": true,
|
||||
"validationPrimitive": true,
|
||||
"validationStructfield": true,
|
||||
"withBaseTypeBody": true,
|
||||
"withoutBaseTypeBody": true,
|
||||
"validationMinimum": true,
|
||||
"validationMaximum": true,
|
||||
"validationMultipleOf": true,
|
||||
|
||||
// all serializers
|
||||
"additionalPropertiesSerializer": true,
|
||||
"tupleSerializer": true,
|
||||
"schemaSerializer": true,
|
||||
"hasDiscriminatedSerializer": true,
|
||||
"discriminatedSerializer": true,
|
||||
}
|
||||
}
|
||||
|
||||
// AddFile adds a file to the default repository. It will create a new template based on the filename.
|
||||
// It trims the .gotmpl from the end and converts the name using swag.ToJSONName. This will strip
|
||||
// directory separators and Camelcase the next letter.
|
||||
// e.g validation/primitive.gotmpl will become validationPrimitive
|
||||
//
|
||||
// If the file contains a definition for a template that is protected the whole file will not be added
|
||||
func AddFile(name, data string) error {
|
||||
return templates.addFile(name, data, false)
|
||||
}
|
||||
|
||||
// NewRepository creates a new template repository with the provided functions defined
|
||||
func NewRepository(funcs template.FuncMap) *Repository {
|
||||
repo := Repository{
|
||||
files: make(map[string]string),
|
||||
templates: make(map[string]*template.Template),
|
||||
funcs: funcs,
|
||||
}
|
||||
|
||||
if repo.funcs == nil {
|
||||
repo.funcs = make(template.FuncMap)
|
||||
}
|
||||
|
||||
return &repo
|
||||
}
|
||||
|
||||
// Repository is the repository for the generator templates
|
||||
type Repository struct {
|
||||
files map[string]string
|
||||
templates map[string]*template.Template
|
||||
funcs template.FuncMap
|
||||
allowOverride bool
|
||||
mux sync.Mutex
|
||||
}
|
||||
|
||||
// ShallowClone a repository.
|
||||
//
|
||||
// Clones the maps of files and templates, so as to be able to use
|
||||
// the cloned repo concurrently.
|
||||
func (t *Repository) ShallowClone() *Repository {
|
||||
clone := &Repository{
|
||||
files: make(map[string]string, len(t.files)),
|
||||
templates: make(map[string]*template.Template, len(t.templates)),
|
||||
funcs: t.funcs,
|
||||
allowOverride: t.allowOverride,
|
||||
}
|
||||
|
||||
t.mux.Lock()
|
||||
defer t.mux.Unlock()
|
||||
|
||||
for k, file := range t.files {
|
||||
clone.files[k] = file
|
||||
}
|
||||
for k, tpl := range t.templates {
|
||||
clone.templates[k] = tpl
|
||||
}
|
||||
return clone
|
||||
}
|
||||
|
||||
// LoadDefaults will load the embedded templates
|
||||
func (t *Repository) LoadDefaults() {
|
||||
|
||||
for name, asset := range assets {
|
||||
if err := t.addFile(name, string(asset), true); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// LoadDir will walk the specified path and add each .gotmpl file it finds to the repository
|
||||
func (t *Repository) LoadDir(templatePath string) error {
|
||||
err := filepath.Walk(templatePath, func(path string, info os.FileInfo, err error) error {
|
||||
|
||||
if strings.HasSuffix(path, ".gotmpl") {
|
||||
if assetName, e := filepath.Rel(templatePath, path); e == nil {
|
||||
if data, e := os.ReadFile(path); e == nil {
|
||||
if ee := t.AddFile(assetName, string(data)); ee != nil {
|
||||
return fmt.Errorf("could not add template: %v", ee)
|
||||
}
|
||||
}
|
||||
// Non-readable files are skipped
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Non-template files are skipped
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not complete template processing in directory \"%s\": %v", templatePath, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadContrib loads template from contrib directory
|
||||
func (t *Repository) LoadContrib(name string) error {
|
||||
log.Printf("loading contrib %s", name)
|
||||
const pathPrefix = "templates/contrib/"
|
||||
basePath := pathPrefix + name
|
||||
filesAdded := 0
|
||||
for _, aname := range AssetNames() {
|
||||
if !strings.HasSuffix(aname, ".gotmpl") {
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(aname, basePath) {
|
||||
target := aname[len(basePath)+1:]
|
||||
err := t.addFile(target, string(MustAsset(aname)), true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Printf("added contributed template %s from %s", target, aname)
|
||||
filesAdded++
|
||||
}
|
||||
}
|
||||
if filesAdded == 0 {
|
||||
return fmt.Errorf("no files added from template: %s", name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Repository) addFile(name, data string, allowOverride bool) error {
|
||||
fileName := name
|
||||
name = swag.ToJSONName(strings.TrimSuffix(name, ".gotmpl"))
|
||||
|
||||
templ, err := template.New(name).Funcs(t.funcs).Parse(data)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load template %s: %v", name, err)
|
||||
}
|
||||
|
||||
// check if any protected templates are defined
|
||||
if !allowOverride && !t.allowOverride {
|
||||
for _, template := range templ.Templates() {
|
||||
if protectedTemplates[template.Name()] {
|
||||
return fmt.Errorf("cannot overwrite protected template %s", template.Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add each defined template into the cache
|
||||
for _, template := range templ.Templates() {
|
||||
|
||||
t.files[template.Name()] = fileName
|
||||
t.templates[template.Name()] = template.Lookup(template.Name())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MustGet a template by name, panics when fails
|
||||
func (t *Repository) MustGet(name string) *template.Template {
|
||||
tpl, err := t.Get(name)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return tpl
|
||||
}
|
||||
|
||||
// AddFile adds a file to the repository. It will create a new template based on the filename.
|
||||
// It trims the .gotmpl from the end and converts the name using swag.ToJSONName. This will strip
|
||||
// directory separators and Camelcase the next letter.
|
||||
// e.g validation/primitive.gotmpl will become validationPrimitive
|
||||
//
|
||||
// If the file contains a definition for a template that is protected the whole file will not be added
|
||||
func (t *Repository) AddFile(name, data string) error {
|
||||
return t.addFile(name, data, false)
|
||||
}
|
||||
|
||||
// SetAllowOverride allows setting allowOverride after the Repository was initialized
|
||||
func (t *Repository) SetAllowOverride(value bool) {
|
||||
t.allowOverride = value
|
||||
}
|
||||
|
||||
func findDependencies(n parse.Node) []string {
|
||||
|
||||
var deps []string
|
||||
depMap := make(map[string]bool)
|
||||
|
||||
if n == nil {
|
||||
return deps
|
||||
}
|
||||
|
||||
switch node := n.(type) {
|
||||
case *parse.ListNode:
|
||||
if node != nil && node.Nodes != nil {
|
||||
for _, nn := range node.Nodes {
|
||||
for _, dep := range findDependencies(nn) {
|
||||
depMap[dep] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
case *parse.IfNode:
|
||||
for _, dep := range findDependencies(node.BranchNode.List) {
|
||||
depMap[dep] = true
|
||||
}
|
||||
for _, dep := range findDependencies(node.BranchNode.ElseList) {
|
||||
depMap[dep] = true
|
||||
}
|
||||
|
||||
case *parse.RangeNode:
|
||||
for _, dep := range findDependencies(node.BranchNode.List) {
|
||||
depMap[dep] = true
|
||||
}
|
||||
for _, dep := range findDependencies(node.BranchNode.ElseList) {
|
||||
depMap[dep] = true
|
||||
}
|
||||
|
||||
case *parse.WithNode:
|
||||
for _, dep := range findDependencies(node.BranchNode.List) {
|
||||
depMap[dep] = true
|
||||
}
|
||||
for _, dep := range findDependencies(node.BranchNode.ElseList) {
|
||||
depMap[dep] = true
|
||||
}
|
||||
|
||||
case *parse.TemplateNode:
|
||||
depMap[node.Name] = true
|
||||
}
|
||||
|
||||
for dep := range depMap {
|
||||
deps = append(deps, dep)
|
||||
}
|
||||
|
||||
return deps
|
||||
|
||||
}
|
||||
|
||||
func (t *Repository) flattenDependencies(templ *template.Template, dependencies map[string]bool) map[string]bool {
|
||||
if dependencies == nil {
|
||||
dependencies = make(map[string]bool)
|
||||
}
|
||||
|
||||
deps := findDependencies(templ.Tree.Root)
|
||||
|
||||
for _, d := range deps {
|
||||
if _, found := dependencies[d]; !found {
|
||||
|
||||
dependencies[d] = true
|
||||
|
||||
if tt := t.templates[d]; tt != nil {
|
||||
dependencies = t.flattenDependencies(tt, dependencies)
|
||||
}
|
||||
}
|
||||
|
||||
dependencies[d] = true
|
||||
|
||||
}
|
||||
|
||||
return dependencies
|
||||
|
||||
}
|
||||
|
||||
func (t *Repository) addDependencies(templ *template.Template) (*template.Template, error) {
|
||||
|
||||
name := templ.Name()
|
||||
|
||||
deps := t.flattenDependencies(templ, nil)
|
||||
|
||||
for dep := range deps {
|
||||
|
||||
if dep == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
tt := templ.Lookup(dep)
|
||||
|
||||
// Check if we have it
|
||||
if tt == nil {
|
||||
tt = t.templates[dep]
|
||||
|
||||
// Still don't have it, return an error
|
||||
if tt == nil {
|
||||
return templ, fmt.Errorf("could not find template %s", dep)
|
||||
}
|
||||
var err error
|
||||
|
||||
// Add it to the parse tree
|
||||
templ, err = templ.AddParseTree(dep, tt.Tree)
|
||||
|
||||
if err != nil {
|
||||
return templ, fmt.Errorf("dependency error: %v", err)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return templ.Lookup(name), nil
|
||||
}
|
||||
|
||||
// Get will return the named template from the repository, ensuring that all dependent templates are loaded.
|
||||
// It will return an error if a dependent template is not defined in the repository.
|
||||
func (t *Repository) Get(name string) (*template.Template, error) {
|
||||
templ, found := t.templates[name]
|
||||
|
||||
if !found {
|
||||
return templ, fmt.Errorf("template doesn't exist %s", name)
|
||||
}
|
||||
|
||||
return t.addDependencies(templ)
|
||||
}
|
||||
|
||||
// DumpTemplates prints out a dump of all the defined templates, where they are defined and what their dependencies are.
|
||||
func (t *Repository) DumpTemplates() {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
fmt.Fprintln(buf, "\n# Templates")
|
||||
for name, templ := range t.templates {
|
||||
fmt.Fprintf(buf, "## %s\n", name)
|
||||
fmt.Fprintf(buf, "Defined in `%s`\n", t.files[name])
|
||||
|
||||
if deps := findDependencies(templ.Tree.Root); len(deps) > 0 {
|
||||
|
||||
fmt.Fprintf(buf, "####requires \n - %v\n\n\n", strings.Join(deps, "\n - "))
|
||||
}
|
||||
fmt.Fprintln(buf, "\n---")
|
||||
}
|
||||
log.Println(buf.String())
|
||||
}
|
||||
|
||||
// FuncMap functions
|
||||
|
||||
func asJSON(data interface{}) (string, error) {
|
||||
b, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
func asPrettyJSON(data interface{}) (string, error) {
|
||||
b, err := json.MarshalIndent(data, "", " ")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
func pluralizeFirstWord(arg string) string {
|
||||
sentence := strings.Split(arg, " ")
|
||||
if len(sentence) == 1 {
|
||||
return inflect.Pluralize(arg)
|
||||
}
|
||||
|
||||
return inflect.Pluralize(sentence[0]) + " " + strings.Join(sentence[1:], " ")
|
||||
}
|
||||
|
||||
func dropPackage(str string) string {
|
||||
parts := strings.Split(str, ".")
|
||||
return parts[len(parts)-1]
|
||||
}
|
||||
|
||||
// return true if the GoType str contains pkg. For example "model.MyType" -> true, "MyType" -> false
|
||||
func containsPkgStr(str string) bool {
|
||||
dropped := dropPackage(str)
|
||||
return !(dropped == str)
|
||||
}
|
||||
|
||||
func padSurround(entry, padWith string, i, ln int) string {
|
||||
var res []string
|
||||
if i > 0 {
|
||||
for j := 0; j < i; j++ {
|
||||
res = append(res, padWith)
|
||||
}
|
||||
}
|
||||
res = append(res, entry)
|
||||
tot := ln - i - 1
|
||||
for j := 0; j < tot; j++ {
|
||||
res = append(res, padWith)
|
||||
}
|
||||
return strings.Join(res, ",")
|
||||
}
|
||||
|
||||
func padComment(str string, pads ...string) string {
|
||||
// pads specifes padding to indent multi line comments.Defaults to one space
|
||||
pad := " "
|
||||
lines := strings.Split(str, "\n")
|
||||
if len(pads) > 0 {
|
||||
pad = strings.Join(pads, "")
|
||||
}
|
||||
return (strings.Join(lines, "\n//"+pad))
|
||||
}
|
||||
|
||||
func blockComment(str string) string {
|
||||
return strings.ReplaceAll(str, "*/", "[*]/")
|
||||
}
|
||||
|
||||
func pascalize(arg string) string {
|
||||
runes := []rune(arg)
|
||||
switch len(runes) {
|
||||
case 0:
|
||||
return "Empty"
|
||||
case 1: // handle special case when we have a single rune that is not handled by swag.ToGoName
|
||||
switch runes[0] {
|
||||
case '+', '-', '#', '_', '*', '/', '=': // those cases are handled differently than swag utility
|
||||
return prefixForName(arg)
|
||||
}
|
||||
}
|
||||
return swag.ToGoName(swag.ToGoName(arg)) // want to remove spaces
|
||||
}
|
||||
|
||||
func prefixForName(arg string) string {
|
||||
first := []rune(arg)[0]
|
||||
if len(arg) == 0 || unicode.IsLetter(first) {
|
||||
return ""
|
||||
}
|
||||
switch first {
|
||||
case '+':
|
||||
return "Plus"
|
||||
case '-':
|
||||
return "Minus"
|
||||
case '#':
|
||||
return "HashTag"
|
||||
case '*':
|
||||
return "Asterisk"
|
||||
case '/':
|
||||
return "ForwardSlash"
|
||||
case '=':
|
||||
return "EqualSign"
|
||||
// other cases ($,@ etc..) handled by swag.ToGoName
|
||||
}
|
||||
return "Nr"
|
||||
}
|
||||
|
||||
func replaceSpecialChar(in rune) string {
|
||||
switch in {
|
||||
case '.':
|
||||
return "-Dot-"
|
||||
case '+':
|
||||
return "-Plus-"
|
||||
case '-':
|
||||
return "-Dash-"
|
||||
case '#':
|
||||
return "-Hashtag-"
|
||||
}
|
||||
return string(in)
|
||||
}
|
||||
|
||||
func cleanupEnumVariant(in string) string {
|
||||
replaced := ""
|
||||
for _, char := range in {
|
||||
replaced += replaceSpecialChar(char)
|
||||
}
|
||||
return replaced
|
||||
}
|
||||
|
||||
func dict(values ...interface{}) (map[string]interface{}, error) {
|
||||
if len(values)%2 != 0 {
|
||||
return nil, fmt.Errorf("expected even number of arguments, got %d", len(values))
|
||||
}
|
||||
dict := make(map[string]interface{}, len(values)/2)
|
||||
for i := 0; i < len(values); i += 2 {
|
||||
key, ok := values[i].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("expected string key, got %+v", values[i])
|
||||
}
|
||||
dict[key] = values[i+1]
|
||||
}
|
||||
return dict, nil
|
||||
}
|
||||
|
||||
func isInteger(arg interface{}) bool {
|
||||
// is integer determines if a value may be represented by an integer
|
||||
switch val := arg.(type) {
|
||||
case int8, int16, int32, int, int64, uint8, uint16, uint32, uint, uint64:
|
||||
return true
|
||||
case *int8, *int16, *int32, *int, *int64, *uint8, *uint16, *uint32, *uint, *uint64:
|
||||
v := reflect.ValueOf(arg)
|
||||
return !v.IsNil()
|
||||
case float64:
|
||||
return math.Round(val) == val
|
||||
case *float64:
|
||||
return val != nil && math.Round(*val) == *val
|
||||
case float32:
|
||||
return math.Round(float64(val)) == float64(val)
|
||||
case *float32:
|
||||
return val != nil && math.Round(float64(*val)) == float64(*val)
|
||||
case string:
|
||||
_, err := strconv.ParseInt(val, 10, 64)
|
||||
return err == nil
|
||||
case *string:
|
||||
if val == nil {
|
||||
return false
|
||||
}
|
||||
_, err := strconv.ParseInt(*val, 10, 64)
|
||||
return err == nil
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func resolvedDocCollectionFormat(cf string, child *GenItems) string {
|
||||
if child == nil {
|
||||
return cf
|
||||
}
|
||||
ccf := cf
|
||||
if ccf == "" {
|
||||
ccf = "csv"
|
||||
}
|
||||
rcf := resolvedDocCollectionFormat(child.CollectionFormat, child.Child)
|
||||
if rcf == "" {
|
||||
return ccf
|
||||
}
|
||||
return ccf + "|" + rcf
|
||||
}
|
||||
|
||||
func resolvedDocType(tn, ft string, child *GenItems) string {
|
||||
if tn == "array" {
|
||||
if child == nil {
|
||||
return "[]any"
|
||||
}
|
||||
return "[]" + resolvedDocType(child.SwaggerType, child.SwaggerFormat, child.Child)
|
||||
}
|
||||
|
||||
if ft != "" {
|
||||
if doc, ok := docFormat[ft]; ok {
|
||||
return doc
|
||||
}
|
||||
return fmt.Sprintf("%s (formatted %s)", ft, tn)
|
||||
}
|
||||
|
||||
return tn
|
||||
}
|
||||
|
||||
func resolvedDocSchemaType(tn, ft string, child *GenSchema) string {
|
||||
if tn == "array" {
|
||||
if child == nil {
|
||||
return "[]any"
|
||||
}
|
||||
return "[]" + resolvedDocSchemaType(child.SwaggerType, child.SwaggerFormat, child.Items)
|
||||
}
|
||||
|
||||
if tn == "object" {
|
||||
if child == nil || child.ElemType == nil {
|
||||
return "map of any"
|
||||
}
|
||||
if child.IsMap {
|
||||
return "map of " + resolvedDocElemType(child.SwaggerType, child.SwaggerFormat, &child.resolvedType)
|
||||
}
|
||||
|
||||
return child.GoType
|
||||
}
|
||||
|
||||
if ft != "" {
|
||||
if doc, ok := docFormat[ft]; ok {
|
||||
return doc
|
||||
}
|
||||
return fmt.Sprintf("%s (formatted %s)", ft, tn)
|
||||
}
|
||||
|
||||
return tn
|
||||
}
|
||||
|
||||
func resolvedDocElemType(tn, ft string, schema *resolvedType) string {
|
||||
if schema == nil {
|
||||
return ""
|
||||
}
|
||||
if schema.IsMap {
|
||||
return "map of " + resolvedDocElemType(schema.ElemType.SwaggerType, schema.ElemType.SwaggerFormat, schema.ElemType)
|
||||
}
|
||||
|
||||
if schema.IsArray {
|
||||
return "[]" + resolvedDocElemType(schema.ElemType.SwaggerType, schema.ElemType.SwaggerFormat, schema.ElemType)
|
||||
}
|
||||
|
||||
if ft != "" {
|
||||
if doc, ok := docFormat[ft]; ok {
|
||||
return doc
|
||||
}
|
||||
return fmt.Sprintf("%s (formatted %s)", ft, tn)
|
||||
}
|
||||
|
||||
return tn
|
||||
}
|
||||
|
||||
func httpStatus(code int) string {
|
||||
if name, ok := runtime.Statuses[code]; ok {
|
||||
return name
|
||||
}
|
||||
// non-standard codes deserve some name
|
||||
return fmt.Sprintf("Status %d", code)
|
||||
}
|
||||
|
||||
func gt0(in *int64) bool {
|
||||
// gt0 returns true if the *int64 points to a value > 0
|
||||
// NOTE: plain {{ gt .MinProperties 0 }} just refuses to work normally
|
||||
// with a pointer
|
||||
return in != nil && *in > 0
|
||||
}
|
||||
242
vendor/github.com/go-swagger/go-swagger/generator/templates/cli/cli.gotmpl
generated
vendored
Normal file
242
vendor/github.com/go-swagger/go-swagger/generator/templates/cli/cli.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
|
||||
{{ if .Copyright -}}// {{ comment .Copyright -}}{{ end }}
|
||||
|
||||
|
||||
package {{ .GenOpts.CliPackage }}
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
{{ imports .DefaultImports }}
|
||||
{{ imports .Imports }}
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/swag"
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
homedir "github.com/mitchellh/go-homedir"
|
||||
)
|
||||
|
||||
// debug flag indicating that cli should output debug logs
|
||||
var debug bool
|
||||
// config file location
|
||||
var configFile string
|
||||
// dry run flag
|
||||
var dryRun bool
|
||||
|
||||
// name of the executable
|
||||
var exeName string = filepath.Base(os.Args[0])
|
||||
|
||||
// logDebugf writes debug log to stdout
|
||||
func logDebugf(format string, v ...interface{}) {
|
||||
if !debug{
|
||||
return
|
||||
}
|
||||
log.Printf(format, v...)
|
||||
}
|
||||
|
||||
{{/*TODO: make this a swagger cli option*/}}
|
||||
// depth of recursion to construct model flags
|
||||
var maxDepth int = 5
|
||||
|
||||
// makeClient constructs a client object
|
||||
func makeClient(cmd *cobra.Command, args []string) (*client.{{ pascalize .Name }}, error) {
|
||||
hostname := viper.GetString("hostname")
|
||||
viper.SetDefault("base_path", client.DefaultBasePath)
|
||||
basePath := viper.GetString("base_path")
|
||||
scheme := viper.GetString("scheme")
|
||||
|
||||
r := httptransport.New(hostname, basePath, []string{scheme})
|
||||
r.SetDebug(debug)
|
||||
|
||||
{{- /* user might define custom mediatype xxx/json and there is no registered ones to handle. */}}
|
||||
// set custom producer and consumer to use the default ones
|
||||
{{ range .Consumes }}
|
||||
{{ range .AllSerializers }}
|
||||
{{- if stringContains .MediaType "json" }}
|
||||
r.Consumers["{{ .MediaType }}"] = runtime.JSONConsumer()
|
||||
{{- else }}
|
||||
// warning: consumes {{ .MediaType }} is not supported by go-swagger cli yet
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
{{ range .Produces }}
|
||||
{{- range .AllSerializers }}
|
||||
{{- if stringContains .MediaType "json" }}
|
||||
r.Producers["{{ .MediaType }}"] = runtime.JSONProducer()
|
||||
{{- else }}
|
||||
// warning: produces {{ .MediaType }} is not supported by go-swagger cli yet
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
|
||||
{{- if .SecurityDefinitions }}
|
||||
auth, err := makeAuthInfoWriter(cmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r.DefaultAuthentication = auth
|
||||
{{ end }}
|
||||
appCli := client.New(r, strfmt.Default)
|
||||
logDebugf("Server url: %v://%v", scheme, hostname)
|
||||
return appCli, nil
|
||||
}
|
||||
|
||||
// MakeRootCmd returns the root cmd
|
||||
func MakeRootCmd() (*cobra.Command, error) {
|
||||
cobra.OnInitialize(initViperConfigs)
|
||||
|
||||
// Use executable name as the command name
|
||||
rootCmd := &cobra.Command{
|
||||
Use: exeName,
|
||||
}
|
||||
{{/*note: viper binded flag value must be retrieved from viper rather than cmd*/}}
|
||||
// register basic flags
|
||||
rootCmd.PersistentFlags().String("hostname", client.DefaultHost, "hostname of the service")
|
||||
viper.BindPFlag("hostname", rootCmd.PersistentFlags().Lookup("hostname"))
|
||||
rootCmd.PersistentFlags().String("scheme", client.DefaultSchemes[0], fmt.Sprintf("Choose from: %v", client.DefaultSchemes))
|
||||
viper.BindPFlag("scheme", rootCmd.PersistentFlags().Lookup("scheme"))
|
||||
rootCmd.PersistentFlags().String("base-path", client.DefaultBasePath, fmt.Sprintf("For example: %v", client.DefaultBasePath))
|
||||
viper.BindPFlag("base_path", rootCmd.PersistentFlags().Lookup("base-path"))
|
||||
|
||||
// configure debug flag
|
||||
rootCmd.PersistentFlags().BoolVar(&debug, "debug", false, "output debug logs")
|
||||
// configure config location
|
||||
rootCmd.PersistentFlags().StringVar(&configFile, "config", "", "config file path")
|
||||
// configure dry run flag
|
||||
rootCmd.PersistentFlags().BoolVar(&dryRun, "dry-run", false, "do not send the request to server")
|
||||
|
||||
// register security flags
|
||||
{{- if .SecurityDefinitions }}
|
||||
if err := registerAuthInoWriterFlags(rootCmd); err != nil{
|
||||
return nil, err
|
||||
}
|
||||
{{- end }}
|
||||
// add all operation groups
|
||||
{{- range .OperationGroups -}}
|
||||
{{- $operationGroupCmdVarName := printf "operationGroup%vCmd" (pascalize .Name) }}
|
||||
{{ $operationGroupCmdVarName }}, err := makeOperationGroup{{ pascalize .Name }}Cmd()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rootCmd.AddCommand({{ $operationGroupCmdVarName }})
|
||||
{{ end }}
|
||||
|
||||
// add cobra completion
|
||||
rootCmd.AddCommand(makeGenCompletionCmd())
|
||||
|
||||
return rootCmd, nil
|
||||
}
|
||||
|
||||
// initViperConfigs initialize viper config using config file in '$HOME/.config/<cli name>/config.<json|yaml...>'
|
||||
// currently hostname, scheme and auth tokens can be specified in this config file.
|
||||
func initViperConfigs() {
|
||||
if configFile != "" {
|
||||
// use user specified config file location
|
||||
viper.SetConfigFile(configFile)
|
||||
}else{
|
||||
// look for default config
|
||||
// Find home directory.
|
||||
home, err := homedir.Dir()
|
||||
cobra.CheckErr(err)
|
||||
|
||||
// Search config in home directory with name ".cobra" (without extension).
|
||||
viper.AddConfigPath(path.Join(home, ".config", exeName))
|
||||
viper.SetConfigName("config")
|
||||
}
|
||||
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
logDebugf("Error: loading config file: %v", err)
|
||||
return
|
||||
}
|
||||
logDebugf("Using config file: %v", viper.ConfigFileUsed())
|
||||
}
|
||||
|
||||
{{- if .SecurityDefinitions }}
|
||||
{{- /*youyuan: rework this since spec may define multiple auth schemes.
|
||||
cli needs to detect which one user passed rather than add all of them.*/}}
|
||||
// registerAuthInoWriterFlags registers all flags needed to perform authentication
|
||||
func registerAuthInoWriterFlags(cmd *cobra.Command) error {
|
||||
{{- range .SecurityDefinitions }}
|
||||
/*{{.Name}} {{.Description}}*/
|
||||
{{- if .IsBasicAuth }}
|
||||
cmd.PersistentFlags().String("username", "", "username for basic auth")
|
||||
viper.BindPFlag("username", cmd.PersistentFlags().Lookup("username"))
|
||||
cmd.PersistentFlags().String("password", "", "password for basic auth")
|
||||
viper.BindPFlag("password", cmd.PersistentFlags().Lookup("password"))
|
||||
{{- end }}
|
||||
{{- if .IsAPIKeyAuth }}
|
||||
cmd.PersistentFlags().String("{{.Name}}", "", `{{.Description}}`)
|
||||
viper.BindPFlag("{{.Name}}", cmd.PersistentFlags().Lookup("{{.Name}}"))
|
||||
{{- end }}
|
||||
{{- if .IsOAuth2 }}
|
||||
// oauth2: let user provide the token in a flag, rather than implement the logic to fetch the token.
|
||||
cmd.PersistentFlags().String("oauth2-token", "", `{{.Description}}`)
|
||||
viper.BindPFlag("oauth2-token", cmd.PersistentFlags().Lookup("oauth2-token"))
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
return nil
|
||||
}
|
||||
|
||||
// makeAuthInfoWriter retrieves cmd flags and construct an auth info writer
|
||||
func makeAuthInfoWriter(cmd *cobra.Command) (runtime.ClientAuthInfoWriter, error) {
|
||||
auths := []runtime.ClientAuthInfoWriter{}
|
||||
{{- range .SecurityDefinitions }}
|
||||
/*{{.Name}} {{.Description}}*/
|
||||
{{- if .IsBasicAuth }}
|
||||
if viper.IsSet("username") {
|
||||
usr := viper.GetString("username")
|
||||
if !viper.IsSet("password"){
|
||||
return nil, fmt.Errorf("Basic Auth password for user [%v] is not provided.", usr)
|
||||
}
|
||||
pwd := viper.GetString("password")
|
||||
auths = append(auths, httptransport.BasicAuth(usr,pwd))
|
||||
}
|
||||
{{- end }}
|
||||
{{- if .IsAPIKeyAuth }}
|
||||
if viper.IsSet("{{.Name}}") {
|
||||
{{ pascalize .Name }}Key := viper.GetString("{{.Name}}")
|
||||
auths = append(auths, httptransport.APIKeyAuth("{{.Name}}", "{{.In}}", {{ pascalize .Name }}Key))
|
||||
}
|
||||
{{- end }}
|
||||
{{- if .IsOAuth2 }}
|
||||
if viper.IsSet("oauth2-token") {
|
||||
// oauth2 workflow for generated CLI is not ideal.
|
||||
// If you have suggestions on how to support it, raise an issue here: https://github.com/go-swagger/go-swagger/issues
|
||||
// This will be added to header: "Authorization: Bearer {oauth2-token value}"
|
||||
token := viper.GetString("oauth2-token")
|
||||
auths = append(auths, httptransport.BearerToken(token))
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
if len(auths) == 0 {
|
||||
logDebugf("Warning: No auth params detected.")
|
||||
return nil, nil
|
||||
}
|
||||
// compose all auths together
|
||||
return httptransport.Compose(auths...), nil
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{ range .OperationGroups -}}
|
||||
func makeOperationGroup{{ pascalize .Name }}Cmd() (*cobra.Command, error) {
|
||||
{{- $operationGroupCmdVarName := printf "operationGroup%vCmd" (pascalize .Name) }}
|
||||
{{ $operationGroupCmdVarName }} := &cobra.Command{
|
||||
Use: "{{ .Name }}",
|
||||
Long: `{{ .Description }}`,
|
||||
}
|
||||
{{ range .Operations }}
|
||||
{{- $operationCmdVarName := printf "operation%vCmd" (pascalize .Name) }}
|
||||
{{ $operationCmdVarName }}, err := makeOperation{{pascalize .Package}}{{ pascalize .Name }}Cmd()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
{{ $operationGroupCmdVarName }}.AddCommand({{ $operationCmdVarName }})
|
||||
{{ end }}
|
||||
return {{ $operationGroupCmdVarName }}, nil
|
||||
}
|
||||
{{ end }} {{/*operation group*/}}
|
||||
77
vendor/github.com/go-swagger/go-swagger/generator/templates/cli/completion.gotmpl
generated
vendored
Normal file
77
vendor/github.com/go-swagger/go-swagger/generator/templates/cli/completion.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
|
||||
{{ if .Copyright -}}// {{ comment .Copyright -}}{{ end }}
|
||||
|
||||
|
||||
package {{ .GenOpts.CliPackage }}
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import(
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func makeGenCompletionCmd() *cobra.Command{
|
||||
|
||||
var completionCmd = &cobra.Command{
|
||||
Use: "completion [bash|zsh|fish|powershell]",
|
||||
Short: "Generate completion script",
|
||||
Long: `To load completions:
|
||||
|
||||
Bash:
|
||||
|
||||
$ source <(yourprogram completion bash)
|
||||
|
||||
# To load completions for each session, execute once:
|
||||
# Linux:
|
||||
$ yourprogram completion bash > /etc/bash_completion.d/yourprogram
|
||||
# macOS:
|
||||
$ yourprogram completion bash > /usr/local/etc/bash_completion.d/yourprogram
|
||||
|
||||
Zsh:
|
||||
|
||||
# If shell completion is not already enabled in your environment,
|
||||
# you will need to enable it. You can execute the following once:
|
||||
|
||||
$ echo "autoload -U compinit; compinit" >> ~/.zshrc
|
||||
|
||||
# To load completions for each session, execute once:
|
||||
$ yourprogram completion zsh > "${fpath[1]}/_yourprogram"
|
||||
|
||||
# You will need to start a new shell for this setup to take effect.
|
||||
|
||||
fish:
|
||||
|
||||
$ yourprogram completion fish | source
|
||||
|
||||
# To load completions for each session, execute once:
|
||||
$ yourprogram completion fish > ~/.config/fish/completions/yourprogram.fish
|
||||
|
||||
PowerShell:
|
||||
|
||||
PS> yourprogram completion powershell | Out-String | Invoke-Expression
|
||||
|
||||
# To load completions for every new session, run:
|
||||
PS> yourprogram completion powershell > yourprogram.ps1
|
||||
# and source this file from your PowerShell profile.
|
||||
`,
|
||||
DisableFlagsInUseLine: true,
|
||||
ValidArgs: []string{"bash", "zsh", "fish", "powershell"},
|
||||
Args: cobra.ExactValidArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
switch args[0] {
|
||||
case "bash":
|
||||
cmd.Root().GenBashCompletion(os.Stdout)
|
||||
case "zsh":
|
||||
cmd.Root().GenZshCompletion(os.Stdout)
|
||||
case "fish":
|
||||
cmd.Root().GenFishCompletion(os.Stdout, true)
|
||||
case "powershell":
|
||||
cmd.Root().GenPowerShellCompletionWithDesc(os.Stdout)
|
||||
}
|
||||
},
|
||||
}
|
||||
return completionCmd
|
||||
}
|
||||
28
vendor/github.com/go-swagger/go-swagger/generator/templates/cli/main.gotmpl
generated
vendored
Normal file
28
vendor/github.com/go-swagger/go-swagger/generator/templates/cli/main.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
|
||||
{{ if .Copyright -}}// {{ comment .Copyright -}}{{ end }}
|
||||
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
{{ imports .DefaultImports }}
|
||||
{{ imports .Imports }}
|
||||
)
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
func main() {
|
||||
rootCmd,err := cli.MakeRootCmd()
|
||||
if err != nil {
|
||||
fmt.Println("Cmd construction error: ", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
25
vendor/github.com/go-swagger/go-swagger/generator/templates/cli/modelcli.gotmpl
generated
vendored
Normal file
25
vendor/github.com/go-swagger/go-swagger/generator/templates/cli/modelcli.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
|
||||
{{ if .Copyright -}}// {{ comment .Copyright -}}{{ end }}
|
||||
|
||||
|
||||
package cli
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
|
||||
import (
|
||||
{{ imports .DefaultImports }}
|
||||
{{ imports .Imports }}
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// Schema cli for {{.GoType}}
|
||||
{{ template "modelschemacli" .}}
|
||||
|
||||
{{ range .ExtraSchemas }}
|
||||
// Extra schema cli for {{.GoType}}
|
||||
{{ template "modelschemacli" .}}
|
||||
{{ end }}
|
||||
230
vendor/github.com/go-swagger/go-swagger/generator/templates/cli/operation.gotmpl
generated
vendored
Normal file
230
vendor/github.com/go-swagger/go-swagger/generator/templates/cli/operation.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
|
||||
{{ if .Copyright -}}// {{ comment .Copyright -}}{{ end }}
|
||||
|
||||
{{- /*TODO: do not hardcode cli pkg*/}}
|
||||
package cli
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
{{ imports .DefaultImports }}
|
||||
{{ imports .Imports }}
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/swag"
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
)
|
||||
|
||||
// makeOperation{{pascalize .Package}}{{ pascalize .Name }}Cmd returns a cmd to handle operation {{ camelize .Name }}
|
||||
func makeOperation{{pascalize .Package}}{{ pascalize .Name }}Cmd() (*cobra.Command, error) {
|
||||
cmd := &cobra.Command{
|
||||
Use: "{{ .Name }}",
|
||||
Short: `{{ escapeBackticks .Description}}`,
|
||||
RunE: runOperation{{pascalize .Package}}{{ pascalize .Name }},
|
||||
}
|
||||
|
||||
if err := registerOperation{{pascalize .Package}}{{ pascalize .Name }}ParamFlags(cmd); err != nil{
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
{{ $operationGroup := .Package }}
|
||||
{{ $operation := .Name }}
|
||||
{{ $operationPkgAlias := .PackageAlias }}
|
||||
// runOperation{{pascalize $operationGroup }}{{ pascalize $operation }} uses cmd flags to call endpoint api
|
||||
func runOperation{{pascalize $operationGroup }}{{ pascalize $operation }}(cmd *cobra.Command, args []string) error{
|
||||
appCli, err := makeClient(cmd, args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// retrieve flag values from cmd and fill params
|
||||
params := {{ .PackageAlias }}.New{{ pascalize .Name}}Params()
|
||||
{{- range .Params }}
|
||||
if err, _ := retrieveOperation{{pascalize $operationGroup }}{{ pascalize $operation }}{{ pascalize .Name }}Flag(params, "", cmd); err != nil{
|
||||
return err
|
||||
}
|
||||
{{- end }} {{/*Params*/}}
|
||||
if dryRun {
|
||||
{{/* Note: dry run is not very useful for now, but useful when validation is added in future*/}}
|
||||
logDebugf("dry-run flag specified. Skip sending request.")
|
||||
return nil
|
||||
}
|
||||
// make request and then print result
|
||||
{{- /*Package string is the operation name*/}}
|
||||
msgStr, err := parseOperation{{pascalize .Package}}{{ pascalize .Name }}Result(appCli.{{- pascalize .Package }}.{{ pascalize .Name }}(params {{- if .Authorized}}, nil{{ end }}{{ if .HasStreamingResponse }}, &bytes.Buffer{}{{ end }}))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !debug{
|
||||
{{/* In debug mode content should have been printed in transport layer, so do not print again*/}}
|
||||
fmt.Println(msgStr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// registerOperation{{pascalize $operationGroup }}{{ pascalize $operation }}ParamFlags registers all flags needed to fill params
|
||||
func registerOperation{{pascalize $operationGroup }}{{ pascalize $operation }}ParamFlags(cmd *cobra.Command) error {
|
||||
{{- range .Params }}
|
||||
if err := registerOperation{{pascalize $operationGroup }}{{ pascalize $operation }}{{pascalize .Name }}ParamFlags("", cmd); err != nil{
|
||||
return err
|
||||
}
|
||||
{{- end }}
|
||||
return nil
|
||||
}
|
||||
|
||||
{{/*register functions for each fields in this operation*/}}
|
||||
{{- range .Params }}
|
||||
func registerOperation{{pascalize $operationGroup }}{{ pascalize $operation }}{{pascalize .Name }}ParamFlags(cmdPrefix string, cmd *cobra.Command) error{
|
||||
{{- if .IsPrimitive }}
|
||||
{{ template "primitiveregistrator" . }}
|
||||
{{- else if .IsArray }}
|
||||
{{ template "arrayregistrator" . }}
|
||||
{{- else if and .IsBodyParam .Schema (not .IsArray) (not .IsMap) (not .IsStream) }}
|
||||
{{ template "modelparamstringregistrator" . }}
|
||||
{{ template "modelparamregistrator" . }}
|
||||
{{/* Do not mark body flag as required, since the individial flag for body field will be added separately */}}
|
||||
{{- else }}
|
||||
// warning: go type {{ .GoType }} is not supported by go-swagger cli yet.
|
||||
{{- end }}
|
||||
return nil
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{/*functions to retreive each field of params*/}}
|
||||
{{- range .Params }}
|
||||
func retrieveOperation{{pascalize $operationGroup }}{{ pascalize $operation }}{{ pascalize .Name }}Flag(m *{{ $operationPkgAlias }}.{{ pascalize $operation }}Params, cmdPrefix string, cmd *cobra.Command) (error,bool){
|
||||
retAdded := false
|
||||
{{- $flagStr := .Name }}
|
||||
{{- $flagValueVar := printf "%vValue" (camelize .Name) }}
|
||||
{{- /*only set the param if user set the flag*/}}
|
||||
if cmd.Flags().Changed("{{ $flagStr }}") {
|
||||
{{- if .IsPrimitive }}
|
||||
{{ template "primitiveretriever" . }}
|
||||
{{- else if .IsArray }}
|
||||
{{ template "arrayretriever" . }}
|
||||
{{- else if .IsMap }}
|
||||
// warning: {{ .Name }} map type {{.GoType}} is not supported by go-swagger cli yet
|
||||
{{- else if and .IsBodyParam .Schema .IsComplexObject (not .IsStream) }}
|
||||
{{- /*schema payload can be passed in cmd as a string and here is unmarshalled to model struct and attached in params*/}}
|
||||
// Read {{ $flagStr }} string from cmd and unmarshal
|
||||
{{ $flagValueVar }}Str, err := cmd.Flags().GetString("{{ $flagStr }}")
|
||||
if err != nil {
|
||||
return err, false
|
||||
}
|
||||
{{/*Note anonymous body schema is not pointer*/}}
|
||||
{{ $flagValueVar }} := {{if containsPkgStr .GoType}}{{ .GoType }}{{else}}{{ .Pkg }}.{{.GoType}}{{ end }}{}
|
||||
if err := json.Unmarshal([]byte({{ $flagValueVar }}Str), &{{ $flagValueVar }}); err!= nil{
|
||||
return fmt.Errorf("cannot unmarshal {{ $flagStr }} string in {{.GoType}}: %v", err), false
|
||||
}
|
||||
m.{{ .ID }} = {{- if .IsNullable }}&{{- end }}{{ $flagValueVar }}
|
||||
{{- else }}
|
||||
// warning: {{.GoType}} is not supported by go-swagger cli yet
|
||||
{{- end }} {{/*end go type case*/}}
|
||||
}
|
||||
{{- if and .IsBodyParam .Schema .IsComplexObject (not .IsArray) (not .IsMap) (not .IsStream) }}
|
||||
{{- /* Add flags to capture fields in Body. If previously Body struct was constructed in unmarshalling body string,
|
||||
then reuse the struct, otherwise construct an empty value struct to fill. Here body field flags overwrites
|
||||
unmarshalled body string values. */}}
|
||||
{{- $flagModelVar := printf "%vModel" (camelize $flagValueVar) }}
|
||||
{{ $flagModelVar }} := m.{{ .ID }}
|
||||
if swag.IsZero({{ $flagModelVar }}){
|
||||
{{ $flagModelVar }} = {{- if .IsNullable }}&{{- end }}{{if containsPkgStr .GoType}}{{ .GoType }}{{else}}{{ .Pkg }}.{{.GoType}}{{ end }}{}
|
||||
}
|
||||
{{- /*Only attach the body struct in params if user passed some flag filling some body fields.*/}}
|
||||
{{- /* add "&" to $flagModelVar when it is not nullable because the retrieve method always expects a pointer */}}
|
||||
err, added := retrieveModel{{ pascalize (dropPackage .GoType) }}Flags(0, {{if not .IsNullable}}&{{end}}{{ $flagModelVar }}, "{{ camelize (dropPackage .GoType) }}", cmd)
|
||||
if err != nil{
|
||||
return err, false
|
||||
}
|
||||
if added {
|
||||
m.{{.ID}} = {{ $flagModelVar }}
|
||||
}
|
||||
if dryRun && debug {
|
||||
{{/* dry run we don't get trasnport debug strings, so print it here*/}}
|
||||
{{- $bodyDebugVar := printf "%vDebugBytes" (camelize $flagValueVar) }}
|
||||
{{ $bodyDebugVar }}, err := json.Marshal(m.{{.ID}})
|
||||
if err != nil{
|
||||
return err, false
|
||||
}
|
||||
logDebugf("{{.ID }} dry-run payload: %v", string({{ $bodyDebugVar }}))
|
||||
}
|
||||
retAdded = retAdded || added
|
||||
{{/*body debug string will be printed in transport layer*/}}
|
||||
{{- end }}
|
||||
return nil, retAdded
|
||||
}
|
||||
{{- end }} {{/*Params*/}}
|
||||
|
||||
// parseOperation{{pascalize .Package}}{{ pascalize .Name }}Result parses request result and return the string content
|
||||
{{- /*TODO: handle multiple success response case*/}}
|
||||
func parseOperation{{pascalize .Package}}{{ pascalize .Name }}Result({{- if .SuccessResponse }}{{ range $i, $v := .SuccessResponses }} resp{{$i}} *{{$v.Package}}.{{pascalize $v.Name}},{{- end }}{{- end }} respErr error) (string, error){
|
||||
if respErr != nil {
|
||||
{{- /*error is of type default model. If we can cast, then print the resp.*/}}
|
||||
{{ if .DefaultResponse }} {{with .DefaultResponse}}
|
||||
{{ if .Schema }}
|
||||
var iRespD interface{} = respErr
|
||||
respD, ok := iRespD.(*{{ .Package }}.{{ pascalize .Name }})
|
||||
if ok {
|
||||
if !swag.IsZero(respD) && !swag.IsZero(respD.Payload) {
|
||||
msgStr,err := json.Marshal(respD.Payload)
|
||||
if err != nil{
|
||||
return "", err
|
||||
}
|
||||
return string(msgStr), nil
|
||||
}
|
||||
}
|
||||
{{ else }}
|
||||
// Non schema case: warning {{.Name}} is not supported
|
||||
{{ end }}
|
||||
{{ end }} {{ end }}
|
||||
{{- range $i, $v := .Responses }}
|
||||
{{ if .Schema }}
|
||||
var iResp{{$i}} interface{} = respErr
|
||||
resp{{$i}}, ok := iResp{{$i}}.(*{{ .Package }}.{{ pascalize .Name }})
|
||||
if ok {
|
||||
if !swag.IsZero(resp{{$i}}) && !swag.IsZero(resp{{$i}}.Payload) {
|
||||
msgStr,err := json.Marshal(resp{{$i}}.Payload)
|
||||
if err != nil{
|
||||
return "", err
|
||||
}
|
||||
return string(msgStr), nil
|
||||
}
|
||||
}
|
||||
{{ else }}
|
||||
// Non schema case: warning {{.Name}} is not supported
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
return "", respErr
|
||||
}
|
||||
{{- range $i, $v := .SuccessResponses }}
|
||||
{{ if .Schema }}
|
||||
{{- with .Schema}}
|
||||
if !swag.IsZero(resp{{$i}}) && !swag.IsZero(resp{{$i}}.Payload) {
|
||||
{{- if or .IsComplexObject .IsArray .IsMap }}
|
||||
msgStr,err := json.Marshal(resp{{$i}}.Payload)
|
||||
if err != nil{
|
||||
return "", err
|
||||
}
|
||||
{{- else }}
|
||||
msgStr := fmt.Sprintf("%v", resp{{$i}}.Payload)
|
||||
{{- end }}
|
||||
return string(msgStr), nil
|
||||
}
|
||||
{{- end }}
|
||||
{{ else }}
|
||||
// warning: non schema response {{.Name}} is not supported by go-swagger cli yet.
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
{{/*for models defined in params, generate their register and retrieve flags functions*/}}
|
||||
{{- range .ExtraSchemas }}
|
||||
{{ template "modelschemacli" . }}
|
||||
{{- end}}
|
||||
97
vendor/github.com/go-swagger/go-swagger/generator/templates/cli/registerflag.gotmpl
generated
vendored
Normal file
97
vendor/github.com/go-swagger/go-swagger/generator/templates/cli/registerflag.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
{{/*util functions to run or register cmd flags*/}}
|
||||
|
||||
{{ define "flagdescriptionvar" }}
|
||||
{{- $fullDescription := (escapeBackticks .Description) }}
|
||||
{{- if .Required}}
|
||||
{{- $fullDescription = printf "Required. %v" $fullDescription}}
|
||||
{{- end}}
|
||||
{{- if .Enum }}
|
||||
{{- $fullDescription = printf "Enum: %v. %v" (json .Enum) $fullDescription}}
|
||||
{{- end }}
|
||||
{{ camelize .Name }}Description := `{{ $fullDescription }}`
|
||||
{{ end }}
|
||||
|
||||
{{ define "flagnamevar" }}
|
||||
{{- $flagNameVar := printf "%vFlagName" (camelize .Name) }}
|
||||
var {{ $flagNameVar }} string
|
||||
if cmdPrefix == "" {
|
||||
{{ $flagNameVar }} = "{{ .Name }}"
|
||||
}else{
|
||||
{{ $flagNameVar }} = fmt.Sprintf("%v.{{ .Name }}", cmdPrefix)
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
{{ define "flagdefaultvar" }}
|
||||
{{ $defaultVar := printf "%vFlagDefault" (camelize .Name) }}
|
||||
var {{ $defaultVar}} {{ .GoType }} {{ if .Default }}= {{ printf "%#v" .Default }}{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{/* Not used. CLI does not mark flag as required, and required will be checked by validation in future */}}
|
||||
{{/* {{ define "requiredregistrator" }}
|
||||
if err := cmd.MarkPersistentFlagRequired({{ camelize .Name }}FlagName); err != nil{
|
||||
return err
|
||||
}
|
||||
{{ end }} */}}
|
||||
|
||||
{{ define "enumcompletion" }} {{/*only used for primitive types. completion type is always string.*/}}
|
||||
{{ if .Enum }}
|
||||
if err := cmd.RegisterFlagCompletionFunc({{ camelize .Name }}FlagName,
|
||||
func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
var res []string
|
||||
if err := json.Unmarshal([]byte(`{{ json .Enum }}`), &res); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return res, cobra.ShellCompDirectiveDefault
|
||||
}); err != nil{
|
||||
return err
|
||||
}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{/* intended to be used on struct GenSchema with .IsPrimitive */}}
|
||||
{{ define "primitiveregistrator" }}
|
||||
{{- if or (eq .GoType "int64") (eq .GoType "int32") (eq .GoType "string") (eq .GoType "float64") (eq .GoType "float32") (eq .GoType "bool") }}
|
||||
{{ template "flagdescriptionvar" . }}
|
||||
{{ template "flagnamevar" . }}
|
||||
{{ template "flagdefaultvar" . }}
|
||||
_ = cmd.PersistentFlags().{{ pascalize .GoType }}({{ camelize .Name }}FlagName, {{ camelize .Name }}FlagDefault, {{ (camelize .Name) }}Description)
|
||||
{{ template "enumcompletion" . }}
|
||||
{{- else if or (eq .GoType "strfmt.DateTime") (eq .GoType "strfmt.UUID") (eq .GoType "strfmt.ObjectId") }} {{/* read as string */}}
|
||||
{{ template "flagdescriptionvar" . }}
|
||||
{{ template "flagnamevar" . }}
|
||||
_ = cmd.PersistentFlags().String({{ camelize .Name }}FlagName, "", {{ (camelize .Name) }}Description)
|
||||
{{ template "enumcompletion" . }}
|
||||
{{- else }}
|
||||
// warning: primitive {{.Name}} {{.GoType }} is not supported by go-swagger cli yet
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
|
||||
{{ define "arrayregistrator" }}
|
||||
{{- if or (eq .GoType "[]int64") (eq .GoType "[]int32") (eq .GoType "[]string") (eq .GoType "[]float64") (eq .GoType "[]float32") (eq .GoType "[]bool") }}
|
||||
{{ template "flagdescriptionvar" . }}
|
||||
{{ template "flagnamevar" . }}
|
||||
{{ template "flagdefaultvar" . }}
|
||||
_ = cmd.PersistentFlags().{{ pascalize .GoType }}Slice({{ camelize .Name }}FlagName, {{ camelize .Name }}FlagDefault, {{ (camelize .Name) }}Description)
|
||||
{{ template "enumcompletion" . }}
|
||||
{{- else if or (eq .GoType "[]strfmt.DateTime") (eq .GoType "[]strfmt.UUID") (eq .GoType "[]strfmt.ObjectId") }} {{/* read as string */}}
|
||||
{{ template "flagdescriptionvar" . }}
|
||||
{{ template "flagnamevar" . }}
|
||||
_ = cmd.PersistentFlags().StringSlice({{ camelize .Name }}FlagName, []string{}, {{ (camelize .Name) }}Description)
|
||||
{{- else }}
|
||||
// warning: array {{.Name}} {{.GoType }} is not supported by go-swagger cli yet
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
|
||||
|
||||
{{/* each body parameter gets a string flag to input json raw string */}}
|
||||
{{ define "modelparamstringregistrator" }}
|
||||
{{ template "flagnamevar" . }}
|
||||
_ = cmd.PersistentFlags().String({{ camelize .Name }}FlagName, "", "Optional json string for [{{ .Name }}]. {{ .Description }}")
|
||||
{{ end }}
|
||||
|
||||
{{ define "modelparamregistrator" }} {{/* register a param that has a schema */}}
|
||||
// add flags for body {{/*use go type as the flag prefix. There is no good way to determine the original str case in spec*/}}
|
||||
if err := registerModel{{ pascalize (dropPackage .GoType) }}Flags(0, "{{ camelize (dropPackage .GoType) }}", cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
{{ end }}
|
||||
59
vendor/github.com/go-swagger/go-swagger/generator/templates/cli/retrieveflag.gotmpl
generated
vendored
Normal file
59
vendor/github.com/go-swagger/go-swagger/generator/templates/cli/retrieveflag.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
{{/*util functions to retrieve flags*/}}
|
||||
|
||||
{{ define "primitiveretriever" }}
|
||||
{{- $flagValueVar := printf "%vFlagValue" (camelize .Name) }}
|
||||
{{- $flagNameVar := printf "%vFlagName" (camelize .Name )}}
|
||||
{{- if or (eq .GoType "int64") (eq .GoType "int32") (eq .GoType "string") (eq .GoType "float64") (eq .GoType "float32") (eq .GoType "bool") }}
|
||||
{{ template "flagnamevar" . }}
|
||||
{{ $flagValueVar }}, err := cmd.Flags().Get{{pascalize .GoType}}({{ $flagNameVar }})
|
||||
if err != nil{
|
||||
return err, false
|
||||
}
|
||||
{{- /* reciever by convention is m for CLI */}}
|
||||
m.{{ pascalize .Name }} = {{- if .IsNullable }}&{{- end }}{{ $flagValueVar }}
|
||||
{{- else if or (eq .GoType "strfmt.DateTime") (eq .GoType "strfmt.ObjectId") (eq .GoType "strfmt.UUID" ) }} {{/*Get flag value as string, then parse it*/}}
|
||||
{{/*Many of the strfmt types can be added here*/}}
|
||||
{{ template "flagnamevar" . }}
|
||||
{{ $flagValueVar }}Str, err := cmd.Flags().GetString({{ $flagNameVar }})
|
||||
if err != nil{
|
||||
return err, false
|
||||
}
|
||||
var {{ $flagValueVar }} {{ .GoType }}
|
||||
if err := {{ $flagValueVar }}.UnmarshalText([]byte({{ $flagValueVar }}Str)); err != nil{
|
||||
return err, false
|
||||
}
|
||||
m.{{ pascalize .Name }} = {{- if .IsNullable }}&{{- end }}{{ $flagValueVar }}
|
||||
{{- else }}
|
||||
// warning: primitive {{.Name}} {{.GoType }} is not supported by go-swagger cli yet
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
|
||||
{{ define "arrayretriever" }}
|
||||
{{- $flagValueVar := printf "%vFlagValues" (camelize .Name) }}
|
||||
{{- $flagNameVar := printf "%vFlagName" (camelize .Name )}}
|
||||
{{- if or (eq .GoType "[]int64") (eq .GoType "[]int32") (eq .GoType "[]string") (eq .GoType "[]float64") (eq .GoType "[]float32") (eq .GoType "[]bool") }}
|
||||
{{ template "flagnamevar" . }}
|
||||
{{ $flagValueVar }}, err := cmd.Flags().Get{{pascalize .GoType}}Slice({{ $flagNameVar }})
|
||||
if err != nil{
|
||||
return err, false
|
||||
}
|
||||
{{- /* reciever by convention is m for CLI */}}
|
||||
m.{{ pascalize .Name }} = {{ $flagValueVar }}
|
||||
{{- else if or (eq .GoType "[]strfmt.DateTime") (eq .GoType "[]strfmt.ObjectId") (eq .GoType "[]strfmt.UUID") }} {{/*Get flag value as string, then parse it*/}}
|
||||
{{ template "flagnamevar" . }}
|
||||
{{ $flagValueVar }}Str, err := cmd.Flags().GetStringSlice({{ $flagNameVar }})
|
||||
if err != nil{
|
||||
return err, false
|
||||
}
|
||||
|
||||
{{ $flagValueVar }} := make({{ .GoType }}, len({{ $flagValueVar }}Str))
|
||||
for i, v := range {{ $flagValueVar }}Str {
|
||||
if err := {{ $flagValueVar }}[i].UnmarshalText([]byte(v)); err != nil{
|
||||
return err, false
|
||||
}
|
||||
}
|
||||
m.{{ pascalize .Name }} = {{- if .IsNullable }}&{{- end }}{{ $flagValueVar }}
|
||||
{{- else }}
|
||||
// warning: array {{.Name}} {{.GoType }} is not supported by go-swagger cli yet
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
193
vendor/github.com/go-swagger/go-swagger/generator/templates/cli/schema.gotmpl
generated
vendored
Normal file
193
vendor/github.com/go-swagger/go-swagger/generator/templates/cli/schema.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
{{/*util functions to generate register and retrieve functions for a model*/}}
|
||||
|
||||
{{ define "modelschemacli" }}
|
||||
{{/*some guards to prevent rendering unsupported models types. TODO: remove this guard*/}}
|
||||
{{if or .IsPrimitive .IsComplexObject }}
|
||||
{{ template "modelschemacliinternal" . }}
|
||||
{{ else }}
|
||||
// Name: [{{.Name}}], Type:[{{ .GoType }}], register and retrieve functions are not rendered by go-swagger cli
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{/*since register and retrieve are the same for properties and all of, share them here*/}}
|
||||
{{ define "propertyregistor" }}
|
||||
{{- if .IsPrimitive }}
|
||||
{{ template "primitiveregistrator" . }}
|
||||
{{- else if .IsArray }}
|
||||
// warning: {{.Name}} {{ .GoType }} array type is not supported by go-swagger cli yet
|
||||
{{- else if .IsMap }}
|
||||
// warning: {{.Name}} {{ .GoType }} map type is not supported by go-swagger cli yet
|
||||
{{- else if .IsComplexObject }} {{/* struct case */}}
|
||||
{{ template "flagnamevar" . }}
|
||||
if err := registerModel{{pascalize (dropPackage .GoType) }}Flags(depth + 1, {{ camelize .Name }}FlagName, cmd); err != nil{
|
||||
return err
|
||||
}
|
||||
{{- else }}
|
||||
// warning: {{.Name}} {{ .GoType }} unkown type is not supported by go-swagger cli yet
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
|
||||
{{ define "propertyretriever" }}
|
||||
{{- $flagNameVar := printf "%vFlagName" (camelize .Name) }}
|
||||
{{- $flagValueVar := printf "%vFlagValue" (camelize .Name) }}
|
||||
{{ $flagNameVar }} := fmt.Sprintf("%v.{{ .Name }}", cmdPrefix)
|
||||
if cmd.Flags().Changed({{ $flagNameVar }}) {
|
||||
{{- if .IsPrimitive }}
|
||||
{{ template "primitiveretriever" . }}
|
||||
retAdded = true
|
||||
{{- else if .IsArray }}
|
||||
// warning: {{ .Name }} array type {{ .GoType }} is not supported by go-swagger cli yet
|
||||
{{- else if .IsMap }}
|
||||
// warning: {{ .Name }} map type {{ .GoType }} is not supported by go-swagger cli yet
|
||||
{{- else if .IsComplexObject }}
|
||||
// info: complex object {{.Name}} {{.GoType}} is retrieved outside this Changed() block
|
||||
{{- else }}
|
||||
// warning: {{.Name}} {{ .GoType }} unkown type is not supported by go-swagger cli yet
|
||||
{{- end }}
|
||||
}
|
||||
{{- if and .IsComplexObject (not .IsArray) (not .IsMap) (not .IsStream) }}
|
||||
{{ $flagValueVar }} := m.{{pascalize .Name}}
|
||||
if swag.IsZero({{ $flagValueVar }}){
|
||||
{{ $flagValueVar }} = {{if .IsNullable }}&{{end}}{{if containsPkgStr .GoType}}{{ .GoType }}{{else}}{{ .Pkg }}.{{.GoType}}{{ end }}{}
|
||||
}
|
||||
{{/* always lift the payload to pointer and pass to model retrieve function. If .GoType has pkg str, use it, else use .Pkg+.GoType */}}
|
||||
err, {{camelize .Name }}Added := retrieveModel{{pascalize (dropPackage .GoType) }}Flags(depth + 1, {{if not .IsNullable }}&{{end}}{{ $flagValueVar }}, {{ $flagNameVar }}, cmd)
|
||||
if err != nil{
|
||||
return err, false
|
||||
}
|
||||
retAdded = retAdded || {{camelize .Name }}Added
|
||||
if {{camelize .Name }}Added {
|
||||
m.{{pascalize .Name}} = {{ $flagValueVar }}
|
||||
}
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
|
||||
{{ define "modelschemacliinternal" }} {{/*used by model definition and in params model*/}}
|
||||
{{- $modelName := .Name }}
|
||||
{{/*model package is filled by generator*/}}
|
||||
{{ $modelPkg := toPackageName .Pkg}}
|
||||
{{ $modelType := .GoType }}
|
||||
|
||||
// register flags to command
|
||||
func registerModel{{pascalize .Name}}Flags(depth int, cmdPrefix string, cmd *cobra.Command) error {
|
||||
{{ range .AllOf }}
|
||||
{{- if not .IsAnonymous }}{{/* named type composition */}}
|
||||
{{ if or .IsPrimitive .IsComplexObject }}
|
||||
// register embedded {{ .GoType }} flags
|
||||
{{/*defer all of registration to the model's regristor method. embed should not lift cmdPrefix */}}
|
||||
if err := registerModel{{ pascalize (dropPackage .GoType) }}Flags(depth, cmdPrefix, cmd); err != nil{
|
||||
return err
|
||||
}
|
||||
{{ else }}
|
||||
// {{ .Name }} {{ .GoType }} register is skipped
|
||||
{{ end }}
|
||||
{{ else }}{{/*inline definition. assume only properties are used*/}}
|
||||
// register anonymous fields for {{.Name}}
|
||||
{{ $anonName := .Name }}
|
||||
{{ range .Properties }}
|
||||
if err := register{{ pascalize $modelName }}Anon{{pascalize $anonName }}{{ pascalize .Name }}(depth, cmdPrefix, cmd); err != nil{
|
||||
return err
|
||||
}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ range .Properties }}
|
||||
if err := register{{ pascalize $modelName }}{{ pascalize .Name }}(depth, cmdPrefix, cmd); err != nil{
|
||||
return err
|
||||
}
|
||||
{{ end }}
|
||||
return nil
|
||||
}
|
||||
|
||||
{{ range .AllOf }}
|
||||
{{- if .IsAnonymous }}{{/* inline definition. schema case is defered. */}}
|
||||
// inline definition name {{ .Name }}, type {{.GoType}}
|
||||
{{ $anonName := .Name }}
|
||||
{{ range .Properties }}
|
||||
func register{{ pascalize $modelName }}Anon{{pascalize $anonName }}{{ pascalize .Name }}(depth int, cmdPrefix string, cmd *cobra.Command) error {
|
||||
if depth > maxDepth {
|
||||
return nil
|
||||
}
|
||||
{{ template "propertyregistor" . }}
|
||||
return nil
|
||||
}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{/*register functions for each fields in this model */}}
|
||||
{{ range .Properties }}
|
||||
func register{{ pascalize $modelName }}{{ pascalize .Name }}(depth int, cmdPrefix string, cmd *cobra.Command) error{
|
||||
if depth > maxDepth {
|
||||
return nil
|
||||
}
|
||||
{{ template "propertyregistor" .}}
|
||||
return nil
|
||||
}
|
||||
{{ end }} {{/*Properties*/}}
|
||||
|
||||
// retrieve flags from commands, and set value in model. Return true if any flag is passed by user to fill model field.
|
||||
func retrieveModel{{pascalize $modelName }}Flags(depth int, m *{{if containsPkgStr .GoType}}{{ .GoType }}{{else}}{{ .Pkg }}.{{.GoType}}{{ end }}, cmdPrefix string, cmd *cobra.Command) (error, bool) {
|
||||
retAdded := false
|
||||
{{ range .AllOf }}
|
||||
{{- if not .IsAnonymous }}{{/* named type composition */}}
|
||||
{{ if or .IsPrimitive .IsComplexObject }}
|
||||
// retrieve model {{.GoType}}
|
||||
err, {{camelize .Name }}Added := retrieveModel{{ pascalize (dropPackage .GoType) }}Flags(depth, &m.{{pascalize (dropPackage .GoType) }}, cmdPrefix, cmd)
|
||||
if err != nil{
|
||||
return err, false
|
||||
}
|
||||
retAdded = retAdded || {{camelize .Name }}Added
|
||||
{{ else }} {{/*inline anonymous case*/}}
|
||||
|
||||
{{ end }}
|
||||
{{- else }}
|
||||
// retrieve allOf {{.Name}} fields
|
||||
{{ $anonName := .Name }}
|
||||
{{ range .Properties }}
|
||||
err, {{camelize .Name}}Added := retrieve{{ pascalize $modelName }}Anon{{pascalize $anonName }}{{ pascalize .Name }}Flags(depth, m, cmdPrefix, cmd)
|
||||
if err != nil{
|
||||
return err, false
|
||||
}
|
||||
retAdded = retAdded || {{ camelize .Name }}Added
|
||||
{{ end }}
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
{{ range .Properties }}
|
||||
err, {{ camelize .Name }}Added := retrieve{{pascalize $modelName }}{{pascalize .Name }}Flags(depth, m, cmdPrefix, cmd)
|
||||
if err != nil{
|
||||
return err, false
|
||||
}
|
||||
retAdded = retAdded || {{ camelize .Name }}Added
|
||||
{{ end }}
|
||||
return nil, retAdded
|
||||
}
|
||||
|
||||
{{ range .AllOf }}
|
||||
{{- if .IsAnonymous }}{{/* inline definition. schema case is defered. */}}
|
||||
// define retrieve functions for fields for inline definition name {{ .Name }}
|
||||
{{ $anonName := .Name }}
|
||||
{{ range .Properties }} {{/*anonymous fields will be registered directly on parent model*/}}
|
||||
func retrieve{{ pascalize $modelName }}Anon{{pascalize $anonName }}{{ pascalize .Name }}Flags(depth int, m *{{if containsPkgStr $modelType}}{{ $modelType }}{{else}}{{ $modelPkg }}.{{$modelType}}{{ end }},cmdPrefix string, cmd *cobra.Command) (error,bool) {
|
||||
if depth > maxDepth {
|
||||
return nil, false
|
||||
}
|
||||
retAdded := false
|
||||
{{ template "propertyretriever" . }}
|
||||
return nil, retAdded
|
||||
}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{ range .Properties }}
|
||||
func retrieve{{pascalize $modelName }}{{pascalize .Name }}Flags(depth int, m *{{if $modelPkg}}{{$modelPkg}}.{{ dropPackage $modelType }}{{else}}{{ $modelType }}{{end}}, cmdPrefix string, cmd *cobra.Command) (error, bool) {
|
||||
if depth > maxDepth {
|
||||
return nil, false
|
||||
}
|
||||
retAdded := false
|
||||
{{ template "propertyretriever" . }}
|
||||
return nil, retAdded
|
||||
}
|
||||
{{ end }} {{/*properties*/}}
|
||||
{{ end }} {{/*define*/}}
|
||||
127
vendor/github.com/go-swagger/go-swagger/generator/templates/client/client.gotmpl
generated
vendored
Normal file
127
vendor/github.com/go-swagger/go-swagger/generator/templates/client/client.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
|
||||
{{ if .Copyright -}}// {{ comment .Copyright -}}{{ end }}
|
||||
|
||||
|
||||
package {{ .Name }}
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/validate"
|
||||
|
||||
{{ imports .DefaultImports }}
|
||||
{{ imports .Imports }}
|
||||
)
|
||||
|
||||
// New creates a new {{ humanize .Name }} API client.
|
||||
func New(transport runtime.ClientTransport, formats strfmt.Registry) ClientService {
|
||||
return &Client{transport: transport, formats: formats}
|
||||
}
|
||||
|
||||
/*
|
||||
Client {{ if .Summary }}{{ .Summary }}{{ if .Description }}
|
||||
|
||||
{{ blockcomment .Description }}{{ end }}{{ else if .Description}}{{ blockcomment .Description }}{{ else }}for {{ humanize .Name }} API{{ end }}
|
||||
*/
|
||||
type Client struct {
|
||||
transport runtime.ClientTransport
|
||||
formats strfmt.Registry
|
||||
}
|
||||
|
||||
// ClientOption is the option for Client methods
|
||||
type ClientOption func(*runtime.ClientOperation)
|
||||
|
||||
// ClientService is the interface for Client methods
|
||||
type ClientService interface {
|
||||
{{ range .Operations }}
|
||||
{{ pascalize .Name }}(params *{{ pascalize .Name }}Params{{ if .Authorized }}, authInfo runtime.ClientAuthInfoWriter{{end}}{{ if .HasStreamingResponse }}, writer io.Writer{{ end }}, opts ...ClientOption) {{ if .SuccessResponse }}({{ range .SuccessResponses }}*{{ pascalize .Name }}, {{ end }}{{ end }}error{{ if .SuccessResponse }}){{ end }}
|
||||
{{ end }}
|
||||
|
||||
SetTransport(transport runtime.ClientTransport)
|
||||
}
|
||||
|
||||
{{ range .Operations }}
|
||||
/*
|
||||
{{ pascalize .Name }} {{ if .Summary }}{{ pluralizeFirstWord (humanize .Summary) }}{{ if .Description }}
|
||||
|
||||
{{ blockcomment .Description }}{{ end }}{{ else if .Description}}{{ blockcomment .Description }}{{ else }}{{ humanize .Name }} API{{ end }}
|
||||
*/
|
||||
func (a *Client) {{ pascalize .Name }}(params *{{ pascalize .Name }}Params{{ if .Authorized }}, authInfo runtime.ClientAuthInfoWriter{{end}}{{ if .HasStreamingResponse }}, writer io.Writer{{ end }}, opts ...ClientOption) {{ if .SuccessResponse }}({{ range .SuccessResponses }}*{{ pascalize .Name }}, {{ end }}{{ end }}error{{ if .SuccessResponse }}){{ end }} {
|
||||
// TODO: Validate the params before sending
|
||||
if params == nil {
|
||||
params = New{{ pascalize .Name }}Params()
|
||||
}
|
||||
op := &runtime.ClientOperation{
|
||||
ID: {{ printf "%q" .Name }},
|
||||
Method: {{ printf "%q" .Method }},
|
||||
PathPattern: {{ printf "%q" .Path }},
|
||||
ProducesMediaTypes: {{ printf "%#v" .ProducesMediaTypes }},
|
||||
ConsumesMediaTypes: {{ printf "%#v" .ConsumesMediaTypes }},
|
||||
Schemes: {{ printf "%#v" .Schemes }},
|
||||
Params: params,
|
||||
Reader: &{{ pascalize .Name }}Reader{formats: a.formats{{ if .HasStreamingResponse }}, writer: writer{{ end }}},{{ if .Authorized }}
|
||||
AuthInfo: authInfo,{{ end}}
|
||||
Context: params.Context,
|
||||
Client: params.HTTPClient,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(op)
|
||||
}
|
||||
{{ $length := len .SuccessResponses }}
|
||||
{{ if .SuccessResponse }}result{{else}}_{{ end }}, err := a.transport.Submit(op)
|
||||
if err != nil {
|
||||
return {{ if .SuccessResponse }}{{ padSurround "nil" "nil" 0 $length }}, {{ end }}err
|
||||
}
|
||||
{{- if .SuccessResponse }}
|
||||
{{- if eq $length 1 }}
|
||||
success, ok := result.(*{{ pascalize .SuccessResponse.Name }})
|
||||
if ok {
|
||||
return success,nil
|
||||
}
|
||||
// unexpected success response
|
||||
{{- if .DefaultResponse }}{{/* if a default response is provided, fill this and return an error */}}
|
||||
unexpectedSuccess := result.(*{{ pascalize .DefaultResponse.Name }})
|
||||
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
|
||||
{{- else }}
|
||||
// safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue
|
||||
msg := fmt.Sprintf("unexpected success response for {{ .Name }}: API contract not enforced by server. Client expected to get an error, but got: %T", result)
|
||||
panic(msg)
|
||||
{{- end }}
|
||||
{{- else }}{{/* several possible success responses */}}
|
||||
switch value := result.(type) {
|
||||
{{- range $i, $v := .SuccessResponses }}
|
||||
case *{{ pascalize $v.Name }}:
|
||||
return {{ padSurround "value" "nil" $i $length }}, nil
|
||||
{{- end }}
|
||||
}
|
||||
{{- if .DefaultResponse }}{{/* if a default response is provided, fill this and return an error */}}
|
||||
// unexpected success response
|
||||
unexpectedSuccess := result.(*{{ pascalize .DefaultResponse.Name }})
|
||||
return {{ padSurround "nil" "nil" 0 $length }}, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
|
||||
{{- else }}
|
||||
// safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue
|
||||
msg := fmt.Sprintf("unexpected success response for {{ $.Name }}: API contract not enforced by server. Client expected to get an error, but got: %T", result)
|
||||
panic(msg)
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
return nil
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
// SetTransport changes the transport on the client
|
||||
func (a *Client) SetTransport(transport runtime.ClientTransport) {
|
||||
a.transport = transport
|
||||
}
|
||||
129
vendor/github.com/go-swagger/go-swagger/generator/templates/client/facade.gotmpl
generated
vendored
Normal file
129
vendor/github.com/go-swagger/go-swagger/generator/templates/client/facade.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
|
||||
{{ if .Copyright -}}// {{ comment .Copyright -}}{{ end }}
|
||||
|
||||
|
||||
package {{ .Package }}
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
|
||||
{{ imports .DefaultImports }}
|
||||
{{ imports .Imports }}
|
||||
)
|
||||
|
||||
// Default {{ humanize .Name }} HTTP client.
|
||||
var Default = NewHTTPClient(nil)
|
||||
|
||||
const (
|
||||
// DefaultHost is the default Host
|
||||
// found in Meta (info) section of spec file
|
||||
DefaultHost string = {{ printf "%#v" .Host }}
|
||||
// DefaultBasePath is the default BasePath
|
||||
// found in Meta (info) section of spec file
|
||||
DefaultBasePath string = {{ printf "%#v" .BasePath }}
|
||||
)
|
||||
|
||||
// DefaultSchemes are the default schemes found in Meta (info) section of spec file
|
||||
var DefaultSchemes = {{ printf "%#v" .Schemes }}
|
||||
|
||||
// NewHTTPClient creates a new {{ humanize .Name }} HTTP client.
|
||||
func NewHTTPClient(formats strfmt.Registry) *{{ pascalize .Name }} {
|
||||
return NewHTTPClientWithConfig(formats, nil)
|
||||
}
|
||||
|
||||
// NewHTTPClientWithConfig creates a new {{ humanize .Name }} HTTP client,
|
||||
// using a customizable transport config.
|
||||
func NewHTTPClientWithConfig(formats strfmt.Registry, cfg *TransportConfig) *{{ pascalize .Name }} {
|
||||
// ensure nullable parameters have default
|
||||
if cfg == nil {
|
||||
cfg = DefaultTransportConfig()
|
||||
}
|
||||
|
||||
// create transport and client
|
||||
transport := httptransport.New(cfg.Host, cfg.BasePath, cfg.Schemes)
|
||||
return New(transport, formats)
|
||||
}
|
||||
|
||||
// New creates a new {{ humanize .Name }} client
|
||||
func New(transport runtime.ClientTransport, formats strfmt.Registry) *{{ pascalize .Name }} {
|
||||
// ensure nullable parameters have default
|
||||
if formats == nil {
|
||||
formats = strfmt.Default
|
||||
}
|
||||
|
||||
cli := new({{ pascalize .Name }})
|
||||
cli.Transport = transport
|
||||
{{- range .OperationGroups }}
|
||||
cli.{{ pascalize .Name }} = {{ .PackageAlias }}.New(transport, formats)
|
||||
{{- end }}
|
||||
return cli
|
||||
}
|
||||
|
||||
// DefaultTransportConfig creates a TransportConfig with the
|
||||
// default settings taken from the meta section of the spec file.
|
||||
func DefaultTransportConfig() *TransportConfig {
|
||||
return &TransportConfig {
|
||||
Host: DefaultHost,
|
||||
BasePath: DefaultBasePath,
|
||||
Schemes: DefaultSchemes,
|
||||
}
|
||||
}
|
||||
|
||||
// TransportConfig contains the transport related info,
|
||||
// found in the meta section of the spec file.
|
||||
type TransportConfig struct {
|
||||
Host string
|
||||
BasePath string
|
||||
Schemes []string
|
||||
}
|
||||
|
||||
// WithHost overrides the default host,
|
||||
// provided by the meta section of the spec file.
|
||||
func (cfg *TransportConfig) WithHost(host string) *TransportConfig {
|
||||
cfg.Host = host
|
||||
return cfg
|
||||
}
|
||||
|
||||
// WithBasePath overrides the default basePath,
|
||||
// provided by the meta section of the spec file.
|
||||
func (cfg *TransportConfig) WithBasePath(basePath string) *TransportConfig {
|
||||
cfg.BasePath = basePath
|
||||
return cfg
|
||||
}
|
||||
|
||||
// WithSchemes overrides the default schemes,
|
||||
// provided by the meta section of the spec file.
|
||||
func (cfg *TransportConfig) WithSchemes(schemes []string) *TransportConfig {
|
||||
cfg.Schemes = schemes
|
||||
return cfg
|
||||
}
|
||||
|
||||
// {{ pascalize .Name }} is a client for {{ humanize .Name }}
|
||||
type {{ pascalize .Name }} struct {
|
||||
{{ range .OperationGroups }}
|
||||
{{ pascalize .Name }} {{ .PackageAlias }}.ClientService
|
||||
{{ end }}
|
||||
Transport runtime.ClientTransport
|
||||
}
|
||||
|
||||
|
||||
// SetTransport changes the transport on the client and all its subresources
|
||||
func (c *{{pascalize .Name}}) SetTransport(transport runtime.ClientTransport) {
|
||||
c.Transport = transport
|
||||
{{- range .OperationGroups }}
|
||||
c.{{ pascalize .Name }}.SetTransport(transport)
|
||||
{{- end }}
|
||||
}
|
||||
406
vendor/github.com/go-swagger/go-swagger/generator/templates/client/parameter.gotmpl
generated
vendored
Normal file
406
vendor/github.com/go-swagger/go-swagger/generator/templates/client/parameter.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,406 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
|
||||
{{ if .Copyright -}}// {{ comment .Copyright -}}{{ end }}
|
||||
|
||||
|
||||
package {{ .Package }}
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
cr "github.com/go-openapi/runtime/client"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/validate"
|
||||
|
||||
{{ imports .DefaultImports }}
|
||||
{{ imports .Imports }}
|
||||
)
|
||||
|
||||
// New{{ pascalize .Name }}Params creates a new {{ pascalize .Name }}Params object,
|
||||
// with the default timeout for this client.
|
||||
//
|
||||
// Default values are not hydrated, since defaults are normally applied by the API server side.
|
||||
//
|
||||
// To enforce default values in parameter, use SetDefaults or WithDefaults.
|
||||
func New{{ pascalize .Name }}Params() *{{ pascalize .Name }}Params {
|
||||
return &{{ pascalize .Name}}Params{
|
||||
{{ camelize .TimeoutName }}: cr.DefaultTimeout,
|
||||
}
|
||||
}
|
||||
|
||||
// New{{ pascalize .Name }}ParamsWithTimeout creates a new {{ pascalize .Name }}Params object
|
||||
// with the ability to set a timeout on a request.
|
||||
func New{{ pascalize .Name }}ParamsWithTimeout(timeout time.Duration) *{{ pascalize .Name }}Params {
|
||||
return &{{ pascalize .Name}}Params{
|
||||
{{ camelize .TimeoutName }}: timeout,
|
||||
}
|
||||
}
|
||||
|
||||
// New{{ pascalize .Name }}ParamsWithContext creates a new {{ pascalize .Name }}Params object
|
||||
// with the ability to set a context for a request.
|
||||
func New{{ pascalize .Name }}ParamsWithContext(ctx context.Context) *{{ pascalize .Name }}Params {
|
||||
return &{{ pascalize .Name}}Params{
|
||||
Context: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
// New{{ pascalize .Name }}ParamsWithHTTPClient creates a new {{ pascalize .Name }}Params object
|
||||
// with the ability to set a custom HTTPClient for a request.
|
||||
func New{{ pascalize .Name }}ParamsWithHTTPClient(client *http.Client) *{{ pascalize .Name }}Params {
|
||||
return &{{ pascalize .Name}}Params{
|
||||
HTTPClient: client,
|
||||
}
|
||||
}
|
||||
|
||||
/* {{ pascalize .Name }}Params contains all the parameters to send to the API endpoint
|
||||
for the {{ humanize .Name }} operation.
|
||||
|
||||
Typically these are written to a http.Request.
|
||||
*/
|
||||
type {{ pascalize .Name }}Params struct {
|
||||
{{- range .Params }}
|
||||
{{- if .Description }}
|
||||
|
||||
/* {{ pascalize .Name }}.
|
||||
|
||||
{{ blockcomment .Description }}
|
||||
{{- if or .SwaggerFormat .Default }}
|
||||
{{ print "" }}
|
||||
{{- if .SwaggerFormat }}
|
||||
Format: {{ .SwaggerFormat }}
|
||||
{{- end }}
|
||||
{{- if .Default }}
|
||||
Default: {{ json .Default }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
*/
|
||||
{{- else }}
|
||||
|
||||
// {{ pascalize .Name }}.
|
||||
{{- if or .SwaggerFormat .Default }}
|
||||
//
|
||||
{{- if .SwaggerFormat }}
|
||||
// Format: {{ .SwaggerFormat }}
|
||||
{{- end }}
|
||||
{{- if .Default }}
|
||||
// Default: {{ json .Default }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{ pascalize .ID }} {{ if and (not .IsArray) (not .IsMap) (not .HasDiscriminator) (not .IsInterface) (not .IsStream) (or .IsNullable ) }}*{{ end }}{{ if not .IsFileParam }}{{ .GoType }}{{ else }}runtime.NamedReadCloser{{ end }}
|
||||
{{- end }}
|
||||
|
||||
{{ camelize .TimeoutName }} time.Duration
|
||||
Context context.Context
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// WithDefaults hydrates default values in the {{ humanize .Name }} params (not the query body).
|
||||
//
|
||||
// All values with no default are reset to their zero value.
|
||||
func ({{ .ReceiverName }} *{{ pascalize .Name }}Params) WithDefaults() *{{ pascalize .Name }}Params {
|
||||
{{ .ReceiverName }}.SetDefaults()
|
||||
return {{ .ReceiverName }}
|
||||
}
|
||||
|
||||
// SetDefaults hydrates default values in the {{ humanize .Name }} params (not the query body).
|
||||
//
|
||||
// All values with no default are reset to their zero value.
|
||||
func ({{ .ReceiverName }} *{{ pascalize .Name }}Params) SetDefaults() {
|
||||
{{- if .Params.HasSomeDefaults }}
|
||||
var (
|
||||
{{- range .Params }}
|
||||
{{- if .HasDefault }}
|
||||
{{- if .IsFileParam }}
|
||||
// NOTE: no default supported for file parameter {{ .ID }}
|
||||
{{- else if .IsStream }}
|
||||
// NOTE: no default supported for stream parameter {{ .ID }}
|
||||
{{- else if not .IsBodyParam }}
|
||||
{{ template "simpleschemaDefaultsvar" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
)
|
||||
{{- range .Params }}
|
||||
{{- if and .HasDefault (not .IsFileParam) (not .IsStream) (not .IsBodyParam) }}
|
||||
{{ template "simpleschemaDefaultsinit" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
val := {{ pascalize .Name }}Params{
|
||||
{{- range .Params }}
|
||||
{{- if and .HasDefault (not .IsFileParam) (not .IsStream) (not .IsBodyParam) }}
|
||||
{{ pascalize .ID }}: {{ if and (not .IsArray) (not .IsMap) (not .HasDiscriminator) (or .IsNullable ) }}&{{ end }}{{ varname .ID }}Default,
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
val.{{ camelize .TimeoutName }} = {{ .ReceiverName }}.{{ camelize .TimeoutName }}
|
||||
val.Context = {{ .ReceiverName }}.Context
|
||||
val.HTTPClient = {{ .ReceiverName }}.HTTPClient
|
||||
*{{ .ReceiverName }} = val
|
||||
{{- else }}
|
||||
// no default values defined for this parameter
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
// With{{ pascalize .TimeoutName }} adds the timeout to the {{ humanize .Name }} params
|
||||
func ({{ .ReceiverName }} *{{ pascalize .Name }}Params) With{{ pascalize .TimeoutName }}(timeout time.Duration) *{{ pascalize .Name }}Params {
|
||||
{{ .ReceiverName }}.Set{{ pascalize .TimeoutName }}(timeout)
|
||||
return {{ .ReceiverName }}
|
||||
}
|
||||
|
||||
// Set{{ pascalize .TimeoutName }} adds the timeout to the {{ humanize .Name }} params
|
||||
func ({{ .ReceiverName }} *{{ pascalize .Name }}Params) Set{{ pascalize .TimeoutName }}(timeout time.Duration) {
|
||||
{{ .ReceiverName }}.{{ camelize .TimeoutName }} = timeout
|
||||
}
|
||||
|
||||
// WithContext adds the context to the {{ humanize .Name }} params
|
||||
func ({{ .ReceiverName }} *{{ pascalize .Name }}Params) WithContext(ctx context.Context) *{{ pascalize .Name }}Params {
|
||||
{{ .ReceiverName }}.SetContext(ctx)
|
||||
return {{ .ReceiverName }}
|
||||
}
|
||||
|
||||
// SetContext adds the context to the {{ humanize .Name }} params
|
||||
func ({{ .ReceiverName }} *{{ pascalize .Name }}Params) SetContext(ctx context.Context) {
|
||||
{{ .ReceiverName }}.Context = ctx
|
||||
}
|
||||
|
||||
// WithHTTPClient adds the HTTPClient to the {{ humanize .Name }} params
|
||||
func ({{ .ReceiverName }} *{{ pascalize .Name }}Params) WithHTTPClient(client *http.Client) *{{ pascalize .Name }}Params {
|
||||
{{ .ReceiverName }}.SetHTTPClient(client)
|
||||
return {{ .ReceiverName }}
|
||||
}
|
||||
|
||||
// SetHTTPClient adds the HTTPClient to the {{ humanize .Name }} params
|
||||
func ({{ .ReceiverName }} *{{ pascalize .Name }}Params) SetHTTPClient(client *http.Client) {
|
||||
{{ .ReceiverName }}.HTTPClient = client
|
||||
}
|
||||
|
||||
{{- range .Params }}
|
||||
|
||||
// With{{ pascalize .ID }} adds the {{ varname .Name }} to the {{ humanize $.Name }} params
|
||||
func ({{ $.ReceiverName }} *{{ pascalize $.Name }}Params) With{{ pascalize .ID }}({{ varname .Name }} {{ if and (not .IsArray) (not .IsMap) (not .HasDiscriminator) (not .IsStream) (or .IsNullable ) }}*{{ end }}{{ if not .IsFileParam }}{{ .GoType }}{{ else }}runtime.NamedReadCloser{{ end }}) *{{ pascalize $.Name }}Params {
|
||||
{{ $.ReceiverName }}.Set{{ pascalize .ID }}({{ varname .Name }})
|
||||
return {{ .ReceiverName }}
|
||||
}
|
||||
|
||||
// Set{{ pascalize .ID }} adds the {{ camelize .Name }} to the {{ humanize $.Name }} params
|
||||
func ({{ $.ReceiverName }} *{{ pascalize $.Name }}Params) Set{{ pascalize .ID }}({{ varname .Name }} {{ if and (not .IsArray) (not .IsMap) (not .HasDiscriminator) (not .IsStream) (or .IsNullable ) }}*{{ end }}{{ if not .IsFileParam }}{{ .GoType }}{{ else }}runtime.NamedReadCloser{{ end }}) {
|
||||
{{ $.ReceiverName }}.{{ pascalize .ID }} = {{ varname .Name }}
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
// WriteToRequest writes these params to a swagger request
|
||||
func ({{ .ReceiverName }} *{{ pascalize .Name }}Params) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
|
||||
|
||||
if err := r.SetTimeout({{ .ReceiverName }}.{{ camelize .TimeoutName }}); err != nil {
|
||||
return err
|
||||
}
|
||||
var res []error
|
||||
{{- range .Params }}
|
||||
{{- if not (or .IsArray .IsMap .IsBodyParam) }}
|
||||
{{- if and .IsNullable (not .AllowEmptyValue) }}
|
||||
|
||||
if {{ .ValueExpression }} != nil {
|
||||
{{- end}}
|
||||
|
||||
{{- if .IsQueryParam }}
|
||||
|
||||
// query param {{ .Name }}
|
||||
{{- if .IsNullable }}
|
||||
var qr{{ pascalize .Name }} {{ .GoType }}
|
||||
|
||||
if {{ .ValueExpression }} != nil {
|
||||
qr{{ pascalize .Name }} = *{{ .ValueExpression }}
|
||||
}
|
||||
{{- else }}
|
||||
qr{{ pascalize .Name }} := {{ .ValueExpression }}
|
||||
{{- end}}
|
||||
q{{ pascalize .Name}} := {{ if .Formatter }}{{ .Formatter }}(qr{{ pascalize .Name }}){{ else }}qr{{ pascalize .Name }}{{ if .IsCustomFormatter }}.String(){{end}}{{end}}
|
||||
{{- if not .AllowEmptyValue }}
|
||||
if q{{ pascalize .Name }} != "" {
|
||||
{{- end }}
|
||||
|
||||
if err := r.SetQueryParam({{ printf "%q" .Name }}, q{{ pascalize .Name }}); err != nil {
|
||||
return err
|
||||
}
|
||||
{{- if not .AllowEmptyValue }}
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{- else if .IsPathParam }}
|
||||
|
||||
// path param {{ .Name }}
|
||||
if err := r.SetPathParam({{ printf "%q" .Name }}, {{ if .Formatter }}{{ .Formatter }}({{ if .IsNullable }}*{{end}}{{ .ValueExpression }}){{ else }}{{ if and (not .IsCustomFormatter) .IsNullable }}*{{end}}{{ .ValueExpression }}{{ if .IsCustomFormatter }}.String(){{end}}{{end}}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{{- else if .IsHeaderParam }}
|
||||
|
||||
// header param {{ .Name }}
|
||||
if err := r.SetHeaderParam({{ printf "%q" .Name }}, {{ if .Formatter }}{{ .Formatter }}({{ if .IsNullable }}*{{end}}{{ .ValueExpression }}){{ else }}{{ if and (not .IsCustomFormatter) .IsNullable }}*{{end}}{{ .ValueExpression }}{{ if .IsCustomFormatter }}.String(){{end}}{{end}}); err != nil {
|
||||
return err
|
||||
}
|
||||
{{- else if .IsFormParam }}
|
||||
{{- if .IsFileParam }}
|
||||
{{- if .IsNullable }}
|
||||
|
||||
if {{ .ValueExpression }} != nil {
|
||||
{{- end }}
|
||||
// form file param {{ .Name }}
|
||||
if err := r.SetFileParam({{ printf "%q" .Name }}, {{ .ValueExpression }}); err != nil {
|
||||
return err
|
||||
}
|
||||
{{- if .IsNullable}}
|
||||
}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
|
||||
// form param {{ .Name }}
|
||||
{{- if .IsNullable }}
|
||||
var fr{{ pascalize .Name }} {{ .GoType }}
|
||||
if {{ .ValueExpression }} != nil {
|
||||
fr{{ pascalize .Name }} = *{{ .ValueExpression }}
|
||||
}
|
||||
{{- else }}
|
||||
fr{{ pascalize .Name }} := {{ .ValueExpression }}
|
||||
{{- end}}
|
||||
f{{ pascalize .Name}} := {{ if .Formatter }}{{ .Formatter }}(fr{{ pascalize .Name }}){{ else }}fr{{ pascalize .Name }}{{ if .IsCustomFormatter }}.String(){{end}}{{end}}
|
||||
{{- if not .AllowEmptyValue }}
|
||||
if f{{ pascalize .Name }} != "" {
|
||||
{{- end }}
|
||||
if err := r.SetFormParam({{ printf "%q" .Name }}, f{{ pascalize .Name }}); err != nil {
|
||||
return err
|
||||
}
|
||||
{{- if not .AllowEmptyValue }}
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if and .IsNullable (not .AllowEmptyValue) }}
|
||||
}
|
||||
{{- end }}
|
||||
{{- else if .IsArray }}
|
||||
|
||||
{{- if not .IsBodyParam }}
|
||||
|
||||
if {{ .ValueExpression }} != nil {
|
||||
|
||||
{{- if .Child }}{{/* bind complex parameters (arrays and nested structures) */}}
|
||||
|
||||
// binding items for {{ .Name }}
|
||||
joined{{ pascalize .Name }} := {{ .ReceiverName }}.bindParam{{ pascalize .Name }}(reg)
|
||||
{{- else }}
|
||||
values{{ pascalize .Name }} := {{ if and (not .IsArray) (not .IsStream) (not .IsMap) (.IsNullable) }}*{{end}}{{ .ValueExpression }}
|
||||
joined{{ pascalize .Name}} := swag.JoinByFormat(values{{ pascalize .Name }}, "{{.CollectionFormat}}")
|
||||
{{- end }}
|
||||
|
||||
{{- if .IsQueryParam }}
|
||||
|
||||
// query array param {{ .Name }}
|
||||
if err := r.SetQueryParam({{ printf "%q" .Name }}, joined{{ pascalize .Name }}...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{{- else if and .IsFormParam }}
|
||||
|
||||
// form array param {{ .Name }}
|
||||
if err := r.SetFormParam({{ printf "%q" .Name }}, joined{{ pascalize .Name }}...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{{- else if and .IsPathParam }}
|
||||
|
||||
// path array param {{ .Name }}
|
||||
// SetPathParam does not support variadic arguments, since we used JoinByFormat
|
||||
// we can send the first item in the array as it's all the items of the previous
|
||||
// array joined together
|
||||
if len(joined{{ pascalize .Name }}) > 0 {
|
||||
if err := r.SetPathParam({{ printf "%q" .Name }}, joined{{ pascalize .Name }}[0]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
{{- else if .IsHeaderParam }}
|
||||
|
||||
// header array param {{ .Name }}
|
||||
if len(joined{{ pascalize .Name }}) > 0 {
|
||||
if err := r.SetHeaderParam({{ printf "%q" .Name }}, joined{{ pascalize .Name }}[0]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- if .IsBodyParam }}
|
||||
{{- if or .Schema.IsInterface .Schema.IsStream (and .Schema.IsArray .Child) (and .Schema.IsMap .Child) (and .Schema.IsNullable (not .HasDiscriminator)) }}
|
||||
if {{ .ValueExpression }} != nil {
|
||||
{{- end }}
|
||||
if err := r.SetBodyParam({{ .ValueExpression }}); err != nil {
|
||||
return err
|
||||
}
|
||||
{{- if or .Schema.IsInterface .Schema.IsStream (and .Schema.IsArray .Child) (and .Schema.IsMap .Child) (and .Schema.IsNullable (not .HasDiscriminator)) }}
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- end }}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
{{- range .Params }}
|
||||
{{- if and (not .IsBodyParam) (not .IsFileParam) .IsArray }}
|
||||
// bindParam{{ pascalize $.Name }} binds the parameter {{ .Name }}
|
||||
func ({{ .ReceiverName }} *{{ pascalize $.Name }}Params) bindParam{{ pascalize .Name }}(formats strfmt.Registry) []string {
|
||||
{{ varname .Child.ValueExpression }}R := {{ if and (not .IsArray) (not .IsStream) (not .IsMap) (.IsNullable) }}*{{end}}{{ .ValueExpression }}
|
||||
|
||||
{{ template "sliceclientparambinder" . }}
|
||||
|
||||
return {{ varname .Child.ValueExpression }}S
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- define "sliceclientparambinder" }}
|
||||
{{- if .IsArray }}
|
||||
var {{ varname .Child.ValueExpression }}C []string
|
||||
for _, {{ varname .Child.ValueExpression }}IR := range {{ varname .Child.ValueExpression }}R { // explode {{ .GoType }}
|
||||
{{ template "sliceclientparambinder" .Child }}
|
||||
{{ varname .Child.ValueExpression }}C = append({{ varname .Child.ValueExpression }}C, {{ varname .Child.ValueExpression }}IV)
|
||||
}
|
||||
|
||||
// {{ .Child.ItemsDepth }}CollectionFormat: {{ printf "%q" .CollectionFormat }}
|
||||
{{ varname .Child.ValueExpression }}S := swag.JoinByFormat({{ varname .Child.ValueExpression }}C, {{ printf "%q" .CollectionFormat }})
|
||||
{{- if .Child.Parent }}{{/* NOTE: we cannot expect a "multi" CollectionFormat within an inner array */}}
|
||||
{{ varname .Child.ValueExpression }}V := {{ varname .Child.ValueExpression }}S[0]
|
||||
{{- end }}
|
||||
|
||||
{{- else }}
|
||||
{{ varname .ValueExpression }}IV :=
|
||||
{{- if .IsCustomFormatter }}
|
||||
{{- print " " }}{{ varname .ValueExpression }}IR.String()
|
||||
{{- else if eq .GoType "string" }}
|
||||
{{- print " " }}{{ varname .ValueExpression }}IR
|
||||
{{- else if .Formatter }}
|
||||
{{- print " "}}{{ .Formatter }}({{ varname .ValueExpression }}IR)
|
||||
{{- else }}
|
||||
{{- print " " }}fmt.Sprintf("%v", {{ varname .ValueExpression }}IR)
|
||||
{{- end }} // {{ .GoType }} as string
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
346
vendor/github.com/go-swagger/go-swagger/generator/templates/client/response.gotmpl
generated
vendored
Normal file
346
vendor/github.com/go-swagger/go-swagger/generator/templates/client/response.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,346 @@
|
|||
{{- define "clientresponse" }}
|
||||
// New{{ pascalize .Name }} creates a {{ pascalize .Name }} with default headers values
|
||||
func New{{ pascalize .Name }}({{ if eq .Code -1 }}code int{{ end }}{{ if .Schema }}{{ if and (eq .Code -1) .Schema.IsStream }}, {{end}}{{ if .Schema.IsStream }}writer io.Writer{{ end }}{{ end }}) *{{ pascalize .Name }} {
|
||||
{{- if .Headers.HasSomeDefaults }}
|
||||
var (
|
||||
// initialize headers with default values
|
||||
{{- range .Headers }}
|
||||
{{- if .HasDefault }}
|
||||
{{ template "simpleschemaDefaultsvar" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
)
|
||||
{{- range .Headers }}
|
||||
{{- if .HasDefault }}
|
||||
{{ template "simpleschemaDefaultsinit" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
return &{{ pascalize .Name }}{
|
||||
{{- if eq .Code -1 }}
|
||||
_statusCode: code,
|
||||
{{- end }}
|
||||
{{ range .Headers }}
|
||||
{{- if .HasDefault }}
|
||||
{{ pascalize .Name}}: {{ if and (not .IsArray) (not .HasDiscriminator) (not .IsInterface) (not .IsStream) .IsNullable }}&{{ end }}{{ varname .ID }}Default,
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Schema }}
|
||||
{{- if .Schema.IsStream }}
|
||||
Payload: writer,
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
}
|
||||
}
|
||||
|
||||
/* {{ pascalize .Name}} describes a response with status code {{ .Code }}, with default header values.
|
||||
|
||||
{{ if .Description }}{{ blockcomment .Description }}{{else}}{{ pascalize .Name }} {{ humanize .Name }}{{end}}
|
||||
*/
|
||||
type {{ pascalize .Name }} struct {
|
||||
{{- if eq .Code -1 }}
|
||||
_statusCode int
|
||||
{{- end }}
|
||||
{{- range .Headers }}
|
||||
{{- if .Description }}
|
||||
|
||||
/* {{ blockcomment .Description }}
|
||||
{{- if or .SwaggerFormat .Default }}
|
||||
{{ print "" }}
|
||||
{{- if .SwaggerFormat }}
|
||||
Format: {{ .SwaggerFormat }}
|
||||
{{- end }}
|
||||
{{- if .Default }}
|
||||
Default: {{ json .Default }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
*/
|
||||
{{- end }}
|
||||
{{ pascalize .Name }} {{ .GoType }}
|
||||
{{- end }}
|
||||
{{- if .Schema }}
|
||||
|
||||
Payload {{ if and (not .Schema.IsBaseType) (not .Schema.IsInterface) .Schema.IsComplexObject (not .Schema.IsStream) }}*{{ end }}{{ if (not .Schema.IsStream) }}{{ .Schema.GoType }}{{ else }}io.Writer{{end}}
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
// IsSuccess returns true when this {{ humanize .Name }} response has a 2xx status code
|
||||
func ({{ .ReceiverName }} *{{ pascalize .Name }}) IsSuccess() bool {
|
||||
{{- if eq .Code -1 }}
|
||||
return {{ .ReceiverName }}._statusCode/100 == 2
|
||||
{{- else }}
|
||||
return {{ and (ge .Code 200) (lt .Code 300) }}
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
// IsRedirect returns true when this {{ humanize .Name }} response has a 3xx status code
|
||||
func ({{ .ReceiverName }} *{{ pascalize .Name }}) IsRedirect() bool {
|
||||
{{- if eq .Code -1 }}
|
||||
return {{ .ReceiverName }}._statusCode/100 == 3
|
||||
{{- else }}
|
||||
return {{ and (ge .Code 300) (lt .Code 400) }}
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
// IsClientError returns true when this {{ humanize .Name }} response has a 4xx status code
|
||||
func ({{ .ReceiverName }} *{{ pascalize .Name }}) IsClientError() bool {
|
||||
{{- if eq .Code -1 }}
|
||||
return {{ .ReceiverName }}._statusCode/100 == 4
|
||||
{{- else }}
|
||||
return {{ and (ge .Code 400) (lt .Code 500) }}
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
// IsServerError returns true when this {{ humanize .Name }} response has a 5xx status code
|
||||
func ({{ .ReceiverName }} *{{ pascalize .Name }}) IsServerError() bool {
|
||||
{{- if eq .Code -1 }}
|
||||
return {{ .ReceiverName }}._statusCode/100 == 5
|
||||
{{- else }}
|
||||
return {{ and (ge .Code 500) (lt .Code 600) }}
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
// IsCode returns true when this {{ humanize .Name }} response a status code equal to that given
|
||||
func ({{ .ReceiverName }} *{{ pascalize .Name }}) IsCode(code int) bool {
|
||||
{{- if eq .Code -1 }}
|
||||
return {{ .ReceiverName }}._statusCode == code
|
||||
{{- else }}
|
||||
return code == {{ .Code }}
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
// Code gets the status code for the {{ humanize .Name }} response
|
||||
func ({{ .ReceiverName }} *{{ pascalize .Name }}) Code() int {
|
||||
{{- if eq .Code -1 }}
|
||||
return {{ .ReceiverName }}._statusCode
|
||||
{{- else }}
|
||||
return {{ .Code }}
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
func ({{ .ReceiverName }} *{{ pascalize .Name }}) Error() string {
|
||||
return fmt.Sprintf("[{{ upper .Method }} {{ .Path }}][%d] {{ if .Name }}{{ .Name }} {{ else }}unknown error {{ end }}{{ if .Schema }} %+v{{ end }}", {{ if eq .Code -1 }}{{ .ReceiverName }}._statusCode{{ else }}{{ .Code }}{{ end }}{{ if .Schema }}, o.Payload{{ end }})
|
||||
}
|
||||
|
||||
func ({{ .ReceiverName }} *{{ pascalize .Name }}) String() string {
|
||||
return fmt.Sprintf("[{{ upper .Method }} {{ .Path }}][%d] {{ if .Name }}{{ .Name }} {{ else }}unknown response {{ end }}{{ if .Schema }} %+v{{ end }}", {{ if eq .Code -1 }}{{ .ReceiverName }}._statusCode{{ else }}{{ .Code }}{{ end }}{{ if .Schema }}, o.Payload{{ end }})
|
||||
}
|
||||
|
||||
{{ if .Schema }}
|
||||
func ({{ .ReceiverName }} *{{ pascalize .Name }}) GetPayload() {{ if and (not .Schema.IsBaseType) (not .Schema.IsInterface) .Schema.IsComplexObject (not .Schema.IsStream) }}*{{ end }}{{ if (not .Schema.IsStream) }}{{ .Schema.GoType }}{{ else }}io.Writer{{end}} {
|
||||
return o.Payload
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
func ({{ .ReceiverName }} *{{ pascalize .Name }}) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
{{- range .Headers }}
|
||||
|
||||
// hydrates response header {{.Name}}
|
||||
hdr{{ pascalize .Name }} := response.GetHeader("{{ .Name }}")
|
||||
|
||||
if hdr{{ pascalize .Name }} != "" {
|
||||
{{- if .Converter }}
|
||||
val{{ camelize .Name }}, err := {{ .Converter }}(hdr{{ pascalize .Name }})
|
||||
if err != nil {
|
||||
return errors.InvalidType({{ .Path }}, "header", "{{ .GoType }}", hdr{{ pascalize .Name }})
|
||||
}
|
||||
{{ .ReceiverName }}.{{ pascalize .Name }} = val{{ camelize .Name }}
|
||||
{{- else if .Child }}
|
||||
|
||||
// binding header items for {{ .Name }}
|
||||
val{{ pascalize .Name }}, err := {{ .ReceiverName }}.bindHeader{{ pascalize .Name }}(hdr{{ pascalize .Name }}, formats)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{{ .ReceiverName }}.{{ pascalize .Name }} = val{{ pascalize .Name }}
|
||||
{{- else if .IsCustomFormatter }}
|
||||
val{{ camelize .Name }}, err := formats.Parse({{ printf "%q" .SwaggerFormat }}, hdr{{ pascalize .Name }})
|
||||
if err != nil {
|
||||
return errors.InvalidType({{ .Path }}, "header", "{{ .GoType }}", hdr{{ pascalize .Name }})
|
||||
}
|
||||
{{- if .IsNullable }}
|
||||
v := (val{{ camelize .Name }}.({{ .GoType }}))
|
||||
{{ .ReceiverName }}.{{ pascalize .Name }} = &v
|
||||
{{- else }}
|
||||
{{ .ReceiverName }}.{{ pascalize .Name }} = *(val{{ camelize .Name }}.(*{{ .GoType }}))
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{- if eq .GoType "string" }}
|
||||
{{ .ReceiverName }}.{{ pascalize .Name }} = hdr{{ pascalize .Name }}
|
||||
{{- else }}
|
||||
{{ .ReceiverName }}.{{ pascalize .Name }} = {{ .GoType }}(hdr{{ pascalize .Name }})
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{- if .Schema }}
|
||||
{{- if .Schema.IsBaseType }}
|
||||
|
||||
// response payload as interface type
|
||||
payload, err := {{ toPackageName .ModelsPackage }}.Unmarshal{{ dropPackage .Schema.GoType }}{{ if .Schema.IsArray}}Slice{{ end }}(response.Body(), consumer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
{{ .ReceiverName }}.Payload = payload
|
||||
{{- else if .Schema.IsComplexObject }}
|
||||
|
||||
{{ .ReceiverName }}.Payload = new({{ .Schema.GoType }})
|
||||
{{- end }}
|
||||
{{- if not .Schema.IsBaseType }}
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), {{ if not (or .Schema.IsComplexObject .Schema.IsStream) }}&{{ end}}{{ .ReceiverName }}.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
return nil
|
||||
}
|
||||
{{- range .Headers }}
|
||||
{{- if .Child }}
|
||||
|
||||
// bindHeader{{ pascalize $.Name }} binds the response header {{ .Name }}
|
||||
func ({{ .ReceiverName }} *{{ pascalize $.Name }}) bindHeader{{ pascalize .Name }}(hdr string, formats strfmt.Registry) ({{ .GoType }}, error) {
|
||||
{{ varname .Child.ValueExpression }}V := hdr
|
||||
|
||||
{{ template "sliceclientheaderbinder" . }}
|
||||
|
||||
return {{ varname .Child.ValueExpression }}C, nil
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
|
||||
{{ if .Copyright -}}// {{ comment .Copyright -}}{{ end }}
|
||||
|
||||
|
||||
package {{ .Package }}
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/validate"
|
||||
|
||||
{{ imports .DefaultImports }}
|
||||
{{ imports .Imports }}
|
||||
)
|
||||
|
||||
// {{ pascalize .Name }}Reader is a Reader for the {{ pascalize .Name }} structure.
|
||||
type {{ pascalize .Name }}Reader struct {
|
||||
formats strfmt.Registry
|
||||
{{- if .HasStreamingResponse }}
|
||||
writer io.Writer
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
// ReadResponse reads a server response into the received {{ .ReceiverName }}.
|
||||
func ({{ .ReceiverName }} *{{ pascalize .Name }}Reader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
|
||||
{{- if .Responses}}
|
||||
switch response.Code() {
|
||||
{{- end }}
|
||||
{{- range .Responses }}
|
||||
case {{ .Code }}:
|
||||
result := New{{ pascalize .Name }}({{ if .Schema }}{{ if .Schema.IsStream }}{{ $.ReceiverName }}.writer{{ end }}{{ end }})
|
||||
if err := result.readResponse(response, consumer, {{ $.ReceiverName }}.formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return {{ if .IsSuccess }}result, nil{{else}}nil, result{{ end }}
|
||||
{{- end }}
|
||||
{{- if .DefaultResponse }}
|
||||
{{- with .DefaultResponse }}
|
||||
{{- if $.Responses}}
|
||||
default:
|
||||
{{- end }}
|
||||
result := New{{ pascalize .Name }}(response.Code(){{ if .Schema }}{{ if .Schema.IsStream }}, {{ $.ReceiverName }}.writer{{ end }}{{ end }})
|
||||
if err := result.readResponse(response, consumer, {{ $.ReceiverName }}.formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if response.Code() / 100 == 2 {
|
||||
return result, nil
|
||||
}
|
||||
return nil, result
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{- if $.Responses}}
|
||||
default:
|
||||
{{- end }}
|
||||
return nil, runtime.NewAPIError("[{{ upper .Method }} {{ .Path }}]{{ if .Name }} {{ .Name }}{{ end }}", response, response.Code())
|
||||
{{- end }}
|
||||
{{- if .Responses}}
|
||||
}
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
{{ range .Responses }}
|
||||
{{ template "clientresponse" . }}
|
||||
{{ end }}
|
||||
{{ if .DefaultResponse }}
|
||||
{{ template "clientresponse" .DefaultResponse }}
|
||||
{{ end }}
|
||||
|
||||
{{ range .ExtraSchemas }}
|
||||
/*{{ pascalize .Name }} {{ template "docstring" . }}
|
||||
swagger:model {{ .Name }}
|
||||
*/
|
||||
{{- template "schema" . }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "sliceclientheaderbinder" }}
|
||||
{{- if .IsArray }}
|
||||
var (
|
||||
{{ varname .Child.ValueExpression }}C {{ .GoType }}
|
||||
)
|
||||
// {{ .Child.ItemsDepth }}CollectionFormat: {{ printf "%q" .CollectionFormat }}
|
||||
{{ varname .Child.ValueExpression }}R := swag.SplitByFormat({{ varname .Child.ValueExpression }}V, {{ printf "%q" .CollectionFormat }})
|
||||
|
||||
for {{ if or .Child.IsCustomFormatter .Child.Converter }}{{ .IndexVar }}{{ else }}_{{ end }}, {{ varname .Child.ValueExpression }}IV := range {{ varname .Child.ValueExpression }}R {
|
||||
{{ template "sliceclientheaderbinder" .Child }}
|
||||
{{ varname .Child.ValueExpression }}C = append({{ varname .Child.ValueExpression }}C, {{ varname .Child.ValueExpression }}IC) // roll-up {{ .Child.GoType }} into {{ .GoType }}
|
||||
}
|
||||
|
||||
{{- else }}
|
||||
// convert split string to {{ .GoType }}
|
||||
{{- if .IsCustomFormatter }}
|
||||
val, err := formats.Parse({{ printf "%q" .SwaggerFormat }}, {{ varname .ValueExpression }}IV)
|
||||
if err != nil {
|
||||
return nil, errors.InvalidType({{ .Path }}, "header{{ .ItemsDepth }}", "{{ .GoType }}", {{ varname .ValueExpression }}IV)
|
||||
}
|
||||
{{- if .IsNullable }}
|
||||
{{ varname .ValueExpression }}IC := (&val).(*{{ .GoType }})
|
||||
{{- else }}
|
||||
{{ varname .ValueExpression }}IC := val.({{ .GoType }})
|
||||
{{- end }}
|
||||
{{- else if .Converter }}
|
||||
val, err := {{- print " "}}{{ .Converter }}({{ varname .ValueExpression }}IV)
|
||||
if err != nil {
|
||||
return nil, errors.InvalidType({{ .Path }}, "header{{ .ItemsDepth }}", "{{ .GoType }}", {{ varname .ValueExpression }}IV)
|
||||
}
|
||||
{{- if .IsNullable }}
|
||||
{{ varname .ValueExpression }}IC := &val
|
||||
{{- else }}
|
||||
{{ varname .ValueExpression }}IC := val
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{ varname .ValueExpression }}IC :=
|
||||
{{- if eq .GoType "string" }}
|
||||
{{- print " " }}{{ varname .ValueExpression }}IV
|
||||
{{- else }}
|
||||
{{- print " " }}fmt.Sprintf("%v", {{ varname .ValueExpression }}IV)
|
||||
{{- end }} // string as {{ .GoType }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
311
vendor/github.com/go-swagger/go-swagger/generator/templates/contrib/stratoscale/README.md
generated
vendored
Normal file
311
vendor/github.com/go-swagger/go-swagger/generator/templates/contrib/stratoscale/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
# swagger
|
||||
|
||||
In Stratoscale, we really like the idea of API-first services, and we also really like Go.
|
||||
We saw the go-swagger library, and thought that most of it can really help us. Generating code from
|
||||
swagger files is a big problem with a lot of corner cases, and go-swagger is doing great job.
|
||||
|
||||
The one thing that we felt missing, is customization of the server to run with our design principles:
|
||||
|
||||
* Custom `main` function
|
||||
* Dependency injection
|
||||
* Limited scopes with unit testing.
|
||||
|
||||
Also:
|
||||
|
||||
* Adding you functions to the generated `configure_swagger_*.go` seems to be a burden.
|
||||
* Lack of Interface that the service implement.
|
||||
* Complicated and custom http clients and runtime.
|
||||
|
||||
Those are the changes that this contributor templates are providing:
|
||||
|
||||
## Server
|
||||
|
||||
### The new `restapi` package exposes interfaces
|
||||
|
||||
* Those interfaces can implemented by the developer and are the business logic of the service.
|
||||
* The implementation of those is extensible.
|
||||
* The implementation is separated from the generated code.
|
||||
|
||||
### The `restapi` returns an `http.Handler`
|
||||
|
||||
The `restapi.Handler` (see [example](./example/restapi/configure_swagger_petstore.go)) function returns
|
||||
a standard `http.Handler`
|
||||
|
||||
* Given objects that implements the business logic, we can create a simple http handler.
|
||||
* This handler is standard go http.Handler, so we can now use any other middleware, library, or framework
|
||||
that support it.
|
||||
* This handler is standard, so we understand it better.
|
||||
|
||||
## Client
|
||||
|
||||
* The new client package exposes interfaces, so functions in our code can receive those
|
||||
interfaces which can be mocked for testing.
|
||||
* The new client has a config that gets an `*url.URL` to customize the endpoint.
|
||||
* The new client has a config that gets an `http.RoundTripper` to customize client with libraries, middleware or
|
||||
frameworks that support the standard library's objects.
|
||||
|
||||
# Example Walk-Through
|
||||
|
||||
In the [example package](https://github.com/Stratoscale/swagger/tree/master/example) you'll find generated code and usage of the pet-store
|
||||
[swagger file](./example/swagger.yaml).
|
||||
|
||||
* The `restapi`, `models` and `client` are auto-generated by the stratoscale/swagger docker file.
|
||||
* The `internal` package was manually added and contains the server's business logic.
|
||||
* The `main.go` file is the entrypoint and contains initializations and dependency injections of the project.
|
||||
|
||||
## Server
|
||||
|
||||
### [restapi](https://github.com/Stratoscale/swagger/tree/master/example/restapi)
|
||||
|
||||
This package is autogenerated and contains the server routing and parameters parsing.
|
||||
|
||||
The modified version contains `restapi.PetAPI` and `restapi.StoreAPI` which were auto generated.
|
||||
|
||||
```go
|
||||
// PetAPI
|
||||
type PetAPI interface {
|
||||
PetCreate(ctx context.Context, params pet.PetCreateParams) middleware.Responder
|
||||
PetDelete(ctx context.Context, params pet.PetDeleteParams) middleware.Responder
|
||||
PetGet(ctx context.Context, params pet.PetGetParams) middleware.Responder
|
||||
PetList(ctx context.Context, params pet.PetListParams) middleware.Responder
|
||||
PetUpdate(ctx context.Context, params pet.PetUpdateParams) middleware.Responder
|
||||
}
|
||||
|
||||
//go:generate mockery -name StoreAPI -inpkg
|
||||
|
||||
// StoreAPI
|
||||
type StoreAPI interface {
|
||||
InventoryGet(ctx context.Context, params store.InventoryGetParams) middleware.Responder
|
||||
OrderCreate(ctx context.Context, params store.OrderCreateParams) middleware.Responder
|
||||
// OrderDelete is For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors
|
||||
OrderDelete(ctx context.Context, params store.OrderDeleteParams) middleware.Responder
|
||||
// OrderGet is For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions
|
||||
OrderGet(ctx context.Context, params store.OrderGetParams) middleware.Responder
|
||||
}
|
||||
```
|
||||
|
||||
Each function matches an `operationId` in the swagger file and they are grouped according to
|
||||
the operation `tags`.
|
||||
|
||||
There is also a `restapi.Config`:
|
||||
|
||||
```go
|
||||
// Config is configuration for Handler
|
||||
type Config struct {
|
||||
PetAPI
|
||||
StoreAPI
|
||||
Logger func(string, ...interface{})
|
||||
// InnerMiddleware is for the handler executors. These do not apply to the swagger.json document.
|
||||
// The middleware executes after routing but before authentication, binding and validation
|
||||
InnerMiddleware func(http.Handler) http.Handler
|
||||
}
|
||||
```
|
||||
|
||||
This config is auto generated and contains all the declared interfaces above.
|
||||
It is used to initiate an http.Handler with the `Handler` function:
|
||||
|
||||
```go
|
||||
// Handler returns an http.Handler given the handler configuration
|
||||
// It mounts all the business logic implementers in the right routing.
|
||||
func Handler(c Config) (http.Handler, error) {
|
||||
...
|
||||
```
|
||||
|
||||
Let's look how we use this generated code to build our server.
|
||||
|
||||
### [internal](https://github.com/Stratoscale/swagger/tree/master/example/internal)
|
||||
|
||||
The `internal` package is **not** auto generated and contains the business logic of our server.
|
||||
We can see two structs that implements the `restapi.PetAPI` and `restapi.StoreAPI` interfaces,
|
||||
needed to make our server work.
|
||||
|
||||
When adding or removing functions from our REST API, we can just add or remove functions to those
|
||||
business logic units. We can also create new logical units when they are added to our REST API.
|
||||
|
||||
### [main.go](./example/main.go)
|
||||
|
||||
The main function is pretty straight forward. We initiate our business logic units.
|
||||
Then create a config for our rest API. We then create a standard `http.Handler` which we can
|
||||
update with middleware, test with `httptest`, or to use with other standard tools.
|
||||
The last piece is to run the handler with `http.ListenAndServe` or to use it with an `http.Server` -
|
||||
it is all very customizable.
|
||||
|
||||
```go
|
||||
func main() {
|
||||
// Initiate business logic implementers.
|
||||
// This is the main function, so here the implementers' dependencies can be
|
||||
// injected, such as database, parameters from environment variables, or different
|
||||
// clients for different APIs.
|
||||
p := internal.Pet{}
|
||||
s := internal.Store{}
|
||||
|
||||
// Initiate the http handler, with the objects that are implementing the business logic.
|
||||
h, err := restapi.Handler(restapi.Config{
|
||||
PetAPI: &p,
|
||||
StoreAPI: &s,
|
||||
Logger: log.Printf,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Run the standard http server
|
||||
log.Fatal(http.ListenAndServe(":8080", h))
|
||||
}
|
||||
```
|
||||
|
||||
## Client
|
||||
|
||||
The client code is in the [client package](https://github.com/Stratoscale/swagger/tree/master/example/client) and is autogenerated.
|
||||
|
||||
To create a new client we use the `client.Config` struct:
|
||||
|
||||
```go
|
||||
type Config struct {
|
||||
// URL is the base URL of the upstream server
|
||||
URL *url.URL
|
||||
// Transport is an inner transport for the client
|
||||
Transport http.RoundTripper
|
||||
}
|
||||
```
|
||||
|
||||
This enables us to use custom server endpoint or custom client middleware. Easily, with the
|
||||
standard components, and with any library that accepts them.
|
||||
|
||||
The client is then generated with the New method:
|
||||
|
||||
```go
|
||||
// New creates a new swagger petstore HTTP client.
|
||||
func New(c Config) *SwaggerPetstore { ... }
|
||||
```
|
||||
|
||||
This method returns an object that has two important fields:
|
||||
|
||||
```go
|
||||
type SwaggerPetstore {
|
||||
...
|
||||
Pet *pet.Client
|
||||
Store *store.Client
|
||||
}
|
||||
```
|
||||
|
||||
Thos fields are objects, which implements interfaces declared in the [pet](./example/client/pet) and
|
||||
[store](./example/client/store) packages:
|
||||
|
||||
For example:
|
||||
|
||||
```go
|
||||
// API is the interface of the pet client
|
||||
type API interface {
|
||||
// PetCreate adds a new pet to the store
|
||||
PetCreate(ctx context.Context, params *PetCreateParams) (*PetCreateCreated, error)
|
||||
// PetDelete deletes a pet
|
||||
PetDelete(ctx context.Context, params *PetDeleteParams) (*PetDeleteNoContent, error)
|
||||
// PetGet gets pet by it s ID
|
||||
PetGet(ctx context.Context, params *PetGetParams) (*PetGetOK, error)
|
||||
// PetList lists pets
|
||||
PetList(ctx context.Context, params *PetListParams) (*PetListOK, error)
|
||||
// PetUpdate updates an existing pet
|
||||
PetUpdate(ctx context.Context, params *PetUpdateParams) (*PetUpdateCreated, error)
|
||||
}
|
||||
```
|
||||
|
||||
They are very similar to the server interfaces, and can be used by consumers of those APIs
|
||||
(instead of using the actual client or the `*Pet` struct)
|
||||
|
||||
# Authentication
|
||||
|
||||
Authenticating and policy enforcement of the application is done in several stages, described below.
|
||||
|
||||
## Define security in swagger.yaml
|
||||
|
||||
Add to the root of the swagger.yaml the security and security definitions sections.
|
||||
|
||||
```yaml
|
||||
securityDefinitions:
|
||||
token:
|
||||
type: apiKey
|
||||
in: header
|
||||
name: Cookie
|
||||
|
||||
security:
|
||||
- token: []
|
||||
```
|
||||
|
||||
The securityDefinitions section defines different security types that your application can handle.
|
||||
The supported types by go-swagger are:
|
||||
* `apiKey` - token that should be able to processed.
|
||||
* `oauth2` - token and scopes that should be processed.
|
||||
* and `basic` - user/password that should be processed.
|
||||
|
||||
Here we defined an apiKey, that is passed through the Cookie header.
|
||||
|
||||
The `security` section defines the default security enforcement for the application. You can select
|
||||
different securityDefinitions, as the keys, and apply "scopes" as the values. Those default definitions
|
||||
can be overriden in each route by a section with the same name:
|
||||
|
||||
```yaml
|
||||
paths:
|
||||
/pets:
|
||||
post:
|
||||
[...]
|
||||
security:
|
||||
- token: [admin]
|
||||
```
|
||||
|
||||
Here we overriden the scope of token in the POST /pets URL so that only admin can use this API.
|
||||
|
||||
Let's see how we can use this functionality.
|
||||
|
||||
## Writing Security Handlers
|
||||
|
||||
Once we created a security definition named "token", a function called "AuthToken" was added to the `restapi.Config`:
|
||||
|
||||
```go
|
||||
type Config struct {
|
||||
...
|
||||
// AuthToken Applies when the "Cookie" header is set
|
||||
AuthToken func(token string) (interface{}, error)
|
||||
}
|
||||
```
|
||||
|
||||
This function gets the content of the Cookie header, and should return an `interface{}` and `error`.
|
||||
The `interface{}` is the object that should represent the user that performed the request, it should
|
||||
be nil to return an unauthorized 401 HTTP response. If the returned `error` is not nil, an HTTP 500,
|
||||
internal server error will be returned.
|
||||
|
||||
The returned object, will be stored in the request context under the `restapi.AuthKey` key.
|
||||
|
||||
There is another function that we should know about, in the `restapi.Config` struct:
|
||||
|
||||
```go
|
||||
type Config struct {
|
||||
...
|
||||
// Authorizer is used to authorize a request after the Auth function was called using the "Auth*" functions
|
||||
// and the principal was stored in the context in the "AuthKey" context value.
|
||||
Authorizer func(*http.Request) error
|
||||
}
|
||||
```
|
||||
|
||||
This one is a custom defined function that gets the request and can return an error.
|
||||
If the returned error is not nil, and 403 HTTP error will be returned to the client - here the policy
|
||||
enforcement comes to place.
|
||||
There are two things that this function should be aware of:
|
||||
|
||||
1. The user - it can retrieve the user information from the context: `ctx.Value(restapi.AuthKey).(MyUserType)`.
|
||||
Usually, a server will have a function for extracting this user information and returns a concrete
|
||||
type which could be used by all the routes.
|
||||
2. The route - it can retrieve the route using the go-swagger function: `middleware.MatchedRouteFrom(*http.Request)`.
|
||||
So no need to parse URL and test the request method.
|
||||
This route struct contains the route information. If for example, we want to check the scopes that were
|
||||
defined for the current route in the swagger.yaml we can use the code below:
|
||||
|
||||
```go
|
||||
for _, auth := range route.Authenticators {
|
||||
for scopeName, scopeValues := range auth.Scopes {
|
||||
for _, scopeValue := range scopeValues {
|
||||
...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
111
vendor/github.com/go-swagger/go-swagger/generator/templates/contrib/stratoscale/client/client.gotmpl
generated
vendored
Normal file
111
vendor/github.com/go-swagger/go-swagger/generator/templates/contrib/stratoscale/client/client.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
|
||||
{{ if .Copyright -}}// {{ comment .Copyright -}}{{ end }}
|
||||
|
||||
|
||||
package {{ .Name }}
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/validate"
|
||||
|
||||
strfmt "github.com/go-openapi/strfmt"
|
||||
|
||||
{{ imports .DefaultImports }}
|
||||
{{ imports .Imports }}
|
||||
)
|
||||
|
||||
//go:generate mockery --name API --keeptree --with-expecter --case underscore
|
||||
|
||||
// API is the interface of the {{ humanize .Name }} client
|
||||
type API interface {
|
||||
{{ range .Operations -}}
|
||||
/*
|
||||
{{ pascalize .Name }} {{ if .Summary }}{{ pluralizeFirstWord (humanize .Summary) }}{{ if .Description }}
|
||||
|
||||
{{ blockcomment .Description }}{{ end }}{{ else if .Description}}{{ blockcomment .Description }}{{ else }}{{ humanize .Name }} API{{ end -}}
|
||||
*/
|
||||
{{ pascalize .Name }}(ctx context.Context, params *{{ pascalize .Name }}Params{{ if .HasStreamingResponse }}, writer io.Writer{{ end }}) {{ if .SuccessResponse }}({{ range .SuccessResponses }}*{{ pascalize .Name }}, {{ end }}{{ end }}error{{ if .SuccessResponse }}){{ end }}
|
||||
{{ end -}}
|
||||
}
|
||||
|
||||
// New creates a new {{ humanize .Name }} API client.
|
||||
func New(transport runtime.ClientTransport, formats strfmt.Registry, authInfo runtime.ClientAuthInfoWriter) *Client {
|
||||
return &Client{
|
||||
transport: transport,
|
||||
formats: formats,
|
||||
authInfo: authInfo,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Client {{ if .Summary }}{{ .Summary }}{{ if .Description }}
|
||||
|
||||
{{ blockcomment .Description }}{{ end }}{{ else if .Description}}{{ blockcomment .Description }}{{ else }}for {{ humanize .Name }} API{{ end }}
|
||||
*/
|
||||
type Client struct {
|
||||
transport runtime.ClientTransport
|
||||
formats strfmt.Registry
|
||||
authInfo runtime.ClientAuthInfoWriter
|
||||
}
|
||||
|
||||
{{ range .Operations -}}
|
||||
/*
|
||||
{{ pascalize .Name }} {{ if .Summary }}{{ pluralizeFirstWord (humanize .Summary) }}{{ if .Description }}
|
||||
|
||||
{{ blockcomment .Description }}{{ end }}{{ else if .Description}}{{ blockcomment .Description }}{{ else }}{{ humanize .Name }} API{{ end }}
|
||||
*/
|
||||
func (a *Client) {{ pascalize .Name }}(ctx context.Context, params *{{ pascalize .Name }}Params{{ if .HasStreamingResponse }}, writer io.Writer{{ end }}) {{ if .SuccessResponse }}({{ range .SuccessResponses }}*{{ pascalize .Name }}, {{ end }}{{ end }}error{{ if .SuccessResponse }}){{ end }} {
|
||||
{{ $length := len .SuccessResponses }}
|
||||
{{ $success := .SuccessResponses }}
|
||||
{{ if .Responses }}result{{else}}_{{end}}, err := a.transport.Submit(&runtime.ClientOperation{
|
||||
ID: {{ printf "%q" .Name }},
|
||||
Method: {{ printf "%q" .Method }},
|
||||
PathPattern: {{ printf "%q" .Path }},
|
||||
ProducesMediaTypes: {{ printf "%#v" .ProducesMediaTypes }},
|
||||
ConsumesMediaTypes: {{ printf "%#v" .ConsumesMediaTypes }},
|
||||
Schemes: {{ printf "%#v" .Schemes }},
|
||||
Params: params,
|
||||
Reader: &{{ pascalize .Name }}Reader{formats: a.formats{{ if .HasStreamingResponse }}, writer: writer{{ end }}},
|
||||
{{ if .Authorized -}}
|
||||
AuthInfo: a.authInfo,
|
||||
{{ end -}}
|
||||
Context: ctx,
|
||||
Client: params.HTTPClient,
|
||||
})
|
||||
if err != nil {
|
||||
return {{ if $success }}{{ padSurround "nil" "nil" 0 $length }}, {{ end }}err
|
||||
}
|
||||
{{- if .Responses }}
|
||||
switch value := result.(type) {
|
||||
{{- range $i, $v := .Responses }}
|
||||
case *{{ pascalize $v.Name }}:
|
||||
{{- if $v.IsSuccess }}
|
||||
return {{ if $success }}{{ padSurround "value" "nil" $i $length }},{{ end }}nil
|
||||
{{- else }}
|
||||
return {{ if $success }}{{ padSurround "nil" "nil" 0 $length }},{{ end }}runtime.NewAPIError("unsuccessful response", value, value.Code())
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
}
|
||||
{{- if .DefaultResponse }}
|
||||
// unexpected success response
|
||||
unexpectedSuccess := result.(*{{ pascalize .DefaultResponse.Name }})
|
||||
return {{ if $success }}{{ padSurround "nil" "nil" 0 $length }}, {{ end }}runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
|
||||
{{- else }}
|
||||
// safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue
|
||||
msg := fmt.Sprintf("unexpected success response for {{ .Name }}: API contract not enforced by server. Client expected to get an error, but got: %T", result)
|
||||
panic(msg)
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
return nil
|
||||
{{- end }}
|
||||
}
|
||||
{{ end }}
|
||||
83
vendor/github.com/go-swagger/go-swagger/generator/templates/contrib/stratoscale/client/facade.gotmpl
generated
vendored
Normal file
83
vendor/github.com/go-swagger/go-swagger/generator/templates/contrib/stratoscale/client/facade.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
|
||||
{{ if .Copyright -}}// {{ comment .Copyright -}}{{ end }}
|
||||
|
||||
|
||||
package {{ .Package }}
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"net/http"
|
||||
|
||||
rtclient "github.com/go-openapi/runtime/client"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
||||
{{ imports .DefaultImports }}
|
||||
{{ imports .Imports }}
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultHost is the default Host
|
||||
// found in Meta (info) section of spec file
|
||||
DefaultHost string = {{ printf "%#v" .Host }}
|
||||
// DefaultBasePath is the default BasePath
|
||||
// found in Meta (info) section of spec file
|
||||
DefaultBasePath string = {{ printf "%#v" .BasePath }}
|
||||
)
|
||||
|
||||
// DefaultSchemes are the default schemes found in Meta (info) section of spec file
|
||||
var DefaultSchemes = {{ printf "%#v" .Schemes }}
|
||||
|
||||
type Config struct {
|
||||
// URL is the base URL of the upstream server
|
||||
URL *url.URL
|
||||
// Transport is an inner transport for the client
|
||||
Transport http.RoundTripper
|
||||
// AuthInfo is for authentication
|
||||
AuthInfo runtime.ClientAuthInfoWriter
|
||||
}
|
||||
|
||||
// New creates a new {{ humanize .Name }} HTTP client.
|
||||
func New(c Config) *{{ pascalize .Name }} {
|
||||
var (
|
||||
host = DefaultHost
|
||||
basePath = DefaultBasePath
|
||||
schemes = DefaultSchemes
|
||||
)
|
||||
|
||||
if c.URL != nil {
|
||||
host = c.URL.Host
|
||||
basePath = c.URL.Path
|
||||
schemes = []string{c.URL.Scheme}
|
||||
}
|
||||
|
||||
transport := rtclient.New(host, basePath, schemes)
|
||||
if c.Transport != nil {
|
||||
transport.Transport = c.Transport
|
||||
}
|
||||
|
||||
cli := new({{ pascalize .Name }})
|
||||
cli.Transport = transport
|
||||
{{ range .OperationGroups -}}
|
||||
cli.{{ pascalize .Name }} = {{ .PackageAlias }}.New(transport, strfmt.Default, c.AuthInfo)
|
||||
{{ end -}}
|
||||
|
||||
return cli
|
||||
}
|
||||
|
||||
// {{ pascalize .Name }} is a client for {{ humanize .Name }}
|
||||
type {{ pascalize .Name }} struct {
|
||||
{{ range .OperationGroups -}}
|
||||
{{ pascalize .Name }} {{ .PackageAlias }}.API
|
||||
{{ end -}}
|
||||
Transport runtime.ClientTransport
|
||||
}
|
||||
222
vendor/github.com/go-swagger/go-swagger/generator/templates/contrib/stratoscale/server/configureapi.gotmpl
generated
vendored
Normal file
222
vendor/github.com/go-swagger/go-swagger/generator/templates/contrib/stratoscale/server/configureapi.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
|
||||
{{ if .Copyright -}}// {{ comment .Copyright -}}{{ end }}
|
||||
|
||||
|
||||
package {{ .APIPackage }}
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net/http"
|
||||
"log"
|
||||
"fmt"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/runtime/security"
|
||||
|
||||
{{ imports .DefaultImports }}
|
||||
{{ imports .Imports }}
|
||||
)
|
||||
{{ $package := .Package }}
|
||||
|
||||
type contextKey string
|
||||
|
||||
const AuthKey contextKey = "Auth"
|
||||
|
||||
{{ range .OperationGroups -}}
|
||||
//go:generate mockery -name {{ pascalize .Name}}API -inpkg
|
||||
|
||||
/* {{ pascalize .Name }}API {{ .Description }} */
|
||||
type {{ pascalize .Name }}API interface {
|
||||
{{ range .Operations -}}
|
||||
{{ if .Summary -}}
|
||||
/* {{ pascalize .Name }} {{ .Summary }} */
|
||||
{{ else if .Description -}}
|
||||
/* {{ pascalize .Name }} {{ .Description }} */
|
||||
{{ end -}}
|
||||
{{ pascalize .Name }}(ctx context.Context, params {{.Package}}.{{ pascalize .Name }}Params) middleware.Responder
|
||||
|
||||
{{ end -}}
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
// Config is configuration for Handler
|
||||
type Config struct {
|
||||
{{ range .OperationGroups -}}
|
||||
{{ pascalize .Name }}API
|
||||
{{ end -}}
|
||||
Logger func(string, ...interface{})
|
||||
// InnerMiddleware is for the handler executors. These do not apply to the swagger.json document.
|
||||
// The middleware executes after routing but before authentication, binding and validation
|
||||
InnerMiddleware func(http.Handler) http.Handler
|
||||
|
||||
// Authorizer is used to authorize a request after the Auth function was called using the "Auth*" functions
|
||||
// and the principal was stored in the context in the "AuthKey" context value.
|
||||
Authorizer func(*http.Request) error
|
||||
|
||||
{{ range .SecurityDefinitions -}}
|
||||
{{ if .IsBasicAuth -}}
|
||||
// Auth{{ pascalize .ID }} for basic authentication
|
||||
Auth{{ pascalize .ID }} func(user string, pass string) ({{ if .PrincipalIsNullable }}*{{ end }}{{ .Principal }}, error)
|
||||
{{ end -}}
|
||||
{{ if .IsAPIKeyAuth -}}
|
||||
// Auth{{ pascalize .ID }} Applies when the "{{ .Name }}" {{ .Source }} is set
|
||||
Auth{{ pascalize .ID }} func(token string) ({{ if .PrincipalIsNullable }}*{{ end }}{{ .Principal }}, error)
|
||||
{{ end }}
|
||||
{{ if .IsOAuth2 -}}
|
||||
// Auth{{ pascalize .ID }} For OAuth2 authentication
|
||||
Auth{{ pascalize .ID }} func(token string, scopes []string) ({{ if .PrincipalIsNullable }}*{{ end }}{{ .Principal }}, error)
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
|
||||
// Authenticator to use for all APIKey authentication
|
||||
APIKeyAuthenticator func(string, string, security.TokenAuthentication) runtime.Authenticator
|
||||
// Authenticator to use for all Bearer authentication
|
||||
BasicAuthenticator func(security.UserPassAuthentication) runtime.Authenticator
|
||||
// Authenticator to use for all Basic authentication
|
||||
BearerAuthenticator func(string, security.ScopedTokenAuthentication) runtime.Authenticator
|
||||
|
||||
{{ range .Consumes -}}
|
||||
{{ if .Implementation -}}
|
||||
// {{ pascalize .Name }}Consumer is a {{ .Name }} consumer that will replace the default if not nil.
|
||||
{{ pascalize .Name }}Consumer runtime.Consumer
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
}
|
||||
|
||||
// Handler returns an http.Handler given the handler configuration
|
||||
// It mounts all the business logic implementers in the right routing.
|
||||
func Handler(c Config) (http.Handler, error) {
|
||||
h, _, err := HandlerAPI(c)
|
||||
return h, err
|
||||
}
|
||||
|
||||
// HandlerAPI returns an http.Handler given the handler configuration
|
||||
// and the corresponding *{{ pascalize .Name }} instance.
|
||||
// It mounts all the business logic implementers in the right routing.
|
||||
func HandlerAPI(c Config) (http.Handler, *{{.Package}}.{{ pascalize .Name }}API, error) {
|
||||
spec, err := loads.Analyzed(swaggerCopy(SwaggerJSON), "")
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("analyze swagger: %v", err)
|
||||
}
|
||||
api := {{.Package}}.New{{ pascalize .Name }}API(spec)
|
||||
api.ServeError = errors.ServeError
|
||||
api.Logger = c.Logger
|
||||
|
||||
if c.APIKeyAuthenticator != nil {
|
||||
api.APIKeyAuthenticator = c.APIKeyAuthenticator
|
||||
}
|
||||
if c.BasicAuthenticator != nil {
|
||||
api.BasicAuthenticator = c.BasicAuthenticator
|
||||
}
|
||||
if c.BearerAuthenticator != nil {
|
||||
api.BearerAuthenticator = c.BearerAuthenticator
|
||||
}
|
||||
|
||||
{{ range .Consumes -}}
|
||||
if c.{{ pascalize .Name }}Consumer != nil {
|
||||
api.{{ pascalize .Name }}Consumer = c.{{ pascalize .Name }}Consumer
|
||||
} else {
|
||||
{{ if .Implementation -}}
|
||||
api.{{ pascalize .Name }}Consumer = {{ .Implementation }}
|
||||
{{ else }}
|
||||
api.{{ pascalize .Name }}Consumer = runtime.ConsumerFunc(func(r io.Reader, target interface{}) error {
|
||||
return errors.NotImplemented("{{.Name}} consumer has not yet been implemented")
|
||||
})
|
||||
{{ end -}}
|
||||
}
|
||||
{{ end -}}
|
||||
{{ range .Produces -}}
|
||||
{{ if .Implementation -}}
|
||||
api.{{ pascalize .Name }}Producer = {{ .Implementation }}
|
||||
{{ else -}}
|
||||
api.{{ pascalize .Name }}Producer = runtime.ProducerFunc(func(w io.Writer, data interface{}) error {
|
||||
return errors.NotImplemented("{{.Name}} producer has not yet been implemented")
|
||||
})
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
|
||||
{{ range .SecurityDefinitions -}}
|
||||
{{ if .IsBasicAuth -}}
|
||||
api.{{ pascalize .ID }}Auth = func(user string, pass string) ({{if .PrincipalIsNullable }}*{{ end }}{{.Principal}}, error) {
|
||||
if c.Auth{{ pascalize .ID }} == nil {
|
||||
{{- if eq .Principal "interface{}" }}
|
||||
return "", nil
|
||||
{{- else }}
|
||||
panic("you specified a custom principal type, but did not provide the authenticator to provide this")
|
||||
{{- end }}
|
||||
}
|
||||
return c.Auth{{ pascalize .ID }}(user, pass)
|
||||
}
|
||||
{{ end -}}
|
||||
{{ if .IsAPIKeyAuth -}}
|
||||
api.{{ pascalize .ID }}Auth = func(token string) ({{ if .PrincipalIsNullable }}*{{ end }}{{.Principal}}, error) {
|
||||
if c.Auth{{ pascalize .ID }} == nil {
|
||||
{{- if eq .Principal "interface{}" }}
|
||||
return token, nil
|
||||
{{- else }}
|
||||
panic("you specified a custom principal type, but did not provide the authenticator to provide this")
|
||||
{{- end }}
|
||||
}
|
||||
return c.Auth{{ pascalize .ID }}(token)
|
||||
}
|
||||
{{ end }}
|
||||
{{ if .IsOAuth2 -}}
|
||||
api.{{ pascalize .ID }}Auth = func(token string, scopes []string) ({{ if .PrincipalIsNullable }}*{{ end }}{{.Principal}}, error) {
|
||||
if c.Auth{{ pascalize .ID }} == nil {
|
||||
{{- if eq .Principal "interface{}" }}
|
||||
return token, nil
|
||||
{{- else }}
|
||||
panic("you specified a custom principal type, but did not provide the authenticator to provide this")
|
||||
{{- end }}
|
||||
}
|
||||
return c.Auth{{ pascalize .ID }}(token, scopes)
|
||||
}
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
|
||||
{{ if .SecurityDefinitions -}}
|
||||
api.APIAuthorizer = authorizer(c.Authorizer)
|
||||
{{ end -}}
|
||||
|
||||
{{ range .Operations -}}
|
||||
api.{{if ne .Package $package}}{{pascalize .Package}}{{end}}{{ pascalize .Name }}Handler =
|
||||
{{- .PackageAlias }}.{{ pascalize .Name }}HandlerFunc(func(params {{.PackageAlias}}.{{ pascalize .Name }}Params{{if .Authorized}}, principal {{ if .PrincipalIsNullable }}*{{ end }}{{ .Principal }}{{end}}) middleware.Responder {
|
||||
ctx := params.HTTPRequest.Context()
|
||||
{{ if .Authorized -}}
|
||||
ctx = storeAuth(ctx, principal)
|
||||
{{ end -}}
|
||||
return c.{{pascalize .Package}}API.{{pascalize .Name}}(ctx, params)
|
||||
})
|
||||
{{ end -}}
|
||||
|
||||
api.ServerShutdown = func() { }
|
||||
return api.Serve(c.InnerMiddleware), api, nil
|
||||
}
|
||||
|
||||
// swaggerCopy copies the swagger json to prevent data races in runtime
|
||||
func swaggerCopy(orig json.RawMessage) json.RawMessage {
|
||||
c := make(json.RawMessage, len(orig))
|
||||
copy(c, orig)
|
||||
return c
|
||||
}
|
||||
|
||||
// authorizer is a helper function to implement the runtime.Authorizer interface.
|
||||
type authorizer func(*http.Request) error
|
||||
|
||||
func (a authorizer) Authorize(req *http.Request, principal interface{}) error {
|
||||
if a == nil {
|
||||
return nil
|
||||
}
|
||||
ctx := storeAuth(req.Context(), principal)
|
||||
return a(req.WithContext(ctx))
|
||||
}
|
||||
|
||||
func storeAuth(ctx context.Context, principal interface{}) context.Context {
|
||||
return context.WithValue(ctx, AuthKey, principal)
|
||||
}
|
||||
9
vendor/github.com/go-swagger/go-swagger/generator/templates/contrib/stratoscale/server/server.gotmpl
generated
vendored
Normal file
9
vendor/github.com/go-swagger/go-swagger/generator/templates/contrib/stratoscale/server/server.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
|
||||
{{ if .Copyright -}}// {{ comment .Copyright -}}{{ end }}
|
||||
|
||||
|
||||
package {{ .APIPackage }}
|
||||
|
||||
// this file is intentionally empty. Otherwise go-swagger will generate a server which we don't want
|
||||
25
vendor/github.com/go-swagger/go-swagger/generator/templates/docstring.gotmpl
generated
vendored
Normal file
25
vendor/github.com/go-swagger/go-swagger/generator/templates/docstring.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{{ define "docstring" }}
|
||||
{{- if .Title }}
|
||||
{{- comment .Title }}
|
||||
{{- if .Description }}
|
||||
//
|
||||
// {{ comment .Description }}
|
||||
{{- end }}
|
||||
{{- else if .Description}}
|
||||
{{- comment .Description }}
|
||||
{{- else }}
|
||||
{{- humanize .Name }}
|
||||
{{- end }}
|
||||
{{- if or .MinProperties .MinProperties }}
|
||||
//
|
||||
{{- if .MinProperties }}
|
||||
// Min Properties: {{ .MinProperties }}
|
||||
{{- end }}
|
||||
{{- if .MaxProperties }}
|
||||
// Max Properties: {{ .MaxProperties }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Example }}
|
||||
// Example: {{ print .Example }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
20
vendor/github.com/go-swagger/go-swagger/generator/templates/header.gotmpl
generated
vendored
Normal file
20
vendor/github.com/go-swagger/go-swagger/generator/templates/header.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
{{ if .Copyright -}}
|
||||
// {{ comment .Copyright }}
|
||||
{{- end }}
|
||||
|
||||
package {{.Package}}
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"github.com/go-openapi/strfmt"
|
||||
{{- if .DefaultImports }}
|
||||
{{ imports .DefaultImports }}
|
||||
{{- end }}
|
||||
{{- if .Imports }}
|
||||
{{ imports .Imports }}
|
||||
{{- end }}
|
||||
)
|
||||
527
vendor/github.com/go-swagger/go-swagger/generator/templates/markdown/docs.gotmpl
generated
vendored
Normal file
527
vendor/github.com/go-swagger/go-swagger/generator/templates/markdown/docs.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,527 @@
|
|||
{{- define "externalDoc" }}{{/* renders external documentation */}}
|
||||
{{- with .ExternalDocs }}
|
||||
{{- if .URL }}
|
||||
{{- if .Description }}
|
||||
> [{{ trimSpace .Description }}]({{ .URL }})
|
||||
{{- else }}
|
||||
> [Read more]({{ .URL }})
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
> {{ trimSpace .Description }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "docParam" }}{{/* renders a parameter with simple schema */}}
|
||||
| {{ .Name }} | `{{ .Location }}` | {{ paramDocType . }} | `{{ .GoType }}` | {{ if .CollectionFormat }}`{{ docCollectionFormat .CollectionFormat .Child }}`{{ end }} | {{ if .Required }}✓{{ end }} | {{ if .Default }}`{{ json .Default }}`{{ end }} | {{ trimSpace .Description }} |
|
||||
{{- end }}
|
||||
|
||||
{{- define "docModelSchema" }}{{/* renders a schema */}}
|
||||
{{- if .IsArray }}
|
||||
{{- if .IsAliased }}
|
||||
[{{- dropPackage .GoType }}](#{{ dasherize (dropPackage .GoType) -}})
|
||||
{{- else if .Items }}
|
||||
{{- if and .Items.IsPrimitive (not .Items.IsAliased) -}}
|
||||
{{- schemaDocType . -}}
|
||||
{{- else -}}
|
||||
[][{{- dropPackage .Items.GoType }}](#{{ dasherize (dropPackage .Items.GoType) -}})
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
[]any{{ printf " " -}}
|
||||
{{- end -}}
|
||||
{{- else if and .IsMap (not .IsAdditionalProperties) -}}
|
||||
{{- if .IsAliased -}}
|
||||
[{{- dropPackage .GoType }}](#{{ dasherize (dropPackage .GoType) -}})
|
||||
{{- else if .ElemType }}
|
||||
{{- if and .ElemType.IsPrimitive (not .ElemType.IsAliased) (not .ElemType.IsInterface) -}}
|
||||
{{ schemaDocMapType . -}}
|
||||
{{- else if .ElemType.IsInterface -}}
|
||||
map of any{{ printf " " -}}
|
||||
{{- else -}}
|
||||
map of [{{- dropPackage .ElemType.GoType }}](#{{ dasherize (dropPackage .ElemType.GoType) -}})
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
map of any{{ printf " " -}}
|
||||
{{- end -}}
|
||||
{{- else if and .IsAliased .IsPrimitive (not .IsSuperAlias) -}}
|
||||
| Name | Type | Go type | Default | Description | Example |
|
||||
|------|------|---------| ------- |-------------|---------|
|
||||
| {{ .Name }} | {{ schemaDocType . }}| {{ .AliasedType }} | {{ if .Default }}`{{ json .Default }}`{{ end }}| {{ trimSpace .Description }} | {{ if .Example }}`{{ .Example }}`{{ end }} |
|
||||
{{ printf "\n" }}
|
||||
{{- else if or (and .IsAliased (not (.IsAdditionalProperties))) (and .IsComplexObject (not .Properties) (not .AllOf)) -}}
|
||||
[{{- dropPackage .GoType }}](#{{ dasherize (dropPackage .GoType) -}})
|
||||
{{- else if and .IsInterface (not .IsAliased) (not .IsMap) -}}
|
||||
any
|
||||
{{- else -}}
|
||||
{{- range .AllOf }}
|
||||
{{- if .IsAnonymous }}
|
||||
* inlined member (*{{ .Name }}*)
|
||||
|
||||
{{ template "docModelSchema" . }}
|
||||
{{- else if or .IsComplexObject .IsPrimitive }}
|
||||
* composed type [{{- dropPackage .GoType }}](#{{ dasherize (dropPackage .GoType) -}})
|
||||
{{- else }}
|
||||
* {{ template "docModelSchema" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Properties }}
|
||||
|
||||
**{{ if .IsTuple }}Tuple members{{ else }}Properties{{ end }}**
|
||||
|
||||
| Name | Type | Go type | Required | Default | Description | Example |
|
||||
|------|------|---------|:--------:| ------- |-------------|---------|
|
||||
{{- range .Properties }}
|
||||
| {{ .Name }} | {{ template "docSchemaSimple" . }}| `{{ .GoType }}` | {{ if .Required }}✓{{ end }} | {{ if .Default }}`{{ json .Default }}`{{ end }}| {{ trimSpace .Description }} | {{ if .Example }}`{{ .Example }}`{{ end }} |
|
||||
{{- end }}
|
||||
{{ printf "\n" }}
|
||||
{{- end }}
|
||||
{{- if .HasAdditionalProperties }}
|
||||
|
||||
**Additional Properties**
|
||||
{{- with .AdditionalProperties }}
|
||||
{{- if .IsInterface }}
|
||||
|
||||
any
|
||||
{{- else if .IsPrimitive }}
|
||||
|
||||
| Type | Go type | Default | Description | Example |
|
||||
|------|---------| ------- |-------------|---------|
|
||||
| {{ template "docSchemaSimple" . }} | `{{ .GoType }}` |{{ if .Default }}`{{ json .Default }}`{{ end }}| {{ trimSpace .Description }} | {{ if .Example }}`{{ .Example }}`{{ end }} |
|
||||
{{- else }}
|
||||
|
||||
{{ template "docModelSchema" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if and .IsTuple .HasAdditionalItems }}
|
||||
{{- with .AdditionalItems }}
|
||||
|
||||
**Additional Items**
|
||||
{{- if .IsInterface }}
|
||||
|
||||
any
|
||||
{{- else if .IsPrimitive }}
|
||||
|
||||
| Type | Go type | Default | Description | Example |
|
||||
|------|---------| ------- |-------------|---------|
|
||||
| {{ template "docSchemaSimple" . }} | `{{ .GoType }}` |{{ if .Default }}`{{ json .Default }}`{{ end }}| {{ trimSpace .Description }} | {{ if .Example }}`{{ .Example }}`{{ end }} |
|
||||
{{- else }}
|
||||
|
||||
{{ template "docModelSchema" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
{{- end }}
|
||||
|
||||
{{- define "docModel" }}{{/* renders a definition */}}
|
||||
{{- with .Description }}
|
||||
> {{ .}}
|
||||
{{- end }}
|
||||
{{- if .ExternalDocs }}
|
||||
{{ template "externalDoc" . }}
|
||||
{{- end }}
|
||||
{{ if or .Description .ExternalDocs }}
|
||||
{{ printf "\n" }}
|
||||
{{- end }}
|
||||
|
||||
{{ template "docModelSchema" .}}
|
||||
{{- end }}
|
||||
|
||||
{{- define "docSchemaSimple" }}{{/* renders a simple property */}}
|
||||
{{- if .IsAliased -}}
|
||||
[{{- dropPackage .GoType }}](#{{ dasherize (dropPackage .GoType) -}})
|
||||
{{- else if .IsArray }}
|
||||
{{- if .Items }}
|
||||
{{- if and .Items.IsPrimitive (not .Items.IsAliased) -}}
|
||||
{{- schemaDocType . -}}
|
||||
{{- else -}}
|
||||
[][{{- dropPackage .Items.GoType }}](#{{ dasherize (dropPackage .Items.GoType) -}})
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
[]any{{ printf " " -}}
|
||||
{{- end -}}
|
||||
{{- else if .IsMap -}}
|
||||
{{- if .ElemType }}
|
||||
{{- if and .ElemType.IsPrimitive (not .ElemType.IsAliased) (not .ElemType.IsInterface) -}}
|
||||
{{ schemaDocMapType . -}}
|
||||
{{- else if .ElemType.IsInterface -}}
|
||||
map of any{{ printf " " -}}
|
||||
{{- else -}}
|
||||
map of [{{- dropPackage .ElemType.GoType }}](#{{ dasherize (dropPackage .ElemType.GoType) -}})
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
map of any{{ printf " " -}}
|
||||
{{- end -}}
|
||||
{{- else if .IsPrimitive -}}
|
||||
{{- schemaDocType . -}}
|
||||
{{- else -}}
|
||||
[{{- dropPackage .GoType }}](#{{ dasherize (dropPackage .GoType) -}})
|
||||
{{- end -}}
|
||||
{{- end }}
|
||||
|
||||
{{- define "docModelBodyParam" }}{{/* layout for body param schema */}}
|
||||
| {{ .Name }} | `body` | {{ template "docSchemaSimple" .Schema }} | `{{ .Schema.GoType }}` | | {{ if .Required }}✓{{ end }} | {{ if .Default }}`{{ json .Default }}`{{ end }}| {{ trimSpace .Description }} |
|
||||
{{- end }}
|
||||
|
||||
{{- define "docHeaders" }}{{/* renders response headers */}}
|
||||
{{- if .Headers }}
|
||||
| Name | Type | Go type | Separator | Default | Description |
|
||||
|------|------|---------|-----------|---------|-------------|
|
||||
{{- range .Headers }}
|
||||
| {{ .Name }} | {{ headerDocType . }} | `{{ .GoType }}` | {{ if .CollectionFormat }}`{{ docCollectionFormat .CollectionFormat .Child }}`{{ end }} | {{ if .Default }}`{{ json .Default }}`{{ end }} | {{ trimSpace .Description }} |
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/* spec top-level information block */}}
|
||||
{{- if .Info }}
|
||||
{{- with .Info.Title }}
|
||||
# {{ . }}
|
||||
{{- end }}
|
||||
|
||||
{{- with .Info.Description }}
|
||||
{{ . }}
|
||||
{{- end }}
|
||||
{{ template "externalDoc" . }}
|
||||
|
||||
{{- if or .Info.Version .Info.License .Info.Contact .Info.TermsOfService }}
|
||||
|
||||
## Informations
|
||||
{{- end }}
|
||||
|
||||
{{- with .Info.Version }}
|
||||
|
||||
### Version
|
||||
|
||||
{{ . }}
|
||||
{{- end }}
|
||||
|
||||
{{- with .Info.License }}
|
||||
|
||||
### License
|
||||
|
||||
{{ if .Name }}[{{ .Name }}]({{ end}}{{ .URL }}{{ if .Name }}){{ end }}
|
||||
{{- end }}
|
||||
|
||||
{{- with .Info.Contact }}
|
||||
|
||||
### Contact
|
||||
|
||||
{{ .Name }} {{ .Email }} {{ .URL }}
|
||||
{{- end }}
|
||||
|
||||
{{- with .Info.TermsOfService }}
|
||||
|
||||
### Terms Of Service
|
||||
|
||||
{{ . }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{ template "externalDoc" . }}
|
||||
{{- end }}
|
||||
|
||||
{{- if .Tags }}
|
||||
|
||||
## Tags
|
||||
{{- range .Tags }}
|
||||
|
||||
### <span id="tag-{{ dasherize .Name }}"></span>{{ if .ExternalDocs }}[{{ .Name }}]({{ .ExternalDocs.URL }}{{ if .ExternalDocs.Description }} {{ printf "%q" .ExternalDocs.Description }}{{ end }}){{ else }}{{ .Name }}{{ end }}
|
||||
{{- if .Description }}
|
||||
|
||||
{{ .Description }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- if or .Schemes .Consumes .Produces }}
|
||||
|
||||
## Content negotiation
|
||||
{{- end }}
|
||||
{{- if .Schemes }}
|
||||
|
||||
### URI Schemes
|
||||
{{- range .Schemes }}
|
||||
* {{ . }}
|
||||
{{- end }}
|
||||
{{- range .ExtraSchemes }}
|
||||
* {{ . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- if .Consumes }}
|
||||
|
||||
### Consumes
|
||||
{{- range .Consumes }}
|
||||
{{- range .AllSerializers }}
|
||||
* {{ .MediaType }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}{{/* end .Schemes */}}
|
||||
|
||||
{{- if .Produces }}
|
||||
|
||||
### Produces
|
||||
{{- range .Produces }}
|
||||
{{- range .AllSerializers }}
|
||||
* {{ .MediaType }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- if or .SecurityDefinitions .SecurityRequirements }}
|
||||
|
||||
## Access control
|
||||
{{- end }}
|
||||
{{- if .SecurityDefinitions }}
|
||||
|
||||
### Security Schemes
|
||||
{{- range .SecurityDefinitions }}
|
||||
|
||||
#### {{ .ID }}{{ if .Source }} ({{ .Source }}{{ with .Name }}: {{ . }}{{ end }}){{ end }}
|
||||
|
||||
{{ .Description }}
|
||||
|
||||
{{- with .Type }}
|
||||
|
||||
> **Type**: {{ . }}
|
||||
{{- end }}
|
||||
{{- if .IsOAuth2}}
|
||||
{{- with .Flow }}
|
||||
>
|
||||
> **Flow**: {{ . }}
|
||||
{{- end }}
|
||||
{{- with .AuthorizationURL }}
|
||||
>
|
||||
> **Authorization URL**: {{ . }}
|
||||
{{- end }}
|
||||
{{- with .TokenURL }}
|
||||
>
|
||||
> **Token URL**: {{ . }}
|
||||
{{- end }}
|
||||
{{ if .ScopesDesc }}
|
||||
|
||||
##### Scopes
|
||||
|
||||
Name | Description
|
||||
-----|-------------
|
||||
{{- range .ScopesDesc }}
|
||||
{{ .Name }} | {{ .Description }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}{{/* end .SecurityDefinitions */}}
|
||||
|
||||
{{- if .SecurityRequirements }}
|
||||
|
||||
### Security Requirements
|
||||
|
||||
{{- range .SecurityRequirements }}
|
||||
* {{ .Name }}{{ if .Scopes }}: {{ range $idx, $scope := .Scopes }}{{ if gt $idx 0 }}, {{ end }}{{ $scope }}{{ end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}{{/* end .SecurityRequirements */}}
|
||||
|
||||
## All endpoints{{/* an index of all API endpoints */}}
|
||||
|
||||
{{- $alltags := .Tags }}
|
||||
{{- range .OperationGroups }}
|
||||
|
||||
### {{ .PackageAlias }}
|
||||
{{- $pkg := .PackageAlias }}
|
||||
{{- range $alltags }}
|
||||
{{- if eq .Name $pkg }}
|
||||
|
||||
{{ template "externalDoc" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
| Method | URI | Name | Summary |
|
||||
|---------|---------|--------|---------|
|
||||
{{- range .Operations }}
|
||||
| {{ upper .Method }} | {{ joinPath .BasePath .Path }} | [{{ humanize .Name }}](#{{ dasherize .Name }}) | {{ .Summary }} |
|
||||
{{- end }}
|
||||
{{ printf "\n" }}
|
||||
{{- end }}
|
||||
|
||||
## Paths{{/* all paths to operations */}}
|
||||
|
||||
{{- range .Operations }}
|
||||
{{- $opname := .Name }}
|
||||
|
||||
### <span id="{{ dasherize .Name }}"></span> {{ if .Summary }}{{ trimSpace .Summary }}{{ else }}{{ humanize .Name }}{{ end }} (*{{ .Name }}*)
|
||||
|
||||
```
|
||||
{{ upper .Method }} {{ joinPath .BasePath .Path }}
|
||||
```
|
||||
{{- with .Description }}
|
||||
|
||||
{{ . }}
|
||||
{{- end }}
|
||||
|
||||
{{- with .ExternalDocs }}
|
||||
|
||||
> {{ if .URL }}[Read more]({{ .URL }} "{{ .Description }}"){{ end }}
|
||||
{{- end }}
|
||||
|
||||
{{- if or (gt (len .SchemeOverrides) 0) (gt (len .ExtraSchemeOverrides) 0) }}
|
||||
|
||||
#### URI Schemes
|
||||
|
||||
{{- range .SchemeOverrides }}
|
||||
* {{ . }}
|
||||
{{- end }}
|
||||
{{- range .ExtraSchemeOverrides }}
|
||||
* {{ . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- if .Consumes }}
|
||||
|
||||
#### Consumes
|
||||
|
||||
{{- range .Consumes }}
|
||||
* {{ . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- if .Produces }}
|
||||
|
||||
#### Produces
|
||||
|
||||
{{- range .Produces }}
|
||||
* {{ . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- if .SecurityRequirements }}
|
||||
|
||||
#### Security Requirements
|
||||
{{- range .SecurityRequirements }}
|
||||
* {{ .Name }}{{ if .Scopes }}: {{ range $idx, $scope := .Scopes }}{{ if gt $idx 0 }}, {{ end }}{{ $scope }}{{ end }}{{ end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- if .Params }}
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Source | Type | Go type | Separator | Required | Default | Description |
|
||||
|------|--------|------|---------|-----------| :------: |---------|-------------|
|
||||
{{- range .PathParams }}{{ template "docParam" . }}{{ end }}
|
||||
{{- range .HeaderParams }}{{ template "docParam" . }}{{ end }}
|
||||
{{- range .QueryParams }}{{ template "docParam" . }}{{ end }}
|
||||
{{- range .FormParams }}{{ template "docParam" . }}{{ end }}
|
||||
{{- range .Params }}
|
||||
{{- if .IsBodyParam }}
|
||||
{{- template "docModelBodyParam" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}{{/* end .Params */}}
|
||||
|
||||
#### All responses
|
||||
| Code | Status | Description | Has headers | Schema |
|
||||
|------|--------|-------------|:-----------:|--------|
|
||||
{{- range .Responses }}
|
||||
| [{{.Code}}](#{{ dasherize $opname }}-{{ .Code }}) | {{ httpStatus .Code }} | {{ trimSpace .Description }} | {{ if .Headers }}✓{{ end }} | [schema](#{{ dasherize $opname }}-{{ .Code }}-schema) |
|
||||
{{- end }}
|
||||
{{- with .DefaultResponse }}
|
||||
| [default](#{{ dasherize $opname }}-default) | | {{ trimSpace .Description }} | {{ if .Headers }}✓{{ end }} | [schema](#{{ dasherize $opname }}-default-schema) |
|
||||
{{- end }}
|
||||
|
||||
#### Responses
|
||||
{{ range .Responses }}
|
||||
|
||||
##### <span id="{{ dasherize $opname }}-{{ .Code }}"></span> {{.Code}}{{ if .Description }} - {{ trimSpace .Description }}{{ end }}
|
||||
Status: {{ httpStatus .Code }}
|
||||
|
||||
###### <span id="{{ dasherize $opname }}-{{ .Code }}-schema"></span> Schema
|
||||
{{- if .Schema }}
|
||||
{{ template "docModel" .Schema }}
|
||||
{{- end }}
|
||||
|
||||
{{- if .Examples }}
|
||||
|
||||
###### Examples
|
||||
{{ range .Examples }}
|
||||
**{{ .MediaType }}**
|
||||
```json
|
||||
{{ prettyjson .Example }}
|
||||
```
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- if .Headers }}
|
||||
|
||||
###### Response headers
|
||||
{{ template "docHeaders" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- with .DefaultResponse }}
|
||||
|
||||
##### <span id="{{ dasherize $opname }}-default"></span> Default Response
|
||||
{{ trimSpace .Description }}
|
||||
|
||||
###### <span id="{{ dasherize $opname }}-default-schema"></span> Schema
|
||||
{{- if .Schema }}
|
||||
{{ template "docModel" .Schema }}
|
||||
{{- else }}
|
||||
empty schema
|
||||
{{- end }}
|
||||
|
||||
{{- if .Examples }}
|
||||
|
||||
###### Examples
|
||||
{{ range .Examples }}
|
||||
**{{ .MediaType }}**
|
||||
```json
|
||||
{{ .Example }}
|
||||
```
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- if .Headers }}
|
||||
|
||||
###### Response headers
|
||||
{{ template "docHeaders" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- if .ExtraSchemas }}
|
||||
|
||||
###### Inlined models
|
||||
{{- range .ExtraSchemas }}
|
||||
{{- if ne .Name "" }}
|
||||
|
||||
**<span id="{{ dasherize .Name }}"></span> {{ .Name }}**
|
||||
|
||||
{{ template "docModel" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- end }}{{/* end .Operations */}}
|
||||
|
||||
## Models
|
||||
|
||||
{{- range .Models }}
|
||||
|
||||
### <span id="{{ dasherize .Name }}"></span> {{ .Name }}
|
||||
|
||||
{{ template "docModel" . }}
|
||||
|
||||
{{- if .ExtraSchemas }}
|
||||
|
||||
#### Inlined models
|
||||
{{- range .ExtraSchemas }}
|
||||
{{- if ne .Name "" }}
|
||||
|
||||
**<span id="{{ dasherize .Name }}"></span> {{ .Name }}**
|
||||
|
||||
{{ template "docModel" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
27
vendor/github.com/go-swagger/go-swagger/generator/templates/model.gotmpl
generated
vendored
Normal file
27
vendor/github.com/go-swagger/go-swagger/generator/templates/model.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
{{ template "header" . }}
|
||||
{{- if .IncludeModel }}
|
||||
{{- if .IsExported }}
|
||||
// {{ pascalize .Name }} {{ template "docstring" . }}
|
||||
{{- template "annotations" . }}
|
||||
{{- end }}
|
||||
{{- template "schema" . }}
|
||||
{{- end }}
|
||||
|
||||
{{ range .ExtraSchemas }}
|
||||
{{- if .IncludeModel }}
|
||||
{{- if .IsExported }}
|
||||
// {{ pascalize .Name }} {{ template "docstring" . }}
|
||||
{{- template "annotations" . }}
|
||||
{{- end }}
|
||||
{{- template "schema" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- define "annotations" }}{{/* annotations to generate spec from source */}}
|
||||
{{- if not .IsBaseType }}
|
||||
//
|
||||
// swagger:model {{ .Name }}
|
||||
{{- else }}
|
||||
//
|
||||
// swagger:discriminator {{ .Name }} {{ .DiscriminatorField }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
131
vendor/github.com/go-swagger/go-swagger/generator/templates/schema.gotmpl
generated
vendored
Normal file
131
vendor/github.com/go-swagger/go-swagger/generator/templates/schema.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
{{- if and .IsBaseType .IsExported (not .IsSuperAlias) }}
|
||||
{{- template "schemaPolymorphic" . }}
|
||||
{{- else if .IsSuperAlias }}
|
||||
type {{ pascalize .Name }} {{ template "typeSchemaType" . }}{{/* For types declared as $ref on some other type, just declare the type as a golang _aliased_ type, e.g. type A = B. No method shall be redeclared. */}}
|
||||
{{- if .IsBaseType }}
|
||||
{{ template "baseTypeSerializer" . }}{{/* When the alias redeclares a polymorphic type, define factory methods with this alias. */}}
|
||||
{{- end }}
|
||||
{{- else if .IsEmbedded }}
|
||||
{{- template "schemaEmbedded" . }}
|
||||
{{- else }}
|
||||
{{- if or .IsComplexObject .IsTuple .IsAdditionalProperties }}{{/* TODO(fred): handle case of subtype inheriting from base type with AdditionalProperties, issue #2220 */}}
|
||||
{{ if .Name }}type {{ if not .IsExported }}{{ .Name }}{{ else }}{{ pascalize .Name }}{{ end }}{{ end }} {{ template "schemaBody" . }}
|
||||
{{- range .Properties }}
|
||||
{{- if .IsBaseType }}
|
||||
// {{ pascalize .Name}} gets the {{ humanize .Name }} of this base type{{/* all properties which are of a base type propagate its interface */}}
|
||||
func ({{ $.ReceiverName}} *{{ pascalize $.Name}}) {{ pascalize .Name}}() {{ template "schemaType" . }}{
|
||||
{{- if eq $.DiscriminatorField .Name }}
|
||||
return {{ printf "%q" $.DiscriminatorValue }}
|
||||
{{- else }}
|
||||
return {{ $.ReceiverName }}.{{camelize .Name}}Field
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
// Set{{ pascalize .Name}} sets the {{ humanize .Name }} of this base type
|
||||
func ({{ $.ReceiverName}} *{{ pascalize $.Name}}) Set{{ pascalize .Name}}(val {{ template "schemaType" . }}) {
|
||||
{{- if ne $.DiscriminatorField .Name }}
|
||||
{{ $.ReceiverName }}.{{camelize .Name}}Field = val
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Default }}{{/* TODO(fred) - issue #2189 */}}
|
||||
func ({{.ReceiverName}} *{{ pascalize .Name }}) UnmarshalJSON(b []byte) error {
|
||||
type {{ pascalize .Name }}Alias {{ pascalize .Name }}
|
||||
var t {{ pascalize .Name }}Alias
|
||||
if err := json.Unmarshal([]byte({{printf "%q" (json .Default)}}), &t); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := json.Unmarshal(b, &t); err != nil {
|
||||
return err
|
||||
}
|
||||
*{{.ReceiverName}} = {{ pascalize .Name }}(t)
|
||||
return nil
|
||||
}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
type {{ pascalize .Name }} {{ template "typeSchemaType" . }}
|
||||
{{- end }}
|
||||
{{- if (and .IsPrimitive .IsAliased .IsCustomFormatter (not (stringContains .Zero "(\""))) }}
|
||||
{{ template "aliasedSerializer" . }}
|
||||
{{- end }}
|
||||
{{- if .IsSubType }}
|
||||
{{ range .AllOf }}
|
||||
{{ range .Properties }}
|
||||
{{- if .IsBaseType }}
|
||||
|
||||
// {{ pascalize .Name}} gets the {{ humanize .Name }} of this subtype
|
||||
func ({{$.ReceiverName}} *{{ pascalize $.Name}}) {{ pascalize .Name}}() {{ template "schemaType" . }}{
|
||||
{{- if eq $.DiscriminatorField .Name }}
|
||||
return {{ printf "%q" $.DiscriminatorValue }}
|
||||
{{- else }}
|
||||
return {{ $.ReceiverName }}.{{camelize .Name}}Field
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
// Set{{ pascalize .Name}} sets the {{ humanize .Name }} of this subtype
|
||||
func ({{$.ReceiverName}} *{{ pascalize $.Name}}) Set{{ pascalize .Name}}(val {{ template "schemaType" . }}) {
|
||||
{{- if ne $.DiscriminatorField .Name }}
|
||||
{{ $.ReceiverName }}.{{camelize .Name}}Field = val
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}{{/* TODO(fred): handle AdditionalProperties in base type */}}
|
||||
{{- end }}
|
||||
{{ template "mapOrSliceGetter" . }}
|
||||
{{- end }}
|
||||
{{ template "schemaSerializer" . }}
|
||||
{{- end }}
|
||||
{{- if and .IncludeValidator (not .IsSuperAlias) (not .IsEmbedded) }}{{/* aliased types type A = B do not redefine methods */}}
|
||||
{{- if and (not (or .IsInterface .IsStream)) (or .Required .HasValidations .HasBaseType) }}
|
||||
{{- if (eq .SwaggerType "string") }}{{/* Enum factory for enums for which we generate const (atm, only strings)*/}}
|
||||
{{- if .Enum }}
|
||||
|
||||
func New{{ pascalize .Name }}(value {{ .GoType }}) *{{ .GoType }} {
|
||||
return &value
|
||||
}
|
||||
|
||||
// Pointer returns a pointer to a freshly-allocated {{ .GoType }}.
|
||||
func ({{ .ReceiverName }} {{ .GoType }}) Pointer() *{{ .GoType }} {
|
||||
return &{{ .ReceiverName }}
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{ template "schemavalidator" . }}
|
||||
{{- else if not (or .IsInterface .IsStream) }}
|
||||
// Validate validates this {{ humanize .Name }}{{/* this schema implements the runtime.Validatable interface but has no validations to check */}}
|
||||
func ({{.ReceiverName}} {{ if or .IsTuple .IsComplexObject .IsAdditionalProperties }}*{{ end }}{{ if or (not .IsExported) .Discriminates }}{{ camelize .Name }}{{ else }}{{ pascalize .Name }}{{ end }}) Validate(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
{{- else }}{{/* {{ .Name }} does not implement the runtime.Validatable interface: noop */}}
|
||||
{{- end }}
|
||||
{{- if and (not (or .IsInterface .IsStream)) (or .HasContextValidations) }}
|
||||
{{ template "schemacontextvalidator" . }}
|
||||
{{- else if not (or .IsInterface .IsStream) }}
|
||||
// ContextValidate validates this {{ humanize .Name }} based on context it is used {{/* this schema implements the runtime.ContextValidatable interface but has no validations to check */}}
|
||||
func ({{.ReceiverName}} {{ if or .IsTuple .IsComplexObject .IsAdditionalProperties }}*{{ end }}{{ if or (not .IsExported) .Discriminates }}{{ camelize .Name }}{{ else }}{{ pascalize .Name }}{{ end }}) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
{{- else }}{{/* {{ .Name }} does not implement the runtime.Validatable interface: noop */}}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .WantsMarshalBinary }}
|
||||
{{ template "marshalBinarySerializer" . }}
|
||||
{{- end }}
|
||||
{{- define "mapOrSliceGetter" }}{{/* signature for AdditionalProperties and AdditionalItems getter funcs */}}
|
||||
{{- if not .IsBaseType }}
|
||||
{{- if .HasAdditionalProperties }}
|
||||
{{- with .AdditionalProperties }}
|
||||
// {{- template "docstring" . }}{{- template "propertyValidationDocString" . }}
|
||||
{{ pascalize .Name }}() map[string]{{ template "schemaType" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- with .AdditionalItems }}
|
||||
// {{- template "docstring" . }}{{- template "propertyValidationDocString" . }}
|
||||
{{ pascalize .Name }}() []{{ template "schemaType" . }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
// AdditionalProperties in base type shoud be handled just like regular properties{{/* TODO(fred): add full support for AdditionalProperties in base type */}}
|
||||
// At this moment, the base type property is pushed down to the subtype
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
330
vendor/github.com/go-swagger/go-swagger/generator/templates/schemabody.gotmpl
generated
vendored
Normal file
330
vendor/github.com/go-swagger/go-swagger/generator/templates/schemabody.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,330 @@
|
|||
{{ define "schemaBody" }}struct {
|
||||
{{ range .AllOf }}
|
||||
{{ if or (and $.IsSubType .IsBaseType .IsExported) .IsAnonymous }}
|
||||
{{ range .Properties }}
|
||||
{{ if ne $.DiscriminatorField .Name }}
|
||||
{{ if or (not $.IsExported) (and $.IsSubType .IsBaseType) }}
|
||||
{{ if $.IsTuple }}
|
||||
{{ template "privtuplefield" . }}
|
||||
{{ else }}
|
||||
{{template "privstructfield" . }}
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
{{ if $.IsTuple }}
|
||||
{{ template "tuplefield" . }}
|
||||
{{ else }}
|
||||
{{template "structfield" . }}
|
||||
{{ end }}
|
||||
{{ end}}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{- if .HasAdditionalProperties }}
|
||||
{{- if .AdditionalProperties }}
|
||||
// {{ template "docstring" .AdditionalProperties }}
|
||||
{{- template "propertyValidationDocString" .AdditionalProperties}}
|
||||
{{- if and .IsExported (not .IsSubType) }}
|
||||
{{ pascalize .AdditionalProperties.Name }}
|
||||
{{- else if or (not .AdditionalProperties.IsExported) (.AdditionalProperties.IsBaseType) }}
|
||||
{{ camelize .AdditionalProperties.Name }}Field
|
||||
{{- else }}
|
||||
{{ .AdditionalProperties.Name }}
|
||||
{{- end }} map[string]{{ template "schemaType" .AdditionalProperties }} `json:"-"`
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .AdditionalItems }}
|
||||
// {{ template "docstring" .AdditionalItems }}
|
||||
{{- template "propertyValidationDocString" .AdditionalItems}}
|
||||
{{- if and .IsExported (not $.IsSubType) }}{{/* TODO(fred): make sure inherited AdditionalItems are camelized */}}
|
||||
{{ pascalize .AdditionalItems.Name }}
|
||||
{{- else }}
|
||||
{{ .AdditionalItems.Name }}
|
||||
{{- end }} []{{ template "schemaType" .AdditionalItems }} `json:"-"`
|
||||
{{- end }}
|
||||
{{ else }}{{/* named type composition */}}
|
||||
{{ if not (and $.IsBaseType .IsExported) }}{{ .GoType }}{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{range .Properties}}
|
||||
{{ if or (not $.IsExported) ($.IsBaseType) (.IsBaseType) }}
|
||||
{{ if $.IsTuple }}{{ template "privtuplefield" . }}{{ else }}{{template "privstructfield" . }}{{ end }}{{ else }}{{ if $.IsTuple }}{{ template "tuplefield" . }}{{ else }}{{template "structfield" . }}{{ end }}{{ end}}
|
||||
{{ end }}
|
||||
{{ if .HasAdditionalProperties }}
|
||||
{{- if .AdditionalProperties }}
|
||||
// {{ template "docstring" .AdditionalProperties }}
|
||||
{{- template "propertyValidationDocString" .AdditionalProperties}}
|
||||
{{- if and .IsExported (not .IsSubType) }}
|
||||
{{ pascalize .AdditionalProperties.Name }}
|
||||
{{- else }}
|
||||
{{ pascalize .AdditionalProperties.Name }}Field
|
||||
{{- end }} map[string]{{ template "schemaType" .AdditionalProperties }} `json:"-"`
|
||||
{{ end }}
|
||||
{{- end }}
|
||||
{{- if .AdditionalItems }}
|
||||
// {{ template "docstring" .AdditionalItems }}
|
||||
{{- template "propertyValidationDocString" .AdditionalItems}}
|
||||
{{ if and .IsExported (not .IsSubType) }}{{ pascalize .AdditionalItems.Name }}{{ else }}{{ pascalize .AdditionalItems.Name }}Field{{ end }} []{{ template "schemaType" .AdditionalItems }} `json:"-"`
|
||||
{{ end }}
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{ define "subTypeBody" }}struct {
|
||||
{{- range .AllOf }}
|
||||
{{- if or (and .IsBaseType .IsExported) .IsAnonymous }}
|
||||
{{- range .Properties }}
|
||||
{{- if not $.IsExported }}
|
||||
{{- if $.IsTuple }}
|
||||
{{- template "privtuplefield" . }}
|
||||
{{- else }}
|
||||
{{- template "privstructfield" . }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{- if $.IsTuple }}
|
||||
{{- template "tuplefield" . }}
|
||||
{{- else }}
|
||||
{{- template "structfield" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .HasAdditionalProperties }}
|
||||
{{- if .AdditionalProperties }}
|
||||
{{- if .IsExported }}
|
||||
{{ pascalize .AdditionalProperties.Name }}
|
||||
{{- else }}
|
||||
{{ .AdditionalProperties.Name }}
|
||||
{{- end }} map[string]{{ template "schemaType" .AdditionalProperties }} `json:"-"`
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .AdditionalItems }}
|
||||
{{- if .IsExported }}
|
||||
{{ pascalize .AdditionalItems.Name }}
|
||||
{{- else }}
|
||||
{{ .AdditionalItems.Name }}
|
||||
{{- end }} []{{ template "schemaType" .AdditionalItems }} `json:"-"`
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{- if not (and .IsBaseType .IsExported) }}
|
||||
{{ .GoType }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{ range .Properties }}
|
||||
{{- if not $.IsExported }}
|
||||
{{- if $.IsTuple }}
|
||||
{{ template "privtuplefield" . }}
|
||||
{{- else }}
|
||||
{{ template "privstructfield" . }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{- if $.IsTuple }}
|
||||
{{ template "tuplefield" . }}
|
||||
{{- else }}
|
||||
{{ template "structfield" . }}
|
||||
{{- end }}
|
||||
{{- end}}
|
||||
{{- end }}
|
||||
{{- if .HasAdditionalProperties }}
|
||||
{{- if .AdditionalProperties }}
|
||||
{{- if and .IsExported }}
|
||||
{{ pascalize .AdditionalProperties.Name }}
|
||||
{{- else }}
|
||||
{{ pascalize .AdditionalProperties.Name }}Field
|
||||
{{- end }} map[string]{{ template "schemaType" .AdditionalProperties }} `json:"-"`
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .AdditionalItems }}
|
||||
{{- if and .IsExported (not .IsSubType) }}
|
||||
{{ pascalize .AdditionalItems.Name }}
|
||||
{{- else }}
|
||||
{{ pascalize .AdditionalItems.Name }}Field
|
||||
{{- end }} []{{ template "schemaType" .AdditionalItems }} `json:"-"`
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{ define "withBaseTypeBody" }}struct {
|
||||
{{ range .AllOf }}
|
||||
{{ if or (and .IsBaseType .IsExported) .IsAnonymous }}{{ range .Properties }}
|
||||
{{ if not .IsExported }}{{ if .IsTuple }}{{ template "privtuplefield" . }}{{ else }}{{template "privstructfield" . }}{{ end }}{{ else }}{{ if $.IsTuple }}{{ template "tuplefield" . }}{{ else }}{{template "structfield" . }}{{ end }}{{ end}}
|
||||
{{ end }}{{ if .HasAdditionalProperties }}{{ if .IsExported }}{{ pascalize .AdditionalProperties.Name }}{{ else }}{{ .AdditionalProperties.Name }}{{ end }} map[string]{{ template "schemaType" .AdditionalProperties }} `json:"-"` {{end}}
|
||||
{{ if .AdditionalItems }}{{ if and .IsExported }}{{ pascalize .AdditionalItems.Name }}{{ else }}{{ .AdditionalItems.Name }}{{ end }} []{{ template "schemaType" .AdditionalItems }} `json:"-"`
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
{{ if not (and .IsBaseType .IsExported) }}{{ .GoType }}{{ end }}{{ end }}
|
||||
{{ end }}
|
||||
{{range .Properties}}{{ if .IsBaseType }}
|
||||
{{ if not $.IsExported }}{{ else }}{{ pascalize .Name}} {{ template "schemaType" . }} `json:"{{ .Name }}{{ if and (not .Required) .IsEmptyOmitted }},omitempty{{ end }}{{ if .IsJSONString }},string{{ end }}"`{{ end}}
|
||||
{{end}}{{ end }}
|
||||
{{ if .HasAdditionalProperties }}{{ if and .IsExported }}{{ pascalize .AdditionalProperties.Name }}{{ else }}{{ pascalize .AdditionalProperties.Name }}Field{{ end }} map[string]{{ template "schemaType" .AdditionalProperties }} `json:"-"`
|
||||
{{ end }}
|
||||
{{ if .AdditionalItems }}{{ if and .IsExported (not .IsSubType) }}{{ pascalize .AdditionalItems.Name }}{{ else }}{{ pascalize .AdditionalItems.Name }}Field{{ end }} []{{ template "schemaType" .AdditionalItems }} `json:"-"`
|
||||
{{ end }}
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{ define "withoutBaseTypeBody" }}struct {
|
||||
{{ range .AllOf }}
|
||||
{{ if .IsAnonymous }}
|
||||
{{ range .Properties }}
|
||||
{{ if and .IsExported (not .IsBaseType) }}
|
||||
{{ if .IsTuple }}
|
||||
{{ template "tuplefield" . }}
|
||||
{{ else }}
|
||||
{{template "structfield" . }}
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
{{ pascalize .Name }} json.RawMessage `json:"{{ .Name }}{{ if and (not .Required) .IsEmptyOmitted }},omitempty{{ end }}{{ if .IsJSONString }},string{{ end }}"`
|
||||
{{ end}}
|
||||
{{ end }}
|
||||
{{ if .HasAdditionalProperties }}
|
||||
{{ if .AdditionalProperties }}
|
||||
{{ if .IsExported }}{{ pascalize .AdditionalProperties.Name }}{{ else }}{{ .AdditionalProperties.Name }}{{ end }} map[string]{{ template "schemaType" .AdditionalProperties }} `json:"-"`
|
||||
{{end}}
|
||||
{{ end }}
|
||||
{{ if .AdditionalItems }}
|
||||
{{ if .IsExported }}{{ pascalize .AdditionalItems.Name }}{{ else }}{{ .AdditionalItems.Name }}{{ end }} []{{ template "schemaType" .AdditionalItems }} `json:"-"`
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
{{ if not (and .IsBaseType .IsExported) }}
|
||||
{{ .GoType }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{range .Properties}}
|
||||
{{ if not .IsBaseType }}
|
||||
{{ if not $.IsExported }}
|
||||
{{template "privstructfield" . }}
|
||||
{{ else }}
|
||||
{{ pascalize .Name}} {{ template "schemaType" . }} `json:"{{ .Name }}{{ if and (not .Required) .IsEmptyOmitted }},omitempty{{ end }}{{ if .IsJSONString }},string{{ end }}"`
|
||||
{{ end}}
|
||||
{{ else }}
|
||||
{{ pascalize .Name }} json.RawMessage `json:"{{ .Name }}{{ if and (not .Required) .IsEmptyOmitted }},omitempty{{ end }}{{ if .IsJSONString }},string{{ end }}"`
|
||||
{{end}}
|
||||
{{ end }}
|
||||
{{ if .HasAdditionalProperties }}
|
||||
{{ pascalize .AdditionalProperties.Name }}{{ if .IsExported }}Field{{ end }} map[string]{{ template "schemaType" .AdditionalProperties }} `json:"-"`
|
||||
{{ end }}
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{ define "withoutBaseTypeBodyOrNonExported" }}struct {
|
||||
{{ range .AllOf }}
|
||||
{{ if .IsAnonymous }}
|
||||
{{ range .Properties }}
|
||||
{{ if and .IsExported (not .IsBaseType) }}
|
||||
{{ if .IsTuple }}
|
||||
{{ template "tuplefield" . }}
|
||||
{{ else }}
|
||||
{{template "structfield" . }}
|
||||
{{ end }}
|
||||
{{ end}}
|
||||
{{ end }}
|
||||
{{ if .HasAdditionalProperties }}
|
||||
{{ if .AdditionalProperties }}
|
||||
{{ if .IsExported }}{{ pascalize .AdditionalProperties.Name }}{{ else }}{{ .AdditionalProperties.Name }}{{ end }} map[string]{{ template "schemaType" .AdditionalProperties }} `json:"-"`
|
||||
{{end}}
|
||||
{{ end }}
|
||||
{{ if .AdditionalItems }}
|
||||
{{ if .IsExported }}{{ pascalize .AdditionalItems.Name }}{{ else }}{{ .AdditionalItems.Name }}{{ end }} []{{ template "schemaType" .AdditionalItems }} `json:"-"`
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
{{ if not (and .IsBaseType .IsExported) }}
|
||||
{{ .GoType }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{range .Properties}}
|
||||
{{ if not .IsBaseType }}
|
||||
{{ if not .IsExported }}
|
||||
{{template "privstructfield" . }}
|
||||
{{ else }}
|
||||
{{ pascalize .Name}} {{ template "schemaType" . }} `json:"{{ .Name }}{{ if and (not .Required) .IsEmptyOmitted }},omitempty{{ end }}{{ if .IsJSONString }},string{{ end }}"`
|
||||
{{ end}}
|
||||
{{end}}
|
||||
{{ end }}
|
||||
{{ if .HasAdditionalProperties }}
|
||||
{{ pascalize .AdditionalProperties.Name }}{{ if .IsExported }}Field{{ end }} map[string]{{ template "schemaType" .AdditionalProperties }} `json:"-"`
|
||||
{{ end }}}{
|
||||
{{ range .AllOf }}
|
||||
{{ if .IsAnonymous }}
|
||||
{{ range .Properties }}
|
||||
{{ if not .IsBaseType }}
|
||||
{{ pascalize .Name }}: {{ .ReceiverName}}.{{ pascalize .Name }},
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
{{ if not (and .IsBaseType .IsExported) }}
|
||||
{{ .GoType }}: {{ .ReceiverName }}.{{ .GoType }},
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ range .Properties }}
|
||||
{{ if and (not .IsBaseType) .IsExported }}
|
||||
{{ pascalize .Name }}: {{ .ReceiverName }}.{{ pascalize .Name }},
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
},
|
||||
{{- end }}
|
||||
|
||||
{{ define "withBaseTypeBodyAndNonExported" }}struct{
|
||||
{{ range .AllOf }}
|
||||
{{ range .Properties }}
|
||||
{{ if .IsBaseType }}
|
||||
{{ pascalize .Name }} {{ template "schemaType" . }} `json:"{{ .Name }}{{ if and (not .Required) .IsEmptyOmitted }},omitempty{{ end }}{{ if .IsJSONString }},string{{ end }}"`
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ range .Properties }}
|
||||
{{ if or (not .IsExported) .IsBaseType }}
|
||||
{{ pascalize .Name }} {{ template "schemaType" . }} `json:"{{ .Name }}{{ if and (not .Required) .IsEmptyOmitted }},omitempty{{ end }}{{ if .IsJSONString }},string{{ end }}"`
|
||||
{{ end }}
|
||||
{{end}}} {
|
||||
{{ range .AllOf }}
|
||||
{{ range .Properties }}
|
||||
{{ if .IsBaseType }}
|
||||
{{ pascalize .Name }}:
|
||||
{{ if ne .DiscriminatorField .Name }}
|
||||
{{ .ReceiverName }}.{{ if .IsSubType}}{{ camelize .Name }}Field{{ else }}{{ pascalize .Name }}(){{ end }},
|
||||
{{ else }}
|
||||
{{ .ReceiverName }}.{{pascalize .Name}}(),
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ range .Properties }}
|
||||
{{ if or (not .IsExported) .IsBaseType }}
|
||||
{{ pascalize .Name }}: {{ .ReceiverName }}.{{ if .IsBaseType}}{{ camelize .Name }}Field{{ else }}{{ pascalize .Name }}{{ end }},
|
||||
{{ end }}
|
||||
{{ end }} },
|
||||
{{- end }}
|
||||
|
||||
{{ define "withoutAdditionalBody" }}struct {
|
||||
{{ range .AllOf }}
|
||||
{{ if or (and $.IsSubType .IsBaseType .IsExported) .IsAnonymous }}{{ range .Properties }}
|
||||
{{ if ne $.DiscriminatorField .Name }}{{ if or (not $.IsExported) (and $.IsSubType .IsBaseType) }}{{ if $.IsTuple }}{{ template "privtuplefield" . }}{{ else }}{{template "privstructfield" . }}{{ end }}{{ else }}{{ if $.IsTuple }}{{ template "tuplefield" . }}{{ else }}{{template "structfield" . }}{{ end }}{{ end}}{{ end }}
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
{{ if not (and .IsBaseType .IsExported) }}{{ .GoType }}{{ end }}{{ end }}
|
||||
{{ end }}
|
||||
{{range .Properties}}
|
||||
{{ if or (not $.IsExported) (and $.IsSubType .IsBaseType) }}{{ if $.IsTuple }}{{ template "privtuplefield" . }}{{ else }}{{template "privstructfield" . }}{{ end }}{{ else }}{{ if $.IsTuple }}{{ template "tuplefield" . }}{{ else }}{{template "structfield" . }}{{ end }}{{ end}}
|
||||
{{end}}
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{ define "JustBaseTypeBody" }}struct {
|
||||
/* Just the base type fields. Used for unmashalling polymorphic types.*/
|
||||
{{ range .AllOf }}
|
||||
{{ if .IsBaseType }}
|
||||
{{ range .Properties }}
|
||||
{{ if .IsExported }}
|
||||
{{ if .IsTuple }}
|
||||
{{ template "tuplefield" . }}
|
||||
{{ else }}
|
||||
{{template "structfield" . }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
}
|
||||
{{- end }}
|
||||
21
vendor/github.com/go-swagger/go-swagger/generator/templates/schemaembedded.gotmpl
generated
vendored
Normal file
21
vendor/github.com/go-swagger/go-swagger/generator/templates/schemaembedded.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{{ define "schemaEmbedded" }}
|
||||
type {{ pascalize .Name }} struct {
|
||||
{{ if .ElemType.IsNullable }}*{{ end }}{{ .ElemType.GoType }}
|
||||
}
|
||||
|
||||
func ({{.ReceiverName }} {{ if or .IsTuple .IsComplexObject }}*{{ end }}{{ if .Discriminates }}{{ camelize .Name }}{{ else if .IsExported }}{{ pascalize .Name }}{{ else }}{{ .Name }}{{ end }}) Validate(formats strfmt.Registry) error {
|
||||
var f interface{} = {{ .ReceiverName }}.{{ dropPackage .ElemType.GoType }}
|
||||
if v, ok := f.(runtime.Validatable) ; ok {
|
||||
return v.Validate(formats)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ({{.ReceiverName }} {{ if or .IsTuple .IsComplexObject }}*{{ end }}{{ if .Discriminates }}{{ camelize .Name }}{{ else if .IsExported }}{{ pascalize .Name }}{{ else }}{{ .Name }}{{ end }}) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||
var f interface{} = {{ .ReceiverName }}.{{ dropPackage .ElemType.GoType }}
|
||||
if v, ok := f.(runtime.ContextValidatable) ; ok {
|
||||
return v.ContextValidate(ctx, formats)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
{{- end }}
|
||||
53
vendor/github.com/go-swagger/go-swagger/generator/templates/schemapolymorphic.gotmpl
generated
vendored
Normal file
53
vendor/github.com/go-swagger/go-swagger/generator/templates/schemapolymorphic.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
{{ define "schemaPolymorphic" }}
|
||||
type {{ pascalize .Name }} interface {
|
||||
{{- if not (or .IsInterface .IsStream) }}{{/*
|
||||
A base type is always Validatable.
|
||||
Under normal conditions, we can't have a base type rendered a .IsStream or .IsInterface: this check is just for sanity check).
|
||||
|
||||
In the definition of the base type itself, this means that the unexported struct holding
|
||||
the definition of the base type has a Validate() func and a ContextValitate() func.
|
||||
*/}}
|
||||
runtime.Validatable
|
||||
runtime.ContextValidatable
|
||||
{{- end }}
|
||||
{{ range .AllOf }}
|
||||
{{- if .IsAnonymous }}
|
||||
{{ range .Properties }}
|
||||
{{ if $.IsTuple }}{{ template "tuplefieldIface" . }}{{ else }}{{template "structfieldIface" . }}{{ end }}
|
||||
{{- end }}
|
||||
{{ template "mapOrSliceGetter" . }}
|
||||
{{- else }}
|
||||
{{ .GoType }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{ range .Properties }}
|
||||
{{- if $.IsTuple }}
|
||||
{{ template "tuplefieldIface" . }}
|
||||
{{- else }}
|
||||
{{ template "structfieldIface" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{ template "mapOrSliceGetter" . }}
|
||||
}
|
||||
|
||||
type {{ camelize .Name }} {{ template "schemaBody" . }}{{/* unexported implementation of the interface (TODO(fred): atm, this is not used, issue #232) */}}
|
||||
{{- range .Properties }}
|
||||
|
||||
// {{ pascalize .Name}} gets the {{ humanize .Name }} of this polymorphic type
|
||||
func ({{ $.ReceiverName}} *{{ camelize $.Name}}) {{ pascalize .Name}}() {{ template "schemaType" . }}{
|
||||
{{- if eq $.DiscriminatorField .Name }}
|
||||
return {{ printf "%q" $.DiscriminatorValue }}
|
||||
{{- else }}
|
||||
return {{ $.ReceiverName }}.{{camelize .Name}}Field
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
// Set{{ pascalize .Name}} sets the {{ humanize .Name }} of this polymorphic type
|
||||
func ({{ $.ReceiverName}} *{{ camelize $.Name}}) Set{{ pascalize .Name}}(val {{ template "schemaType" . }}) {
|
||||
{{- if ne $.DiscriminatorField .Name }}
|
||||
{{ $.ReceiverName }}.{{camelize .Name}}Field = val
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}{{/* TODO(fred): AdditionalProperties */}}
|
||||
{{ template "polymorphicSerializer" . }}
|
||||
{{- end }}
|
||||
29
vendor/github.com/go-swagger/go-swagger/generator/templates/schematype.gotmpl
generated
vendored
Normal file
29
vendor/github.com/go-swagger/go-swagger/generator/templates/schematype.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
{{ define "schemaType" }}
|
||||
{{- if and (or (gt (len .AllOf) 0) .IsAnonymous) ( not .IsMap) }}
|
||||
{{- template "schemaBody" . }}
|
||||
{{- else }}
|
||||
{{- if and (not .IsMap) .IsNullable (not .IsSuperAlias) }}*{{ end }}
|
||||
{{- if .IsSuperAlias }} = {{ end }}
|
||||
{{- .GoType }}
|
||||
{{- end}}
|
||||
{{- end }}
|
||||
|
||||
{{ define "dereffedSchemaType" }}
|
||||
{{- if and (or (gt (len .AllOf) 0) .IsAnonymous) ( not .IsMap) }}
|
||||
{{- template "schemaBody" . }}
|
||||
{{- else }}
|
||||
{{- .GoType }}
|
||||
{{- end}}
|
||||
{{- end }}
|
||||
|
||||
{{ define "typeSchemaType" }}
|
||||
{{- if and (or (gt (len .AllOf) 0) .IsAnonymous) ( not .IsMap) ( not .IsSuperAlias ) }}
|
||||
{{- template "schemaBody" . }}
|
||||
{{- else if and .IsSubType ( not .IsSuperAlias ) }}
|
||||
{{- template "subTypeBody" . }}
|
||||
{{- else }}
|
||||
{{- if and (not .IsMap) .IsNullable (not .IsSuperAlias) }}*{{ end }}
|
||||
{{- if .IsSuperAlias }} = {{ end }}
|
||||
{{- if .AliasedType }}{{ .AliasedType }}{{ else }}{{ .GoType }}{{ end }}
|
||||
{{- end}}
|
||||
{{- end }}
|
||||
1194
vendor/github.com/go-swagger/go-swagger/generator/templates/schemavalidator.gotmpl
generated
vendored
Normal file
1194
vendor/github.com/go-swagger/go-swagger/generator/templates/schemavalidator.gotmpl
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
94
vendor/github.com/go-swagger/go-swagger/generator/templates/serializers/additionalpropertiesserializer.gotmpl
generated
vendored
Normal file
94
vendor/github.com/go-swagger/go-swagger/generator/templates/serializers/additionalpropertiesserializer.gotmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
{{ define "additionalPropertiesSerializer" }}
|
||||
// UnmarshalJSON unmarshals this object with additional properties from JSON
|
||||
func ({{.ReceiverName}} *{{ pascalize .Name }}) UnmarshalJSON(data []byte) error {
|
||||
// stage 1, bind the properties
|
||||
var stage1 {{ template "withoutAdditionalBody" . }}
|
||||
if err := json.Unmarshal(data, &stage1); err != nil {
|
||||
return err
|
||||
}
|
||||
var rcv {{ pascalize .Name }}
|
||||
{{ range .Properties }}
|
||||
rcv.{{ pascalize .Name }} = stage1.{{ pascalize .Name }}
|
||||
{{- end }}
|
||||
*{{ .ReceiverName }} = rcv
|
||||
|
||||
// stage 2, remove properties and add to map
|
||||
stage2 := make(map[string]{{ if .AdditionalProperties }}json.RawMessage{{ else }}interface{}{{ end }})
|
||||
if err := json.Unmarshal(data, &stage2); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{{ range .Properties }}
|
||||
delete(stage2, {{ printf "%q" .Name }})
|
||||
{{- end }}
|
||||
|
||||
{{- if .AdditionalProperties }}
|
||||
// stage 3, add additional properties values
|
||||
if len(stage2) > 0 {
|
||||
result := make(map[string]{{ template "schemaType" .AdditionalProperties }})
|
||||
for k, v := range stage2 {
|
||||
var toadd {{ template "schemaType" .AdditionalProperties }}
|
||||
if err := json.Unmarshal(v, {{if not .AdditionalProperties.IsNullable }}&{{ end }}toadd); err != nil {
|
||||
return err
|
||||
}
|
||||
result[k] = toadd
|
||||
}
|
||||
{{ .ValueExpression }} = result
|
||||
}
|
||||
{{- else }}
|
||||
{{ .ValueExpression }} = stage2
|
||||
{{- end }}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalJSON marshals this object with additional properties into a JSON object
|
||||
func ({{.ReceiverName}} {{ pascalize .Name }}) MarshalJSON() ([]byte, error) {
|
||||
var stage1 {{ template "withoutAdditionalBody" . }}
|
||||
{{ range .Properties }}
|
||||
stage1.{{ pascalize .Name }} = {{ .ValueExpression }}
|
||||
{{- end }}
|
||||
|
||||
// make JSON object for known properties
|
||||
props, err := json.Marshal(stage1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len({{ .ValueExpression }}) == 0 { // no additional properties
|
||||
return props, nil
|
||||
}
|
||||
|
||||
// make JSON object for the additional properties
|
||||
additional, err := json.Marshal({{ .ValueExpression }})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(props) < 3 { // "{}": only additional properties
|
||||
return additional, nil
|
||||
}
|
||||
|
||||
// concatenate the 2 objects
|
||||
return swag.ConcatJSON(props, additional), nil
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{ define "noAdditionalPropertiesSerializer" }}
|
||||
// UnmarshalJSON unmarshals this object while disallowing additional properties from JSON
|
||||
func ({{.ReceiverName}} *{{ pascalize .Name }}) UnmarshalJSON(data []byte) error {
|
||||
var props {{ template "withoutAdditionalBody" . }}
|
||||
|
||||
dec := json.NewDecoder(bytes.NewReader(data))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&props); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{{- $rcv := .ReceiverName }}
|
||||
{{ range .Properties }}
|
||||
{{ .ReceiverName }}.{{ pascalize .Name }} = props.{{ pascalize .Name }}
|
||||
{{- end }}
|
||||
return nil
|
||||
}
|
||||
{{- end }}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue