我有两个关于graphql的问题。
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
})
}))
但是我想知道为schema
和rootvalue
传递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
}
}
欢迎任何帮助!
rootvalue
是传递到查询和变异解析器中的值(作为父值)。 这个值很少使用,但是您可以使用它将任何东西传递给这些解析器。
类型名称和在__typename
中返回的字符串需要完全相同。 例如。 您的类型似乎称为PasswordError
,但您返回的类型名称为PasswordInCorrection
。