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  }