1package cmd
2
3import (
4 "bytes"
5 "fmt"
6 "io/ioutil"
7 "os"
8 "strings"
9
10 "github.com/99designs/gqlgen/codegen"
11 "github.com/pkg/errors"
12 "github.com/urfave/cli"
13 "gopkg.in/yaml.v2"
14)
15
16var configComment = `
17# .gqlgen.yml example
18#
19# Refer to https://gqlgen.com/config/
20# for detailed .gqlgen.yml documentation.
21`
22
23var schemaDefault = `
24# GraphQL schema example
25#
26# https://gqlgen.com/getting-started/
27
28type Todo {
29 id: ID!
30 text: String!
31 done: Boolean!
32 user: User!
33}
34
35type User {
36 id: ID!
37 name: String!
38}
39
40type Query {
41 todos: [Todo!]!
42}
43
44input NewTodo {
45 text: String!
46 userId: String!
47}
48
49type Mutation {
50 createTodo(input: NewTodo!): Todo!
51}
52`
53
54var initCmd = cli.Command{
55 Name: "init",
56 Usage: "create a new gqlgen project",
57 Flags: []cli.Flag{
58 cli.BoolFlag{Name: "verbose, v", Usage: "show logs"},
59 cli.StringFlag{Name: "config, c", Usage: "the config filename"},
60 cli.StringFlag{Name: "server", Usage: "where to write the server stub to", Value: "server/server.go"},
61 cli.StringFlag{Name: "schema", Usage: "where to write the schema stub to", Value: "schema.graphql"},
62 },
63 Action: func(ctx *cli.Context) {
64 initSchema(ctx.String("schema"))
65 config := initConfig(ctx)
66
67 GenerateGraphServer(config, ctx.String("server"))
68 },
69}
70
71func GenerateGraphServer(config *codegen.Config, serverFilename string) {
72 for _, filename := range config.SchemaFilename {
73 schemaRaw, err := ioutil.ReadFile(filename)
74 if err != nil {
75 fmt.Fprintln(os.Stderr, "unable to open schema: "+err.Error())
76 os.Exit(1)
77 }
78 config.SchemaStr[filename] = string(schemaRaw)
79 }
80
81 if err := config.Check(); err != nil {
82 fmt.Fprintln(os.Stderr, "invalid config format: "+err.Error())
83 os.Exit(1)
84 }
85
86 if err := codegen.Generate(*config); err != nil {
87 fmt.Fprintln(os.Stderr, err.Error())
88 os.Exit(1)
89 }
90
91 if err := codegen.GenerateServer(*config, serverFilename); err != nil {
92 fmt.Fprintln(os.Stderr, err.Error())
93 os.Exit(1)
94 }
95
96 fmt.Fprintf(os.Stdout, "Exec \"go run ./%s\" to start GraphQL server\n", serverFilename)
97}
98
99func initConfig(ctx *cli.Context) *codegen.Config {
100 var config *codegen.Config
101 var err error
102 configFilename := ctx.String("config")
103 if configFilename != "" {
104 config, err = codegen.LoadConfig(configFilename)
105 } else {
106 config, err = codegen.LoadConfigFromDefaultLocations()
107 }
108
109 if config != nil {
110 fmt.Fprintf(os.Stderr, "init failed: a configuration file already exists at %s\n", config.FilePath)
111 os.Exit(1)
112 }
113
114 if !os.IsNotExist(errors.Cause(err)) {
115 fmt.Fprintln(os.Stderr, err.Error())
116 os.Exit(1)
117 }
118
119 if configFilename == "" {
120 configFilename = "gqlgen.yml"
121 }
122 config = codegen.DefaultConfig()
123
124 config.Resolver = codegen.PackageConfig{
125 Filename: "resolver.go",
126 Type: "Resolver",
127 }
128
129 var buf bytes.Buffer
130 buf.WriteString(strings.TrimSpace(configComment))
131 buf.WriteString("\n\n")
132 {
133 var b []byte
134 b, err = yaml.Marshal(config)
135 if err != nil {
136 fmt.Fprintln(os.Stderr, "unable to marshal yaml: "+err.Error())
137 os.Exit(1)
138 }
139 buf.Write(b)
140 }
141
142 err = ioutil.WriteFile(configFilename, buf.Bytes(), 0644)
143 if err != nil {
144 fmt.Fprintln(os.Stderr, "unable to write config file: "+err.Error())
145 os.Exit(1)
146 }
147
148 return config
149}
150
151func initSchema(schemaFilename string) {
152 _, err := os.Stat(schemaFilename)
153 if !os.IsNotExist(err) {
154 return
155 }
156
157 err = ioutil.WriteFile(schemaFilename, []byte(strings.TrimSpace(schemaDefault)), 0644)
158 if err != nil {
159 fmt.Fprintln(os.Stderr, "unable to write schema file: "+err.Error())
160 os.Exit(1)
161 }
162}