package templ import ( "bufio" "bytes" "embed" "errors" "fmt" "log" "os" "path/filepath" "regexp" "strings" "text/template" "git.ymnuktech.ru/ymnuk/yt-gen-app/structs" ) //go:embed tmpl/* var Content embed.FS var funcMap = template.FuncMap{ "fieldName": FieldName, "fieldNamePrepare": FieldNamePrepare, "fieldNameLowerPrepare": FieldNameLowerPrepare, "fieldType": FieldType, "hasFieldType": HasFieldType, "fieldDescript": FieldDescript, "configParamName": ConfigParamName, "configParamType": ConfigParamType, "configParamTag": ConfigParamTag, "packageName": PackageName, "methodNameGetId": MethodNameGetId, "methodSummary": MethodSummary, "methodComment": MethodComment, "getModelName": GetModelName, "displayMethodNamePost": DisplayMethodNamePost, "methodNamePost": MethodNamePost, "displayMethodNameGet": DisplayMethodNameGet, "methodNameGet": MethodNameGet, "isMethod": IsMethod, "roles": Roles, "removeFirstChar": RemoveFirstChar, "angularRestName": AngularRestName, "angularFilename": AngularFilename, } func IsMethod(arr map[string][]string, method string) bool { if arr == nil { return false } _, ok := arr[method] return ok } func Roles(arr map[string][]string, method string) []string { if arr == nil { return nil } return arr[method] } func FieldNamePrepare(value string) string { value = strings.Trim(value, " ") if value == "" { log.Fatal("Should be set name for field") } asRunes := []rune(value) asRunes[0] = []rune(strings.ToUpper(string([]rune(value)[0])))[0] value = string(asRunes) i := strings.Index(value, "_") for i != -1 { asRunes := []rune(value) if i >= len(value) { break } asRunes[i+1] = []rune(strings.ToUpper(string(asRunes[i+1])))[0] asRunes = append(asRunes[:i], asRunes[i+1:]...) value = string(asRunes) i = strings.Index(value, "_") } return value } func FieldNameLowerPrepare(value string) string { var regexpForReplace = regexp.MustCompile(`([A-Z])`) value = strings.ToLower(regexpForReplace.ReplaceAllString(value, "_$1")) if []rune(value)[0] == '_' { value = string([]rune(value)[1:]) } value = strings.ReplaceAll(value, "i_d", "id") return value } func FieldName(field *structs.Field) string { if field == nil { log.Fatal("Field is null") } field.Name = strings.Trim(field.Name, " ") if field.Name == "" { log.Fatal("Should be set name for field") } field.Name = FieldNamePrepare(field.Name) return field.Name } // Возвращает имя в БД func FieldDBName(field *structs.Field) (res string) { res = strings.Trim(field.Name, " ") if res == "" { log.Fatal("Shoudl be set name for field") } //res = strings.ToLower(res) res = FieldNameLowerPrepare(res) return } func FieldType(field *structs.Field) string { if field == nil { log.Fatal("field is empty") } field.Type = strings.ToLower(strings.Trim(field.Type, " ")) if field.Type == "" { field.Type = "text" } switch field.Type { case "text": return "*string" case "string": return "*string" case "int": return "*int" case "bigint": return "*int64" case "double": return "*float64" case "float": return "*float32" case "uuid": return "*uuid.UUID" case "date": return "*time.Time" case "time": return "*time.Time" default: log.Fatalf("Unknow format %s", field.Type) } return "" } func HasFieldType(fields []structs.Field, typeName string) (has bool) { for _, field := range fields { if (field.Type == "date" || field.Type == "time") && (typeName == "date" || typeName == "time") { return true } if field.Type == typeName { return true } } return false } func FieldTypeDB(field *structs.Field) string { field.Type = strings.ToLower(strings.Trim(field.Type, " ")) switch field.Type { case "text": return "TEXT" case "string": tmp := "VARCHAR" if field.Length != nil && *field.Length == 0 { tmp += fmt.Sprintf("(%d)", *field.Length) } else { tmp += "(255)" } //return "TEXT" return tmp case "int": return "INT" case "bigint": return "BIGINT" case "uuid": return "UUID" case "float": return "FLOAT" case "double": return "DOUBLE" case "date": return "DATE" case "time": return "timestamp" default: log.Fatalf("Unknow format %s", field.Type) } return "" } // Генерирование описания таблиц в БД func FieldDescript(field *structs.Field, fieldId bool) (str string) { str = "`" if fieldId { str = fmt.Sprintf("`gorm:\"column:%s;type:%s", FieldDBName(field), FieldTypeDB(field)) field.Description = strings.Trim(field.Description, " ") if field.Description != "" { str += fmt.Sprintf(";comment:%s", field.Description) } str += "\"" } if fieldId { str = fmt.Sprintf("%s json:\"%sId,omitempty\"`", str, FieldJsonName(field)) } else { str = fmt.Sprintf("%s json:\"%s,omitempty\"`", str, FieldJsonName(field)) } return } // Вернуть название параметра func ConfigParamName(field *structs.ParamConfig) string { if field == nil { log.Fatal("Field is null") } field.Name = strings.Trim(field.Name, " ") if field.Name == "" { log.Fatal("Should be set name for field") } return FieldNamePrepare(field.Name) } // Вернуть тип параметра func ConfigParamType(field *structs.ParamConfig) string { if field == nil { log.Fatal("Param should be set") } field.Type = strings.Trim(field.Type, " ") if field.Type == "" { log.Fatal("Param type should be set") } switch field.Type { case "string": return "string" default: log.Fatal("Unknow type") } return "" } // Вернуть строку для тэгирования параметров func ConfigParamTag(field *structs.ParamConfig) string { if field == nil { log.Fatal("Param should be set") } if field == nil { log.Fatal("Field is null") } field.Name = strings.Trim(field.Name, " ") if field.Name == "" { log.Fatal("Shoudl be set name for field") } tag := fmt.Sprintf("`arg:\"--%s,env:%s\"", strings.ReplaceAll(strings.ToLower(field.Name), "_", "-"), strings.ReplaceAll(strings.ToUpper(field.Name), "-", "_")) field.Help = strings.Trim(field.Help, " ") if field.Help != "" { tag += fmt.Sprintf(" help:\"%s\"", field.Help) } tag += "`" // TODO return tag } func WriteTmplFile(filename string, outname string) error { fmt.Printf("Generate: %s\n", outname) if buff, err := Content.ReadFile(filename); err != nil { return err } else { if err = os.WriteFile(outname, buff, 0755); err != nil { return err } } return nil } // Использование шаблона func PrepareTmplFile(filename string, data interface{}, outname string) (err error) { dir := filepath.Dir(outname) if err = MkdirIsNotExists(dir); err != nil { return err } fmt.Printf("Generate: %s\n", outname) var ( buff []byte ) if buff, err = Content.ReadFile(filename); err != nil { return err } var ( tmp string tmpl *template.Template ) if tmp, err = RandomHex(4); err != nil { return err } if tmpl, err = template.New(tmp).Funcs(funcMap).Parse(string(buff)); err != nil { return err } var b bytes.Buffer w := bufio.NewWriter(&b) if err = tmpl.Execute(w, data); err != nil { return err } w.Flush() if err = os.WriteFile(outname, b.Bytes(), 0755); err != nil { return err } return } func PrepareTmplIsNotExists(filename string, data interface{}, outname string) (err error) { if err = MkdirIsNotExists(filepath.Dir(outname)); err != nil { return } if _, err := os.Stat(outname); errors.Is(err, os.ErrNotExist) { return PrepareTmplFile(filename, data, outname) } return nil } func MkdirIsNotExists(pathdir string) (err error) { if _, err = os.Stat(pathdir); os.IsNotExist(err) { if err = os.MkdirAll(pathdir, 0775); err != nil { return } } err = nil return } func AngularRestName(tmp string) string { value := tmp value = strings.Trim(value, " ") if value == "" { return "Unknow" } value = strings.ReplaceAll(value, "/", "_") value = FieldNamePrepare(value) /*var regexpForReplace = regexp.MustCompile(`_([a-z])`) value = strings.ToUpper(regexpForReplace.ReplaceAllString(value, `$1`)) asRunes := []rune(value) asRunes[0] = []rune(strings.ToUpper(string([]rune(value)[0])))[0] value = string(asRunes)*/ return value } func AngularFilename(value string) string { value = strings.Trim(value, " ") if value == "" { return "unknow" } value = strings.ReplaceAll(value, "/", "-") if []rune(value)[0] == '-' { value = string([]rune(value)[1:]) } return value } func RemoveFirstChar(value string) string { value = strings.Trim(value, " ") if value == "" { return "" } value = string([]rune(value)[1:]) return value }