Подготовка некоторых функций для моделей
This commit is contained in:
parent
3097759c96
commit
709f842952
|
@ -5,4 +5,11 @@ db:
|
|||
pk: uuid
|
||||
fields:
|
||||
- name: f1
|
||||
- name: test2
|
||||
pk: int
|
||||
fields:
|
||||
- name: f1
|
||||
- name: f2
|
||||
fks:
|
||||
- name: test1
|
||||
|
|
@ -11,8 +11,8 @@ func Backend() {
|
|||
generateDB()
|
||||
}
|
||||
|
||||
// Генерирование структуры БД
|
||||
func generateDB() {
|
||||
// TODO
|
||||
if err := os.MkdirAll(filepath.Join(AppConfig.OutdirBackend, "db", "model"), 0775); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
@ -30,6 +30,9 @@ func generateModelBase() {
|
|||
if err := WriteTmplFile("tmpl/backend/db/transaction.tmpl", filepath.Join(AppConfig.OutdirBackend, "db", "transaction.go")); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := PrepareTmplFile("tmpl/backend/go.tmpl", Project, filepath.Join(AppConfig.OutdirBackend, "go.mod")); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := PrepareTmplFile("tmpl/backend/db/db.tmpl", Project, filepath.Join(AppConfig.OutdirBackend, "db", "db.go")); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
var AppConfig struct {
|
||||
IsYaml bool
|
||||
IsJson bool
|
||||
IsHelp bool
|
||||
|
||||
Help bool // Вывести справку на экран
|
||||
Filename string // Файл с метоописанием в формате YAML или JSON
|
||||
|
@ -28,20 +29,13 @@ func parseArgs() {
|
|||
flag.StringVar(&AppConfig.Filename, "metafile", "", "Путь к файлу с описанием для генерации кода")
|
||||
flag.StringVar(&AppConfig.OutdirBackend, "outdir-backend", "", "Путь к директории для сохранения генерируемого кода сервера")
|
||||
flag.StringVar(&AppConfig.OutdirFrontend, "outdir-frontend", "", "Путь к директории для сохранения генерируемого кода клиенат")
|
||||
help := flag.Bool("help", false, "Справка")
|
||||
flag.BoolVar(&AppConfig.IsHelp, "help", false, "Справка")
|
||||
flag.Parse()
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintf(flag.CommandLine.Output(), "Usage of %s:\n", os.Args[0])
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
if help != nil && *help {
|
||||
flag.Usage()
|
||||
os.Exit(0)
|
||||
}
|
||||
if AppConfig.Filename == "" {
|
||||
flag.Usage()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func HelpPrint() {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package lib
|
||||
|
||||
// Генерирование исходного кода для клиента
|
||||
func Frontend() {
|
||||
// TODO
|
||||
}
|
||||
|
|
31
lib/lib_test.go
Normal file
31
lib/lib_test.go
Normal file
|
@ -0,0 +1,31 @@
|
|||
package lib
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.ymnuktech.ru/ymnuk/yt-gen-app/structs"
|
||||
)
|
||||
|
||||
func TestFieldType(t *testing.T) {
|
||||
if fieldDBName(&structs.Field{Name: "Field"}) != "field" {
|
||||
t.Fail()
|
||||
}
|
||||
if fieldDBName(&structs.Field{Name: "Field_NAME"}) != "field_name" {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
if fieldDBName(&structs.Field{Name: "fIELD_nAMe"}) != "field_name" {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestDBModelAttrib(t *testing.T) {
|
||||
str := fieldDescript(&structs.Field{
|
||||
Name: "Field_naME1",
|
||||
Type: "int",
|
||||
Description: "Hello world",
|
||||
})
|
||||
if str != "`gorm:\"column:field_name1;type:INT;comment:Hello world\"`" {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
package lib
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"git.ymnuktech.ru/ymnuk/yt-gen-app/structs"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
|
@ -24,9 +26,32 @@ func PrepareMetadata(project *structs.Project) {
|
|||
}
|
||||
if len(project.DB.Tables[i].Fields) > 0 {
|
||||
for j := range project.DB.Tables[i].Fields {
|
||||
project.DB.Tables[i].Fields[j].Name = fieldDBName(&project.DB.Tables[i].Fields[j])
|
||||
if project.DB.Tables[i].Fields[j].ID == uuid.Nil {
|
||||
project.DB.Tables[i].Fields[j].ID = uuid.NewV4()
|
||||
}
|
||||
project.DB.Tables[i].Fields[j].Type = strings.Trim(project.DB.Tables[i].Fields[j].Type, " ")
|
||||
project.DB.Tables[i].Fields[j].Type = strings.ToLower(project.DB.Tables[i].Fields[j].Type)
|
||||
if project.DB.Tables[i].Fields[j].Type == "" {
|
||||
project.DB.Tables[i].Fields[j].Type = "text"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if project.DB.Tables[i].Recursive {
|
||||
project.DB.Tables[i].FkFields = append(project.DB.Tables[i].FkFields, structs.Field{
|
||||
Name: "parent_id",
|
||||
Description: "Recursive foreign key for self table",
|
||||
})
|
||||
switch project.DB.Tables[i].Pk {
|
||||
case "uuid":
|
||||
project.DB.Tables[i].FkFields[len(project.DB.Tables[i].FkFields)-1].Type = "uuid"
|
||||
case "int":
|
||||
project.DB.Tables[i].FkFields[len(project.DB.Tables[i].FkFields)-1].Type = "bigint"
|
||||
case "bigintint":
|
||||
project.DB.Tables[i].FkFields[len(project.DB.Tables[i].FkFields)-1].Type = "bigint"
|
||||
default:
|
||||
log.Fatalf("Error primary key type '%s' in table '%s'", project.DB.Tables[i].Pk, project.DB.Tables[i].Name)
|
||||
}
|
||||
}
|
||||
if len(project.DB.Tables[i].FKs) > 0 {
|
||||
|
@ -48,6 +73,13 @@ func PrepareMetadata(project *structs.Project) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if project.DB.Tables[i].FKs[j].TableName == "" {
|
||||
log.Fatalf("Error foreign key for '%s' table", project.DB.Tables[i].FKs[j].TableID.String())
|
||||
}
|
||||
project.DB.Tables[i].FkFields = append(project.DB.Tables[i].FkFields, structs.Field{
|
||||
Name: fmt.Sprintf("%s_id", strings.ToLower(project.DB.Tables[i].FKs[j].TableName)),
|
||||
Description: fmt.Sprintf("Foreign key for \"%s\" table", project.DB.Tables[i].FKs[j].TableName),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
102
lib/template.go
102
lib/template.go
|
@ -4,39 +4,117 @@ import (
|
|||
"bufio"
|
||||
"bytes"
|
||||
"embed"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"git.ymnuktech.ru/ymnuk/yt-gen-app/structs"
|
||||
)
|
||||
|
||||
//go:embed tmpl/*
|
||||
var content embed.FS
|
||||
|
||||
var funcMap = template.FuncMap{
|
||||
"fieldName": fieldName,
|
||||
"fieldName": fieldName,
|
||||
"fieldType": fieldType,
|
||||
"fieldDescript": fieldDescript,
|
||||
}
|
||||
|
||||
func fieldName(name string) (res string) {
|
||||
res = strings.Trim(name, " ")
|
||||
if res == "" {
|
||||
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("Shoudl be set name for field")
|
||||
}
|
||||
asRunes := []rune(res)
|
||||
asRunes := []rune(field.Name)
|
||||
|
||||
asRunes[0] = []rune(strings.ToUpper(string([]rune(res)[0])))[0]
|
||||
res = string(asRunes)
|
||||
i := strings.Index(res, "_")
|
||||
asRunes[0] = []rune(strings.ToUpper(string([]rune(field.Name)[0])))[0]
|
||||
field.Name = string(asRunes)
|
||||
i := strings.Index(field.Name, "_")
|
||||
for i != -1 {
|
||||
asRunes := []rune(res)
|
||||
if i >= len(res) {
|
||||
asRunes := []rune(field.Name)
|
||||
if i >= len(field.Name) {
|
||||
break
|
||||
}
|
||||
asRunes[i+1] = []rune(strings.ToUpper(string(asRunes[i+1])))[0]
|
||||
asRunes = append(asRunes[:i-1], asRunes[i+1:]...)
|
||||
res = string(asRunes)
|
||||
i = strings.Index(res, "_")
|
||||
field.Name = string(asRunes)
|
||||
i = strings.Index(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)
|
||||
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"
|
||||
default:
|
||||
log.Fatalf("Unknow format %s", field.Type)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
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"
|
||||
default:
|
||||
log.Fatalf("Unknow format %s", field.Type)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Генерирование описания таблиц в БД
|
||||
func fieldDescript(field *structs.Field) (str string) {
|
||||
// TODO
|
||||
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 += "\"`"
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
// This file generated automatic. Do not change this!
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
|
||||
type BaseInt struct {
|
||||
ID uint64 `gorm:"type:autoIncrement;primaryKey" json:"id,omitempty"`
|
||||
CreatedAt time.Time `json:"createdAt,omitempty"`
|
||||
UpdatedAt time.Time `json:"updatedAt,omitempty"`
|
||||
// DeletedAt gorm.DeletedAt `sql:"index" json:"deletedAt"`
|
||||
DeletedAt gorm.DeletedAt `sql:"index" json:"deletedAt"`
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// This file generated automatic. Do not change this!
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
|
@ -11,7 +13,7 @@ type Base struct {
|
|||
ID uuid.UUID `gorm:"type:uuid;primary_key;" json:"id,omitempty"`
|
||||
CreatedAt time.Time `json:"createdAt,omitempty"`
|
||||
UpdatedAt time.Time `json:"updatedAt,omitempty"`
|
||||
// DeletedAt gorm.DeletedAt `sql:"index" json:"deletedAt"`
|
||||
DeletedAt gorm.DeletedAt `sql:"index" json:"deletedAt"`
|
||||
}
|
||||
|
||||
// BeforeCreate will set a UUID rather than numeric ID.
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// This file generated automatic. Do not change this!
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
|
@ -13,6 +15,6 @@ type {{.Name}} struct {
|
|||
BaseInt
|
||||
{{ end }}
|
||||
{{ range $index, $field := .Fields }}
|
||||
{{ fieldName $field.Name }} {{ $field.Type }}
|
||||
{{ fieldName $field }} {{ fieldType $field }} {{ fieldDescript $field }}
|
||||
{{ end }}
|
||||
}
|
||||
|
|
3
lib/tmpl/backend/go.tmpl
Normal file
3
lib/tmpl/backend/go.tmpl
Normal file
|
@ -0,0 +1,3 @@
|
|||
module {{ .Name }}
|
||||
|
||||
go 1.20
|
14
main.go
14
main.go
|
@ -2,6 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
|
@ -10,11 +11,16 @@ import (
|
|||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func init() {
|
||||
lib.PrepareParams()
|
||||
}
|
||||
|
||||
func main() {
|
||||
lib.PrepareParams()
|
||||
if lib.AppConfig.IsHelp {
|
||||
flag.Usage()
|
||||
os.Exit(0)
|
||||
}
|
||||
if lib.AppConfig.Filename == "" {
|
||||
flag.Usage()
|
||||
os.Exit(0)
|
||||
}
|
||||
lib.Project = &structs.Project{}
|
||||
if _, err := os.Stat(lib.AppConfig.Filename); os.IsNotExist(err) {
|
||||
log.Fatal(`Метафайл не найден`)
|
||||
|
|
|
@ -15,14 +15,15 @@ type Table struct {
|
|||
Pk string `yaml:"pk,omitempty" json:"pk,omitempty"` // Тип первичного ключа. Если uuid, то генерируется V4, int и bigint - используется bigint с автоинкрементом, string - первичный ключ как текстовое поле. Если не указано, то поумолчанию используется UUID
|
||||
Description string `yaml:"description,omitempty" json:"description,omitempty"` // Описание таблицы
|
||||
Fields []Field `yaml:"fields,omitempty" json:"fields,omitempty"` // Поля таблицы
|
||||
Recursive bool `yaml:"recursive,omitempty" json:"recursive,omitempty"` // Рекурсивная таблица
|
||||
FKs []FK `yaml:"fks,omitempty" json:"fks,omitempty"` // Внешние ключи
|
||||
FkFields []Field `yaml:"-" json:"-"` // Поля с описанием внешних ключей
|
||||
}
|
||||
|
||||
// Описание поля
|
||||
type Field struct {
|
||||
ID uuid.UUID `yaml:"id,omitempty" json:"id,omitempty"` // Идентификатор поля. Если пустой, то генерируется автоматически для дальнейше работы
|
||||
Name string `yaml:"name,omitempty" json:"name,omitempty"` // Название поля
|
||||
Recursive bool `yaml:"recursive,omitempty" json:"recursive,omitempty"` // Рекурсивная таблица
|
||||
Type string `yaml:"type,omitempty" json:"type,omitempty"` // Тип поля. По умолчанию text
|
||||
Length *int `yaml:"length,omitempty" json:"len,omitempty"` // Размер поля для строковых типов и Decimal
|
||||
Accuracy *int `yaml:"accuracy,omitempty" json:"accuracy,omitempty"` // Точность поля для Decimal
|
||||
|
|
Loading…
Reference in New Issue
Block a user