Генерирование с учетом структур
continuous-integration/drone/tag Build is passing
Details
continuous-integration/drone/tag Build is passing
Details
This commit is contained in:
parent
03127a0ee0
commit
4631b5973e
10
README.md
10
README.md
|
@ -34,4 +34,12 @@ java -jar swagger-codegen-cli-2.4.32.jar generate -i docs/swagger.json -l typesc
|
|||
|
||||
## Предустановленные списки
|
||||
|
||||
В каждой таблице могут быть предустановленные данные (values). Такие данные являются константными, т.е. во время миграции все бредыдущие записи будут удалены и созданы новые. Все значения справочника подразумеваются как строковые, а генерируемы индетификатор может быть подставлен только UUID. Имена полей должны совпадать.
|
||||
В каждой таблице могут быть предустановленные данные (values). Такие данные являются константными, т.е. во время миграции все бредыдущие записи будут удалены и созданы новые. Все значения справочника подразумеваются как строковые, а генерируемы индетификатор может быть подставлен только UUID. Имена полей должны совпадать.
|
||||
|
||||
# REST
|
||||
|
||||
Если в пути указаны параметры, например */geocoder/tile/:z/:y:x*, то *z*, *x* и *y* являются переменными и они вставляются в параметры path. Все что дальше идет по пути оставляется как есть, а директория в route формируется до переменных и, как в примере, имеет вид *geocoder/tile*
|
||||
|
||||
## data.name
|
||||
|
||||
Если указана binary, то клиенту возвращаются двоичные данные независимо от других условий (картинки, документы и т.д.)
|
|
@ -20,11 +20,13 @@ func generateBackendRest() {
|
|||
if len(Project.Backend.Rest) > 0 {
|
||||
for i := range Project.Backend.Rest {
|
||||
restStruct := &structs.RestStruct{
|
||||
Project: Project,
|
||||
Path: i,
|
||||
Rest: Project.Backend.Rest[i],
|
||||
Project: Project,
|
||||
Path: templ.ParseRestPath(i),
|
||||
PathPackageName: templ.ParseRestPathForName(i),
|
||||
Rest: Project.Backend.Rest[i],
|
||||
PathParams: templ.ParseRestPathParams(i),
|
||||
}
|
||||
destPath := filepath.Join(AppConfig.OutdirBackend, "route", "api", i)
|
||||
destPath := filepath.Join(AppConfig.OutdirBackend, "route", "api", templ.BackendFsPath(i))
|
||||
fmt.Println(destPath)
|
||||
if err := templ.PrepareTmplFile("tmpl/backend/route/api/templ/index.tmpl", restStruct, filepath.Join(destPath, "index.go")); err != nil {
|
||||
log.Fatal(err)
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package lib
|
||||
|
||||
import (
|
||||
"log"
|
||||
"path/filepath"
|
||||
|
||||
"git.ymnuktech.ru/ymnuk/yt-gen-app/lib/templ"
|
||||
)
|
||||
|
||||
func backendGenerateStructs() {
|
||||
if len(Project.Interfaces) > 0 {
|
||||
for i := range Project.Interfaces {
|
||||
err := templ.PrepareTmplFile("tmpl/backend/structs/struct.tmpl",
|
||||
Project.Interfaces[i],
|
||||
filepath.Join(AppConfig.OutdirBackend, "structs", templ.AngularFilename(Project.Interfaces[i].Name)+".go"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@ func Backend() {
|
|||
}
|
||||
}
|
||||
|
||||
backendGenerateStructs()
|
||||
generateDB()
|
||||
generateBackendTmpl()
|
||||
|
||||
|
|
|
@ -54,12 +54,12 @@ func execCommands() {
|
|||
cmd.Dir = filepath.Join(AppConfig.OutdirBackend)
|
||||
//cmd.Output()
|
||||
if buff, err := cmd.Output(); err != nil {
|
||||
log.Fatal(err)
|
||||
log.Fatalf("Error swag init: %s", err)
|
||||
} else {
|
||||
fmt.Println(string(buff))
|
||||
}
|
||||
if cmd.Err != nil {
|
||||
log.Fatal(cmd.Err)
|
||||
log.Fatalf("Error swag init: %s", cmd.Err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -257,15 +257,15 @@ func generateFrontendAngularTmpl() {
|
|||
templs := []structs.TmplInOut{
|
||||
{
|
||||
FileIn: "tmpl/frontend/angular/src/app/page/page/page.component.ts.tmpl",
|
||||
FileOut: filepath.Join(AppConfig.OutdirFrontend, "src", "app", "page", templ.RemoveFirstChar(i), fmt.Sprintf("%s.component.ts", templ.AngularFilename(i))),
|
||||
FileOut: filepath.Join(AppConfig.OutdirFrontend, "src", "app", "page", templ.BackendFsPath(templ.RemoveFirstChar(i)), fmt.Sprintf("%s.component.ts", templ.AngularFilename(i))),
|
||||
},
|
||||
{
|
||||
FileIn: "tmpl/frontend/angular/src/app/page/page/page.component.scss.tmpl",
|
||||
FileOut: filepath.Join(AppConfig.OutdirFrontend, "src", "app", "page", templ.RemoveFirstChar(i), fmt.Sprintf("%s.component.scss", templ.AngularFilename(i))),
|
||||
FileOut: filepath.Join(AppConfig.OutdirFrontend, "src", "app", "page", templ.BackendFsPath(templ.RemoveFirstChar(i)), fmt.Sprintf("%s.component.scss", templ.AngularFilename(i))),
|
||||
},
|
||||
{
|
||||
FileIn: "tmpl/frontend/angular/src/app/page/page/page.component.html.tmpl",
|
||||
FileOut: filepath.Join(AppConfig.OutdirFrontend, "src", "app", "page", templ.RemoveFirstChar(i), fmt.Sprintf("%s.component.html", templ.AngularFilename(i))),
|
||||
FileOut: filepath.Join(AppConfig.OutdirFrontend, "src", "app", "page", templ.BackendFsPath(templ.RemoveFirstChar(i)), fmt.Sprintf("%s.component.html", templ.AngularFilename(i))),
|
||||
},
|
||||
}
|
||||
for _, item := range templs {
|
||||
|
@ -277,15 +277,15 @@ func generateFrontendAngularTmpl() {
|
|||
templs := []structs.TmplInOut{
|
||||
{
|
||||
FileIn: "tmpl/frontend/angular/src/app/page/page/form/form.component.ts.tmpl",
|
||||
FileOut: filepath.Join(AppConfig.OutdirFrontend, "src", "app", "page", templ.RemoveFirstChar(i), "form", fmt.Sprintf("%s-form.component.ts", templ.AngularFilename(i))),
|
||||
FileOut: filepath.Join(AppConfig.OutdirFrontend, "src", "app", "page", templ.BackendFsPath(templ.RemoveFirstChar(i)), "form", fmt.Sprintf("%s-form.component.ts", templ.AngularFilename(i))),
|
||||
},
|
||||
{
|
||||
FileIn: "tmpl/frontend/angular/src/app/page/page/form/form.component.scss.tmpl",
|
||||
FileOut: filepath.Join(AppConfig.OutdirFrontend, "src", "app", "page", templ.RemoveFirstChar(i), "form", fmt.Sprintf("%s-form.component.scss", templ.AngularFilename(i))),
|
||||
FileOut: filepath.Join(AppConfig.OutdirFrontend, "src", "app", "page", templ.BackendFsPath(templ.RemoveFirstChar(i)), "form", fmt.Sprintf("%s-form.component.scss", templ.AngularFilename(i))),
|
||||
},
|
||||
{
|
||||
FileIn: "tmpl/frontend/angular/src/app/page/page/form/form.component.html.tmpl",
|
||||
FileOut: filepath.Join(AppConfig.OutdirFrontend, "src", "app", "page", templ.RemoveFirstChar(i), "form", fmt.Sprintf("%s-form.component.html", templ.AngularFilename(i))),
|
||||
FileOut: filepath.Join(AppConfig.OutdirFrontend, "src", "app", "page", templ.BackendFsPath(templ.RemoveFirstChar(i)), "form", fmt.Sprintf("%s-form.component.html", templ.AngularFilename(i))),
|
||||
},
|
||||
}
|
||||
for _, item := range templs {
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package prepare
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"git.ymnuktech.ru/ymnuk/yt-gen-app/lib/templ"
|
||||
"git.ymnuktech.ru/ymnuk/yt-gen-app/structs"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
func prepareInterfaces(project *structs.Project) *structs.Project {
|
||||
if len(project.Interfaces) == 0 {
|
||||
return project
|
||||
}
|
||||
for i := range project.Interfaces {
|
||||
project.Interfaces[i].Name = strings.Trim(project.Interfaces[i].Name, " ")
|
||||
if project.Interfaces[i].Name == "" {
|
||||
log.Fatal("Name interface is empty")
|
||||
}
|
||||
project.Interfaces[i].Name = templ.FieldNamePrepare(project.Interfaces[i].Name)
|
||||
if project.Interfaces[i].ID == uuid.Nil {
|
||||
project.Interfaces[i].ID = uuid.NewV4()
|
||||
}
|
||||
if len(project.Interfaces[i].Fields) == 0 {
|
||||
continue
|
||||
}
|
||||
for j := range project.Interfaces[i].Fields {
|
||||
project.Interfaces[i].Fields[j].Name = strings.Trim(project.Interfaces[i].Fields[j].Name, " ")
|
||||
if project.Interfaces[i].Fields[j].Name == "" {
|
||||
log.Fatalf("Field in interface %s should be set", project.Interfaces[i].Name)
|
||||
}
|
||||
project.Interfaces[i].Fields[j].Name = templ.FieldNamePrepare(project.Interfaces[i].Fields[j].Name)
|
||||
}
|
||||
}
|
||||
|
||||
return project
|
||||
}
|
|
@ -14,7 +14,7 @@ func PrepareMetadata(project *structs.Project) *structs.Project {
|
|||
if project.Name == "" {
|
||||
log.Fatal("Should be set project name")
|
||||
}
|
||||
|
||||
project = prepareInterfaces(project)
|
||||
project = prepareDB(project)
|
||||
project = prepareRoles(project)
|
||||
project = prepareRest(project)
|
||||
|
|
|
@ -27,9 +27,16 @@ func prepareRest(project *structs.Project) *structs.Project {
|
|||
if project.Backend.Rest[i].Data.Name != "" && project.Backend.Rest[i].Data.ID == uuid.Nil {
|
||||
// Есть имя, но нет ID. Найдем
|
||||
dataArr := strings.Split(project.Backend.Rest[i].Data.Name, ".")
|
||||
if len(dataArr) > 2 {
|
||||
if len(dataArr) > 2 || len(dataArr) < 1 {
|
||||
log.Fatal("Неверно указано имя источника данных в REST. Формат: <db/interface>.<Название>")
|
||||
}
|
||||
if len(dataArr) == 1 {
|
||||
if dataArr[0] == "binary" {
|
||||
project.Backend.Rest[i].Data.ID = uuid.Nil
|
||||
} else {
|
||||
log.Fatal("Неверно указано имя источника данных в REST. Формат: <db/interface>.<Название>")
|
||||
}
|
||||
}
|
||||
if len(dataArr) == 2 {
|
||||
// Есть интерфейс
|
||||
switch strings.ToLower(dataArr[0]) {
|
||||
|
@ -70,7 +77,7 @@ func prepareRest(project *structs.Project) *structs.Project {
|
|||
for j := range project.Backend.Rest[i].Edit {
|
||||
if project.Backend.Rest[i].Edit[j].ID == uuid.Nil {
|
||||
tmp := templ.FindFieldIdInInterfaceByName(project, project.Backend.Rest[i].Data.ID, project.Backend.Rest[i].Edit[j].Name)
|
||||
project.Backend.Rest[i].Edit[j].ID = tmp.ID //templ.FindFieldIdInInterfaceByName(project, project.Backend.Rest[i].Data.ID, project.Backend.Rest[i].Edit[j].Name)
|
||||
project.Backend.Rest[i].Edit[j].ID = tmp //templ.FindFieldIdInInterfaceByName(project, project.Backend.Rest[i].Data.ID, project.Backend.Rest[i].Edit[j].Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +86,7 @@ func prepareRest(project *structs.Project) *structs.Project {
|
|||
for j := range project.Backend.Rest[i].Filter {
|
||||
if project.Backend.Rest[i].Filter[j].ID == uuid.Nil {
|
||||
tmp := templ.FindFieldIdInInterfaceByName(project, project.Backend.Rest[i].Data.ID, project.Backend.Rest[i].Filter[j].Name)
|
||||
project.Backend.Rest[i].Filter[j].ID = tmp.ID //templ.FindFieldIdInInterfaceByName(project, project.Backend.Rest[i].Data.ID, project.Backend.Rest[i].Filter[j].Name)
|
||||
project.Backend.Rest[i].Filter[j].ID = tmp //templ.FindFieldIdInInterfaceByName(project, project.Backend.Rest[i].Data.ID, project.Backend.Rest[i].Filter[j].Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -90,16 +97,17 @@ func prepareRest(project *structs.Project) *structs.Project {
|
|||
}
|
||||
if len(dataArr) == 1 {
|
||||
// Нет интерфейса, по этому ищем где первым попадется
|
||||
tmpSrc := templ.FindSourceDataInDBByName(project, dataArr[1])
|
||||
project.Backend.Rest[i].Data.ID = tmpSrc.ID
|
||||
//tmpSrc := templ.FindSourceDataInDBByName(project, dataArr[1])
|
||||
/*project.Backend.Rest[i].Data.ID = tmpSrc.ID
|
||||
if project.Backend.Rest[i].Data.ID != uuid.Nil {
|
||||
continue
|
||||
}
|
||||
tmpSrc1 := templ.FindSourceDataInInterfaceByName(project, dataArr[1])
|
||||
}*/
|
||||
/*tmpSrc1 := templ.FindSourceDataInInterfaceByName(project, dataArr[1])
|
||||
project.Backend.Rest[i].Data.ID = tmpSrc1.ID //templ.FindSourceDataInInterfaceByName(project, dataArr[1])
|
||||
if project.Backend.Rest[i].Data.ID == uuid.Nil {
|
||||
log.Fatal("Не найдена структура данных для REST")
|
||||
}
|
||||
}*/
|
||||
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
@ -124,7 +132,7 @@ func prepareRest(project *structs.Project) *structs.Project {
|
|||
}
|
||||
|
||||
for j := range project.Backend.Rest[i].Edit {
|
||||
project.Backend.Rest[i].Edit[j].Name = templ.FindFieldNameInInterfaceById(project, project.Backend.Rest[i].Data.ID, project.Backend.Rest[i].Edit[j].ID)
|
||||
project.Backend.Rest[i].Edit[j].Name = templ.FindFieldNameInTableById(project, project.Backend.Rest[i].Data.ID, project.Backend.Rest[i].Edit[j].ID)
|
||||
}
|
||||
for j := range project.Backend.Rest[i].Filter {
|
||||
project.Backend.Rest[i].Edit[j].Name = templ.FindFieldNameInInterfaceById(project, project.Backend.Rest[i].Data.ID, project.Backend.Rest[i].Filter[j].ID)
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
package templ
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"git.ymnuktech.ru/ymnuk/yt-gen-app/structs"
|
||||
)
|
||||
|
||||
func BackendFsPath(value string) string {
|
||||
pathArr := strings.Split(RemoveFirstChar(value), "/")
|
||||
var newPathArr []string
|
||||
if len(pathArr) > 0 {
|
||||
for _, str := range pathArr {
|
||||
if []rune(str)[0] != ':' {
|
||||
newPathArr = append(newPathArr, str)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return strings.Join(newPathArr, "/")
|
||||
}
|
||||
|
||||
func ParseRestPath(value string) string {
|
||||
pathArr := strings.Split(RemoveFirstChar(value), "/")
|
||||
var newPathArr []string
|
||||
if len(pathArr) > 0 {
|
||||
for _, str := range pathArr {
|
||||
runes := []rune(str)
|
||||
if runes[0] == ':' {
|
||||
if len(runes) <= 1 {
|
||||
log.Fatalf("Error value in path \"%s\"", value)
|
||||
}
|
||||
runes = runes[1:]
|
||||
newPathArr = append(newPathArr, fmt.Sprintf("{%s}", string(runes)))
|
||||
} else {
|
||||
newPathArr = append(newPathArr, str)
|
||||
}
|
||||
}
|
||||
}
|
||||
return strings.Join(newPathArr, "/")
|
||||
}
|
||||
|
||||
func ParseRestPathForName(value string) string {
|
||||
pathArr := strings.Split(RemoveFirstChar(value), "/")
|
||||
var newPathArr []string
|
||||
if len(pathArr) > 0 {
|
||||
for _, str := range pathArr {
|
||||
runes := []rune(str)
|
||||
if runes[0] != ':' {
|
||||
if len(runes) <= 1 {
|
||||
log.Fatalf("Error value in path \"%s\"", value)
|
||||
}
|
||||
newPathArr = append(newPathArr, string(runes))
|
||||
}
|
||||
}
|
||||
}
|
||||
return strings.Join(newPathArr, "/")
|
||||
}
|
||||
|
||||
func ParseRestPathParams(value string) (res []structs.Field) {
|
||||
pathArr := strings.Split(RemoveFirstChar(value), "/")
|
||||
//var newPathArr []string
|
||||
if len(pathArr) > 0 {
|
||||
for _, str := range pathArr {
|
||||
runes := []rune(str)
|
||||
if runes[0] == ':' {
|
||||
if len(runes) <= 1 {
|
||||
log.Fatalf("Error value in path \"%s\"", value)
|
||||
}
|
||||
runes = runes[1:]
|
||||
res = append(res, structs.Field{
|
||||
Name: string(runes),
|
||||
Type: "string",
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
package templ
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"git.ymnuktech.ru/ymnuk/yt-gen-app/structs"
|
||||
|
@ -73,26 +72,48 @@ func FindFieldNameInDBById(project *structs.Project, tblID uuid.UUID, fldId uuid
|
|||
}
|
||||
|
||||
func FindSourceDataInInterfaceByName(project *structs.Project, name string) *structs.Interface {
|
||||
// TODO
|
||||
log.Fatal("Функция в разработки")
|
||||
if len(project.Interfaces) == 0 {
|
||||
return nil
|
||||
}
|
||||
for i := range project.Interfaces {
|
||||
if project.Interfaces[i].Name == FieldNamePrepare(name) {
|
||||
return &project.Interfaces[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func FindSourceDataInInterfaceByID(project *structs.Project, id uuid.UUID) *structs.Interface {
|
||||
// TODO
|
||||
log.Fatal("Функция в разработки")
|
||||
if len(project.Interfaces) == 0 {
|
||||
return nil
|
||||
}
|
||||
for i := range project.Interfaces {
|
||||
if project.Interfaces[i].ID == id {
|
||||
return &project.Interfaces[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Найти ID поля по имени
|
||||
func FindFieldIdInInterfaceByName(project *structs.Project, tblID uuid.UUID, fldName string) *structs.Field {
|
||||
// TODO
|
||||
log.Fatal("Функция в разработки")
|
||||
return nil
|
||||
func FindFieldIdInInterfaceByName(project *structs.Project, interfaceID uuid.UUID, fldName string) uuid.UUID {
|
||||
if len(project.Interfaces) == 0 {
|
||||
return uuid.Nil
|
||||
}
|
||||
for i := range project.Interfaces {
|
||||
if project.Interfaces[i].ID == interfaceID {
|
||||
for j := range project.Interfaces[i].Fields {
|
||||
if project.Interfaces[i].Fields[j].Name == strings.ToLower(fldName) {
|
||||
return project.Interfaces[i].Fields[j].ID
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return uuid.Nil
|
||||
}
|
||||
|
||||
// Найти имя поля в интерфейсе по ID
|
||||
func FindFieldNameInInterfaceById(project *structs.Project, tblID uuid.UUID, fldId uuid.UUID) string {
|
||||
func FindFieldNameInTableById(project *structs.Project, tblID uuid.UUID, fldId uuid.UUID) string {
|
||||
if len(project.DB.Tables) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
@ -107,3 +128,20 @@ func FindFieldNameInInterfaceById(project *structs.Project, tblID uuid.UUID, fld
|
|||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Найти имя поля в интерфейсе по ID
|
||||
func FindFieldNameInInterfaceById(project *structs.Project, interfaceID uuid.UUID, fldId uuid.UUID) string {
|
||||
if len(project.DB.Tables) == 0 {
|
||||
return ""
|
||||
}
|
||||
for i := range project.Interfaces {
|
||||
if project.Interfaces[i].ID == interfaceID {
|
||||
for j := range project.Interfaces[i].Fields {
|
||||
if project.Interfaces[i].Fields[j].ID == fldId {
|
||||
return project.Interfaces[i].Fields[j].Name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
|
|
@ -20,6 +20,9 @@ func MethodComment(value string) string {
|
|||
}
|
||||
|
||||
func GetModelName(project *structs.Project, value structs.VisField) string {
|
||||
if value.Name == "binary" {
|
||||
return "[]byte"
|
||||
}
|
||||
if project == nil {
|
||||
log.Fatal("project is null")
|
||||
}
|
||||
|
@ -28,6 +31,11 @@ func GetModelName(project *structs.Project, value structs.VisField) string {
|
|||
return fmt.Sprintf("model.%s", FieldNamePrepare(tbl.Name))
|
||||
}
|
||||
}
|
||||
for _, interf := range project.Interfaces {
|
||||
if interf.ID == value.ID {
|
||||
return fmt.Sprintf("structs.%s", FieldNamePrepare(interf.Name))
|
||||
}
|
||||
}
|
||||
log.Fatal("model not found")
|
||||
return ""
|
||||
}
|
||||
|
@ -36,11 +44,19 @@ func GetModelNameAngular(project *structs.Project, value structs.VisField) strin
|
|||
if project == nil {
|
||||
log.Fatal("project is null")
|
||||
}
|
||||
if value.Name == "binary" {
|
||||
return "any"
|
||||
}
|
||||
for _, tbl := range project.DB.Tables {
|
||||
if tbl.ID == value.ID {
|
||||
return fmt.Sprintf("Model%s", FieldNamePrepare(tbl.Name))
|
||||
}
|
||||
}
|
||||
for _, interf := range project.Interfaces {
|
||||
if interf.ID == value.ID {
|
||||
return fmt.Sprintf("Structs%s", FieldNamePrepare(interf.Name))
|
||||
}
|
||||
}
|
||||
log.Fatal("model not found")
|
||||
return ""
|
||||
}
|
||||
|
|
|
@ -10,7 +10,8 @@ func PackageName(name string) string {
|
|||
if name == "" {
|
||||
log.Fatal("Пустое название пакета")
|
||||
}
|
||||
name = strings.ReplaceAll(name, "/", "_")
|
||||
name = BackendFsPath(name)
|
||||
name = "_" + strings.ReplaceAll(name, "/", "_")
|
||||
if []rune(name)[0] == '/' {
|
||||
name = string([]rune(name)[1:])
|
||||
}
|
||||
|
|
|
@ -62,6 +62,11 @@ var funcMap = template.FuncMap{
|
|||
"fieldToVisField": FieldToVisField,
|
||||
"fieldToVisField2": FieldToVisField2,
|
||||
"fieldJsonDescriptionStrClear": FieldJsonDescriptionStrClear,
|
||||
|
||||
"backendFsPath": BackendFsPath,
|
||||
"parseRestPath": ParseRestPath,
|
||||
"parseRestPathForName": ParseRestPathForName,
|
||||
"parseRestPathParams": ParseRestPathParams,
|
||||
}
|
||||
|
||||
func IsMethod(arr map[string][]string, method string) bool {
|
||||
|
@ -173,6 +178,8 @@ func FieldType(field *structs.Field) string {
|
|||
return "*time.Time"
|
||||
case "bool":
|
||||
return "*bool"
|
||||
case "any":
|
||||
return "[]byte"
|
||||
default:
|
||||
fkTmp := &structs.Field{
|
||||
Name: field.Type,
|
||||
|
@ -390,7 +397,7 @@ func AngularRestName(tmp string) string {
|
|||
return "Unknow"
|
||||
}
|
||||
|
||||
value = strings.ReplaceAll(value, "/", "_")
|
||||
value = strings.ReplaceAll(ParseRestPathForName(value), "/", "_")
|
||||
|
||||
value = FieldNamePrepare(value)
|
||||
|
||||
|
@ -408,7 +415,7 @@ func AngularFilename(value string) string {
|
|||
if value == "" {
|
||||
return "unknow"
|
||||
}
|
||||
value = strings.ReplaceAll(value, "/", "-")
|
||||
value = strings.ReplaceAll(ParseRestPathForName(value), "/", "-")
|
||||
if []rune(value)[0] == '-' {
|
||||
value = string([]rune(value)[1:])
|
||||
}
|
||||
|
@ -421,7 +428,7 @@ func RemoveFirstChar(value string) string {
|
|||
return ""
|
||||
}
|
||||
runes := []rune(value)
|
||||
if runes[0] == '-' || runes[0] == '/' || runes[0] == '\\' || runes[0] == '_' {
|
||||
if runes[0] == '-' || runes[0] == '/' || runes[0] == '\\' || runes[0] == '_' || runes[0] == '*' {
|
||||
value = string(runes[1:])
|
||||
} else {
|
||||
value = string(runes)
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"{{ .Name }}/route/api/user"
|
||||
"{{ .Name }}/structs"
|
||||
{{ range $index, $table := .Backend.Rest }}
|
||||
{{ packageName $index}} "{{ $.Name }}/route/api{{ $index }}"
|
||||
{{ packageName $index}} "{{ $.Name }}/route/api/{{ backendFsPath $index }}"
|
||||
{{ end }}
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package {{ packageName .Path }}
|
||||
package {{ packageName .PathPackageName }}
|
||||
|
||||
import (
|
||||
|
||||
|
@ -21,18 +21,20 @@ func Init(c *echo.Group) {
|
|||
{{ end }}
|
||||
}
|
||||
|
||||
// Get{{ methodNameGetId .Path }} get{{ methodNameGetId .Path }}
|
||||
{{ $methodName := packageName .PathPackageName }}
|
||||
|
||||
// Get{{ fieldNamePrepare $methodName }} get{{ fieldNamePrepare $methodName }}
|
||||
// @Summary {{ .Rest.Summary }}
|
||||
// @Description {{ .Rest.Comment }}
|
||||
// @Tags {{ .Rest.GroupName }}
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Produce json{{ range $index, $param := .Rest.ParamQuery }}{{ "\n" }}// @Param {{ fieldJsonNameStr $param.Name }} query {{ $typeParamName := fieldType $param }}{{ removeFirstChar $typeParamName }} false "{{ fieldJsonNameStr $param.Name }}"{{ end }}{{ range $index, $param := .PathParams }}{{ "\n" }}// @Param {{ fieldJsonNameStr $param.Name }} query {{ $typeParamName := fieldType $param }}{{ removeFirstChar $typeParamName }} false "{{ fieldJsonNameStr $param.Name }}"{{ end }}
|
||||
// @Success 200 {object} []{{ getModelName .Project .Rest.Data }}
|
||||
// @Failure 400 {object} structs.Result
|
||||
// @Failure 401 {object} structs.Result
|
||||
// @Failure 404 {object} structs.Result
|
||||
// @Failure 500 {object} structs.Result
|
||||
// @Router {{ .Path }} [get]
|
||||
// @Router /{{ .Path }} [get]
|
||||
// @Security BearerAuth
|
||||
func list(c echo.Context) error {
|
||||
user := c.Get("user").(*jwt.Token)
|
||||
|
@ -62,12 +64,13 @@ func list(c echo.Context) error {
|
|||
// @Tags {{ .Rest.GroupName }}
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Produce json{{ range $index, $param := .Rest.ParamQuery }}{{ "\n" }}// @Param {{ fieldJsonNameStr $param.Name }} query {{ $typeParamName := fieldType $param }}{{ removeFirstChar $typeParamName }} false "{{ fieldJsonNameStr $param.Name }}"{{ end }}{{ range $index, $param := .PathParams }}{{ "\n" }}// @Param {{ fieldJsonNameStr $param.Name }} query {{ $typeParamName := fieldType $param }}{{ removeFirstChar $typeParamName }} false "{{ fieldJsonNameStr $param.Name }}"{{ end }}
|
||||
// @Success 200 {object} int
|
||||
// @Failure 400 {object} structs.Result
|
||||
// @Failure 401 {object} structs.Result
|
||||
// @Failure 404 {object} structs.Result
|
||||
// @Failure 500 {object} structs.Result
|
||||
// @Router {{ .Path }}/count [get]
|
||||
// @Router /{{ .Path }}/count [get]
|
||||
// @Security BearerAuth
|
||||
func count(c echo.Context) error {
|
||||
|
||||
|
@ -99,12 +102,13 @@ func count(c echo.Context) error {
|
|||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "Identificator record"
|
||||
// @Produce json{{ range $index, $param := .Rest.ParamQuery }}{{ "\n" }}// @Param {{ fieldJsonNameStr $param.Name }} query {{ $typeParamName := fieldType $param }}{{ removeFirstChar $typeParamName }} false "{{ fieldJsonNameStr $param.Name }}"{{ end }}{{ range $index, $param := .PathParams }}{{ "\n" }}// @Param {{ fieldJsonNameStr $param.Name }} query {{ $typeParamName := fieldType $param }}{{ removeFirstChar $typeParamName }} false "{{ fieldJsonNameStr $param.Name }}"{{ end }}
|
||||
// @Success 200 {object} {{ getModelName .Project .Rest.Data }}
|
||||
// @Failure 400 {object} structs.Result
|
||||
// @Failure 401 {object} structs.Result
|
||||
// @Failure 404 {object} structs.Result
|
||||
// @Failure 500 {object} structs.Result
|
||||
// @Router {{ .Path }}/{id} [get]
|
||||
// @Router /{{ .Path }}/{id} [get]
|
||||
// @Security BearerAuth
|
||||
func get(c echo.Context) error {
|
||||
|
||||
|
@ -137,12 +141,13 @@ func get(c echo.Context) error {
|
|||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body {{ getModelName .Project .Rest.Data }} true "Structure for request"
|
||||
// @Produce json{{ range $index, $param := .Rest.ParamQuery }}{{ "\n" }}// @Param {{ fieldJsonNameStr $param.Name }} query {{ $typeParamName := fieldType $param }}{{ removeFirstChar $typeParamName }} false "{{ fieldJsonNameStr $param.Name }}"{{ end }}{{ range $index, $param := .PathParams }}{{ "\n" }}// @Param {{ fieldJsonNameStr $param.Name }} query {{ $typeParamName := fieldType $param }}{{ removeFirstChar $typeParamName }} false "{{ fieldJsonNameStr $param.Name }}"{{ end }}
|
||||
// @Success 200 {object} structs.Result
|
||||
// @Failure 400 {object} structs.Result
|
||||
// @Failure 401 {object} structs.Result
|
||||
// @Failure 404 {object} structs.Result
|
||||
// @Failure 500 {object} structs.Result
|
||||
// @Router {{ .Path }} [post]
|
||||
// @Router /{{ .Path }} [post]
|
||||
// @Security BearerAuth
|
||||
func post(c echo.Context) error {
|
||||
user := c.Get("user").(*jwt.Token)
|
||||
|
@ -174,12 +179,13 @@ func post(c echo.Context) error {
|
|||
// @Produce json
|
||||
// @Param id path string true "Identificator record"
|
||||
// @Param body body {{ getModelName .Project .Rest.Data }} true "Structure for request"
|
||||
// @Produce json{{ range $index, $param := .Rest.ParamQuery }}{{ "\n" }}// @Param {{ fieldJsonNameStr $param.Name }} query {{ $typeParamName := fieldType $param }}{{ removeFirstChar $typeParamName }} false "{{ fieldJsonNameStr $param.Name }}"{{ end }}{{ range $index, $param := .PathParams }}{{ "\n" }}// @Param {{ fieldJsonNameStr $param.Name }} query {{ $typeParamName := fieldType $param }}{{ removeFirstChar $typeParamName }} false "{{ fieldJsonNameStr $param.Name }}"{{ end }}
|
||||
// @Success 200 {object} structs.Result
|
||||
// @Failure 400 {object} structs.Result
|
||||
// @Failure 401 {object} structs.Result
|
||||
// @Failure 404 {object} structs.Result
|
||||
// @Failure 500 {object} structs.Result
|
||||
// @Router {{ .Path }}/{id} [put]
|
||||
// @Router /{{ .Path }}/{id} [put]
|
||||
// @Security BearerAuth
|
||||
func put(c echo.Context) error {
|
||||
|
||||
|
@ -211,12 +217,13 @@ func put(c echo.Context) error {
|
|||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "Identificator record"
|
||||
// @Produce json{{ range $index, $param := .Rest.ParamQuery }}{{ "\n" }}// @Param {{ fieldJsonNameStr $param.Name }} query {{ $typeParamName := fieldType $param }}{{ removeFirstChar $typeParamName }} false "{{ fieldJsonNameStr $param.Name }}"{{ end }}{{ range $index, $param := .PathParams }}{{ "\n" }}// @Param {{ fieldJsonNameStr $param.Name }} query {{ $typeParamName := fieldType $param }}{{ removeFirstChar $typeParamName }} false "{{ fieldJsonNameStr $param.Name }}"{{ end }}
|
||||
// @Success 200 {object} structs.Result
|
||||
// @Failure 400 {object} structs.Result
|
||||
// @Failure 401 {object} structs.Result
|
||||
// @Failure 404 {object} structs.Result
|
||||
// @Failure 500 {object} structs.Result
|
||||
// @Router {{ .Path }}/{id} [delete]
|
||||
// @Router /{{ .Path }}/{id} [delete]
|
||||
// @Security BearerAuth
|
||||
func delete(c echo.Context) error {
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package structs
|
||||
|
||||
type {{ fieldNamePrepare .Name }} struct {
|
||||
{{ range $index, $field := .Fields }}
|
||||
{{ fieldName $field }} {{ fieldType $field }} `yaml:"{{ fieldJsonNameStr .Name }},omitempty" json:"{{ fieldJsonNameStr .Name }},omitempty"` // {{ $field.Description }}
|
||||
{{ end }}
|
||||
}
|
|
@ -18,10 +18,8 @@ import { ApiModule } from './module/api';
|
|||
//import { TokenIncerceptorService } from './service/token-interceptor.service';
|
||||
|
||||
{{ range $index, $rest := .Backend.Rest }}
|
||||
import { {{ angularRestName $index }}Component } from './page/{{ removeFirstChar $index }}/{{ angularFilename $index }}.component';
|
||||
{{ if $rest.Editable }}
|
||||
import { {{ angularRestName $index }}FormComponent } from './page/{{ removeFirstChar $index }}/form/{{ angularFilename $index }}-form.component';
|
||||
{{ end }}
|
||||
import { {{ angularRestName $index }}Component } from './page/{{ parseRestPathForName $index }}/{{ angularFilename $index }}.component';
|
||||
{{ if $rest.Editable }}import { {{ angularRestName $index }}FormComponent } from './page/{{ parseRestPathForName $index }}/form/{{ angularFilename $index }}-form.component';{{ end }}
|
||||
{{ end }}
|
||||
|
||||
@NgModule({
|
||||
|
|
|
@ -3,7 +3,8 @@ import { UntypedFormGroup, UntypedFormControl, Validators } from '@angular/forms
|
|||
import { Subscription, Observable, firstValueFrom } from 'rxjs';
|
||||
import { Router, ActivatedRoute, Params } from '@angular/router';
|
||||
import { MessageService } from 'primeng/api';
|
||||
import { {{ getModelNameAngular .Project .Rest.Data }}, {{ fieldNamePrepare .Rest.GroupName }}Service{{ range $index, $field := getFksByModelID2 .Project .Rest.Data.ID }}{{ $visField := fieldToVisField2 $field }}, {{ getModelNameAngular $.Project $visField }}{{ end }} } from 'src/app/module/api';
|
||||
{{ $modelNameAngular := getModelNameAngular .Project .Rest.Data }}
|
||||
import { {{ if ne $modelNameAngular "any" }}{{ $modelNameAngular }}, {{ end }}{{ fieldNamePrepare .Rest.GroupName }}Service{{ range $index, $field := getFksByModelID2 .Project .Rest.Data.ID }}{{ $visField := fieldToVisField2 $field }}, {{ getModelNameAngular $.Project $visField }}{{ end }} } from 'src/app/module/api';
|
||||
|
||||
@Component({
|
||||
selector: 'app-{{ angularFilename .Path }}-form',
|
||||
|
|
|
@ -2,7 +2,8 @@ import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
|||
import { firstValueFrom, Observable, Subscription } from 'rxjs';
|
||||
import { Router } from '@angular/router';
|
||||
import { ConfirmationService, MessageService } from 'primeng/api';
|
||||
import { {{ getModelNameAngular .Project .Rest.Data }}, {{ fieldNamePrepare .Rest.GroupName }}Service } from 'src/app/module/api';
|
||||
{{ $modelNameAngular := getModelNameAngular .Project .Rest.Data }}
|
||||
import { {{ if ne $modelNameAngular "any" }}{{ $modelNameAngular }}, {{ end }}{{ fieldNamePrepare .Rest.GroupName }}Service } from 'src/app/module/api';
|
||||
|
||||
|
||||
@Component({
|
||||
|
|
|
@ -20,16 +20,18 @@ type VisField struct {
|
|||
}
|
||||
|
||||
type Rest struct {
|
||||
Name string `yam:"name,omitempty" json:"name,omitempty" default:"noname"` // Имя раздела запросов
|
||||
GroupName string `yaml:"groupName,omitempty" json:"groupName,omitempty" default:"nogroup"` // Имя группы, в которую входит данный путь REST
|
||||
Summary string `yaml:"summary,omitempty" json:"summary,omitempty" default:"Общее описание"` // Общее краткое описание
|
||||
Comment string `yaml:"comment,omitempty" json:"comment,omitempty" default:"Описание"` // Описание (комментарий)
|
||||
Data VisField `yaml:"data,omitempty" json:"data,omitempty"` // Модель данных, на основе которой строиться запрос
|
||||
Edit []VisField `yaml:"edits,omitempty" json:"edits,omitempty"` // Список полей для редактирования
|
||||
Visible []VisField `yaml:"visible,omitempty" json:"visible,omitempty"` // Список видимых полей. Если указан хоть один, то отображаются только те, которые указаны, иначе отображаются все
|
||||
Invisible []VisField `yaml:"invisible,omitempty" json:"invisible,omitempty"` // Список невидимых полей. Если указан хоть один, то отображаются все кроме указанного, иначе берется правило из поля "visible". Является приоритетным и в данном случае поле "visible" игнорируется
|
||||
Filter []VisField `yaml:"filter,omitempty" json:"filter,omitempty"` // Указывается список полей, по которым будет осуществляться поиск
|
||||
Editable bool `yaml:"editable,omitempty" json:"editable,omitempty"` // Модель является редактируемой, т.е. необходимо сгенерировать rest для данной модели. Для данного пути будут сформированы методы GET, POST, PUT и DELETE с соответствующим путем /<path>/{id}
|
||||
FieldID VisField `yaml:"fieldId,omitempty" json:"fieldId,omitempty"` // Поле, которое является ключевым при работе с конкретной записью. Если модель данных указана db, то ключевое поле берется из описания БД и игнорируется.
|
||||
Roles map[string][]string `yaml:"roles,omitempty" json:"roles,omitempty"` // Список ролей, которым разрешено работать с данным. Операция: массив строк с названием ролей. Если не указано, то все роли. Операция для просмотра списка: LIST
|
||||
Name string `yam:"name,omitempty" json:"name,omitempty" default:"noname"` // Имя раздела запросов
|
||||
GroupName string `yaml:"groupName,omitempty" json:"groupName,omitempty" default:"nogroup"` // Имя группы, в которую входит данный путь REST
|
||||
Summary string `yaml:"summary,omitempty" json:"summary,omitempty" default:"Общее описание"` // Общее краткое описание
|
||||
Comment string `yaml:"comment,omitempty" json:"comment,omitempty" default:"Описание"` // Описание (комментарий)
|
||||
Data VisField `yaml:"data,omitempty" json:"data,omitempty"` // Модель данных, на основе которой строиться запрос
|
||||
Edit []VisField `yaml:"edits,omitempty" json:"edits,omitempty"` // Список полей для редактирования
|
||||
Visible []VisField `yaml:"visible,omitempty" json:"visible,omitempty"` // Список видимых полей. Если указан хоть один, то отображаются только те, которые указаны, иначе отображаются все
|
||||
Invisible []VisField `yaml:"invisible,omitempty" json:"invisible,omitempty"` // Список невидимых полей. Если указан хоть один, то отображаются все кроме указанного, иначе берется правило из поля "visible". Является приоритетным и в данном случае поле "visible" игнорируется
|
||||
Filter []VisField `yaml:"filter,omitempty" json:"filter,omitempty"` // Указывается список полей, по которым будет осуществляться поиск
|
||||
Editable bool `yaml:"editable,omitempty" json:"editable,omitempty"` // Модель является редактируемой, т.е. необходимо сгенерировать rest для данной модели. Для данного пути будут сформированы методы GET, POST, PUT и DELETE с соответствующим путем /<path>/{id}
|
||||
FieldID VisField `yaml:"fieldId,omitempty" json:"fieldId,omitempty"` // Поле, которое является ключевым при работе с конкретной записью. Если модель данных указана db, то ключевое поле берется из описания БД и игнорируется.
|
||||
Roles map[string][]string `yaml:"roles,omitempty" json:"roles,omitempty"` // Список ролей, которым разрешено работать с данным. Операция: массив строк с названием ролей. Если не указано, то все роли. Операция для просмотра списка: LIST
|
||||
Methods []string `yaml:"methods,omitempty" json:"methods,omitempty"` // Методы, которые нужно генерировать. Если указаны, то стандартные методы и параметр "editable" игнорируется
|
||||
ParamQuery []Field `yaml:"paramQuery,omitempty" json:"paramQuery,omitempty"`
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ type Field struct {
|
|||
Length *int `yaml:"length,omitempty" json:"len,omitempty"` // Размер поля для строковых типов и Decimal
|
||||
Accuracy *int `yaml:"accuracy,omitempty" json:"accuracy,omitempty"` // Точность поля для Decimal
|
||||
Description string `yaml:"description,omitempty" json:"description,omitempty"` // Описание поля
|
||||
IsArray bool `yaml:"isArray,omitempty" json:"isArray,omitempty"` // Если является массивом
|
||||
}
|
||||
|
||||
// Описание внешних ключей
|
||||
|
|
|
@ -3,7 +3,7 @@ package structs
|
|||
import uuid "github.com/satori/go.uuid"
|
||||
|
||||
type Interface struct {
|
||||
ID uuid.UUID `yaml:"id" json:"id"`
|
||||
ID uuid.UUID `yaml:"id,omitempty" json:"id,omitempty"`
|
||||
Name string `yaml:"name,omitempty" json:"name,omitempty" default:"noname"`
|
||||
Fields []Field `yaml:"fields,omitempty" json:"fields,omitempty"`
|
||||
// TODO
|
||||
|
|
|
@ -2,18 +2,19 @@ package structs
|
|||
|
||||
type Project struct {
|
||||
// Language string `yaml:"lang"` // Язык генерации. Поддерживаются go (серверная часть) и angular (клиентская часть)
|
||||
Name string `yaml:"name,omitempty" json:"name,omitempty"`
|
||||
Title string `yaml:"title,omitempty" json:"title,omitempty"`
|
||||
Version string `yaml:"version,omitempty" json:"version,omitempty"`
|
||||
Description string `yaml:"description,omitempty" json:"description,omitempty"`
|
||||
TermsOfServices string `yaml:"termsOfServices,omitempty" json:"termsOfServices,omitempty"`
|
||||
ContactName string `yaml:"contactName,omitempty" json:"contactName,omitempty"`
|
||||
ContactUrl string `yaml:"contactUrl,omitempty" json:"contactUrl,omitempty"`
|
||||
ContactEmail string `yaml:"contactEmail,omitempty" json:"contactEmail,omitempty"`
|
||||
LicenseName string `yaml:"licenseName,omitempty" json:"licenseName,omitempty"`
|
||||
LicenseUrl string `yaml:"licenseUrl,omitempty" json:"licenseUrl,omitempty"`
|
||||
Host string `yaml:"host,omitempty" json:"host,omitempty"`
|
||||
BasePath string `yaml:"basePath,omitempty" json:"basePath,omitempty"`
|
||||
Name string `yaml:"name,omitempty" json:"name,omitempty"`
|
||||
Title string `yaml:"title,omitempty" json:"title,omitempty"`
|
||||
Version string `yaml:"version,omitempty" json:"version,omitempty"`
|
||||
Description string `yaml:"description,omitempty" json:"description,omitempty"`
|
||||
TermsOfServices string `yaml:"termsOfServices,omitempty" json:"termsOfServices,omitempty"`
|
||||
ContactName string `yaml:"contactName,omitempty" json:"contactName,omitempty"`
|
||||
ContactUrl string `yaml:"contactUrl,omitempty" json:"contactUrl,omitempty"`
|
||||
ContactEmail string `yaml:"contactEmail,omitempty" json:"contactEmail,omitempty"`
|
||||
LicenseName string `yaml:"licenseName,omitempty" json:"licenseName,omitempty"`
|
||||
LicenseUrl string `yaml:"licenseUrl,omitempty" json:"licenseUrl,omitempty"`
|
||||
Host string `yaml:"host,omitempty" json:"host,omitempty"`
|
||||
BasePath string `yaml:"basePath,omitempty" json:"basePath,omitempty"`
|
||||
Interfaces []Interface `yaml:"interfaces,omitempty" json:"interfaces,omitempty"` // Структуры интерфейсов
|
||||
|
||||
DB DB `yaml:"db,omitempty" json:"db,omitempty"` // Структура БД
|
||||
Roles []Role `yaml:"roles,omitempty" json:"roles,omitempty"` // Роли приложения
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package structs
|
||||
|
||||
type RestStruct struct {
|
||||
Path string
|
||||
Project *Project
|
||||
Rest *Rest
|
||||
Path string
|
||||
PathPackageName string
|
||||
Project *Project
|
||||
Rest *Rest
|
||||
PathParams []Field
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue