PROBLEM
the mutation below
mutation {
signUp(signUpInput: {email: "newuser@gmail.com", username: "newUser", password: "asdfasdfawerawer"}) {
email
username
}
}
errors out the following
{
"errors": [
{
"message": "Cannot query field \"email\" on type \"SignUpResponse\".",
"locations": [
{
"line": 3,
"column": 5
}
]
},
{
"message": "Cannot query field \"username\" on type \"SignUpResponse\".",
"locations": [
{
"line": 4,
"column": 5
}
]
}
]
}
EXPECTATION
{
"data": {
"signUp": {
"email": "newuser@gmail.com",
"username": "newUser"
}
}
}
snippets of code
schema.graphql
snippet
...
input SignUpInput {
username: String!
email: String!
password: String!
}
type Mutation {
signUp(signUpInput: SignUpInput): SignUpResponse!
}
type SignUpResponse {
ok: Boolean!
error: String
addedUser: User
}
resolvers.go
snippet
...
// UserResolver ingests properties from User
type UserResolver struct{ u *User }
// UserID returns the userId of the user
func (r *UserResolver) UserID() graphql.ID {
return r.u.UserID
}
// Username returns the username of the user
func (r *UserResolver) Username() string {
return r.u.Username
}
// Email returns the email of the user
func (r *UserResolver) Email() string {
return r.u.Email
}
// Password returns the password of the user
func (r *UserResolver) Password() string {
return r.u.Password
}
type SignUpArgs struct {
Username string
Email string
Password string
}
// SignUp returns a new User from Db and its responses
func (r *RootResolver) SignUp(args struct{ SignUpInput *SignUpArgs }) (*SignUpResolver, error) {
// Find user:
u, err := r.Db.CreateUser(args.SignUpInput)
// need to deal with this different, so sort of error if we can't create the user
// a. user already exists
// b. email already exists
if err != nil {
// error creating the user
msg := "already signed up"
return &SignUpResolver{
Status: false,
Msg: &msg,
User: nil,
}, err
}
return &SignUpResolver{
Status: true,
Msg: nil,
User: &UserResolver{&u},
}, nil
}
// SignUpResolver is the response type
type SignUpResolver struct {
Status bool
Msg *string
User *UserResolver
}
// Ok for SignUpResponse
func (r *SignUpResolver) Ok() bool {
return r.Status
}
// Error for SignUpResponse
func (r *SignUpResolver) Error() *string {
return r.Msg
}
// AddedUser for SignUpResponse
func (r *SignUpResolver) AddedUser() *UserResolver {
return r.User
}
postgres.go - db operations
// User returns a single user
func (d *Db) User(uid graphql.ID) (User, error) {
var (
sqlStatement = `SELECT * FROM users WHERE user_id=$1;`
row *sql.Row
err error
u User
)
row = d.QueryRow(sqlStatement, uid)
err = row.Scan(
&u.UserID,
&u.Username,
&u.Email,
&u.Password,
)
util.Check(err, "row.Scan")
return u, nil
}
// CreateUser - inserts a new user
func (d *Db) CreateUser(i *SignUpArgs) (User, error) {
var (
sqlStatement = `
INSERT INTO users (email, username, password)
VALUES ($1, $2, $3)
RETURNING user_id`
userID graphql.ID
row *sql.Row
err error
u User
)
/***************************************************************************
* retrieve the UserID of the newly inserted record
* db.Exec() requires the Result interface with the
LastInsertId() method which relies on a returned value from postgresQL
* lib/pq does not however return the last inserted record
****************************************************************************/
row = d.QueryRow(sqlStatement, i.Email, i.Username, i.Password)
if err = row.Scan(&userID); err != nil {
// err: username or email is not unqiue --> user already exsits
return u, err
}
u, _ = d.User(userID)
return u, nil
}
I've tried to change the CreateUser
to this
// CreateUser - inserts a new user
func (d *Db) CreateUser(i *SignUpArgs) (User, error) {
var (
sqlStatement = `
INSERT INTO users (email, username, password)
VALUES ($1, $2, $3)
RETURNING user_id`
userID graphql.ID
row *sql.Row
err error
u User
)
/***************************************************************************
* retrieve the UserID of the newly inserted record
* db.Exec() requires the Result interface with the
LastInsertId() method which relies on a returned value from postgresQL
* lib/pq does not however return the last inserted record
****************************************************************************/
row = d.QueryRow(sqlStatement, i.Email, i.Username, i.Password)
if err = row.Scan(&userID); err != nil {
// err: username or email is not unqiue --> user already exsits
return u, err
}
err = row.Scan(
&u.UserID,
&u.Username,
&u.Email,
&u.Password,
)
util.Check(err, "row.Scan User")
return u, nil
}
didn't do it obviously. hence the question, why the query error? seems like UserResolver
can't return the User
data provided the row is being returned from db.
Your type definitions include:
type Mutation {
signUp(signUpInput: SignUpInput): SignUpResponse!
}
type SignUpResponse {
ok: Boolean!
error: String
addedUser: User
}
It appears you're attempting to query the fields for the returned User
, but signUp
does not return a User
object. Instead, signUp
returns a SignUpResponse
object, which, as the error states, does not have any fields named email
or username
.
The correct query would look something like this:
mutation {
signUp(signUpInput: {email: "newuser@gmail.com", username: "newUser", password: "asdfasdfawerawer"}) {
addedUser {
email
username
}
ok
error
}
}