Генерирование с учетом структур
continuous-integration/drone/tag Build is passing Details

This commit is contained in:
Ymnuk 2023-08-25 15:05:28 +03:00
parent 03127a0ee0
commit 4631b5973e
25 changed files with 323 additions and 81 deletions

View File

@ -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, то клиенту возвращаются двоичные данные независимо от других условий (картинки, документы и т.д.)

View File

@ -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)

View File

@ -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)
}
}
}
}

View File

@ -28,6 +28,7 @@ func Backend() {
}
}
backendGenerateStructs()
generateDB()
generateBackendTmpl()

View File

@ -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)
}
}

View File

@ -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 {

View File

@ -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
}

View File

@ -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)

View File

@ -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)

82
lib/templ/backend-path.go Normal file
View File

@ -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
}

View File

@ -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 ""
}

View File

@ -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 ""
}

View File

@ -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:])
}

View File

@ -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)

View File

@ -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"

View File

@ -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 {

View File

@ -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 }}
}

View File

@ -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({

View File

@ -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',

View File

@ -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({

View File

@ -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"`
}

View File

@ -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"` // Если является массивом
}
// Описание внешних ключей

View File

@ -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

View File

@ -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"` // Роли приложения

View File

@ -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
}