Ошибка запроса мутации graphql с использованием пакета graph-gophers/graphql-go

ПРОБЛЕМА

мутация ниже

mutation {
  signUp(signUpInput: {email: "newuser@gmail.com", username: "newUser", password: "asdfasdfawerawer"}) {
    email
    username
  }
}

ошибки следующие

{
    "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
                }
            ]
        }
    ]
}

ОЖИДАНИЕ

{
  "data": {
    "signUp": {
      "email": "newuser@gmail.com",
      "username": "newUser"
    }
  }
}

фрагменты кода

schema.graphql фрагмент

...

input SignUpInput {
  username: String!
  email: String!
  password: String!
}

type Mutation {
  signUp(signUpInput: SignUpInput): SignUpResponse!
}

type SignUpResponse {
  ok: Boolean!
  error: String
  addedUser: User
}

resolvers.go фрагмент

...

// 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 - операции с базой данных

// 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
}

Я пытался изменить CreateUser к этому

// 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
}

явно не делал этого. Отсюда вопрос, почему ошибка запроса? похоже наUserResolver не могу вернуть User данные при условии, что строка возвращается из базы данных.

1 ответ

Решение

Определения вашего типа включают:

type Mutation {
  signUp(signUpInput: SignUpInput): SignUpResponse!
}

type SignUpResponse {
  ok: Boolean!
  error: String
  addedUser: User
}

Похоже, вы пытаетесь запросить поля для возвращенного User, но signUp не возвращает Userобъект. Вместо,signUp возвращает SignUpResponse объект, который, как указано в ошибке, не имеет полей с именем email или username.

Правильный запрос будет выглядеть примерно так:

mutation {
  signUp(signUpInput: {email: "newuser@gmail.com", username: "newUser", password: "asdfasdfawerawer"}) {
    addedUser {
      email
      username
    }
    ok
    error
  }
}
Другие вопросы по тегам