refactor: extract all generators into independent TOOLS/ modules
Each generator is now a standalone Go module with its own go.mod: TOOLS/ ├── yaml-generator/ ← service_spec_gen (API → YAML) ├── resource-generator/ ← gen_v2 (YAML → Go resources) ├── docs-generator/ ← docs_template_gen_v2 (YAML → Markdown) ├── ops-generator/ ← ops_docs_gen (ops documentation) └── bin/ ← pre-built binaries All scripts updated to use TOOLS/bin/* binaries. Removed old universal_rebuild/tools/ and universal_rebuild/bin/.
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
// Package helpers — конвертация имён, форматирование, plan-модификаторы.
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/format"
|
||||
"os"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"resource-generator/types"
|
||||
)
|
||||
|
||||
// ToCamel конвертирует snake_case → CamelCase.
|
||||
func ToCamel(s string) string {
|
||||
parts := strings.FieldsFunc(s, func(r rune) bool { return r == '_' || r == '-' })
|
||||
for i, p := range parts {
|
||||
if len(p) == 0 {
|
||||
continue
|
||||
}
|
||||
parts[i] = strings.ToUpper(p[:1]) + p[1:]
|
||||
}
|
||||
out := strings.Join(parts, "")
|
||||
return EnsureGoIdent(out)
|
||||
}
|
||||
|
||||
// ToSnake конвертирует CamelCase → snake_case.
|
||||
func ToSnake(s string) string {
|
||||
var out []rune
|
||||
for i, r := range s {
|
||||
if i > 0 && r >= 'A' && r <= 'Z' {
|
||||
out = append(out, '_')
|
||||
}
|
||||
out = append(out, rune(strings.ToLower(string(r))[0]))
|
||||
}
|
||||
return string(out)
|
||||
}
|
||||
|
||||
// ParamType возвращает Go-тип для параметра (types.Bool/Int64/String).
|
||||
func ParamType(p types.Param) string {
|
||||
switch strings.ToLower(p.Type) {
|
||||
case "bool":
|
||||
return "types.Bool"
|
||||
case "int", "int64", "number":
|
||||
return "types.Int64"
|
||||
default:
|
||||
return "types.String"
|
||||
}
|
||||
}
|
||||
|
||||
// ParamDefaultExpr возвращает выражение значения по умолчанию.
|
||||
func ParamDefaultExpr(p types.Param) string {
|
||||
if p.Default == "" {
|
||||
return ""
|
||||
}
|
||||
switch strings.ToLower(p.Type) {
|
||||
case "bool":
|
||||
val := strings.ToLower(p.Default)
|
||||
return fmt.Sprintf("booldefault.StaticBool(%s)", val)
|
||||
case "int", "int64", "number":
|
||||
return fmt.Sprintf("int64default.StaticInt64(%s)", p.Default)
|
||||
default:
|
||||
return fmt.Sprintf("stringdefault.StaticString(%q)", p.Default)
|
||||
}
|
||||
}
|
||||
|
||||
// ParamFormat возвращает вызов Format* для форматирования значения параметра.
|
||||
func ParamFormat(p types.Param, varName string) string {
|
||||
switch strings.ToLower(p.Type) {
|
||||
case "bool":
|
||||
return fmt.Sprintf("resources_core.FormatBool(%s)", varName)
|
||||
case "int", "int64", "number":
|
||||
return fmt.Sprintf("resources_core.FormatInt64(%s)", varName)
|
||||
default:
|
||||
return fmt.Sprintf("resources_core.FormatString(%s)", varName)
|
||||
}
|
||||
}
|
||||
|
||||
// ParamParse возвращает имя Parse*-функции для параметра.
|
||||
func ParamParse(p types.Param) string {
|
||||
switch strings.ToLower(p.Type) {
|
||||
case "bool":
|
||||
return "resources_core.ParseBool"
|
||||
case "int", "int64", "number":
|
||||
return "resources_core.ParseInt64"
|
||||
default:
|
||||
return "resources_core.ParseString"
|
||||
}
|
||||
}
|
||||
|
||||
// ParamDescription формирует MarkdownDescription для параметра.
|
||||
func ParamDescription(p types.Param) string {
|
||||
var desc string
|
||||
if strings.TrimSpace(p.Descr) != "" {
|
||||
desc = strings.TrimSpace(p.Descr)
|
||||
} else if strings.TrimSpace(p.Man) != "" {
|
||||
desc = strings.TrimSpace(p.Man)
|
||||
} else if p.RefSvcId > 0 {
|
||||
desc = fmt.Sprintf("UI display_name for service_id=%d (mapped to UUID in core)", p.RefSvcId)
|
||||
}
|
||||
if p.CreateOnly {
|
||||
if desc == "" {
|
||||
desc = "Не изменяется после создания."
|
||||
} else {
|
||||
desc = desc + " Не изменяется после создания."
|
||||
}
|
||||
}
|
||||
if p.ForceNew {
|
||||
if desc == "" {
|
||||
desc = "Изменение требует пересоздания."
|
||||
} else {
|
||||
desc = desc + " Изменение требует пересоздания."
|
||||
}
|
||||
}
|
||||
if desc == "" {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("%q", desc)
|
||||
}
|
||||
|
||||
// OutputParamType возвращает Go-тип для выходного параметра (types.Map/List/String).
|
||||
func OutputParamType(p types.OutputParam) string {
|
||||
switch strings.ToLower(p.Type) {
|
||||
case "map":
|
||||
return "types.Map"
|
||||
case "list":
|
||||
return "types.List"
|
||||
default:
|
||||
return "types.String"
|
||||
}
|
||||
}
|
||||
|
||||
// OutputParamIsMap возвращает true, если выходной параметр — map.
|
||||
func OutputParamIsMap(p types.OutputParam) bool {
|
||||
return strings.EqualFold(strings.TrimSpace(p.Type), "map")
|
||||
}
|
||||
|
||||
// OutputParamIsList возвращает true, если выходной параметр — list.
|
||||
func OutputParamIsList(p types.OutputParam) bool {
|
||||
return strings.EqualFold(strings.TrimSpace(p.Type), "list")
|
||||
}
|
||||
|
||||
// OutputParamSensitive возвращает true, если параметр секретный.
|
||||
func OutputParamSensitive(p types.OutputParam) bool {
|
||||
return p.Sensitive
|
||||
}
|
||||
|
||||
// EnsureGoIdent проверяет, что строка начинается с буквы или _.
|
||||
func EnsureGoIdent(s string) string {
|
||||
if s == "" {
|
||||
return "R"
|
||||
}
|
||||
first := rune(s[0])
|
||||
if unicode.IsLetter(first) || first == '_' {
|
||||
return s
|
||||
}
|
||||
return "R" + s
|
||||
}
|
||||
|
||||
// FormatSourceOrWarn форматирует Go-код. При ошибке пишет warning в stderr.
|
||||
func FormatSourceOrWarn(filePath string, src []byte) []byte {
|
||||
formatted, err := format.Source(src)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "WARNING: gofmt failed for %s: %v — writing unformatted code\n", filePath, err)
|
||||
return src
|
||||
}
|
||||
return formatted
|
||||
}
|
||||
|
||||
// PlanModifierType возвращает суффикс типа план-модификатора (Bool/Int64/String).
|
||||
func PlanModifierType(p types.Param) string {
|
||||
switch strings.ToLower(strings.TrimSpace(p.Type)) {
|
||||
case "bool":
|
||||
return "Bool"
|
||||
case "int", "int64", "number":
|
||||
return "Int64"
|
||||
default:
|
||||
return "String"
|
||||
}
|
||||
}
|
||||
|
||||
// PlanModifierExpr возвращает выражение план-модификатора RequiresReplace.
|
||||
func PlanModifierExpr(p types.Param) string {
|
||||
switch strings.ToLower(strings.TrimSpace(p.Type)) {
|
||||
case "bool":
|
||||
return "boolplanmodifier.RequiresReplace()"
|
||||
case "int", "int64", "number":
|
||||
return "int64planmodifier.RequiresReplace()"
|
||||
default:
|
||||
return "stringplanmodifier.RequiresReplace()"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user