package dbmeta import ( "bytes" "encoding/csv" "encoding/json" "fmt" "path" "time" "github.com/ManyakRus/crud_generator/pkg/utils" "go/format" "io/ioutil" "os" "path/filepath" "reflect" "regexp" "strings" "text/template" "github.com/davecgh/go-spew/spew" "github.com/jinzhu/inflection" "github.com/serenize/snaker" "golang.org/x/tools/imports" ) // GenTemplate template info struct type GenTemplate struct { Name string Content string } // TemplateLoader loader function to retrieve a template contents type TemplateLoader func(filename string) (tpl *GenTemplate, err error) var replaceFuncMap = template.FuncMap{ "singular": inflection.Singular, "pluralize": inflection.Plural, "title": strings.Title, "toLower": strings.ToLower, "toUpper": strings.ToUpper, "toLowerCamelCase": camelToLowerCamel, "toUpperCamelCase": camelToUpperCamel, "toSnakeCase": snaker.CamelToSnake, "StringsJoin": strings.Join, "replace": replace, "stringifyFirstChar": stringifyFirstChar, "FmtFieldName": FmtFieldName, } func replace(input, from, to string) string { return strings.Replace(input, from, to, -1) } // Replace takes a template based name format and will render a name using it func Replace(nameFormat, name string) string { var tpl bytes.Buffer //fmt.Printf("Replace: %s\n",nameFormat) t := template.Must(template.New("t1").Funcs(replaceFuncMap).Parse(nameFormat)) //sanek start if name[0:1] == "$" { name = name[1:] + "$" } //sanek end if err := t.Execute(&tpl, name); err != nil { //fmt.Printf("Error creating name format: %s error: %v\n", nameFormat, err) return name } result := tpl.String() result = strings.Trim(result, " \t") result = strings.Replace(result, " ", "_", -1) result = strings.Replace(result, "\t", "_", -1) //fmt.Printf("Replace( '%s' '%s')= %s\n",nameFormat, name, result) return result } // ReplaceFileNamingTemplate use the FileNamingTemplate to format a table name func (c *Config) ReplaceFileNamingTemplate(name string) string { return Replace(c.FileNamingTemplate, name) } // ReplaceModelNamingTemplate use the ModelNamingTemplate to format a table name func (c *Config) ReplaceModelNamingTemplate(name string) string { return Replace(c.ModelNamingTemplate, name) } // ReplaceFieldNamingTemplate use the FieldNamingTemplate to format a table name func (c *Config) ReplaceFieldNamingTemplate(name string) string { return Replace(c.FieldNamingTemplate, name) } // GetTemplate return a Template based on a name and template contents func (c *Config) GetTemplate(genTemplate *GenTemplate) (*template.Template, error) { var s State var funcMap = template.FuncMap{ "ReplaceFileNamingTemplate": c.ReplaceFileNamingTemplate, "ReplaceModelNamingTemplate": c.ReplaceModelNamingTemplate, "ReplaceFieldNamingTemplate": c.ReplaceFieldNamingTemplate, "stringifyFirstChar": stringifyFirstChar, "singular": inflection.Singular, "pluralize": inflection.Plural, "title": strings.Title, "toLower": strings.ToLower, "toUpper": strings.ToUpper, "toLowerCamelCase": camelToLowerCamel, "toUpperCamelCase": camelToUpperCamel, "FormatSource": FormatSource, "toSnakeCase": snaker.CamelToSnake, "markdownCodeBlock": markdownCodeBlock, "wrapBash": wrapBash, "escape": escape, "GenerateTableFile": c.GenerateTableFile, "GenerateFile": c.GenerateFile, "ToJSON": ToJSON, "spew": Spew, "set": s.Set, "inc": s.Inc, "StringsJoin": strings.Join, "replace": replace, "hasField": hasField, "FmtFieldName": FmtFieldName, "copy": c.FileSystemCopy, "mkdir": c.Mkdir, "touch": c.Touch, "pwd": Pwd, "config": c.DisplayConfig, "insertFragment": c.insertFragment, } baseName := filepath.Base(genTemplate.Name) tmpl, err := template.New(baseName).Option("missingkey=error").Funcs(funcMap).Parse(genTemplate.Content) if err != nil { return nil, err } if baseName == "api.go.tmpl" || baseName == "dao_gorm.go.tmpl" || baseName == "dao_sqlx.go.tmpl" || baseName == "code_dao_sqlx.md.tmpl" || baseName == "code_dao_gorm.md.tmpl" || baseName == "code_http.md.tmpl" { operations := []string{"add", "delete", "get", "getall", "update"} for _, op := range operations { var filename string if baseName == "api.go.tmpl" { filename = fmt.Sprintf("api_%s.go.tmpl", op) } if baseName == "dao_gorm.go.tmpl" { filename = fmt.Sprintf("dao_gorm_%s.go.tmpl", op) } if baseName == "dao_sqlx.go.tmpl" { filename = fmt.Sprintf("dao_sqlx_%s.go.tmpl", op) } if baseName == "code_dao_sqlx.md.tmpl" { filename = fmt.Sprintf("dao_sqlx_%s.go.tmpl", op) } if baseName == "code_dao_gorm.md.tmpl" { filename = fmt.Sprintf("dao_gorm_%s.go.tmpl", op) } if baseName == "code_http.md.tmpl" { filename = fmt.Sprintf("api_%s.go.tmpl", op) } var subTemplate *GenTemplate if subTemplate, err = c.TemplateLoader(filename); err != nil { fmt.Printf("Error loading template %v\n", err) return nil, err } // fmt.Printf("loading sub template %v\n", filename) tmpl.Parse(subTemplate.Content) } } return tmpl, nil } func hasField(v interface{}, name string) bool { rv := reflect.ValueOf(v) if rv.Kind() == reflect.Ptr { rv = rv.Elem() } if rv.Kind() != reflect.Struct { return false } return rv.FieldByName(name).IsValid() } // ToJSON func to return json string representation of struct func ToJSON(val interface{}, indent int) string { pad := fmt.Sprintf("%*s", indent, "") strB, _ := json.MarshalIndent(val, "", pad) response := string(strB) response = strings.Replace(response, "\n", "", -1) return response } // Spew func to return spewed string representation of struct func Spew(val interface{}) string { return spew.Sdump(val) } // State struct used for storing state in template parsing type State struct { n int } // Set set state value in template parsing func (s *State) Set(n int) int { s.n = n return n } // Inc increment state value in template parsing func (s *State) Inc() int { s.n++ return s.n } func camelToLowerCamel(s string) string { ss := strings.Split(s, "") ss[0] = strings.ToLower(ss[0]) return strings.Join(ss, "") } func camelToUpperCamel(s string) string { ss := strings.Split(s, "") ss[0] = strings.ToUpper(ss[0]) return strings.Join(ss, "") } // FormatSource format source code contents func FormatSource(s string) string { formattedSource, err := format.Source([]byte(s)) if err != nil { return fmt.Sprintf("Error in formatting source: %s\n", err.Error()) } formattedSource, err = imports.Process("", formattedSource, nil) if err != nil { return fmt.Sprintf("Error in formatting source: %s\n", err.Error()) } return string(formattedSource) } func markdownCodeBlock(contentType, content string) string { // fmt.Printf("%s - %s\n", contentType, content) return fmt.Sprintf("```%s\n%s\n```\n", contentType, content) } func wrapBash(content string) string { r := csv.NewReader(strings.NewReader(content)) r.Comma = ' ' record, err := r.Read() if err != nil { return content } fmt.Printf("[%s]\n", content) for i, j := range record { fmt.Printf("wrapBash [%d] %s\n", i, j) } out := strings.Join(record, " \\\n ") return out // // //r := regexp.MustCompile(`[^\s"']+|"([^"]*)"|'([^']*)`) //arr := r.FindAllString(content, -1) //return strings.Join(arr, " \\\n ") // // //splitter := "[^\\s\"']+|\"[^\"]*\"|'[^']*'" //result := RegSplit(content, splitter) //return strings.Join(result, " \\\n ") // //result, err := parseCommandLine(content) //if err != nil { // return content //} //return strings.Join(result, " \\\n ") } // RegSplit split text based on regex func RegSplit(text string, delimeter string) []string { reg := regexp.MustCompile(delimeter) indexes := reg.FindAllStringIndex(text, -1) laststart := 0 result := make([]string, len(indexes)+1) for i, element := range indexes { result[i] = text[laststart:element[0]] laststart = element[1] } result[len(indexes)] = text[laststart:] return result } func parseCommandLine(command string) ([]string, error) { var args []string state := "start" current := "" quote := "\"" escapeNext := true for i := 0; i < len(command); i++ { c := command[i] if state == "quotes" { if string(c) != quote { current += string(c) } else { args = append(args, current) current = "" state = "start" } continue } if escapeNext { current += string(c) escapeNext = false continue } if c == '\\' { escapeNext = true continue } if c == '"' || c == '\'' { state = "quotes" quote = string(c) continue } if state == "arg" { if c == ' ' || c == '\t' { args = append(args, current) current = "" state = "start" } else { current += string(c) } continue } if c != ' ' && c != '\t' { state = "arg" current += string(c) } } if state == "quotes" { return []string{}, fmt.Errorf("unclosed quote in command line: %s", command) } if current != "" { args = append(args, current) } return args, nil } func escape(content string) string { content = strings.Replace(content, "\"", "\\\"", -1) content = strings.Replace(content, "'", "\\'", -1) return content } // LoadFragments read all filed inside dirname to `fragments` func (c *Config) LoadFragments(dirname string) error { c.FragmentsDir = dirname files, err := ioutil.ReadDir(dirname) if err != nil { return err } c.fragments = &bytes.Buffer{} for _, file := range files { if !file.IsDir() { filename := path.Join(dirname, file.Name()) content, err := ioutil.ReadFile(filename) if err != nil { return err } c.fragments.Write(content) c.fragments.WriteRune('\n') } } return nil } // Insert code fragment from file. // Within a single file, fragment can be marked as // fragment: ... // end func (c *Config) insertFragment(name, defValue string) (string, error) { if c.fragments == nil || c.fragments.Len() == 0 { return defValue, nil } // pointer to fragment content content := c.fragments.Bytes() // if fragment name is not defined, // return whole content if name == "" { return string(content), nil } // Use regex to extract fragment name from given file. // Below is an example of code fragment. /* //fragment: func (w *Model) MyCode() { } // end */ begExp := fmt.Sprintf(`//[\s]{0,}fragment[\s]{0,}:[\s]{0,}%s[\s]{1,}`, name) reBeg, err := regexp.Compile(begExp) if err != nil { return defValue, nil } begLoc := reBeg.FindIndex(content) if begLoc == nil || begLoc[1] == len(content) { // not found or no content specified after // fragment: return defValue, nil } fromIdx := begLoc[1] subContent := content[fromIdx:] reEnd := regexp.MustCompile(`//[\s]end[\s]{0,}`) endLoc := reEnd.FindIndex(subContent) if endLoc == nil { // not found, return remaining content return string(subContent), nil } return string(subContent[:endLoc[0]]), nil } // JSONFieldName convert name to appropriate case func (c *Config) JSONFieldName(name string) string { return formatFieldName(c.JSONNameFormat, name) } // JSONTag converts name to `json:"name"` respecting json-fmt option func (c *Config) JSONTag(name string) string { return fmt.Sprintf("`json:\"%s\"`", c.JSONFieldName(name)) } // JSONTagOmitEmpty converts name to JSON tag with omitempty func (c *Config) JSONTagOmitEmpty(name string) string { return fmt.Sprintf("`json:\"%s,omitempty\"`", c.JSONFieldName(name)) } // GenerateTableFile generate file from template using specific table used within templates func (c *Config) GenerateTableFile(tableName, templateFilename, outputDirectory, outputFileName string) string { buf := bytes.Buffer{} buf.WriteString(fmt.Sprintf("GenerateTableFile( %s, %s, %s, %s)\n", tableName, templateFilename, outputDirectory, outputFileName)) tableInfo, ok := c.TableInfos[tableName] if !ok { buf.WriteString(fmt.Sprintf("Table: %s - No tableInfo found\n", tableName)) return buf.String() } if len(tableInfo.Fields) == 0 { buf.WriteString(fmt.Sprintf("able: %s - No Fields Available\n", tableName)) return buf.String() } data := c.CreateContextForTableFile(tableInfo) fileOutDir := filepath.Join(c.OutDir, outputDirectory) err := os.MkdirAll(fileOutDir, 0777) if err != nil && !c.Overwrite { buf.WriteString(fmt.Sprintf("unable to create fileOutDir: %s error: %v\n", fileOutDir, err)) return buf.String() } var tpl *GenTemplate if tpl, err = c.TemplateLoader(templateFilename); err != nil { buf.WriteString(fmt.Sprintf("Error loading template %v\n", err)) return buf.String() } outputFile := filepath.Join(fileOutDir, outputFileName) buf.WriteString(fmt.Sprintf("Writing %s -> %s\n", templateFilename, outputFile)) err = c.WriteTemplate(tpl, data, outputFile) return buf.String() } // CreateContextForTableFile create map context for a db table func (c *Config) CreateContextForTableFile(tableInfo *ModelInfo) map[string]interface{} { var modelInfo = map[string]interface{}{ "StructName": tableInfo.StructName, "TableName": tableInfo.DBMeta.TableName(), "ShortStructName": strings.ToLower(string(tableInfo.StructName[0])), "TableInfo": tableInfo, } nonPrimaryKeys := NonPrimaryKeyNames(tableInfo.DBMeta) modelInfo["NonPrimaryKeyNamesList"] = nonPrimaryKeys modelInfo["NonPrimaryKeysJoined"] = strings.Join(nonPrimaryKeys, ",") primaryKeys := PrimaryKeyNames(tableInfo.DBMeta) modelInfo["PrimaryKeyNamesList"] = primaryKeys modelInfo["PrimaryKeysJoined"] = strings.Join(primaryKeys, ",") delSQL, err := GenerateDeleteSQL(tableInfo.DBMeta) if err == nil { modelInfo["delSql"] = delSQL } updateSQL, err := GenerateUpdateSQL(tableInfo.DBMeta) if err == nil { modelInfo["updateSql"] = updateSQL } insertSQL, err := GenerateInsertSQL(tableInfo.DBMeta) if err == nil { modelInfo["insertSql"] = insertSQL } selectOneSQL, err := GenerateSelectOneSQL(tableInfo.DBMeta) if err == nil { modelInfo["selectOneSql"] = selectOneSQL } selectMultiSQL, err := GenerateSelectMultiSQL(tableInfo.DBMeta) if err == nil { modelInfo["selectMultiSql"] = selectMultiSQL } return modelInfo } // WriteTemplate write a template out func (c *Config) WriteTemplate(genTemplate *GenTemplate, data map[string]interface{}, outputFile string) error { //fmt.Printf("WriteTemplate %s\n", outputFile) if !c.Overwrite && Exists(outputFile) { fmt.Printf("not overwriting %s\n", outputFile) return nil } for key, value := range c.ContextMap { data[key] = value } dir := filepath.Dir(outputFile) parent := filepath.Base(dir) data["File"] = outputFile data["Dir"] = dir data["Parent"] = parent data["DatabaseName"] = c.SQLDatabase data["module"] = c.Module data["modelFQPN"] = c.ModelFQPN data["modelPackageName"] = c.ModelPackageName data["daoFQPN"] = c.DaoFQPN data["daoPackageName"] = c.DaoPackageName data["UseGuregu"] = c.UseGureguTypes data["apiFQPN"] = c.APIFQPN data["apiPackageName"] = c.APIPackageName data["sqlType"] = c.SQLType data["sqlConnStr"] = c.SQLConnStr data["serverPort"] = c.ServerPort data["serverHost"] = c.ServerHost data["serverScheme"] = c.ServerScheme data["serverListen"] = c.ServerListen data["SwaggerInfo"] = c.Swagger data["outDir"] = c.OutDir data["Config"] = c rt, err := c.GetTemplate(genTemplate) if err != nil { return fmt.Errorf("error in loading %s template, error: %v", genTemplate.Name, err) } var buf bytes.Buffer err = rt.Execute(&buf, data) if err != nil { return fmt.Errorf("error in rendering %s: %s", genTemplate.Name, err.Error()) } fileContents, err := c.format(genTemplate, buf.Bytes(), outputFile) if err != nil { return fmt.Errorf("error writing %s - error: %v", outputFile, err) } err = ioutil.WriteFile(outputFile, fileContents, 0777) if err != nil { return fmt.Errorf("error writing %s - error: %v", outputFile, err) } if c.Verbose { fmt.Printf("writing %s\n", outputFile) } return nil } func (c *Config) format(genTemplate *GenTemplate, content []byte, outputFile string) ([]byte, error) { extension := filepath.Ext(outputFile) if extension == ".go" { formattedSource, err := format.Source([]byte(content)) if err != nil { return nil, fmt.Errorf("error in formatting template: %s outputfile: %s source: %s", genTemplate.Name, outputFile, err.Error()) } fileContents := NormalizeNewlines(formattedSource) if c.LineEndingCRLF { fileContents = CRLFNewlines(formattedSource) } return fileContents, nil } fileContents := NormalizeNewlines([]byte(content)) if c.LineEndingCRLF { fileContents = CRLFNewlines(fileContents) } return fileContents, nil } // NormalizeNewlines normalizes \r\n (windows) and \r (mac) // into \n (unix) func NormalizeNewlines(d []byte) []byte { // replace CR LF \r\n (windows) with LF \n (unix) d = bytes.Replace(d, []byte{13, 10}, []byte{10}, -1) // replace CF \r (mac) with LF \n (unix) d = bytes.Replace(d, []byte{13}, []byte{10}, -1) return d } // CRLFNewlines transforms \n to \r\n (windows) func CRLFNewlines(d []byte) []byte { // replace LF (unix) with CR LF \r\n (windows) d = bytes.Replace(d, []byte{10}, []byte{13, 10}, -1) return d } // Exists reports whether the named file or directory exists. func Exists(name string) bool { if _, err := os.Stat(name); err != nil { if os.IsNotExist(err) { return false } } return true } // GenerateFile generate file from template, non table used within templates func (c *Config) GenerateFile(templateFilename, outputDirectory, outputFileName string, overwrite bool) string { buf := bytes.Buffer{} buf.WriteString(fmt.Sprintf("GenerateFile( %s, %s, %s)\n", templateFilename, outputDirectory, outputFileName)) fileOutDir := outputDirectory err := os.MkdirAll(fileOutDir, 0777) if err != nil && !overwrite { buf.WriteString(fmt.Sprintf("unable to create fileOutDir: %s error: %v\n", fileOutDir, err)) return buf.String() } data := map[string]interface{}{} var tpl *GenTemplate if tpl, err = c.TemplateLoader(templateFilename); err != nil { buf.WriteString(fmt.Sprintf("Error loading template %v\n", err)) return buf.String() } outputFile := filepath.Join(fileOutDir, outputFileName) buf.WriteString(fmt.Sprintf("Writing %s -> %s\n", templateFilename, outputFile)) err = c.WriteTemplate(tpl, data, outputFile) if err != nil { buf.WriteString(fmt.Sprintf("Error calling WriteTemplate %s -> %v\n", templateFilename, err)) } return buf.String() } // DisplayConfig display config info func (c *Config) DisplayConfig() string { info := fmt.Sprintf( `DisplayConfig SQLType : %s SQLConnStr : %s SQLDatabase : %s Module : %s OutDir : %s `, c.SQLType, c.SQLConnStr, c.SQLDatabase, c.Module, c.OutDir) return info } type copyRules struct { result bool pattern string r *regexp.Regexp } // FileSystemCopy template command to copy files, directories and to pass --include XXX and --exclude YYY regular expressions. Files ending in .tmpl will be processed as a template. // Files ending in .table.tmpl will be processed as a template iterating through all the tables func (c *Config) FileSystemCopy(src, dst string, options ...string) string { dstDir := filepath.Join(c.OutDir, dst) patterns := make([]*copyRules, 0) for _, o := range options { if strings.HasPrefix(o, "--exclude ") { pattern := o[len("--exclude "):] r, _ := regexp.Compile(pattern) if r != nil { patterns = append(patterns, ©Rules{result: false, r: r, pattern: pattern}) } } if strings.HasPrefix(o, "--include ") { pattern := o[len("--include "):] r, _ := regexp.Compile(pattern) if r != nil { patterns = append(patterns, ©Rules{result: true, r: r, pattern: pattern}) } } } opt := utils.DefaultCopyOptions() opt.ShouldCopy = func(info os.FileInfo) bool { name := info.Name() for _, r := range patterns { if r.r.Match([]byte(name)) { //fmt.Printf("copy ShouldCopy %s pattern: [%s] result: %t\n", name, r.pattern, r.result) return r.result } } return true } opt.FileHandler = func(src, dest string, info os.FileInfo) utils.FileHandlerFunc { if !opt.ShouldCopy(info) { return func(src, dest string, info os.FileInfo, opt utils.Options, results *utils.Results) (err error) { results.Info.WriteString(fmt.Sprintf("CopyFile Skipping %s\n", src)) return nil } } if strings.HasSuffix(src, ".table.tmpl") { //fmt.Printf("@@ HandleTableTemplateFile: src: %s dest: %s Name: %s\n", src, dest, info.Name()) return c.tableFileHandlerFunc } if strings.HasSuffix(src, ".tmpl") { //fmt.Printf("@@ HandleTemplateFile: src: %s dest: %s Name: %s\n", src, dest, info.Name()) return c.fileHandlerFunc } return func(src, dest string, info os.FileInfo, opt utils.Options, results *utils.Results) (err error) { results.Info.WriteString(fmt.Sprintf("CopyFile %s\n", dest)) return utils.DefaultFileCopy(src, dest, info, opt, results) } } result, err := utils.Copy(src, dstDir, opt) if err != nil { return fmt.Sprintf("copy returned an error %v", err) } return fmt.Sprintf("copy %s %s\n%s\n", src, dstDir, result.String()) } // Mkdir template command to mkdir under the output directory func (c *Config) Mkdir(dst string) string { dstDir := filepath.Join(c.OutDir, dst) err := os.MkdirAll(dstDir, os.ModePerm) if err != nil { return fmt.Sprintf("mkdir returned an error %v", err) } return fmt.Sprintf("mkdir %s", dstDir) } // Touch template command to touch a file under the output directory func (c *Config) Touch(dst string) string { dstDir := filepath.Join(c.OutDir, dst) _, err := os.Stat(dstDir) if os.IsNotExist(err) { file, err := os.Create(dstDir) if err != nil { return fmt.Sprintf("touch returned an error %v", err) } defer file.Close() } else { currentTime := time.Now().Local() err = os.Chtimes(dstDir, currentTime, currentTime) if err != nil { return fmt.Sprintf("touch returned an error %v", err) } } return fmt.Sprintf("touch %s", dstDir) } // ".tmpl" func (c *Config) fileHandlerFunc(src, dest string, info os.FileInfo, opt utils.Options, results *utils.Results) (err error) { genTemplate := &GenTemplate{ Name: info.Name(), Content: loadFile(src), } data := make(map[string]interface{}) outputFile := dest[0 : len(dest)-5] results.Info.WriteString(fmt.Sprintf("WriteTemplate %s\n", outputFile)) return c.WriteTemplate(genTemplate, data, outputFile) } // ".table.tmpl" func (c *Config) tableFileHandlerFunc(src, dest string, info os.FileInfo, opt utils.Options, results *utils.Results) (err error) { genTemplate := &GenTemplate{ Name: info.Name(), Content: loadFile(src), } outputFile := dest[0 : len(dest)-11] dir := filepath.Dir(outputFile) tmplateName := filepath.Base(outputFile) // parent := filepath.Base(dir) results.Info.WriteString(fmt.Sprintf("WriteTableTemplate %s\n", src)) for tableName, tableInfo := range c.TableInfos { data := c.CreateContextForTableFile(tableInfo) // fileName := filepath.Join(dir, tableName+name) name := c.ReplaceFileNamingTemplate(tableName) + filepath.Ext(tmplateName) fileName := filepath.Join(dir, name) results.Info.WriteString(fmt.Sprintf(" table: %-25s %s\n", tableName, fileName)) c.WriteTemplate(genTemplate, data, fileName) } return nil } func loadFile(src string) string { // Read entire file content, giving us little control but // making it very simple. No need to close the file. content, err := ioutil.ReadFile(src) if err != nil { return fmt.Sprintf("error loading %s error: %v", src, err) } // Convert []byte to string and print to screen text := string(content) return text } // SwaggerInfoDetails swagger details type SwaggerInfoDetails struct { Version string Host string BasePath string Title string Description string TOS string ContactName string ContactURL string ContactEmail string } // Config for generating code type Config struct { SQLType string SQLConnStr string SQLDatabase string Module string ModelPackageName string ModelFQPN string AddJSONAnnotation bool AddGormAnnotation bool AddProtobufAnnotation bool AddXMLAnnotation bool AddDBAnnotation bool UseGureguTypes bool JSONNameFormat string XMLNameFormat string ProtobufNameFormat string DaoPackageName string DaoFQPN string APIPackageName string APIFQPN string GrpcPackageName string GrpcFQPN string Swagger *SwaggerInfoDetails ServerPort int ServerHost string ServerScheme string ServerListen string Verbose bool OutDir string Overwrite bool LineEndingCRLF bool CmdLine string CmdLineWrapped string CmdLineArgs []string FileNamingTemplate string ModelNamingTemplate string FieldNamingTemplate string ContextMap map[string]interface{} TemplateLoader TemplateLoader TableInfos map[string]*ModelInfo FragmentsDir string fragments *bytes.Buffer } // NewConfig create a new code config func NewConfig(templateLoader TemplateLoader) *Config { conf := &Config{ Swagger: &SwaggerInfoDetails{ Version: "1.0", BasePath: "/", Title: "Swagger Example API", Description: "This is a sample server Petstore server.", TOS: "", ContactName: "", ContactURL: "", ContactEmail: "", }, TemplateLoader: templateLoader, } conf.CmdLineArgs = os.Args conf.CmdLineWrapped = strings.Join(os.Args, " \\\n ") conf.CmdLine = strings.Join(os.Args, " ") conf.ContextMap = make(map[string]interface{}) conf.FileNamingTemplate = "{{.}}" conf.ModelNamingTemplate = "{{FmtFieldName .}}" conf.FieldNamingTemplate = "{{FmtFieldName (stringifyFirstChar .) }}" outDir := "." module := "github.com/alexj212/test" modelPackageName := "model" daoPackageName := "dao" apiPackageName := "api" conf.ModelPackageName = modelPackageName conf.DaoPackageName = daoPackageName conf.APIPackageName = apiPackageName conf.AddJSONAnnotation = true conf.AddXMLAnnotation = true conf.AddGormAnnotation = true conf.AddProtobufAnnotation = true conf.AddDBAnnotation = true conf.UseGureguTypes = false conf.JSONNameFormat = "snake" conf.XMLNameFormat = "snake" conf.ProtobufNameFormat = "snake" conf.Verbose = false conf.OutDir = outDir conf.Overwrite = true conf.ServerPort = 8080 conf.ServerHost = "127.0.0.1" conf.ServerScheme = "http" conf.ServerListen = ":8080" conf.Overwrite = true conf.Module = module conf.ModelFQPN = module + "/" + modelPackageName conf.DaoFQPN = module + "/" + daoPackageName conf.APIFQPN = module + "/" + apiPackageName if conf.ServerPort == 80 { conf.Swagger.Host = conf.ServerHost } else { conf.Swagger.Host = fmt.Sprintf("%s:%d", conf.ServerHost, conf.ServerPort) } return conf }