github.com/senomas/gqlgen@v0.17.11-0.20220626120754-9aee61b0716a/main.go (about) 1 package main 2 3 import ( 4 "bytes" 5 _ "embed" 6 "errors" 7 "fmt" 8 "html/template" 9 "io" 10 "io/fs" 11 "log" 12 "os" 13 "path/filepath" 14 15 "github.com/99designs/gqlgen/api" 16 "github.com/99designs/gqlgen/codegen/config" 17 "github.com/99designs/gqlgen/graphql" 18 "github.com/99designs/gqlgen/internal/code" 19 "github.com/99designs/gqlgen/plugin/servergen" 20 "github.com/urfave/cli/v2" 21 ) 22 23 //go:embed init-templates/schema.graphqls 24 var schemaFileContent string 25 26 //go:embed init-templates/gqlgen.yml.gotmpl 27 var configFileTemplate string 28 29 func getConfigFileContent(pkgName string) string { 30 var buf bytes.Buffer 31 if err := template.Must(template.New("gqlgen.yml").Parse(configFileTemplate)).Execute(&buf, pkgName); err != nil { 32 panic(err) 33 } 34 return buf.String() 35 } 36 37 func fileExists(filename string) bool { 38 _, err := os.Stat(filename) 39 return !errors.Is(err, fs.ErrNotExist) 40 } 41 42 func initFile(filename, contents string) error { 43 if err := os.MkdirAll(filepath.Dir(filename), 0o755); err != nil { 44 return fmt.Errorf("unable to create directory for file '%s': %w\n", filename, err) 45 } 46 if err := os.WriteFile(filename, []byte(contents), 0o644); err != nil { 47 return fmt.Errorf("unable to write file '%s': %w\n", filename, err) 48 } 49 50 return nil 51 } 52 53 var initCmd = &cli.Command{ 54 Name: "init", 55 Usage: "create a new gqlgen project", 56 Flags: []cli.Flag{ 57 &cli.BoolFlag{Name: "verbose, v", Usage: "show logs"}, 58 &cli.StringFlag{Name: "config, c", Usage: "the config filename", Value: "gqlgen.yml"}, 59 &cli.StringFlag{Name: "server", Usage: "where to write the server stub to", Value: "server.go"}, 60 &cli.StringFlag{Name: "schema", Usage: "where to write the schema stub to", Value: "graph/schema.graphqls"}, 61 }, 62 Action: func(ctx *cli.Context) error { 63 configFilename := ctx.String("config") 64 serverFilename := ctx.String("server") 65 schemaFilename := ctx.String("schema") 66 67 pkgName := code.ImportPathForDir(".") 68 if pkgName == "" { 69 return fmt.Errorf("unable to determine import path for current directory, you probably need to run 'go mod init' first") 70 } 71 72 // check schema and config don't already exist 73 for _, filename := range []string{configFilename, schemaFilename, serverFilename} { 74 if fileExists(filename) { 75 return fmt.Errorf("%s already exists", filename) 76 } 77 } 78 _, err := config.LoadConfigFromDefaultLocations() 79 if err == nil { 80 return fmt.Errorf("gqlgen.yml already exists in a parent directory\n") 81 } 82 83 // create config 84 fmt.Println("Creating", configFilename) 85 if err := initFile(configFilename, getConfigFileContent(pkgName)); err != nil { 86 return err 87 } 88 89 // create schema 90 fmt.Println("Creating", schemaFilename) 91 92 if err := initFile(schemaFilename, schemaFileContent); err != nil { 93 return err 94 } 95 96 // create the package directory with a temporary file so that go recognises it as a package 97 // and autobinding doesn't error out 98 tmpPackageNameFile := "graph/model/_tmp_gqlgen_init.go" 99 if err := initFile(tmpPackageNameFile, "package model"); err != nil { 100 return err 101 } 102 defer os.Remove(tmpPackageNameFile) 103 104 var cfg *config.Config 105 if cfg, err = config.LoadConfig(configFilename); err != nil { 106 panic(err) 107 } 108 109 fmt.Println("Creating", serverFilename) 110 fmt.Println("Generating...") 111 if err := api.Generate(cfg, api.AddPlugin(servergen.New(serverFilename))); err != nil { 112 return err 113 } 114 115 fmt.Printf("\nExec \"go run ./%s\" to start GraphQL server\n", serverFilename) 116 return nil 117 }, 118 } 119 120 var generateCmd = &cli.Command{ 121 Name: "generate", 122 Usage: "generate a graphql server based on schema", 123 Flags: []cli.Flag{ 124 &cli.BoolFlag{Name: "verbose, v", Usage: "show logs"}, 125 &cli.StringFlag{Name: "config, c", Usage: "the config filename"}, 126 }, 127 Action: func(ctx *cli.Context) error { 128 var cfg *config.Config 129 var err error 130 if configFilename := ctx.String("config"); configFilename != "" { 131 cfg, err = config.LoadConfig(configFilename) 132 if err != nil { 133 return err 134 } 135 } else { 136 cfg, err = config.LoadConfigFromDefaultLocations() 137 if errors.Is(err, fs.ErrNotExist) { 138 cfg, err = config.LoadDefaultConfig() 139 } 140 141 if err != nil { 142 return err 143 } 144 } 145 146 if err = api.Generate(cfg); err != nil { 147 return err 148 } 149 return nil 150 }, 151 } 152 153 var versionCmd = &cli.Command{ 154 Name: "version", 155 Usage: "print the version string", 156 Action: func(ctx *cli.Context) error { 157 fmt.Println(graphql.Version) 158 return nil 159 }, 160 } 161 162 func main() { 163 app := cli.NewApp() 164 app.Name = "gqlgen" 165 app.Usage = generateCmd.Usage 166 app.Description = "This is a library for quickly creating strictly typed graphql servers in golang. See https://gqlgen.com/ for a getting started guide." 167 app.HideVersion = true 168 app.Flags = generateCmd.Flags 169 app.Version = graphql.Version 170 app.Before = func(context *cli.Context) error { 171 if context.Bool("verbose") { 172 log.SetFlags(0) 173 } else { 174 log.SetOutput(io.Discard) 175 } 176 return nil 177 } 178 179 app.Action = generateCmd.Action 180 app.Commands = []*cli.Command{ 181 generateCmd, 182 initCmd, 183 versionCmd, 184 } 185 186 if err := app.Run(os.Args); err != nil { 187 fmt.Fprint(os.Stderr, err.Error()+"\n") 188 os.Exit(1) 189 } 190 }