git.sr.ht/~sircmpwn/gqlgen@v0.0.0-20200522192042-c84d29a1c940/cmd/init.go (about)

     1  package cmd
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"html/template"
     7  	"io/ioutil"
     8  	"os"
     9  	"path/filepath"
    10  	"strings"
    11  
    12  	"git.sr.ht/~sircmpwn/gqlgen/api"
    13  	"git.sr.ht/~sircmpwn/gqlgen/codegen/config"
    14  	"git.sr.ht/~sircmpwn/gqlgen/internal/code"
    15  	"git.sr.ht/~sircmpwn/gqlgen/plugin/servergen"
    16  	"github.com/urfave/cli/v2"
    17  )
    18  
    19  var configTemplate = template.Must(template.New("name").Parse(
    20  	`# Where are all the schema files located? globs are supported eg  src/**/*.graphqls
    21  schema:
    22    - graph/*.graphqls
    23  
    24  # Where should the generated server code go?
    25  exec:
    26    filename: graph/generated/generated.go
    27    package: generated
    28  
    29  # Uncomment to enable federation
    30  # federation:
    31  #   filename: graph/generated/federation.go
    32  #   package: generated
    33  
    34  # Where should any generated models go?
    35  model:
    36    filename: graph/model/models_gen.go
    37    package: model
    38  
    39  # Where should the resolver implementations go?
    40  resolver:
    41    layout: follow-schema
    42    dir: graph
    43    package: graph
    44  
    45  # Optional: turn on use ` + "`" + `gqlgen:"fieldName"` + "`" + ` tags in your models
    46  # struct_tag: json
    47  
    48  # Optional: turn on to use []Thing instead of []*Thing
    49  # omit_slice_element_pointers: false
    50  
    51  # Optional: set to speed up generation time by not performing a final validation pass.
    52  # skip_validation: true
    53  
    54  # gqlgen will search for any type names in the schema in these go packages
    55  # if they match it will use them, otherwise it will generate them.
    56  autobind:
    57    - "{{.}}/graph/model"
    58  
    59  # This section declares type mapping between the GraphQL and go type systems
    60  #
    61  # The first line in each type will be used as defaults for resolver arguments and
    62  # modelgen, the others will be allowed when binding to fields. Configure them to
    63  # your liking
    64  models:
    65    ID:
    66      model:
    67        - git.sr.ht/~sircmpwn/gqlgen/graphql.ID
    68        - git.sr.ht/~sircmpwn/gqlgen/graphql.Int
    69        - git.sr.ht/~sircmpwn/gqlgen/graphql.Int64
    70        - git.sr.ht/~sircmpwn/gqlgen/graphql.Int32
    71    Int:
    72      model:
    73        - git.sr.ht/~sircmpwn/gqlgen/graphql.Int
    74        - git.sr.ht/~sircmpwn/gqlgen/graphql.Int64
    75        - git.sr.ht/~sircmpwn/gqlgen/graphql.Int32
    76  `))
    77  
    78  var schemaDefault = `# GraphQL schema example
    79  #
    80  # https://gqlgen.com/getting-started/
    81  
    82  type Todo {
    83    id: ID!
    84    text: String!
    85    done: Boolean!
    86    user: User!
    87  }
    88  
    89  type User {
    90    id: ID!
    91    name: String!
    92  }
    93  
    94  type Query {
    95    todos: [Todo!]!
    96  }
    97  
    98  input NewTodo {
    99    text: String!
   100    userId: String!
   101  }
   102  
   103  type Mutation {
   104    createTodo(input: NewTodo!): Todo!
   105  }
   106  `
   107  
   108  var initCmd = &cli.Command{
   109  	Name:  "init",
   110  	Usage: "create a new gqlgen project",
   111  	Flags: []cli.Flag{
   112  		&cli.BoolFlag{Name: "verbose, v", Usage: "show logs"},
   113  		&cli.StringFlag{Name: "config, c", Usage: "the config filename"},
   114  		&cli.StringFlag{Name: "server", Usage: "where to write the server stub to", Value: "server.go"},
   115  		&cli.StringFlag{Name: "schema", Usage: "where to write the schema stub to", Value: "graph/schema.graphqls"},
   116  	},
   117  	Action: func(ctx *cli.Context) error {
   118  		configFilename := ctx.String("config")
   119  		serverFilename := ctx.String("server")
   120  
   121  		pkgName := code.ImportPathForDir(".")
   122  		if pkgName == "" {
   123  			return fmt.Errorf("unable to determine import path for current directory, you probably need to run go mod init first")
   124  		}
   125  
   126  		if err := initSchema(ctx.String("schema")); err != nil {
   127  			return err
   128  		}
   129  		if !configExists(configFilename) {
   130  			if err := initConfig(configFilename, pkgName); err != nil {
   131  				return err
   132  			}
   133  		}
   134  
   135  		GenerateGraphServer(serverFilename)
   136  		return nil
   137  	},
   138  }
   139  
   140  func GenerateGraphServer(serverFilename string) {
   141  	cfg, err := config.LoadConfigFromDefaultLocations()
   142  	if err != nil {
   143  		fmt.Fprintln(os.Stderr, err.Error())
   144  	}
   145  
   146  	if err := api.Generate(cfg, api.AddPlugin(servergen.New(serverFilename))); err != nil {
   147  		fmt.Fprintln(os.Stderr, err.Error())
   148  	}
   149  
   150  	fmt.Fprintf(os.Stdout, "Exec \"go run ./%s\" to start GraphQL server\n", serverFilename)
   151  }
   152  
   153  func configExists(configFilename string) bool {
   154  	var cfg *config.Config
   155  
   156  	if configFilename != "" {
   157  		cfg, _ = config.LoadConfig(configFilename)
   158  	} else {
   159  		cfg, _ = config.LoadConfigFromDefaultLocations()
   160  	}
   161  	return cfg != nil
   162  }
   163  
   164  func initConfig(configFilename string, pkgName string) error {
   165  	if configFilename == "" {
   166  		configFilename = "gqlgen.yml"
   167  	}
   168  
   169  	if err := os.MkdirAll(filepath.Dir(configFilename), 0755); err != nil {
   170  		return fmt.Errorf("unable to create config dir: " + err.Error())
   171  	}
   172  
   173  	var buf bytes.Buffer
   174  	if err := configTemplate.Execute(&buf, pkgName); err != nil {
   175  		panic(err)
   176  	}
   177  
   178  	if err := ioutil.WriteFile(configFilename, buf.Bytes(), 0644); err != nil {
   179  		return fmt.Errorf("unable to write cfg file: " + err.Error())
   180  	}
   181  
   182  	return nil
   183  }
   184  
   185  func initSchema(schemaFilename string) error {
   186  	_, err := os.Stat(schemaFilename)
   187  	if !os.IsNotExist(err) {
   188  		return nil
   189  	}
   190  
   191  	if err := os.MkdirAll(filepath.Dir(schemaFilename), 0755); err != nil {
   192  		return fmt.Errorf("unable to create schema dir: " + err.Error())
   193  	}
   194  
   195  	if err = ioutil.WriteFile(schemaFilename, []byte(strings.TrimSpace(schemaDefault)), 0644); err != nil {
   196  		return fmt.Errorf("unable to write schema file: " + err.Error())
   197  	}
   198  	return nil
   199  }