diff --git a/entities/field.go b/entities/field.go index 79eeb3d..e2dbeb9 100644 --- a/entities/field.go +++ b/entities/field.go @@ -1,82 +1,7 @@ package entities -import ( - "fmt" - "slices" - "strings" -) - type Field struct { Name string Type string Metadata []Metadata } - -var PrimitiveTypes = map[string]string{ - "date": "date", - "number": "number", - "string": "string", - "multiple": "multiple", - "boolean": "boolean", - "bool": "boolean", - "int": "number", - "uint": "number", - "float32": "number", - "float64": "number", - "int32": "number", - "int64": "number", - "uint32": "number", - "uint64": "number", - "int8": "number", - "int16": "number", - "uint8": "number", - "uint16": "number", - "byte": "number", - "rune": "number", -} - -func (f *Field) GenerateType() string { - result := " type: {\n" - - keys := make([]string, 0, len(PrimitiveTypes)) - for k := range PrimitiveTypes { - keys = append(keys, k) - } - - if slices.Contains(keys, strings.ToLower(f.Type)) { - result += fmt.Sprintf(` primitive: "%s",`, PrimitiveTypes[strings.ToLower(f.Type)]) - } else { - var field = "[]" - for _, meta := range f.Metadata { - if meta.Name == "field" { - if len(meta.Values) > 0 { - field = "['" + strings.Join(meta.Values, "', '") + "']" - } - } - } - result += fmt.Sprintf(` nested: { - values: [], - field: %s - }, `, field) - } - result += "\n }," - return result -} - -func (f *Field) Generate() string { - result := "{\n" - for _, meta := range f.Metadata { - if meta.Name == "hidden" { - result += " hidden: true,\n" - } else if meta.Name == "label" { - result += fmt.Sprintf(` russian: "%s",`+"\n", meta.Values[0]) - } else if meta.Name == "readonly" { - result += " readonly: true,\n" - } - } - if f.Type[0:2] == "[]" { - result += " many: true,\n" - } - result += f.GenerateType() - return result + "\n}" -} diff --git a/entities/field_type.go b/entities/field_type.go new file mode 100644 index 0000000..32b5493 --- /dev/null +++ b/entities/field_type.go @@ -0,0 +1,81 @@ +package entities + +import ( + "bytes" + "fmt" + "slices" + "strings" + "text/template" +) + +var PrimitiveTypes = map[string]string{ + "date": "date", + "number": "number", + "string": "string", + "multiple": "multiple", + "boolean": "boolean", + "bool": "boolean", + "int": "number", + "uint": "number", + "float32": "number", + "float64": "number", + "int32": "number", + "int64": "number", + "uint32": "number", + "uint64": "number", + "int8": "number", + "int16": "number", + "uint8": "number", + "uint16": "number", + "byte": "number", + "rune": "number", +} + +const typeTemplate = ` type: { +{{ if .IsPrimitive }} primitive: "{{ .PrimitiveType }}",{{ else }} nested: { + values: [], + field: {{ .Field }} + }, {{ end }} + },` + +type TypeTemplateContext struct { + IsPrimitive bool + PrimitiveType string + Field string +} + +func (f *Field) GenerateType() string { + keys := make([]string, 0, len(PrimitiveTypes)) + for k := range PrimitiveTypes { + keys = append(keys, k) + } + + var data TypeTemplateContext + + if slices.Contains(keys, strings.ToLower(f.Type)) { + data.IsPrimitive = true + data.PrimitiveType = PrimitiveTypes[strings.ToLower(f.Type)] + } else { + data.IsPrimitive = false + field := "[]" + for _, meta := range f.Metadata { + if meta.Name == "field" && len(meta.Values) > 0 { + field = "['" + strings.Join(meta.Values, "', '") + "']" + break + } + } + data.Field = field + } + + tmpl, err := template.New("type").Parse(typeTemplate) + if err != nil { + panic(fmt.Sprintf("Error parsing template: %v", err)) + } + + var result bytes.Buffer + if err := tmpl.Execute(&result, data); err != nil { + panic(fmt.Sprintf("Error executing template: %v", err)) + } + + return result.String() +} diff --git a/entities/gen_field.go b/entities/gen_field.go new file mode 100644 index 0000000..8fee312 --- /dev/null +++ b/entities/gen_field.go @@ -0,0 +1,43 @@ +package entities + +import ( + "bytes" + "fmt" + "text/template" +) + +const fieldTemplate = `{ +{{ range .Metadata }}{{ if eq .Name "hidden" }} hidden: true, +{{ else if eq .Name "label" }} russian: "{{ index .Values 0 }}", +{{ else if eq .Name "readonly" }} readonly: true, +{{ end }}{{ end }}{{ if .IsArray }} many: true, +{{ end }}{{ .GeneratedType }} +}` + +type FieldTemplateContext struct { + Metadata []Metadata + IsArray bool + GeneratedType string +} + +func (f *Field) Generate() string { + tmpl, err := template.New("field").Parse(fieldTemplate) + if err != nil { + panic(fmt.Sprintf("Error parsing field template: %v", err)) + } + + isArray := len(f.Type) >= 2 && f.Type[0:2] == "[]" + + data := FieldTemplateContext{ + Metadata: f.Metadata, + IsArray: isArray, + GeneratedType: f.GenerateType(), + } + + var result bytes.Buffer + if err := tmpl.Execute(&result, data); err != nil { + panic(fmt.Sprintf("Error executing field template: %v", err)) + } + + return result.String() +} diff --git a/generation/scheme.go b/generation/scheme.go index becee22..9f195d1 100644 --- a/generation/scheme.go +++ b/generation/scheme.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "nto_cli/entities" + "nto_cli/utils" "os" "path/filepath" "strings" @@ -63,6 +64,7 @@ func GenerateScheme(structName string, fields []entities.Field, mkPath string) { log.Fatalf("Failed to execute template: %s", err) } log.Printf("Scheme for `%s` model is written: %s", structName, schemeFilePath) + _ = utils.FormatFilesWithPrettier([]string{schemeFilePath}) } func processDependencies(fields []entities.Field) []Dependency { diff --git a/generation/service.go b/generation/service.go index cf26d8f..6a40ec9 100644 --- a/generation/service.go +++ b/generation/service.go @@ -4,6 +4,7 @@ import ( _ "embed" "fmt" "log" + "nto_cli/utils" "os" "path/filepath" "strings" @@ -50,4 +51,5 @@ func GenerateService(structName, mkPath string) { log.Fatalf("Failed to execute template: %s", err) } log.Printf("Service for `%s` model is written: %s", structName, servicePath) + _ = utils.FormatFilesWithPrettier([]string{servicePath}) } diff --git a/utils/prettier.go b/utils/prettier.go new file mode 100644 index 0000000..e84dad6 --- /dev/null +++ b/utils/prettier.go @@ -0,0 +1,26 @@ +package utils + +import ( + "fmt" + "log" + "os/exec" +) + +func FormatFilesWithPrettier(files []string) error { + if len(files) == 0 { + return fmt.Errorf("empty file list") + } + + args := append([]string{"prettier", "--write"}, files...) + + cmd := exec.Command("npx", args...) + output, err := cmd.CombinedOutput() + + if err != nil { + return fmt.Errorf("formatter error: %s\nOutput: %s", err, output) + } + + log.Println("prettier was applied") + + return nil +} diff --git a/utils/split_struct_field.go b/utils/split_struct_field.go index 2c522a0..358128f 100644 --- a/utils/split_struct_field.go +++ b/utils/split_struct_field.go @@ -25,14 +25,13 @@ func SplitStructField(field string) (*entities.Field, error) { endBacktick = strings.Index(field[startBacktick+1:], "`") if endBacktick > -1 { endBacktick += startBacktick + 1 - meta := field[startBacktick+1 : endBacktick] - tags, err := structtag.Parse(meta) + structTag := field[startBacktick+1 : endBacktick] + tags, err := structtag.Parse(structTag) if err != nil { log.Fatalf("failed to parse struct tag: %s", err) } - uiTag, err := tags.Get("ui") - if err == nil { + if uiTag, e := tags.Get("ui"); e == nil { uiTags := append([]string{uiTag.Name}, uiTag.Options...) for _, t := range uiTags { analyzed := entities.NewMetadata(t)