Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Getting Started" docs seem pretty broken? #773

Closed
dvelitchkov opened this issue Jul 2, 2019 · 17 comments · Fixed by #781
Closed

"Getting Started" docs seem pretty broken? #773

dvelitchkov opened this issue Jul 2, 2019 · 17 comments · Fixed by #781

Comments

@dvelitchkov
Copy link

What happened?

Multiple steps seem broken/missing
The tutorial tells you to define your own "getting started" schema - https://gqlgen.com/getting-started/#define-the-schema - then to run go run github.com/99designs/gqlgen init. Defining your own schema is completely pointless because init will just drop one in for you.

➜  work mkdir graphql-todos
➜  work cd graphql-todos 
➜  graphql-todos go mod init github.com/foobar/todos
go: creating new go.mod: module github.com/foobar/todos
 graphql-todos  go run github.com/99designs/gqlgen init
Exec "go run ./server/server.go" to start GraphQL server
➜  graphql-todos ls
generated.go   go.mod         go.sum         gqlgen.yml     models_gen.go  resolver.go    schema.graphql server
➜  graphql-todos cat schema.graphql 
# GraphQL schema example
#
# https://gqlgen.com/getting-started/

type Todo {
  id: ID!
  text: String!
  done: Boolean!
  user: User!
}

type User {
  id: ID!
  name: String!
}

type Query {
  todos: [Todo!]!
}

input NewTodo {
  text: String!
  userId: String!
}

type Mutation {
  createTodo(input: NewTodo!): Todo!
}

Ok, so far so good. Got my stuff in place. Second problem - need to enable "lazy loading" for the User model in the Todo model (sorry if my terminology is off, a bit new to graphql)

So I change

type Todo struct {
	ID   string `json:"id"`
	Text string `json:"text"`
	Done bool   `json:"done"`
	User *User  `json:"user"`
}

to

type Todo struct {
	ID     string `json:"id"`
	Text   string `json:"text"`
	Done   bool   `json:"done"`
	UserID string `json:"user"`
}

Ok then it says to run go run github.com/99designs/gqlgen and proceeds to tell me about the "verbose" flag which isn't even in the command I just ran (?) But let's ignore that and run gqlgen without any parameters which is the same as running it with the generate command (probably mention that?)

graphql-todos go run github.com/99designs/gqlgen
unable to parse config: yaml: unmarshal errors:
  line 18: key "deprecated" already set in map
  line 20: key "include" already set in map
  line 22: key "skip" already set in map
exit status 2
➜  graphql-todos 

Ouch? At this point, all I've done is changed the User entity a bit and I'm getting yaml unmarshal errors? Ok let's remove the offending keys (why is the default gqlgen.yml causing errors?)

graphql-todos cat gqlgen.yml 
# .gqlgen.yml example
#
# Refer to https://gqlgen.com/config/
# for detailed .gqlgen.yml documentation.

schema:
- schema.graphql
exec:
  filename: generated.go
model:
  filename: models_gen.go
resolver:
  filename: resolver.go
  type: Resolver
autobind: []
# directives:
#   deprecated:
#     skip_runtime: true
#   include:
#     skip_runtime: true
#   skip:
#     skip_runtime: true
➜  graphql-todos go run github.com/99designs/gqlgen
➜  graphql-todos 

Finally - success. So is the expected workflow for me to comment out the directives every time I run generate?

So to sum up:

  1. Docs make user create a schema needlessly
  2. Mention of a "verbose" flag
  3. Following the steps with version 0.9.1 gives yaml unmarshal errors

What did you expect?

Stuff to mostly work.

Minimal graphql.schema and models to reproduce

Default from init command

versions

  • gqlgen version - v0.9.1
  • go version? - 1.12.6 darwin/amd64
  • dep or go modules? - go modules
@Igorpollo
Copy link

@dvelitchkov Same error here. Got any solution?

@als9xd
Copy link

als9xd commented Jul 4, 2019

I think there is also a typo with the Todos resolver.

.\resolver.go:17:24: cannot use &queryResolver literal (type *queryResolver) as type QueryResolver in return argument:
*queryResolver does not implement QueryResolver (wrong type for Todos method)
have Todos(context.Context) ([]Todo, error)
want Todos(context.Context) ([]*Todo, error)
.\resolver.go:38:10: cannot use r.Resolver.todos (type []*Todo) as type []Todo in return argument

func (r *queryResolver) Todos(ctx context.Context) ([]*Todo, error) {
	return r.todos, nil
}

instead of

func (r *queryResolver) Todos(ctx context.Context) ([]Todo, error) {
	return r.todos, nil
}

@haswalt
Copy link

haswalt commented Jul 5, 2019

@als9xd I think you may have commented on the wrong issue buddy.

I can replicate the issue too, looks like something to do with how the default config already has the directives fields set and is used to unmarshal the local config here: https://github.com/99designs/gqlgen/blob/master/codegen/config/config.go#L36

Which was added in 17a82c3 by @lwc

Rolling back to an earlier version before May 27th may work due to removing this change, but will unfortunately roll back a load of other additions.

Simple reproduction here: https://play.golang.org/p/vFVkfwFpCTk

From the Yaml docs:

"UnmarshalStrict is like Unmarshal except that any fields that are found in the data that do not have corresponding struct members, or mapping keys that are duplicates, will result in an error."

Shows that this would never work. Should probably add those keys in to the default config only for writing the initial or if they are not found AFTER parsing the local gqlgen.yml

@the-vampiire
Copy link

not sure why this was closed. i am very familiar with graphql but new to go. wanted to learn how its implemented on the go side and was recommended gqlgen.

i am appreciative of your tool and guide. but i hope that given a complete beginner perspective we can improve the docs. if you can sort me out id be happy to open a PR with fixes to improve it for future beginners

this is a list of my own confusions:

Create the database models
The generated model for Todo isn’t right, it has a user embeded in it but we only want to fetch it if the user actually requested it. So instead lets make a new model in todo.go:

  • it is not clear what todo.go is. that was not one of the generated files. did it mean to say edit the models_gen.go file (as it appears OP has done)? i read that as to create a file called todo.go and to put in the suggested struct

Next tell gqlgen to use this new struct by adding it to gqlgen.yml:

models:
  Todo:
    model: github.com/[username]/gqlgen-todos.Todo

my own gqlgen.yml file did not have a models field so i added it like this, is this correct?:

# .gqlgen.yml example
#
# Refer to https://gqlgen.com/config/
# for detailed .gqlgen.yml documentation.

schema:
- schema.graphql
exec:
  filename: generated.go
model:
  filename: models_gen.go
# there is no models field so i added it here
models:
  Todo:
    model: github.com/the-vampiire/gqlgen-todos.Todo
resolver:
  filename: resolver.go
  type: Resolver
autobind: []
directives:
  deprecated:
    skip_runtime: true
  include:
    skip_runtime: true
  skip:
    skip_runtime: true

i then ran the following commands:

$ vim gqlgen.yml
$ go run github.com/99designs/gqlgen     
unable to parse config: yaml: unmarshal errors:
  line 21: key "deprecated" already set in map
  line 23: key "include" already set in map
  line 25: key "skip" already set in map
exit status 2

using what i saw from OP i commented out the directives bit and then ran using the -v flag for the following result

$ vim gqlgen.yml
$ go run github.com/99designs/gqlgen -v
/Users/vampiire/codes/personal/gqlgen-todos/todo.go:3 adding resolver method for Todo.user, nothing matched
Skipped resolver: /Users/vampiire/codes/personal/gqlgen-todos/resolver.go already exists

since this is not working, instead of creating a todo.go file i was to edit the models_gen.go file itself (as in OP). but when i enter the file it looks like the Todo struct had been removed. pretty neat that it blends this generated models with your own models. but now i am unsure how to proceed

@the-vampiire
Copy link

so the warning about "nothing matched" and "skipped resolver" did not have an impact. i continued with the rest of the guide and it worked.

maybe just clarify those beginning parts because the rest seems to be correct. thanks

@bugzpodder
Copy link

In Go everything in the package can be spread over many files in the same directory. So todo.go should be placed in the same directory as models_gen.go. I would not recommend modifying models_gen.go, just move it out.

The model field should be your the full package + struct type i think (more of a go packages thing).
I would recommend autobind function, you don't need to indicate every different struct and just the package is enough.

@the-vampiire
Copy link

the-vampiire commented Jul 12, 2019

good to know man thank you for the information. if its not too much to ask i was trying to implement a little extension to the code so cement my understanding.

i added the following mutation to the schema

type Mutation {
  completeTodo(todoID: ID!): Todo
}

then in my resolver.go i tried doing the following

edit: im dumb. in go types come after the var name!

string todoID -> todoID string
func (r *mutationResolver) CompleteTodo(ctx context.Context, todoID string) (*Todo, error) {
  for _, todo := range r.todos {
    if todo.ID == todoID {
      todo.Done = true
      return todo, nil
    }
  }

  return nil, nil
}

this is clearly because i should learn more go and not a fault of the package. but could you tell me why i cant accept a string arg todoID here? i get undeclared name: todoID error. are scalar inputs not allowed in gqlgen?

@the-vampiire
Copy link

another curiosity i have is why the schema uses lowercase but in the go code all the properties are capitalized. is this a go convention for structs or something to do with the lib itself?

@haswalt
Copy link

haswalt commented Jul 12, 2019

In Go lowercase properties are private banks uppercase are exported I.e. public

@the-vampiire
Copy link

In Go lowercase properties are private banks uppercase are exported I.e. public

is that a convention (like __prop in python) or a feature of the language?

@the-vampiire
Copy link

deconstructing the code it looks like adding "methods" (not sure of terminology in go) onto a struct has the form

func (*this StructName) FuncName(args) returnType | (returnType, returnType2) {
  // implementation
  // this refers to the instance of the struct for accessing properties in the method
}

anyways this was pretty cool thank you for the guide. i think i will spend some time learning go now!

@briskt
Copy link
Contributor

briskt commented Jul 23, 2019

I submitted PR #801 to address a few of the inconsistencies, but I still get these errors:

$ go run github.com/99designs/gqlgen
unable to parse config: yaml: unmarshal errors:
  line 18: key "deprecated" already set in map
  line 20: key "include" already set in map
  line 22: key "skip" already set in map
exit status 2

I see that #781 appears to address this, but I don't get the benefit. Do I need to do something to get this update?

@molon
Copy link

molon commented Jul 25, 2019

This issue of yaml still exists.

@rof20004
Copy link

Why issue was closed? The issue still exists:

unable to parse config: yaml: unmarshal errors:
  line 18: key "deprecated" already set in map
  line 20: key "include" already set in map
  line 22: key "skip" already set in map
exit status 2

@LiZhenchong
Copy link

It seems that just change from yarm.UnmarshalStrict to yarm. Unmarshal works, and also get the result we expect.
BUT I don't know whether any side effect exists.
https://github.com/99designs/gqlgen/blob/master/codegen/config/config.go#L76

Related Issue: #781

@hboylan
Copy link

hboylan commented Jul 30, 2019

Still getting this error when following the getting started tutorial. Removing the following lines from gqlgen.yml squashes the error, but also not sure of the side effects:

directives:
  deprecated:
    skip_runtime: true
  include:
    skip_runtime: true
  skip:
    skip_runtime: true

@rickyseezy
Copy link

rickyseezy commented Apr 21, 2022

I'm still having this error field layout not found in type config.PackageConfig and field dir not found in type config.PackageConfig with the following configuration (from the documentation) gqlgen version v0.17.3

exec:
  layout: follow-schema
  dir: pkg/graphql/generated
  package: generated

So I have switched it to

exec:
  filename: pkg/graphql/generated/generated.go
  package: generated

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.