1

I have been losing all Saturday trying to figure out this. I am good in frontend and decided to jump in and learn back end as well. I have been very interested in graphQl and since I was already doing a lot with firebase it was a go. I decided to learn the graphQl server but cannot figure out what I am doing wrong.

I have this resolver to create a firebase account:

module.exports = {
  Mutation: {
    registerUser: async (
      _,
      { registerInput: { username, email, password } },
      context,
      info
    ) => {


      const register = await admin
        .auth()
        .createUser({
          email,
          emailVerified: false,
          password: password,
          displayName: username,
          disabled: false
        })
        .then(function(userRecord) {
          console.log("Successfully created new user:", userRecord.uid);
           const {userData} = admin
             .firestore()
             .collection("users")
             .doc(userRecord.uid)
             .set(
               {
                 email,
                 role: "user",
                 username,
                 uid: userRecord.uid
             }, {merge: true});
            return register
        })
        .catch(function(error) {
            console.log("Error creating new user:", error);
        });
        return register
    }

and in the schema:

type Mutation {
    registerUser(registerInput: RegisterInput): User!

type User {
     firstName: String
     lastName: String
    password: String!
     adress: String
     postCode: String
     role: String
     ort: String
    email: String!
     phone: String
     responseRate: Float
     responseTime: Int
     profilePicture: String
     token: String
    username: String!
     personnummer: Int
  }

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

However when I run it in the playground, sometimes the account and the document about the user gets created, other times doesn't, but I always get the same error on the playground:

"errors": [
    {
      "message": "Cannot return null for non-nullable field Mutation.registerUser.",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "registerUser"
      ],
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR",
        "exception": {
          "stacktrace": [
            "Error: Cannot return null for non-nullable field Mutation.registerUser.",
            "    at completeValue 
Oblicion A
  • 157
  • 1
  • 1
  • 12

1 Answers1

1

Your resolver is an async function, so it will always return a Promise, but that promise will resolve to whatever is returned inside the function. If you return undefined or null, then the field in question (registerUser) will resolve to null. Since you've told GraphQL that can't happen, it throws an error to that effect.

When you call then on a Promise, whatever is returned inside then's callback becomes the value the Promise resolves to (provided no errors are thrown that would cause the Promise to reject). What you're returning inside the then callback in your code is register, which is effectively undefined because it's being used before being initialized.

If you're already using async/await syntax, there's no point in continuing to use then. Just stick with await -- it will keep your code cleaner, easier to read and less error-prone.

const userRecord = await admin
  .auth()
  .createUser({...})

// if `set` returns a Promise, we should await that as well
const { userData } = await admin
  .firestore()
  .collection("users")
  .doc(userRecord.uid)
  .set(...)

return userData

Note that GraphQL will catch any errors or rejected Promises for you and surface them as part of the response, so you don't need to use try/catch here unless you want to mask or otherwise format the error.

Daniel Rearden
  • 80,636
  • 11
  • 185
  • 183
  • thanks man! I actually had among those, other errors and was not thinking it was a promise that was returned, needless to say, i fixed it. Now I am struggling with the login part, where I need to find a way to compare passwords, but that is entirely firebase admin sdk stuff. – Oblicion A Mar 14 '20 at 19:49