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