github.com/hasura/ndc-sdk-go/cmd/hasura-ndc-go@v0.0.0-20240508172728-e960be013ca2/template.go (about) 1 package main 2 3 import ( 4 "bufio" 5 "embed" 6 "fmt" 7 "io/fs" 8 "os" 9 "os/exec" 10 "path" 11 "strings" 12 "text/template" 13 14 "github.com/rs/zerolog/log" 15 "golang.org/x/mod/modfile" 16 ) 17 18 //go:embed all:* templates/new 19 var initTemplateFS embed.FS 20 21 //go:embed templates/connector/connector.go.tmpl 22 var connectorTemplateStr string 23 var connectorTemplate *template.Template 24 25 const ( 26 templateNewPath = "templates/new" 27 ) 28 29 func init() { 30 var err error 31 connectorTemplate, err = template.New(connectorOutputFile).Parse(connectorTemplateStr) 32 if err != nil { 33 panic(fmt.Errorf("failed to parse connector template: %s", err)) 34 } 35 } 36 37 func generateNewProject(args *NewArguments, silent bool) error { 38 srcPath := args.Output 39 if srcPath == "" { 40 p, err := os.Getwd() 41 if err != nil { 42 return err 43 } 44 srcPath = path.Join(p, args.Name) 45 } 46 if err := os.MkdirAll(srcPath, 0755); err != nil { 47 return err 48 } 49 50 if err := generateNewProjectFiles(args, srcPath); err != nil { 51 return err 52 } 53 54 if err := os.Chdir(srcPath); err != nil { 55 return err 56 } 57 58 log.Info().Msg("downloading dependencies...") 59 if err := execGoModTidy(""); err != nil { 60 if silent { 61 return nil 62 } 63 return err 64 } 65 66 log.Info().Msg("generating connector functions...") 67 if err := parseAndGenerateConnector(&GenerateArguments{ 68 Path: ".", 69 Directories: []string{"functions", "types"}, 70 }, args.Module); err != nil { 71 return err 72 } 73 74 // reverify dependencies after generated 75 if err := execGoModTidy(""); err != nil { 76 if silent { 77 return nil 78 } 79 return err 80 } 81 82 err := execGoFormat(".") 83 if err != nil && silent { 84 return nil 85 } 86 return err 87 } 88 89 func generateNewProjectFiles(args *NewArguments, srcPath string) error { 90 91 return fs.WalkDir(initTemplateFS, templateNewPath, func(filePath string, d fs.DirEntry, err error) error { 92 if err != nil { 93 return err 94 } 95 96 log.Debug().Msgf("%s", filePath) 97 if filePath == templateNewPath { 98 return nil 99 } 100 101 targetPath := path.Join(srcPath, strings.TrimPrefix(filePath, fmt.Sprintf("%s/", templateNewPath))) 102 if d.IsDir() { 103 return os.Mkdir(targetPath, 0755) 104 } 105 106 fileTemplate, err := template.ParseFS(initTemplateFS, filePath) 107 if err != nil { 108 return err 109 } 110 111 targetPath = strings.TrimSuffix(targetPath, ".tmpl") 112 f, err := os.Create(targetPath) 113 if err != nil { 114 return err 115 } 116 defer func() { 117 _ = f.Close() 118 }() 119 120 w := bufio.NewWriter(f) 121 err = fileTemplate.Execute(w, map[string]any{ 122 "Name": args.Name, 123 "Module": args.Module, 124 "Version": args.Version, 125 }) 126 if err != nil { 127 return err 128 } 129 return w.Flush() 130 }) 131 } 132 133 func execGoModTidy(basePath string) error { 134 return execCommand(basePath, "go", "mod", "tidy") 135 } 136 137 func execGoFormat(basePath string) error { 138 return execCommand(basePath, "gofmt", "-w", "-s", ".") 139 } 140 141 func execCommand(basePath string, commandName string, args ...string) error { 142 cmd := exec.Command(commandName, args...) 143 if basePath != "" { 144 cmd.Dir = basePath 145 } 146 out, err := cmd.Output() 147 l := log.Debug() 148 if err != nil { 149 l = log.Error().Err(err) 150 } 151 l.Strs("args", args).Str("result", string(out)).Msg(commandName) 152 return err 153 } 154 155 func getModuleName(basePath string) (string, error) { 156 goModBytes, err := os.ReadFile(path.Join(basePath, "go.mod")) 157 if err != nil { 158 return "", err 159 } 160 161 return modfile.ModulePath(goModBytes), nil 162 }