yt-gen-app/lib/templ/template.go
Ymnuk 73f2b83112
All checks were successful
continuous-integration/drone/tag Build is passing
Исправление типов в файле миграции БД
2023-09-01 10:39:12 +03:00

498 lines
12 KiB
Go

package templ
import (
"bufio"
"bytes"
"embed"
"errors"
"fmt"
"log"
"os"
"path/filepath"
"regexp"
"strings"
"text/template"
"git.ymnuktech.ru/ymnuk/yt-gen-app/structs"
uuid "github.com/satori/go.uuid"
)
//go:embed tmpl/*
var Content embed.FS
var funcMap = template.FuncMap{
"fieldName": FieldName,
"fieldChildName": FieldChildName,
"fieldNamePrepare": FieldNamePrepare,
"fieldNameLowerPrepare": FieldNameLowerPrepare,
"fieldJsonNameStr": FieldJsonNameStr,
"fieldType": FieldType,
"fieldStringToType": FieldStringToType,
//"fieldDbTableType": FieldDbTableType,
"fieldTypeParentTable": FieldTypeParentTable,
"hasFieldType": HasFieldType,
"fieldDescript": FieldDescript,
"configParamName": ConfigParamName,
"configParamType": ConfigParamType,
"configParamTag": ConfigParamTag,
"packageName": PackageName,
"methodNameGetId": MethodNameGetId,
"methodSummary": MethodSummary,
"methodComment": MethodComment,
"getModelName": GetModelName,
"getModelNameAngular": GetModelNameAngular,
"displayMethodNamePost": DisplayMethodNamePost,
"methodNamePost": MethodNamePost,
"displayMethodNameGet": DisplayMethodNameGet,
"methodNameGet": MethodNameGet,
"isMethod": IsMethod,
"roles": Roles,
"removeFirstChar": RemoveFirstChar,
"angularRestName": AngularRestName,
"angularFilename": AngularFilename,
"getFieldsByModelID": GetFieldsByModelID,
"getFksByModelID": GetFksByModelID,
"getFksByModelID2": GetFksByModelID2,
"fieldToVisField": FieldToVisField,
"fieldToVisField2": FieldToVisField2,
"fieldJsonDescriptionStrClear": FieldJsonDescriptionStrClear,
"backendFsPath": BackendFsPath,
"parseRestPath": ParseRestPath,
"parseRestPathForName": ParseRestPathForName,
"parseRestPathParams": ParseRestPathParams,
"fieldInTableByName": FieldInTableByName,
}
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.SetFlags(log.Llongfile)
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 FieldChildName(field *structs.Field) string {
return FieldName(field)
}
// Возвращает имя в БД
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 FieldTypeParentTable(field *structs.Field) string {
return FieldType(&structs.Field{Type: field.TypeParentTable})
}
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"
case "bool":
return "*bool"
case "any":
return "[]byte"
default:
fkTmp := &structs.Field{
Name: field.Type,
}
return FieldName(fkTmp)
//log.Fatalf("Unknow format %s", field.Type)
}
//return ""
}
func FieldDbTableType(field *structs.Field) string {
return FieldNamePrepare(FieldDBName(&structs.Field{
Name: field.Type,
}))
}
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 || field.TypeParentTable == 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"
case "bool":
return "int"
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(ParseRestPathForName(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(ParseRestPathForName(value), "/", "-")
if []rune(value)[0] == '-' {
value = string([]rune(value)[1:])
}
return value
}
func RemoveFirstChar(value string) string {
value = strings.Trim(value, " ")
if value == "" {
return ""
}
runes := []rune(value)
if runes[0] == '-' || runes[0] == '/' || runes[0] == '\\' || runes[0] == '_' || runes[0] == '*' {
value = string(runes[1:])
} else {
value = string(runes)
}
return value
}
func GetFieldsByModelID(project *structs.Project, id uuid.UUID) []structs.Field {
tmpSrc := FindSourceDataInDBByID(project, id)
if tmpSrc != nil {
return tmpSrc.Fields
}
tmpInterface := FindSourceDataInInterfaceByID(project, id)
if tmpInterface != nil {
return tmpInterface.Fields
}
return nil
}
func GetFksByModelID(project *structs.Project, id uuid.UUID) []structs.Field {
tmpSrc := FindSourceDataInDBByID(project, id)
if tmpSrc != nil {
return tmpSrc.FkFields
}
return nil
}
func GetFksByModelID2(project *structs.Project, id uuid.UUID) []structs.FK {
tmpSrc := FindSourceDataInDBByID(project, id)
if tmpSrc != nil {
return tmpSrc.FKs
}
return nil
}
func GetFieldsByModelName(project *structs.Project, name string) []structs.Field {
tmpSrc := FindSourceDataInDBByName(project, name)
if tmpSrc != nil {
return tmpSrc.Fields
}
tmpInterface := FindSourceDataInInterfaceByName(project, name)
if tmpInterface != nil {
return tmpInterface.Fields
}
return nil
}
func FieldToVisField(field structs.Field) (res structs.VisField) {
res.Name = field.Name
res.ID = field.ID
// fmt.Println(res)
return
}
func FieldToVisField2(field structs.FK) (res structs.VisField) {
res.Name = field.Name
res.ID = field.TableID
// fmt.Println(res)
return
}
func FieldJsonDescriptionStrClear(value string) string {
return strings.ReplaceAll(strings.ReplaceAll(value, "\"", ""), "\\", "")
}