如何在 express 中实现 resolveType 函数/初始化 graphQL 服务器
how to implement resolveType function / initialise graphQL server in express
我有 2 个关于 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
是否是正确的方法?
- 如何实现
resolveType
功能以及在哪里?
我收到一条错误消息
Error: Abstract type "LoginResult" must resolve to an Object type at runtime for field "Query.login" with value { __typename: "EmailNotFound" }, received "undefined". Either the "LoginResult" type should provide a "resolveType" function or each possible type should provide an "isTypeOf" function.
一般来说,我将 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
中 return 的字符串必须完全相同。例如。您的类型似乎被称为 PasswordError
但您 return 类型名称 PasswordIncorrect
.
我有 2 个关于 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
是否是正确的方法?
- 如何实现
resolveType
功能以及在哪里?
我收到一条错误消息
Error: Abstract type "LoginResult" must resolve to an Object type at runtime for field "Query.login" with value { __typename: "EmailNotFound" }, received "undefined". Either the "LoginResult" type should provide a "resolveType" function or each possible type should provide an "isTypeOf" function.
一般来说,我将 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
中 return 的字符串必须完全相同。例如。您的类型似乎被称为 PasswordError
但您 return 类型名称 PasswordIncorrect
.