github.com/josephspurrier/go-swagger@v0.2.1-0.20221129144919-1f672a142a00/cmd/swagger/commands/generate/spec.go (about) 1 //go:build !go1.11 2 // +build !go1.11 3 4 // Copyright 2015 go-swagger maintainers 5 // 6 // Licensed under the Apache License, Version 2.0 (the "License"); 7 // you may not use this file except in compliance with the License. 8 // You may obtain a copy of the License at 9 // 10 // http://www.apache.org/licenses/LICENSE-2.0 11 // 12 // Unless required by applicable law or agreed to in writing, software 13 // distributed under the License is distributed on an "AS IS" BASIS, 14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 // See the License for the specific language governing permissions and 16 // limitations under the License. 17 18 package generate 19 20 import ( 21 "encoding/json" 22 "fmt" 23 "os" 24 "strings" 25 26 "github.com/go-openapi/loads" 27 "github.com/go-openapi/spec" 28 "github.com/go-swagger/go-swagger/scan" 29 "github.com/jessevdk/go-flags" 30 "gopkg.in/yaml.v3" 31 ) 32 33 // SpecFile command to generate a swagger spec from a go application 34 type SpecFile struct { 35 BasePath string `long:"base-path" short:"b" description:"the base path to use" default:"."` 36 BuildTags string `long:"tags" short:"t" description:"build tags" default:""` 37 ScanModels bool `long:"scan-models" short:"m" description:"includes models that were annotated with 'swagger:model'"` 38 Compact bool `long:"compact" description:"when present, doesn't prettify the json"` 39 Output flags.Filename `long:"output" short:"o" description:"the file to write to"` 40 Input flags.Filename `long:"input" short:"i" description:"an input swagger file with which to merge"` 41 Include []string `long:"include" short:"c" description:"include packages matching pattern"` 42 Exclude []string `long:"exclude" short:"x" description:"exclude packages matching pattern"` 43 IncludeTags []string `long:"include-tag" short:"" description:"include routes having specified tags (can be specified many times)"` 44 ExcludeTags []string `long:"exclude-tag" short:"" description:"exclude routes having specified tags (can be specified many times)"` 45 } 46 47 // Execute runs this command 48 func (s *SpecFile) Execute(args []string) error { 49 input, err := loadSpec(string(s.Input)) 50 if err != nil { 51 return err 52 } 53 54 var opts scan.Opts 55 opts.BasePath = s.BasePath 56 opts.Input = input 57 opts.ScanModels = s.ScanModels 58 opts.BuildTags = s.BuildTags 59 opts.Include = s.Include 60 opts.Exclude = s.Exclude 61 opts.IncludeTags = s.IncludeTags 62 opts.ExcludeTags = s.ExcludeTags 63 swspec, err := scan.Application(opts) 64 if err != nil { 65 return err 66 } 67 68 return writeToFile(swspec, !s.Compact, string(s.Output)) 69 } 70 71 func loadSpec(input string) (*spec.Swagger, error) { 72 if fi, err := os.Stat(input); err == nil { 73 if fi.IsDir() { 74 return nil, fmt.Errorf("expected %q to be a file not a directory", input) 75 } 76 sp, err := loads.Spec(input) 77 if err != nil { 78 return nil, err 79 } 80 return sp.Spec(), nil 81 } 82 return nil, nil 83 } 84 85 func writeToFile(swspec *spec.Swagger, pretty bool, output string) error { 86 var b []byte 87 var err error 88 89 if strings.HasSuffix(output, "yml") || strings.HasSuffix(output, "yaml") { 90 b, err = marshalToYAMLFormat(swspec) 91 } else { 92 b, err = marshalToJSONFormat(swspec, pretty) 93 } 94 95 if err != nil { 96 return err 97 } 98 99 if output == "" { 100 fmt.Println(string(b)) 101 return nil 102 } 103 return os.WriteFile(output, b, 0644) 104 } 105 106 func marshalToJSONFormat(swspec *spec.Swagger, pretty bool) ([]byte, error) { 107 if pretty { 108 return json.MarshalIndent(swspec, "", " ") 109 } 110 return json.Marshal(swspec) 111 } 112 113 func marshalToYAMLFormat(swspec *spec.Swagger) ([]byte, error) { 114 b, err := json.Marshal(swspec) 115 if err != nil { 116 return nil, err 117 } 118 119 var jsonObj interface{} 120 if err := yaml.Unmarshal(b, &jsonObj); err != nil { 121 return nil, err 122 } 123 124 return yaml.Marshal(jsonObj) 125 }