Reputation: 118
Starting out with a GraphQL / Node / Express / Typescript stack, I am coming across an issue where field arguments are not being passed to the resolver function. I have two queries:
UserList:
UserList: {
type: new GraphQLList(UserType),
args: {
userName: {
type: GraphQLString
},
userIsLocked: {
type: GraphQLBoolean
},
userIsConfirmed: {
type: GraphQLBoolean
},
userAwaitingPassword: {
type: GraphQLBoolean
}
},
resolve: ((_, {fields}) => new User().where({fields}))
}
And User:
User: {
type: UserType,
args: {
userId: {
type: GraphQLID
}
},
resolve: ((_, {userId}) => new User().getById({userId}))
}
The User().where()
function defaults to displaying all users if no criteria is provided. However, consider the following query and results:
query All {
UserList(userIsLocked:true){
userId
userName
userIsLocked
}
}
// Results
{
"data": {
"UserList": [
{
"userId": "a4f1d968-52d6-4148-bf62-1e132a4defde",
"userName": "user1",
"userIsLocked": false
},
{
"userId": "b42a1170-096a-11e9-b568-0800200c9a66",
"userName": "administrator",
"userIsLocked": false
}
]
}
}
Obviously, userIsLocked is not being passed the fields argument on the where()
function. However, the following works:
query Individual {
User(userId: "a4f1d968-52d6-4148-bf62-1e132a4defde") {
userId
userName
userIsLocked
}
}
// Results
{
"data": {
"User": {
"userId": "a4f1d968-52d6-4148-bf62-1e132a4defde",
"userName": "user1",
"userIsLocked": false
}
}
}
When userId
is logged on a request to getById()
, I see {"userId":"a4f1d968-52d6-4148-bf62-1e132a4defde"}
in the console. But when fields
is logged on a request to where()
, all that shows in the console is undefined
and my query defaults to displaying all users. I can not figure out why 2 apparently equal queries would be behaving in such different ways. I have scoured the documentation for GraphQL but all I can find are sample queries and general query structure.
Upvotes: 1
Views: 8050
Reputation: 84687
The second argument passed to the resolve
function is an object the properties of which map to the arguments for that field. Let's look at the working resolver:
resolve: (_, {userId}) => new User().getById({userId})
Here, you're using object destructuring syntax to unpack the userId
property from the second parameter and sign it to a variable of the same name. You then use shorthand property name syntax to create an object with the userId
property (with the value of the userId
variable you defined) and this object is passed to the getById
method.
This is syntactically equivalent to the following function:
resolve: (_, args) => {
const userId = args.userId
return new User().getById({ userId: userId })
}
It's unclear from your question what ORM you're using, so I can't speak to whether you're correctly calling the where
method in other resolver. However, you are definitely not unpacking any of the arguments for that field. Here's your function:
resolve: (_, {fields}) => new User().where({fields})
Which is equivalent to:
resolve: (_, args) => {
const fields = args.fields
return new User().where({ fields: fields })
}
Your field has the following four arguments: userName
, userIsLocked
, userIsConfirmed
and userAwaitingPassword
. fields
is not a valid argument and therefore will always be undefined unless you add an argument named fields to your UserList
field and actually pass it in. I'm going to hazard a guess and say your model also doesn't have a fields
property. If you simply want to pass in the arguments object to the where
method, you can do:
resolve: (_, fields) => new User().where(fields)
Note the lack of curly braces. Again, you haven't told us anything about what ORM you're using or the User model itself, so this still may not give you the desired results if you're not correctly using that API. However, hopefully this puts you on the right track.
Upvotes: 6