github.com/josephspurrier/go-swagger@v0.2.1-0.20221129144919-1f672a142a00/cmd/swagger/commands/generate/spec_go111.go (about) 1 //go:build go1.11 2 // +build go1.11 3 4 package generate 5 6 import ( 7 "encoding/json" 8 "fmt" 9 "os" 10 "strings" 11 12 "github.com/go-swagger/go-swagger/codescan" 13 14 "github.com/go-openapi/loads" 15 "github.com/go-openapi/spec" 16 "github.com/jessevdk/go-flags" 17 "gopkg.in/yaml.v3" 18 ) 19 20 // SpecFile command to generate a swagger spec from a go application 21 type SpecFile struct { 22 WorkDir string `long:"work-dir" short:"w" description:"the base path to use" default:"."` 23 BuildTags string `long:"tags" short:"t" description:"build tags" default:""` 24 ScanModels bool `long:"scan-models" short:"m" description:"includes models that were annotated with 'swagger:model'"` 25 Compact bool `long:"compact" description:"when present, doesn't prettify the json"` 26 Output flags.Filename `long:"output" short:"o" description:"the file to write to"` 27 Input flags.Filename `long:"input" short:"i" description:"an input swagger file with which to merge"` 28 Include []string `long:"include" short:"c" description:"include packages matching pattern"` 29 Exclude []string `long:"exclude" short:"x" description:"exclude packages matching pattern"` 30 IncludeTags []string `long:"include-tag" short:"" description:"include routes having specified tags (can be specified many times)"` 31 ExcludeTags []string `long:"exclude-tag" short:"" description:"exclude routes having specified tags (can be specified many times)"` 32 ExcludeDeps bool `long:"exclude-deps" short:"" description:"exclude all dependencies of project"` 33 } 34 35 // Execute runs this command 36 func (s *SpecFile) Execute(args []string) error { 37 if len(args) == 0 { // by default consider all the paths under the working directory 38 args = []string{"./..."} 39 } 40 41 input, err := loadSpec(string(s.Input)) 42 if err != nil { 43 return err 44 } 45 46 var opts codescan.Options 47 opts.Packages = args 48 opts.WorkDir = s.WorkDir 49 opts.InputSpec = input 50 opts.ScanModels = s.ScanModels 51 opts.BuildTags = s.BuildTags 52 opts.Include = s.Include 53 opts.Exclude = s.Exclude 54 opts.IncludeTags = s.IncludeTags 55 opts.ExcludeTags = s.ExcludeTags 56 opts.ExcludeDeps = s.ExcludeDeps 57 swspec, err := codescan.Run(&opts) 58 if err != nil { 59 return err 60 } 61 62 return writeToFile(swspec, !s.Compact, string(s.Output)) 63 } 64 65 func loadSpec(input string) (*spec.Swagger, error) { 66 if fi, err := os.Stat(input); err == nil { 67 if fi.IsDir() { 68 return nil, fmt.Errorf("expected %q to be a file not a directory", input) 69 } 70 sp, err := loads.Spec(input) 71 if err != nil { 72 return nil, err 73 } 74 return sp.Spec(), nil 75 } 76 return nil, nil 77 } 78 79 func writeToFile(swspec *spec.Swagger, pretty bool, output string) error { 80 var b []byte 81 var err error 82 83 if strings.HasSuffix(output, "yml") || strings.HasSuffix(output, "yaml") { 84 b, err = marshalToYAMLFormat(swspec) 85 } else { 86 b, err = marshalToJSONFormat(swspec, pretty) 87 } 88 89 if err != nil { 90 return err 91 } 92 93 if output == "" { 94 fmt.Println(string(b)) 95 return nil 96 } 97 return os.WriteFile(output, b, 0644) // #nosec 98 } 99 100 func marshalToJSONFormat(swspec *spec.Swagger, pretty bool) ([]byte, error) { 101 if pretty { 102 return json.MarshalIndent(swspec, "", " ") 103 } 104 return json.Marshal(swspec) 105 } 106 107 func marshalToYAMLFormat(swspec *spec.Swagger) ([]byte, error) { 108 b, err := json.Marshal(swspec) 109 if err != nil { 110 return nil, err 111 } 112 113 var jsonObj interface{} 114 if err := yaml.Unmarshal(b, &jsonObj); err != nil { 115 return nil, err 116 } 117 118 return yaml.Marshal(jsonObj) 119 }