yt-gen-app/lib/templ/template.go

571 lines
13 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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{
//"includeTemplPart": IncludeTemplPart,
"fieldName": FieldName,
"fieldChildName": FieldChildName,
"fieldNamePrepare": FieldNamePrepare,
"fieldNameLowerPrepare": FieldNameLowerPrepare,
"fieldJsonNameStr": FieldJsonNameStr,
"fieldType": FieldType,
"fieldTypeStr": FieldTypeStr,
"fieldStringToType": FieldStringToType,
//"fieldDbTableType": FieldDbTableType,
"fieldTypeDB": FieldTypeDB,
"fieldTypeDBStr": FieldTypeDBStr,
"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,
"escapeChars": EscapeChars,
}
func EscapeChars(value string) string {
value = strings.ReplaceAll(value, "/", "\\/")
return value
}
func IncludeTemplPart(templName string, data interface{}) string {
var err error
var tmpl *template.Template
if tmpl, err = ReadTmplFile(templName); err != nil {
panic(err)
}
var out []byte
if out, err = ExecuteTmplFile(tmpl, data); err != nil {
panic(err)
}
/*arr:=strings.Split(string(out))
var newArr []string
for*/
return string(out)
}
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, "_")
}
var regexpForReplace = regexp.MustCompile(`([Ii][Dd]$)`)
value = regexpForReplace.ReplaceAllString(value, "ID")
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 FieldTypeStr(value string) string {
value = strings.ToLower(strings.Trim(value, " "))
if value == "" {
return value
}
switch value {
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: value,
}
return FieldName(fkTmp)
//log.Fatalf("Unknow format %s", field.Type)
}
}
func FieldType(field *structs.Field) string {
if field == nil {
log.Fatal("field is empty")
}
field.Type = strings.ToLower(strings.Trim(field.Type, " "))
value := FieldTypeStr(field.Type)
if value == "" {
field.Type = "text"
value = "text"
}
return value
//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 FieldTypeDBStr(value string, length *int) string {
switch value {
case "text":
return "TEXT"
case "string":
tmp := "VARCHAR"
if length != nil && *length == 0 {
tmp += fmt.Sprintf("(%d)", *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", value)
}
return ""
}
func FieldTypeDB(field *structs.Field) string {
field.Type = strings.ToLower(strings.Trim(field.Type, " "))
return FieldTypeDBStr(field.Type, field.Length)
}
// Генерирование описания таблиц в БД
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 += "`"
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 ReadTmplFile(filename string) (tmpl *template.Template, err error) {
var (
buff []byte
)
if buff, err = Content.ReadFile(filename); err != nil {
return
}
var (
tmp string
//tmpl *template.Template
)
if tmp, err = RandomHex(4); err != nil {
return
}
if _, ok := funcMap["includeTemplPart"]; !ok {
funcMap["includeTemplPart"] = IncludeTemplPart
}
tmpl, err = template.New(tmp).Funcs(funcMap).Parse(string(buff))
return
}
// Запись файла на диск
func WriteFile(outname string, data []byte) (err error) {
err = os.WriteFile(outname, data, 0755)
return
}
// Выполнить шаблон
func ExecuteTmplFile(tmpl *template.Template, data interface{}) (out []byte, err error) {
var b bytes.Buffer
w := bufio.NewWriter(&b)
if err = tmpl.Execute(w, data); err != nil {
return
}
w.Flush()
out = b.Bytes()
return
}
// Использование шаблона
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 b bytes.Buffer
w := bufio.NewWriter(&b)*/
var tmpl *template.Template
if tmpl, err = ReadTmplFile(filename); err != nil {
return
}
/*if err = tmpl.Execute(w, data); err != nil {
return err
}
w.Flush()*/
var out []byte
if out, err = ExecuteTmplFile(tmpl, data); err != nil {
return
}
return WriteFile(outname, out)
}
// Подготовка файла, если его нет на диске
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, "\"", ""), "\\", "")
}