3
votes

I'm following a Udemy course on apollo, and also fairly new to nodeJS. This course has gone well so far, but on a step where they are introducing combineResolvers() from the graphql-resolvers module, something is breaking.

It is trying to add an authentication step to a resolver by using combineResolvers() from graphql-resolvers module. Each part works fine independently, meaning the isAuthenticated() is working fine by itself, as well as the user query that gets a user by user.id.

When I use combineResolvers(), I get an INTERNAL_SERVER_ERROR, "Error: Cannot return null for non-nullable field User.id.". Also, when I get this error, the console.log from the isAuthenticated() is displayed with an email, so it should return/skip, but the console.log from the user resolver, before the users.find... , is not. How is it failing between them?

Here is the relevant code. The commented lines are the ones that worked before introducing combineResolvers:

const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const { combineResolvers } = require('graphql-resolvers');

const { users, tasks } = require('../constants');
const User = require('../database/models/user');
const { isAuthenticated } = require('./middleware');

module.exports = {
    Query: {
        users: () => {
            return users;
        }, 
        // user: ( _, args, { email }) => {
        //     console.log("===", email);
        //     return users.find(user => user.id == args.id);
        // }
        user: combineResolvers(isAuthenticated, ( _, { id }, { email }) => {
            console.log("===", email);
            return users.find(user => user.id == id);
        })
    }
}

And here is the isAuthenticated module, from /resolvers/middleware/index.js:

const skip = require('graphql-resolvers');

module.exports.isAuthenticated = (_, __, { email }) => {
    console.log("isAuthenticated...email : ", email);
    if (!email) {
        throw new Error("Access Denied! Please login to continue");
    }
    return skip;
}
1

1 Answers

0
votes

You can define combined resolver before export (as in docs, no real change, both methods should work) ...

... but probably you need to use async/await for DB/datasource related resolvers:

const authedUserById = combineResolvers(
  isAuthenticated, 
  async ( _, { id }, { email }) => {
        console.log("==>>", id, email);
        return await users.find(user => user.id == id);
  }
)

module.exports = {
  Query: {
    users: () => {
        return users;
    }, 
    user: authedUserById
  }
}

What id is logged??? how tested? how passed variable?