I have 2 questions regarding the GraphQL.
- I created a schema using
makeExecutableSchema
so I can create aexecutableSchema
. I exportsexecutableSchema
and initialising the server in myapp.js
like this.
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
})
}))
but I wonder if it is the right way to pass executableSchema
for both schema
and rootValue
?
- How can I implement the
resolveType
function and where?
I am getting an error saying
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.
In general I created my LoginResult
as union
so I could receive more specific error message to my front end, to handle different error messages.
This is how my LoginResult
in schema
looks like
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!
}
and login
resolver method looks like this
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)
}
}
}
}
and this is how I created a query from front end
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
}
}
Any help is appriciated!