提问者:小点点

如何在express中实现resolveType函数/初始化graphQL服务器


我有两个关于graphql的问题。

  1. 我使用MakeExecutableSchema创建了一个模式,因此我可以创建一个ExecutableSchema。 我导出executableSchema并在app.js中初始化服务器,如下所示。
app.use('/graphql', graphqlHTTP({
    schema: executableSchema,
    rootValue: executableSchema,
    graphiql: true,
    customFormatErrorFn: (error) => ({
        message: error.message,
        locations: error.locations,
        stack: error.stack ? error.stack.split('\n') : [],
        path: error.path
    })
}))

但是我想知道为schemarootvalue传递executableSchema是否正确?

我收到一个错误,说明错误:字段“query.login”的抽象类型“LoginResult”必须在运行时解析为对象类型,值为{__TypeName:“EmailNotFound”},接收到的是“未定义”。 “LoginResult”类型应该提供一个“ResolveType”函数,或者每个可能的类型都应该提供一个“ISTypeOf”函数。

通常,我将LoginResult创建为Union,这样我可以向前端接收更具体的错误消息,以处理不同的错误消息。

这就是schema中的LoginResult的外观

    type AuthData {
        token: String!
        refreshToken: String!
        userId: String!
    }

    type EmailError {
        message: String
    }

    type PasswordError {
        message: String
    }

    type VerificationError {
        message: String
    }

    union LoginResult = AuthData | EmailError | PasswordError | VerificationError

    type Query {
        login(email: String!, password: String!): LoginResult!
    }

login解析程序方法如下所示

const resolvers = {
    Query: {
        login: async function ({ email, password }) {
            try {
                const user = await User.findOne({ email: email })
    
                const errors = []
    
                if(!user) {
                    const error = new Error('User not found.')
                    error.code = 404
                    errors.push('404')
                    
                    return {
                        __typename: 'EmailNotFound'
                    }
    
                    // throw error
                }
    
                const isEqual = await bcrypt.compare(password, user.password)
    
                if(!isEqual) {
                    const error = new Error('Password is incorrect.')
                    error.code = 401
                    errors.push('401')
                    // throw error
                    return {
                        __typename: 'PasswordIncorrect'
                    }
                }
    
                if(!user.isVerified) {
                    const error = new Error('Please verify your email address')
                    error.code = 403
                    errors.push('403')
                    // throw error
                    return {
                        __typename: 'NotVerified'
                    }
                }
    
                // if (errors.length > 0) {
                //     const error = new Error('Invalid input.')
                //     error.data = errors
                //     error.code = 422
                //     throw error
                // }
    
                const token = jwt.sign(
                    {
                        userId: user._id.toString(),
                        email: user.email
                    },
                    JWT_SECRET_KEY,
                    { expiresIn: '30min' }
                )
    
                const refreshToken = jwt.sign(
                    {
                        userId: user._id.toString(),
                        email: user.email
                    },
                    JWT_SECRET_KEY,
                    { expiresIn: '1h' }
                )
    
                return {
                    token,
                    refreshToken,
                    userId: user._id.toString(),
                    __typename: 'AuthData'
                }
    
            } catch(err) {
                console.log(err)
            }
        }
    }
}

这就是我如何从前端创建一个查询

const graphqlQuery = {
          query: `
            query UserLogin($email: String!, $password: String!){
              login(email: $email, password: $password) {
                __typename
                ...on AuthData {
                    token
                    userId
                }
                ...on EmailError {
                   message
                }
                ...on PasswordError {
                   message
                }
                ...on VerificationError {
                   message
                }

              }
            }
          `,
          variables: {
            email,
            password
          }
        }

欢迎任何帮助!


共1个答案

匿名用户

rootvalue是传递到查询和变异解析器中的值(作为父值)。 这个值很少使用,但是您可以使用它将任何东西传递给这些解析器。

类型名称和在__typename中返回的字符串需要完全相同。 例如。 您的类型似乎称为PasswordError,但您返回的类型名称为PasswordInCorrection