tercul-backend/create_repo_interfaces.go
2025-09-05 21:37:42 +00:00

144 lines
3.4 KiB
Go

//go:build tools
package main
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"io/ioutil"
"os"
"path/filepath"
"strings"
)
func main() {
sqlDir := "internal/data/sql"
domainDir := "internal/domain"
files, err := ioutil.ReadDir(sqlDir)
if err != nil {
fmt.Println("Error reading sql directory:", err)
return
}
for _, file := range files {
if strings.HasSuffix(file.Name(), "_repository.go") {
repoName := strings.TrimSuffix(file.Name(), "_repository.go")
repoInterfaceName := strings.Title(repoName) + "Repository"
domainPackageName := repoName
// Create domain directory
domainRepoDir := filepath.Join(domainDir, domainPackageName)
if err := os.MkdirAll(domainRepoDir, 0755); err != nil {
fmt.Printf("Error creating directory %s: %v\n", domainRepoDir, err)
continue
}
// Read the sql repository file
filePath := filepath.Join(sqlDir, file.Name())
src, err := ioutil.ReadFile(filePath)
if err != nil {
fmt.Printf("Error reading file %s: %v\n", filePath, err)
continue
}
// Parse the file
fset := token.NewFileSet()
node, err := parser.ParseFile(fset, "", src, parser.ParseComments)
if err != nil {
fmt.Printf("Error parsing file %s: %v\n", filePath, err)
continue
}
// Find public methods
var methods []string
ast.Inspect(node, func(n ast.Node) bool {
if fn, ok := n.(*ast.FuncDecl); ok {
if fn.Recv != nil && len(fn.Recv.List) > 0 {
if star, ok := fn.Recv.List[0].Type.(*ast.StarExpr); ok {
if ident, ok := star.X.(*ast.Ident); ok {
if strings.HasSuffix(ident.Name, "Repository") && fn.Name.IsExported() {
methods = append(methods, getFuncSignature(fn))
}
}
}
}
}
return true
})
// Create the repo.go file
repoFilePath := filepath.Join(domainRepoDir, "repo.go")
repoFileContent := fmt.Sprintf(`package %s
import (
"context"
"tercul/internal/domain"
)
// %s defines CRUD methods specific to %s.
type %s interface {
domain.BaseRepository[domain.%s]
%s
}
`, domainPackageName, repoInterfaceName, strings.Title(repoName), repoInterfaceName, strings.Title(repoName), formatMethods(methods))
if err := ioutil.WriteFile(repoFilePath, []byte(repoFileContent), 0644); err != nil {
fmt.Printf("Error writing file %s: %v\n", repoFilePath, err)
} else {
fmt.Printf("Created %s\n", repoFilePath)
}
}
}
}
func getFuncSignature(fn *ast.FuncDecl) string {
params := ""
for _, p := range fn.Type.Params.List {
if len(p.Names) > 0 {
params += p.Names[0].Name + " "
}
params += getTypeString(p.Type) + ", "
}
if len(params) > 0 {
params = params[:len(params)-2]
}
results := ""
if fn.Type.Results != nil {
for _, r := range fn.Type.Results.List {
results += getTypeString(r.Type) + ", "
}
if len(results) > 0 {
results = "(" + results[:len(results)-2] + ")"
}
}
return fmt.Sprintf("\t%s(%s) %s", fn.Name.Name, params, results)
}
func getTypeString(expr ast.Expr) string {
switch t := expr.(type) {
case *ast.Ident:
return t.Name
case *ast.SelectorExpr:
return getTypeString(t.X) + "." + t.Sel.Name
case *ast.StarExpr:
return "*" + getTypeString(t.X)
case *ast.ArrayType:
return "[]" + getTypeString(t.Elt)
case *ast.InterfaceType:
return "interface{}"
default:
return ""
}
}
func formatMethods(methods []string) string {
if len(methods) == 0 {
return ""
}
return "\n" + strings.Join(methods, "\n")
}